FreeRDP
rpc_bind.c
1 
20 #include <freerdp/config.h>
21 
22 #include "../settings.h"
23 
24 #include <winpr/crt.h>
25 #include <winpr/assert.h>
26 #include <winpr/cast.h>
27 
28 #include <freerdp/log.h>
29 
30 #include "rpc_client.h"
31 
32 #include "rts.h"
33 
34 #include "rpc_bind.h"
35 #include "../utils.h"
36 
37 #define TAG FREERDP_TAG("core.gateway.rpc")
38 
39 #define AUTH_PKG NTLM_SSP_NAME
40 
46 /* Syntax UUIDs */
47 
48 const p_uuid_t TSGU_UUID = {
49  0x44E265DD, /* time_low */
50  0x7DAF, /* time_mid */
51  0x42CD, /* time_hi_and_version */
52  0x85, /* clock_seq_hi_and_reserved */
53  0x60, /* clock_seq_low */
54  { 0x3C, 0xDB, 0x6E, 0x7A, 0x27, 0x29 } /* node[6] */
55 };
56 
57 const p_uuid_t NDR_UUID = {
58  0x8A885D04, /* time_low */
59  0x1CEB, /* time_mid */
60  0x11C9, /* time_hi_and_version */
61  0x9F, /* clock_seq_hi_and_reserved */
62  0xE8, /* clock_seq_low */
63  { 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60 } /* node[6] */
64 };
65 
66 const p_uuid_t BTFN_UUID = {
67  0x6CB71C2C, /* time_low */
68  0x9812, /* time_mid */
69  0x4540, /* time_hi_and_version */
70  0x03, /* clock_seq_hi_and_reserved */
71  0x00, /* clock_seq_low */
72  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } /* node[6] */
73 };
74 
112 static int rpc_bind_setup(rdpRpc* rpc)
113 {
114  SEC_WINNT_AUTH_IDENTITY identity = { 0 };
115 
116  WINPR_ASSERT(rpc);
117 
118  rdpContext* context = transport_get_context(rpc->transport);
119  WINPR_ASSERT(context);
120 
121  rdpSettings* settings = context->settings;
122  WINPR_ASSERT(settings);
123 
124  freerdp* instance = context->instance;
125  WINPR_ASSERT(instance);
126 
127  credssp_auth_free(rpc->auth);
128  rpc->auth = credssp_auth_new(context);
129  if (!rpc->auth)
130  return -1;
131 
132  auth_status rc = utils_authenticate_gateway(instance, GW_AUTH_RPC);
133  switch (rc)
134  {
135  case AUTH_SUCCESS:
136  case AUTH_SKIP:
137  break;
138  case AUTH_CANCELLED:
139  freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
140  return -1;
141  case AUTH_NO_CREDENTIALS:
142  WLog_INFO(TAG, "No credentials provided - using NULL identity");
143  break;
144  case AUTH_FAILED:
145  default:
146  return -1;
147  }
148 
149  if (!credssp_auth_init(rpc->auth, AUTH_PKG, NULL))
150  return -1;
151 
152  if (!identity_set_from_settings(&identity, settings, FreeRDP_GatewayUsername,
153  FreeRDP_GatewayDomain, FreeRDP_GatewayPassword))
154  return -1;
155 
156  SEC_WINNT_AUTH_IDENTITY* identityArg = (settings->GatewayUsername ? &identity : NULL);
157  if (!credssp_auth_setup_client(rpc->auth, NULL, settings->GatewayHostname, identityArg, NULL))
158  {
159  sspi_FreeAuthIdentity(&identity);
160  return -1;
161  }
162  sspi_FreeAuthIdentity(&identity);
163 
164  credssp_auth_set_flags(rpc->auth, ISC_REQ_USE_DCE_STYLE | ISC_REQ_DELEGATE |
165  ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT);
166 
167  if (credssp_auth_authenticate(rpc->auth) < 0)
168  return -1;
169 
170  return 1;
171 }
172 
173 int rpc_send_bind_pdu(rdpRpc* rpc, BOOL initial)
174 {
175  int status = -1;
176  wStream* buffer = NULL;
177  UINT32 offset = 0;
178  RpcClientCall* clientCall = NULL;
179  p_cont_elem_t* p_cont_elem = NULL;
180  rpcconn_bind_hdr_t bind_pdu = { 0 };
181  RpcVirtualConnection* connection = NULL;
182  RpcInChannel* inChannel = NULL;
183  const SecBuffer* sbuffer = NULL;
184 
185  WINPR_ASSERT(rpc);
186 
187  connection = rpc->VirtualConnection;
188 
189  WINPR_ASSERT(connection);
190 
191  inChannel = connection->DefaultInChannel;
192 
193  if (initial && rpc_bind_setup(rpc) < 0)
194  return -1;
195 
196  WLog_DBG(TAG, initial ? "Sending Bind PDU" : "Sending Alter Context PDU");
197 
198  sbuffer = credssp_auth_get_output_buffer(rpc->auth);
199 
200  if (!sbuffer)
201  goto fail;
202 
203  bind_pdu.header = rpc_pdu_header_init(rpc);
204  bind_pdu.header.auth_length = (UINT16)sbuffer->cbBuffer;
205  bind_pdu.auth_verifier.auth_value = sbuffer->pvBuffer;
206  bind_pdu.header.ptype = initial ? PTYPE_BIND : PTYPE_ALTER_CONTEXT;
207  bind_pdu.header.pfc_flags =
208  PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_SUPPORT_HEADER_SIGN | PFC_CONC_MPX;
209  bind_pdu.header.call_id = 2;
210  bind_pdu.max_xmit_frag = rpc->max_xmit_frag;
211  bind_pdu.max_recv_frag = rpc->max_recv_frag;
212  bind_pdu.assoc_group_id = 0;
213  bind_pdu.p_context_elem.n_context_elem = 2;
214  bind_pdu.p_context_elem.reserved = 0;
215  bind_pdu.p_context_elem.reserved2 = 0;
216  bind_pdu.p_context_elem.p_cont_elem =
217  calloc(bind_pdu.p_context_elem.n_context_elem, sizeof(p_cont_elem_t));
218 
219  if (!bind_pdu.p_context_elem.p_cont_elem)
220  goto fail;
221 
222  p_cont_elem = &bind_pdu.p_context_elem.p_cont_elem[0];
223  p_cont_elem->p_cont_id = 0;
224  p_cont_elem->n_transfer_syn = 1;
225  p_cont_elem->reserved = 0;
226  CopyMemory(&(p_cont_elem->abstract_syntax.if_uuid), &TSGU_UUID, sizeof(p_uuid_t));
227  p_cont_elem->abstract_syntax.if_version = TSGU_SYNTAX_IF_VERSION;
228  p_cont_elem->transfer_syntaxes = malloc(sizeof(p_syntax_id_t));
229 
230  if (!p_cont_elem->transfer_syntaxes)
231  goto fail;
232 
233  CopyMemory(&(p_cont_elem->transfer_syntaxes[0].if_uuid), &NDR_UUID, sizeof(p_uuid_t));
234  p_cont_elem->transfer_syntaxes[0].if_version = NDR_SYNTAX_IF_VERSION;
235  p_cont_elem = &bind_pdu.p_context_elem.p_cont_elem[1];
236  p_cont_elem->p_cont_id = 1;
237  p_cont_elem->n_transfer_syn = 1;
238  p_cont_elem->reserved = 0;
239  CopyMemory(&(p_cont_elem->abstract_syntax.if_uuid), &TSGU_UUID, sizeof(p_uuid_t));
240  p_cont_elem->abstract_syntax.if_version = TSGU_SYNTAX_IF_VERSION;
241  p_cont_elem->transfer_syntaxes = malloc(sizeof(p_syntax_id_t));
242 
243  if (!p_cont_elem->transfer_syntaxes)
244  goto fail;
245 
246  CopyMemory(&(p_cont_elem->transfer_syntaxes[0].if_uuid), &BTFN_UUID, sizeof(p_uuid_t));
247  p_cont_elem->transfer_syntaxes[0].if_version = BTFN_SYNTAX_IF_VERSION;
248  offset = 116;
249 
250  bind_pdu.auth_verifier.auth_type =
251  rpc_auth_pkg_to_security_provider(credssp_auth_pkg_name(rpc->auth));
252  bind_pdu.auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
253  bind_pdu.auth_verifier.auth_reserved = 0x00;
254  bind_pdu.auth_verifier.auth_context_id = 0x00000000;
255  offset += (8 + bind_pdu.header.auth_length);
256 
257  WINPR_ASSERT(offset <= UINT16_MAX);
258  bind_pdu.header.frag_length = (UINT16)offset;
259 
260  buffer = Stream_New(NULL, bind_pdu.header.frag_length);
261 
262  if (!buffer)
263  goto fail;
264 
265  if (!rts_write_pdu_bind(buffer, &bind_pdu))
266  goto fail;
267 
268  clientCall = rpc_client_call_new(bind_pdu.header.call_id, 0);
269 
270  if (!clientCall)
271  goto fail;
272 
273  if (!ArrayList_Append(rpc->client->ClientCallList, clientCall))
274  {
275  rpc_client_call_free(clientCall);
276  goto fail;
277  }
278 
279  Stream_SealLength(buffer);
280  status = rpc_in_channel_send_pdu(inChannel, Stream_Buffer(buffer), Stream_Length(buffer));
281 fail:
282 
283  if (bind_pdu.p_context_elem.p_cont_elem)
284  {
285  free(bind_pdu.p_context_elem.p_cont_elem[0].transfer_syntaxes);
286  free(bind_pdu.p_context_elem.p_cont_elem[1].transfer_syntaxes);
287  }
288 
289  free(bind_pdu.p_context_elem.p_cont_elem);
290  bind_pdu.p_context_elem.p_cont_elem = NULL;
291 
292  Stream_Free(buffer, TRUE);
293  return (status > 0) ? 1 : -1;
294 }
295 
322 BOOL rpc_recv_bind_ack_pdu(rdpRpc* rpc, wStream* s)
323 {
324  BOOL rc = FALSE;
325  const BYTE* auth_data = NULL;
326  size_t pos = 0;
327  size_t end = 0;
328  rpcconn_hdr_t header = { 0 };
329  SecBuffer buffer = { 0 };
330 
331  WINPR_ASSERT(rpc);
332  WINPR_ASSERT(rpc->auth);
333  WINPR_ASSERT(s);
334 
335  pos = Stream_GetPosition(s);
336  if (!rts_read_pdu_header(s, &header))
337  goto fail;
338 
339  WLog_DBG(TAG, header.common.ptype == PTYPE_BIND_ACK ? "Receiving BindAck PDU"
340  : "Receiving AlterContextResp PDU");
341 
342  rpc->max_recv_frag = header.bind_ack.max_xmit_frag;
343  rpc->max_xmit_frag = header.bind_ack.max_recv_frag;
344 
345  /* Get the correct offset in the input data and pass that on as input buffer.
346  * rts_read_pdu_header did already do consistency checks */
347  end = Stream_GetPosition(s);
348  Stream_SetPosition(s, pos + header.common.frag_length - header.common.auth_length);
349  auth_data = Stream_ConstPointer(s);
350  Stream_SetPosition(s, end);
351 
352  buffer.cbBuffer = header.common.auth_length;
353  buffer.pvBuffer = malloc(buffer.cbBuffer);
354  if (!buffer.pvBuffer)
355  goto fail;
356  memcpy(buffer.pvBuffer, auth_data, buffer.cbBuffer);
357  credssp_auth_take_input_buffer(rpc->auth, &buffer);
358 
359  if (credssp_auth_authenticate(rpc->auth) < 0)
360  goto fail;
361 
362  rc = TRUE;
363 fail:
364  rts_free_pdu_header(&header, FALSE);
365  return rc;
366 }
367 
375 int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
376 {
377  int status = -1;
378  wStream* buffer = NULL;
379  size_t offset = 0;
380  const SecBuffer* sbuffer = NULL;
381  RpcClientCall* clientCall = NULL;
382  rpcconn_rpc_auth_3_hdr_t auth_3_pdu = { 0 };
383  RpcVirtualConnection* connection = NULL;
384  RpcInChannel* inChannel = NULL;
385 
386  WINPR_ASSERT(rpc);
387 
388  connection = rpc->VirtualConnection;
389  WINPR_ASSERT(connection);
390 
391  inChannel = connection->DefaultInChannel;
392  WINPR_ASSERT(inChannel);
393 
394  WLog_DBG(TAG, "Sending RpcAuth3 PDU");
395 
396  sbuffer = credssp_auth_get_output_buffer(rpc->auth);
397 
398  if (!sbuffer)
399  return -1;
400 
401  auth_3_pdu.header = rpc_pdu_header_init(rpc);
402  auth_3_pdu.header.auth_length = (UINT16)sbuffer->cbBuffer;
403  auth_3_pdu.auth_verifier.auth_value = sbuffer->pvBuffer;
404  auth_3_pdu.header.ptype = PTYPE_RPC_AUTH_3;
405  auth_3_pdu.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX;
406  auth_3_pdu.header.call_id = 2;
407  auth_3_pdu.max_xmit_frag = rpc->max_xmit_frag;
408  auth_3_pdu.max_recv_frag = rpc->max_recv_frag;
409  offset = 20;
410 
411  const size_t align = rpc_offset_align(&offset, 4);
412  WINPR_ASSERT(align <= UINT8_MAX);
413  auth_3_pdu.auth_verifier.auth_pad_length = (BYTE)align;
414  auth_3_pdu.auth_verifier.auth_type =
415  rpc_auth_pkg_to_security_provider(credssp_auth_pkg_name(rpc->auth));
416  auth_3_pdu.auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
417  auth_3_pdu.auth_verifier.auth_reserved = 0x00;
418  auth_3_pdu.auth_verifier.auth_context_id = 0x00000000;
419  offset += (8 + auth_3_pdu.header.auth_length);
420 
421  WINPR_ASSERT(offset <= UINT16_MAX);
422  auth_3_pdu.header.frag_length = (UINT16)offset;
423 
424  buffer = Stream_New(NULL, auth_3_pdu.header.frag_length);
425 
426  if (!buffer)
427  return -1;
428 
429  if (!rts_write_pdu_auth3(buffer, &auth_3_pdu))
430  goto fail;
431 
432  clientCall = rpc_client_call_new(auth_3_pdu.header.call_id, 0);
433 
434  if (ArrayList_Append(rpc->client->ClientCallList, clientCall))
435  {
436  Stream_SealLength(buffer);
437  status = rpc_in_channel_send_pdu(inChannel, Stream_Buffer(buffer), Stream_Length(buffer));
438  }
439 
440 fail:
441  Stream_Free(buffer, TRUE);
442  return (status > 0) ? 1 : -1;
443 }
444 
445 enum RPC_BIND_STATE rpc_bind_state(rdpRpc* rpc)
446 {
447  BOOL complete = 0;
448  BOOL have_token = 0;
449  WINPR_ASSERT(rpc);
450 
451  complete = credssp_auth_is_complete(rpc->auth);
452  have_token = credssp_auth_have_output_token(rpc->auth);
453 
454  return complete ? (have_token ? RPC_BIND_STATE_LAST_LEG : RPC_BIND_STATE_COMPLETE)
455  : RPC_BIND_STATE_INCOMPLETE;
456 }
457 
458 BYTE rpc_auth_pkg_to_security_provider(const char* name)
459 {
460  if (strcmp(name, CREDSSP_AUTH_PKG_SPNEGO) == 0)
461  return RPC_C_AUTHN_GSS_NEGOTIATE;
462  else if (strcmp(name, CREDSSP_AUTH_PKG_NTLM) == 0)
463  return RPC_C_AUTHN_WINNT;
464  else if (strcmp(name, CREDSSP_AUTH_PKG_KERBEROS) == 0)
465  return RPC_C_AUTHN_GSS_KERBEROS;
466  else if (strcmp(name, CREDSSP_AUTH_PKG_SCHANNEL) == 0)
467  return RPC_C_AUTHN_GSS_SCHANNEL;
468  else
469  return RPC_C_AUTHN_NONE;
470 }