20#include <freerdp/config.h> 
   22#include "../settings.h" 
   23#include "ncacn_http.h" 
   26#include <winpr/tchar.h> 
   27#include <winpr/stream.h> 
   28#include <winpr/dsparse.h> 
   32#define TAG FREERDP_TAG("core.gateway.ntlm") 
   34#define AUTH_PKG NTLM_SSP_NAME 
   36static wStream* rpc_auth_http_request(HttpContext* http, 
const char* method, 
size_t contentLength,
 
   37                                      const SecBuffer* authToken, 
const char* auth_scheme)
 
   40  HttpRequest* request = NULL;
 
   41  char* base64AuthToken = NULL;
 
   42  const char* uri = NULL;
 
   47  request = http_request_new();
 
   53    base64AuthToken = crypto_base64_encode(authToken->pvBuffer, authToken->cbBuffer);
 
   55  uri = http_context_get_uri(http);
 
   57  if (!http_request_set_method(request, method) ||
 
   58      !http_request_set_content_length(request, contentLength) ||
 
   59      !http_request_set_uri(request, uri))
 
   64    if (!http_request_set_auth_scheme(request, auth_scheme) ||
 
   65        !http_request_set_auth_param(request, base64AuthToken))
 
   69  s = http_request_write(http, request);
 
   71  http_request_free(request);
 
   72  free(base64AuthToken);
 
   76BOOL rpc_ncacn_http_send_in_channel_request(
RpcChannel* inChannel)
 
   80  rdpCredsspAuth* auth = NULL;
 
   81  HttpContext* http = NULL;
 
   85  if (!inChannel || !inChannel->auth || !inChannel->http)
 
   88  auth = inChannel->auth;
 
   89  http = inChannel->http;
 
   91  rc = credssp_auth_authenticate(auth);
 
   95  const size_t contentLength = (rc == 0) ? 0 : 0x40000000;
 
   96  buffer = credssp_auth_have_output_token(auth) ? credssp_auth_get_output_buffer(auth) : NULL;
 
   97  s = rpc_auth_http_request(http, 
"RPC_IN_DATA", contentLength, buffer,
 
   98                            credssp_auth_pkg_name(auth));
 
  103  status = rpc_channel_write(inChannel, Stream_Buffer(s), Stream_Length(s));
 
  104  Stream_Free(s, TRUE);
 
  105  return (status > 0) ? 1 : -1;
 
  108BOOL rpc_ncacn_http_recv_in_channel_response(
RpcChannel* inChannel, HttpResponse* response)
 
  110  size_t authTokenLength = 0;
 
  111  BYTE* authTokenData = NULL;
 
  113  if (!inChannel || !response || !inChannel->auth)
 
  116  rdpCredsspAuth* auth = inChannel->auth;
 
  117  const char* token64 = http_response_get_auth_token(response, credssp_auth_pkg_name(auth));
 
  120    crypto_base64_decode(token64, strlen(token64), &authTokenData, &authTokenLength);
 
  122  if (authTokenLength > UINT32_MAX)
 
  128  SecBuffer buffer = { .pvBuffer = authTokenData, .cbBuffer = (UINT32)authTokenLength };
 
  130  if (authTokenData && authTokenLength)
 
  132    credssp_auth_take_input_buffer(auth, &buffer);
 
  136  sspi_SecBufferFree(&buffer);
 
  140BOOL rpc_ncacn_http_auth_init(rdpContext* context, 
RpcChannel* channel)
 
  143  rdpCredsspAuth* auth = NULL;
 
  144  rdpSettings* settings = NULL;
 
  145  freerdp* instance = NULL;
 
  146  auth_status rc = AUTH_FAILED;
 
  147  SEC_WINNT_AUTH_IDENTITY identity = { 0 };
 
  149  if (!context || !channel)
 
  153  auth = channel->auth;
 
  154  settings = context->settings;
 
  155  instance = context->instance;
 
  157  if (!tls || !auth || !instance || !settings)
 
  160  rc = utils_authenticate_gateway(instance, GW_AUTH_HTTP);
 
  167      freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
 
  169    case AUTH_NO_CREDENTIALS:
 
  170      WLog_INFO(TAG, 
"No credentials provided - using NULL identity");
 
  177  if (!credssp_auth_init(auth, AUTH_PKG, tls->Bindings))
 
  180  if (!identity_set_from_settings(&identity, settings, FreeRDP_GatewayUsername,
 
  181                                  FreeRDP_GatewayDomain, FreeRDP_GatewayPassword))
 
  184  SEC_WINNT_AUTH_IDENTITY* identityArg = (settings->GatewayUsername ? &identity : NULL);
 
  186      credssp_auth_setup_client(auth, 
"HTTP", settings->GatewayHostname, identityArg, NULL);
 
  188  sspi_FreeAuthIdentity(&identity);
 
  190  credssp_auth_set_flags(auth, ISC_REQ_CONFIDENTIALITY);
 
  195void rpc_ncacn_http_auth_uninit(
RpcChannel* channel)
 
  200  credssp_auth_free(channel->auth);
 
  201  channel->auth = NULL;
 
  204BOOL rpc_ncacn_http_send_out_channel_request(
RpcChannel* outChannel, BOOL replacement)
 
  208  size_t contentLength = 0;
 
  209  rdpCredsspAuth* auth = NULL;
 
  210  HttpContext* http = NULL;
 
  214  if (!outChannel || !outChannel->auth || !outChannel->http)
 
  217  auth = outChannel->auth;
 
  218  http = outChannel->http;
 
  220  rc = credssp_auth_authenticate(auth);
 
  225    contentLength = (rc == 0) ? 0 : 76;
 
  227    contentLength = (rc == 0) ? 0 : 120;
 
  229  buffer = credssp_auth_have_output_token(auth) ? credssp_auth_get_output_buffer(auth) : NULL;
 
  230  s = rpc_auth_http_request(http, 
"RPC_OUT_DATA", contentLength, buffer,
 
  231                            credssp_auth_pkg_name(auth));
 
  236  if (rpc_channel_write(outChannel, Stream_Buffer(s), Stream_Length(s)) < 0)
 
  239  Stream_Free(s, TRUE);
 
  243BOOL rpc_ncacn_http_recv_out_channel_response(
RpcChannel* outChannel, HttpResponse* response)
 
  245  size_t authTokenLength = 0;
 
  246  BYTE* authTokenData = NULL;
 
  248  if (!outChannel || !response || !outChannel->auth)
 
  251  rdpCredsspAuth* auth = outChannel->auth;
 
  252  const char* token64 = http_response_get_auth_token(response, credssp_auth_pkg_name(auth));
 
  255    crypto_base64_decode(token64, strlen(token64), &authTokenData, &authTokenLength);
 
  257  if (authTokenLength > UINT32_MAX)
 
  262  SecBuffer buffer = { .pvBuffer = authTokenData, .cbBuffer = (UINT32)authTokenLength };
 
  264  if (authTokenData && authTokenLength)
 
  266    credssp_auth_take_input_buffer(auth, &buffer);
 
  270  sspi_SecBufferFree(&buffer);
 
  274BOOL rpc_ncacn_http_is_final_request(
RpcChannel* channel)
 
  276  WINPR_ASSERT(channel);
 
  277  return credssp_auth_is_complete(channel->auth);