20 #include <freerdp/config.h>
22 #include "../settings.h"
23 #include "ncacn_http.h"
25 #include <winpr/crt.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
36 static wStream* rpc_auth_http_request(HttpContext* http,
const char* method,
int 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);
76 BOOL rpc_ncacn_http_send_in_channel_request(
RpcChannel* inChannel)
80 int contentLength = 0;
81 rdpCredsspAuth* auth = NULL;
82 HttpContext* http = NULL;
86 if (!inChannel || !inChannel->auth || !inChannel->http)
89 auth = inChannel->auth;
90 http = inChannel->http;
92 rc = credssp_auth_authenticate(auth);
96 contentLength = (rc == 0) ? 0 : 0x40000000;
97 buffer = credssp_auth_have_output_token(auth) ? credssp_auth_get_output_buffer(auth) : NULL;
98 s = rpc_auth_http_request(http,
"RPC_IN_DATA", contentLength, buffer,
99 credssp_auth_pkg_name(auth));
104 status = rpc_channel_write(inChannel, Stream_Buffer(s), Stream_Length(s));
105 Stream_Free(s, TRUE);
106 return (status > 0) ? 1 : -1;
109 BOOL rpc_ncacn_http_recv_in_channel_response(
RpcChannel* inChannel, HttpResponse* response)
111 size_t authTokenLength = 0;
112 BYTE* authTokenData = NULL;
114 if (!inChannel || !response || !inChannel->auth)
117 rdpCredsspAuth* auth = inChannel->auth;
118 const char* token64 = http_response_get_auth_token(response, credssp_auth_pkg_name(auth));
121 crypto_base64_decode(token64, strlen(token64), &authTokenData, &authTokenLength);
123 if (authTokenLength > UINT32_MAX)
129 SecBuffer buffer = { .pvBuffer = authTokenData, .cbBuffer = (UINT32)authTokenLength };
131 if (authTokenData && authTokenLength)
133 credssp_auth_take_input_buffer(auth, &buffer);
137 sspi_SecBufferFree(&buffer);
141 BOOL rpc_ncacn_http_auth_init(rdpContext* context,
RpcChannel* channel)
144 rdpCredsspAuth* auth = NULL;
145 rdpSettings* settings = NULL;
146 freerdp* instance = NULL;
147 auth_status rc = AUTH_FAILED;
148 SEC_WINNT_AUTH_IDENTITY identity = { 0 };
150 if (!context || !channel)
154 auth = channel->auth;
155 settings = context->settings;
156 instance = context->instance;
158 if (!tls || !auth || !instance || !settings)
161 rc = utils_authenticate_gateway(instance, GW_AUTH_HTTP);
168 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
170 case AUTH_NO_CREDENTIALS:
171 WLog_INFO(TAG,
"No credentials provided - using NULL identity");
178 if (!credssp_auth_init(auth, AUTH_PKG, tls->Bindings))
181 if (!identity_set_from_settings(&identity, settings, FreeRDP_GatewayUsername,
182 FreeRDP_GatewayDomain, FreeRDP_GatewayPassword))
185 SEC_WINNT_AUTH_IDENTITY* identityArg = (settings->GatewayUsername ? &identity : NULL);
187 credssp_auth_setup_client(auth,
"HTTP", settings->GatewayHostname, identityArg, NULL);
189 sspi_FreeAuthIdentity(&identity);
191 credssp_auth_set_flags(auth, ISC_REQ_CONFIDENTIALITY);
196 void rpc_ncacn_http_auth_uninit(
RpcChannel* channel)
201 credssp_auth_free(channel->auth);
202 channel->auth = NULL;
205 BOOL rpc_ncacn_http_send_out_channel_request(
RpcChannel* outChannel, BOOL replacement)
209 int contentLength = 0;
210 rdpCredsspAuth* auth = NULL;
211 HttpContext* http = NULL;
215 if (!outChannel || !outChannel->auth || !outChannel->http)
218 auth = outChannel->auth;
219 http = outChannel->http;
221 rc = credssp_auth_authenticate(auth);
226 contentLength = (rc == 0) ? 0 : 76;
228 contentLength = (rc == 0) ? 0 : 120;
230 buffer = credssp_auth_have_output_token(auth) ? credssp_auth_get_output_buffer(auth) : NULL;
231 s = rpc_auth_http_request(http,
"RPC_OUT_DATA", contentLength, buffer,
232 credssp_auth_pkg_name(auth));
237 if (rpc_channel_write(outChannel, Stream_Buffer(s), Stream_Length(s)) < 0)
240 Stream_Free(s, TRUE);
244 BOOL rpc_ncacn_http_recv_out_channel_response(
RpcChannel* outChannel, HttpResponse* response)
246 size_t authTokenLength = 0;
247 BYTE* authTokenData = NULL;
249 if (!outChannel || !response || !outChannel->auth)
252 rdpCredsspAuth* auth = outChannel->auth;
253 const char* token64 = http_response_get_auth_token(response, credssp_auth_pkg_name(auth));
256 crypto_base64_decode(token64, strlen(token64), &authTokenData, &authTokenLength);
258 if (authTokenLength > UINT32_MAX)
263 SecBuffer buffer = { .pvBuffer = authTokenData, .cbBuffer = (UINT32)authTokenLength };
265 if (authTokenData && authTokenLength)
267 credssp_auth_take_input_buffer(auth, &buffer);
271 sspi_SecBufferFree(&buffer);
275 BOOL rpc_ncacn_http_is_final_request(
RpcChannel* channel)
277 WINPR_ASSERT(channel);
278 return credssp_auth_is_complete(channel->auth);