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 
27 #include <freerdp/log.h>
28 
29 #include "rpc_client.h"
30 
31 #include "rts.h"
32 
33 #include "rpc_bind.h"
34 #include "../utils.h"
35 
36 #define TAG FREERDP_TAG("core.gateway.rpc")
37 
38 #define AUTH_PKG NTLM_SSP_NAME
39 
45 /* Syntax UUIDs */
46 
47 const p_uuid_t TSGU_UUID = {
48  0x44E265DD, /* time_low */
49  0x7DAF, /* time_mid */
50  0x42CD, /* time_hi_and_version */
51  0x85, /* clock_seq_hi_and_reserved */
52  0x60, /* clock_seq_low */
53  { 0x3C, 0xDB, 0x6E, 0x7A, 0x27, 0x29 } /* node[6] */
54 };
55 
56 const p_uuid_t NDR_UUID = {
57  0x8A885D04, /* time_low */
58  0x1CEB, /* time_mid */
59  0x11C9, /* time_hi_and_version */
60  0x9F, /* clock_seq_hi_and_reserved */
61  0xE8, /* clock_seq_low */
62  { 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60 } /* node[6] */
63 };
64 
65 const p_uuid_t BTFN_UUID = {
66  0x6CB71C2C, /* time_low */
67  0x9812, /* time_mid */
68  0x4540, /* time_hi_and_version */
69  0x03, /* clock_seq_hi_and_reserved */
70  0x00, /* clock_seq_low */
71  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } /* node[6] */
72 };
73 
111 static int rpc_bind_setup(rdpRpc* rpc)
112 {
113  int rc = -1;
114  rdpContext* context = NULL;
115  rdpSettings* settings = NULL;
116  freerdp* instance = NULL;
117  SEC_WINNT_AUTH_IDENTITY identity = { 0 };
118 
119  WINPR_ASSERT(rpc);
120 
121  context = transport_get_context(rpc->transport);
122  WINPR_ASSERT(context);
123 
124  settings = context->settings;
125  WINPR_ASSERT(settings);
126 
127  instance = context->instance;
128  WINPR_ASSERT(instance);
129 
130  credssp_auth_free(rpc->auth);
131  rpc->auth = credssp_auth_new(context);
132  if (!rpc->auth)
133  return -1;
134 
135  rc = utils_authenticate_gateway(instance, GW_AUTH_RPC);
136  switch (rc)
137  {
138  case AUTH_SUCCESS:
139  case AUTH_SKIP:
140  break;
141  case AUTH_CANCELLED:
142  freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
143  return -1;
144  case AUTH_NO_CREDENTIALS:
145  WLog_INFO(TAG, "No credentials provided - using NULL identity");
146  break;
147  case AUTH_FAILED:
148  default:
149  return -1;
150  }
151 
152  if (!credssp_auth_init(rpc->auth, AUTH_PKG, NULL))
153  return -1;
154 
155  if (!identity_set_from_settings(&identity, settings, FreeRDP_GatewayUsername,
156  FreeRDP_GatewayDomain, FreeRDP_GatewayPassword))
157  return -1;
158 
159  SEC_WINNT_AUTH_IDENTITY* identityArg = (settings->GatewayUsername ? &identity : NULL);
160  if (!credssp_auth_setup_client(rpc->auth, NULL, settings->GatewayHostname, identityArg, NULL))
161  {
162  sspi_FreeAuthIdentity(&identity);
163  return -1;
164  }
165  sspi_FreeAuthIdentity(&identity);
166 
167  credssp_auth_set_flags(rpc->auth, ISC_REQ_USE_DCE_STYLE | ISC_REQ_DELEGATE |
168  ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT);
169 
170  if (credssp_auth_authenticate(rpc->auth) < 0)
171  return -1;
172 
173  return 1;
174 }
175 
176 int rpc_send_bind_pdu(rdpRpc* rpc, BOOL initial)
177 {
178  int status = -1;
179  wStream* buffer = NULL;
180  UINT32 offset = 0;
181  RpcClientCall* clientCall = NULL;
182  p_cont_elem_t* p_cont_elem = NULL;
183  rpcconn_bind_hdr_t bind_pdu = { 0 };
184  RpcVirtualConnection* connection = NULL;
185  RpcInChannel* inChannel = NULL;
186  const SecBuffer* sbuffer = NULL;
187 
188  WINPR_ASSERT(rpc);
189 
190  connection = rpc->VirtualConnection;
191 
192  WINPR_ASSERT(connection);
193 
194  inChannel = connection->DefaultInChannel;
195 
196  if (initial && rpc_bind_setup(rpc) < 0)
197  return -1;
198 
199  WLog_DBG(TAG, initial ? "Sending Bind PDU" : "Sending Alter Context PDU");
200 
201  sbuffer = credssp_auth_get_output_buffer(rpc->auth);
202 
203  if (!sbuffer)
204  goto fail;
205 
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));
221 
222  if (!bind_pdu.p_context_elem.p_cont_elem)
223  goto fail;
224 
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));
232 
233  if (!p_cont_elem->transfer_syntaxes)
234  goto fail;
235 
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));
245 
246  if (!p_cont_elem->transfer_syntaxes)
247  goto fail;
248 
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;
251  offset = 116;
252 
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;
260 
261  buffer = Stream_New(NULL, bind_pdu.header.frag_length);
262 
263  if (!buffer)
264  goto fail;
265 
266  if (!rts_write_pdu_bind(buffer, &bind_pdu))
267  goto fail;
268 
269  clientCall = rpc_client_call_new(bind_pdu.header.call_id, 0);
270 
271  if (!clientCall)
272  goto fail;
273 
274  if (!ArrayList_Append(rpc->client->ClientCallList, clientCall))
275  {
276  rpc_client_call_free(clientCall);
277  goto fail;
278  }
279 
280  Stream_SealLength(buffer);
281  status = rpc_in_channel_send_pdu(inChannel, Stream_Buffer(buffer), Stream_Length(buffer));
282 fail:
283 
284  if (bind_pdu.p_context_elem.p_cont_elem)
285  {
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);
288  }
289 
290  free(bind_pdu.p_context_elem.p_cont_elem);
291  bind_pdu.p_context_elem.p_cont_elem = NULL;
292 
293  Stream_Free(buffer, TRUE);
294  return (status > 0) ? 1 : -1;
295 }
296 
323 BOOL rpc_recv_bind_ack_pdu(rdpRpc* rpc, wStream* s)
324 {
325  BOOL rc = FALSE;
326  const BYTE* auth_data = NULL;
327  size_t pos = 0;
328  size_t end = 0;
329  rpcconn_hdr_t header = { 0 };
330  SecBuffer buffer = { 0 };
331 
332  WINPR_ASSERT(rpc);
333  WINPR_ASSERT(rpc->auth);
334  WINPR_ASSERT(s);
335 
336  pos = Stream_GetPosition(s);
337  if (!rts_read_pdu_header(s, &header))
338  goto fail;
339 
340  WLog_DBG(TAG, header.common.ptype == PTYPE_BIND_ACK ? "Receiving BindAck PDU"
341  : "Receiving AlterContextResp PDU");
342 
343  rpc->max_recv_frag = header.bind_ack.max_xmit_frag;
344  rpc->max_xmit_frag = header.bind_ack.max_recv_frag;
345 
346  /* Get the correct offset in the input data and pass that on as input buffer.
347  * rts_read_pdu_header did already do consistency checks */
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);
352 
353  buffer.cbBuffer = header.common.auth_length;
354  buffer.pvBuffer = malloc(buffer.cbBuffer);
355  if (!buffer.pvBuffer)
356  goto fail;
357  memcpy(buffer.pvBuffer, auth_data, buffer.cbBuffer);
358  credssp_auth_take_input_buffer(rpc->auth, &buffer);
359 
360  if (credssp_auth_authenticate(rpc->auth) < 0)
361  goto fail;
362 
363  rc = TRUE;
364 fail:
365  rts_free_pdu_header(&header, FALSE);
366  return rc;
367 }
368 
376 int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
377 {
378  int status = -1;
379  wStream* buffer = NULL;
380  size_t offset = 0;
381  const SecBuffer* sbuffer = NULL;
382  RpcClientCall* clientCall = NULL;
383  rpcconn_rpc_auth_3_hdr_t auth_3_pdu = { 0 };
384  RpcVirtualConnection* connection = NULL;
385  RpcInChannel* inChannel = NULL;
386 
387  WINPR_ASSERT(rpc);
388 
389  connection = rpc->VirtualConnection;
390  WINPR_ASSERT(connection);
391 
392  inChannel = connection->DefaultInChannel;
393  WINPR_ASSERT(inChannel);
394 
395  WLog_DBG(TAG, "Sending RpcAuth3 PDU");
396 
397  sbuffer = credssp_auth_get_output_buffer(rpc->auth);
398 
399  if (!sbuffer)
400  return -1;
401 
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;
410  offset = 20;
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;
419 
420  buffer = Stream_New(NULL, auth_3_pdu.header.frag_length);
421 
422  if (!buffer)
423  return -1;
424 
425  if (!rts_write_pdu_auth3(buffer, &auth_3_pdu))
426  goto fail;
427 
428  clientCall = rpc_client_call_new(auth_3_pdu.header.call_id, 0);
429 
430  if (ArrayList_Append(rpc->client->ClientCallList, clientCall))
431  {
432  Stream_SealLength(buffer);
433  status = rpc_in_channel_send_pdu(inChannel, Stream_Buffer(buffer), Stream_Length(buffer));
434  }
435 
436 fail:
437  Stream_Free(buffer, TRUE);
438  return (status > 0) ? 1 : -1;
439 }
440 
441 enum RPC_BIND_STATE rpc_bind_state(rdpRpc* rpc)
442 {
443  BOOL complete = 0;
444  BOOL have_token = 0;
445  WINPR_ASSERT(rpc);
446 
447  complete = credssp_auth_is_complete(rpc->auth);
448  have_token = credssp_auth_have_output_token(rpc->auth);
449 
450  return complete ? (have_token ? RPC_BIND_STATE_LAST_LEG : RPC_BIND_STATE_COMPLETE)
451  : RPC_BIND_STATE_INCOMPLETE;
452 }
453 
454 BYTE rpc_auth_pkg_to_security_provider(const char* name)
455 {
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;
464  else
465  return RPC_C_AUTHN_NONE;
466 }