20 #include <freerdp/config.h>
22 #include "../settings.h"
24 #include <winpr/crt.h>
25 #include <winpr/assert.h>
27 #include <freerdp/log.h>
29 #include "rpc_client.h"
36 #define TAG FREERDP_TAG("core.gateway.rpc")
38 #define AUTH_PKG NTLM_SSP_NAME
53 { 0x3C, 0xDB, 0x6E, 0x7A, 0x27, 0x29 }
62 { 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60 }
71 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
111 static int rpc_bind_setup(rdpRpc* rpc)
114 rdpContext* context = NULL;
115 rdpSettings* settings = NULL;
116 freerdp* instance = NULL;
117 SEC_WINNT_AUTH_IDENTITY identity = { 0 };
121 context = transport_get_context(rpc->transport);
122 WINPR_ASSERT(context);
124 settings = context->settings;
125 WINPR_ASSERT(settings);
127 instance = context->instance;
128 WINPR_ASSERT(instance);
130 credssp_auth_free(rpc->auth);
131 rpc->auth = credssp_auth_new(context);
135 rc = utils_authenticate_gateway(instance, GW_AUTH_RPC);
142 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
144 case AUTH_NO_CREDENTIALS:
145 WLog_INFO(TAG,
"No credentials provided - using NULL identity");
152 if (!credssp_auth_init(rpc->auth, AUTH_PKG, NULL))
155 if (!identity_set_from_settings(&identity, settings, FreeRDP_GatewayUsername,
156 FreeRDP_GatewayDomain, FreeRDP_GatewayPassword))
159 SEC_WINNT_AUTH_IDENTITY* identityArg = (settings->GatewayUsername ? &identity : NULL);
160 if (!credssp_auth_setup_client(rpc->auth, NULL, settings->GatewayHostname, identityArg, NULL))
162 sspi_FreeAuthIdentity(&identity);
165 sspi_FreeAuthIdentity(&identity);
167 credssp_auth_set_flags(rpc->auth, ISC_REQ_USE_DCE_STYLE | ISC_REQ_DELEGATE |
168 ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT);
170 if (credssp_auth_authenticate(rpc->auth) < 0)
176 int rpc_send_bind_pdu(rdpRpc* rpc, BOOL initial)
190 connection = rpc->VirtualConnection;
192 WINPR_ASSERT(connection);
194 inChannel = connection->DefaultInChannel;
196 if (initial && rpc_bind_setup(rpc) < 0)
199 WLog_DBG(TAG, initial ?
"Sending Bind PDU" :
"Sending Alter Context PDU");
201 sbuffer = credssp_auth_get_output_buffer(rpc->auth);
206 bind_pdu.header = rpc_pdu_header_init(rpc);
207 bind_pdu.header.auth_length = (UINT16)sbuffer->cbBuffer;
208 bind_pdu.auth_verifier.auth_value = sbuffer->pvBuffer;
209 bind_pdu.header.ptype = initial ? PTYPE_BIND : PTYPE_ALTER_CONTEXT;
210 bind_pdu.header.pfc_flags =
211 PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_SUPPORT_HEADER_SIGN | PFC_CONC_MPX;
212 bind_pdu.header.call_id = 2;
213 bind_pdu.max_xmit_frag = rpc->max_xmit_frag;
214 bind_pdu.max_recv_frag = rpc->max_recv_frag;
215 bind_pdu.assoc_group_id = 0;
216 bind_pdu.p_context_elem.n_context_elem = 2;
217 bind_pdu.p_context_elem.reserved = 0;
218 bind_pdu.p_context_elem.reserved2 = 0;
219 bind_pdu.p_context_elem.p_cont_elem =
220 calloc(bind_pdu.p_context_elem.n_context_elem,
sizeof(
p_cont_elem_t));
222 if (!bind_pdu.p_context_elem.p_cont_elem)
225 p_cont_elem = &bind_pdu.p_context_elem.p_cont_elem[0];
226 p_cont_elem->p_cont_id = 0;
227 p_cont_elem->n_transfer_syn = 1;
228 p_cont_elem->reserved = 0;
229 CopyMemory(&(p_cont_elem->abstract_syntax.if_uuid), &TSGU_UUID,
sizeof(
p_uuid_t));
230 p_cont_elem->abstract_syntax.if_version = TSGU_SYNTAX_IF_VERSION;
231 p_cont_elem->transfer_syntaxes = malloc(
sizeof(
p_syntax_id_t));
233 if (!p_cont_elem->transfer_syntaxes)
236 CopyMemory(&(p_cont_elem->transfer_syntaxes[0].if_uuid), &NDR_UUID,
sizeof(
p_uuid_t));
237 p_cont_elem->transfer_syntaxes[0].if_version = NDR_SYNTAX_IF_VERSION;
238 p_cont_elem = &bind_pdu.p_context_elem.p_cont_elem[1];
239 p_cont_elem->p_cont_id = 1;
240 p_cont_elem->n_transfer_syn = 1;
241 p_cont_elem->reserved = 0;
242 CopyMemory(&(p_cont_elem->abstract_syntax.if_uuid), &TSGU_UUID,
sizeof(
p_uuid_t));
243 p_cont_elem->abstract_syntax.if_version = TSGU_SYNTAX_IF_VERSION;
244 p_cont_elem->transfer_syntaxes = malloc(
sizeof(
p_syntax_id_t));
246 if (!p_cont_elem->transfer_syntaxes)
249 CopyMemory(&(p_cont_elem->transfer_syntaxes[0].if_uuid), &BTFN_UUID,
sizeof(
p_uuid_t));
250 p_cont_elem->transfer_syntaxes[0].if_version = BTFN_SYNTAX_IF_VERSION;
253 bind_pdu.auth_verifier.auth_type =
254 rpc_auth_pkg_to_security_provider(credssp_auth_pkg_name(rpc->auth));
255 bind_pdu.auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
256 bind_pdu.auth_verifier.auth_reserved = 0x00;
257 bind_pdu.auth_verifier.auth_context_id = 0x00000000;
258 offset += (8 + bind_pdu.header.auth_length);
259 bind_pdu.header.frag_length = offset;
261 buffer = Stream_New(NULL, bind_pdu.header.frag_length);
266 if (!rts_write_pdu_bind(buffer, &bind_pdu))
269 clientCall = rpc_client_call_new(bind_pdu.header.call_id, 0);
274 if (!ArrayList_Append(rpc->client->ClientCallList, clientCall))
276 rpc_client_call_free(clientCall);
280 Stream_SealLength(buffer);
281 status = rpc_in_channel_send_pdu(inChannel, Stream_Buffer(buffer), Stream_Length(buffer));
284 if (bind_pdu.p_context_elem.p_cont_elem)
286 free(bind_pdu.p_context_elem.p_cont_elem[0].transfer_syntaxes);
287 free(bind_pdu.p_context_elem.p_cont_elem[1].transfer_syntaxes);
290 free(bind_pdu.p_context_elem.p_cont_elem);
291 bind_pdu.p_context_elem.p_cont_elem = NULL;
293 Stream_Free(buffer, TRUE);
294 return (status > 0) ? 1 : -1;
323 BOOL rpc_recv_bind_ack_pdu(rdpRpc* rpc,
wStream* s)
326 const BYTE* auth_data = NULL;
333 WINPR_ASSERT(rpc->auth);
336 pos = Stream_GetPosition(s);
337 if (!rts_read_pdu_header(s, &header))
340 WLog_DBG(TAG, header.common.ptype == PTYPE_BIND_ACK ?
"Receiving BindAck PDU"
341 :
"Receiving AlterContextResp PDU");
343 rpc->max_recv_frag = header.bind_ack.max_xmit_frag;
344 rpc->max_xmit_frag = header.bind_ack.max_recv_frag;
348 end = Stream_GetPosition(s);
349 Stream_SetPosition(s, pos + header.common.frag_length - header.common.auth_length);
350 auth_data = Stream_ConstPointer(s);
351 Stream_SetPosition(s, end);
353 buffer.cbBuffer = header.common.auth_length;
354 buffer.pvBuffer = malloc(buffer.cbBuffer);
355 if (!buffer.pvBuffer)
357 memcpy(buffer.pvBuffer, auth_data, buffer.cbBuffer);
358 credssp_auth_take_input_buffer(rpc->auth, &buffer);
360 if (credssp_auth_authenticate(rpc->auth) < 0)
365 rts_free_pdu_header(&header, FALSE);
376 int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
389 connection = rpc->VirtualConnection;
390 WINPR_ASSERT(connection);
392 inChannel = connection->DefaultInChannel;
393 WINPR_ASSERT(inChannel);
395 WLog_DBG(TAG,
"Sending RpcAuth3 PDU");
397 sbuffer = credssp_auth_get_output_buffer(rpc->auth);
402 auth_3_pdu.header = rpc_pdu_header_init(rpc);
403 auth_3_pdu.header.auth_length = (UINT16)sbuffer->cbBuffer;
404 auth_3_pdu.auth_verifier.auth_value = sbuffer->pvBuffer;
405 auth_3_pdu.header.ptype = PTYPE_RPC_AUTH_3;
406 auth_3_pdu.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX;
407 auth_3_pdu.header.call_id = 2;
408 auth_3_pdu.max_xmit_frag = rpc->max_xmit_frag;
409 auth_3_pdu.max_recv_frag = rpc->max_recv_frag;
411 auth_3_pdu.auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4);
412 auth_3_pdu.auth_verifier.auth_type =
413 rpc_auth_pkg_to_security_provider(credssp_auth_pkg_name(rpc->auth));
414 auth_3_pdu.auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
415 auth_3_pdu.auth_verifier.auth_reserved = 0x00;
416 auth_3_pdu.auth_verifier.auth_context_id = 0x00000000;
417 offset += (8 + auth_3_pdu.header.auth_length);
418 auth_3_pdu.header.frag_length = offset;
420 buffer = Stream_New(NULL, auth_3_pdu.header.frag_length);
425 if (!rts_write_pdu_auth3(buffer, &auth_3_pdu))
428 clientCall = rpc_client_call_new(auth_3_pdu.header.call_id, 0);
430 if (ArrayList_Append(rpc->client->ClientCallList, clientCall))
432 Stream_SealLength(buffer);
433 status = rpc_in_channel_send_pdu(inChannel, Stream_Buffer(buffer), Stream_Length(buffer));
437 Stream_Free(buffer, TRUE);
438 return (status > 0) ? 1 : -1;
441 enum RPC_BIND_STATE rpc_bind_state(rdpRpc* rpc)
447 complete = credssp_auth_is_complete(rpc->auth);
448 have_token = credssp_auth_have_output_token(rpc->auth);
450 return complete ? (have_token ? RPC_BIND_STATE_LAST_LEG : RPC_BIND_STATE_COMPLETE)
451 : RPC_BIND_STATE_INCOMPLETE;
454 BYTE rpc_auth_pkg_to_security_provider(
const char* name)
456 if (strcmp(name, CREDSSP_AUTH_PKG_SPNEGO) == 0)
457 return RPC_C_AUTHN_GSS_NEGOTIATE;
458 else if (strcmp(name, CREDSSP_AUTH_PKG_NTLM) == 0)
459 return RPC_C_AUTHN_WINNT;
460 else if (strcmp(name, CREDSSP_AUTH_PKG_KERBEROS) == 0)
461 return RPC_C_AUTHN_GSS_KERBEROS;
462 else if (strcmp(name, CREDSSP_AUTH_PKG_SCHANNEL) == 0)
463 return RPC_C_AUTHN_GSS_SCHANNEL;
465 return RPC_C_AUTHN_NONE;