20#include <freerdp/config.h> 
   22#include "../settings.h" 
   25#include <winpr/assert.h> 
   26#include <winpr/cast.h> 
   28#include <freerdp/log.h> 
   30#include "rpc_client.h" 
   37#define TAG FREERDP_TAG("core.gateway.rpc") 
   39#define AUTH_PKG NTLM_SSP_NAME 
   54  { 0x3C, 0xDB, 0x6E, 0x7A, 0x27, 0x29 } 
 
   63  { 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60 } 
 
   72  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } 
 
  112static int rpc_bind_setup(rdpRpc* rpc)
 
  114  SEC_WINNT_AUTH_IDENTITY identity = { 0 };
 
  118  rdpContext* context = transport_get_context(rpc->transport);
 
  119  WINPR_ASSERT(context);
 
  121  rdpSettings* settings = context->settings;
 
  122  WINPR_ASSERT(settings);
 
  124  freerdp* instance = context->instance;
 
  125  WINPR_ASSERT(instance);
 
  127  credssp_auth_free(rpc->auth);
 
  128  rpc->auth = credssp_auth_new(context);
 
  132  auth_status rc = utils_authenticate_gateway(instance, GW_AUTH_RPC);
 
  139      freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
 
  141    case AUTH_NO_CREDENTIALS:
 
  142      WLog_INFO(TAG, 
"No credentials provided - using NULL identity");
 
  149  if (!credssp_auth_init(rpc->auth, AUTH_PKG, NULL))
 
  152  if (!identity_set_from_settings(&identity, settings, FreeRDP_GatewayUsername,
 
  153                                  FreeRDP_GatewayDomain, FreeRDP_GatewayPassword))
 
  156  SEC_WINNT_AUTH_IDENTITY* identityArg = (settings->GatewayUsername ? &identity : NULL);
 
  157  if (!credssp_auth_setup_client(rpc->auth, NULL, settings->GatewayHostname, identityArg, NULL))
 
  159    sspi_FreeAuthIdentity(&identity);
 
  162  sspi_FreeAuthIdentity(&identity);
 
  164  credssp_auth_set_flags(rpc->auth, ISC_REQ_USE_DCE_STYLE | ISC_REQ_DELEGATE |
 
  165                                        ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT);
 
  167  if (credssp_auth_authenticate(rpc->auth) < 0)
 
  173int rpc_send_bind_pdu(rdpRpc* rpc, BOOL initial)
 
  187  connection = rpc->VirtualConnection;
 
  189  WINPR_ASSERT(connection);
 
  191  inChannel = connection->DefaultInChannel;
 
  193  if (initial && rpc_bind_setup(rpc) < 0)
 
  196  WLog_DBG(TAG, initial ? 
"Sending Bind PDU" : 
"Sending Alter Context PDU");
 
  198  sbuffer = credssp_auth_get_output_buffer(rpc->auth);
 
  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));
 
  219  if (!bind_pdu.p_context_elem.p_cont_elem)
 
  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));
 
  230  if (!p_cont_elem->transfer_syntaxes)
 
  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));
 
  243  if (!p_cont_elem->transfer_syntaxes)
 
  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;
 
  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);
 
  257  WINPR_ASSERT(offset <= UINT16_MAX);
 
  258  bind_pdu.header.frag_length = (UINT16)offset;
 
  260  buffer = Stream_New(NULL, bind_pdu.header.frag_length);
 
  265  if (!rts_write_pdu_bind(buffer, &bind_pdu))
 
  268  clientCall = rpc_client_call_new(bind_pdu.header.call_id, 0);
 
  273  if (!ArrayList_Append(rpc->client->ClientCallList, clientCall))
 
  275    rpc_client_call_free(clientCall);
 
  279  Stream_SealLength(buffer);
 
  280  status = rpc_in_channel_send_pdu(inChannel, Stream_Buffer(buffer), Stream_Length(buffer));
 
  283  if (bind_pdu.p_context_elem.p_cont_elem)
 
  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);
 
  289  free(bind_pdu.p_context_elem.p_cont_elem);
 
  290  bind_pdu.p_context_elem.p_cont_elem = NULL;
 
  292  Stream_Free(buffer, TRUE);
 
  293  return (status > 0) ? 1 : -1;
 
  322BOOL rpc_recv_bind_ack_pdu(rdpRpc* rpc, 
wStream* s)
 
  325  const BYTE* auth_data = NULL;
 
  332  WINPR_ASSERT(rpc->auth);
 
  335  pos = Stream_GetPosition(s);
 
  336  if (!rts_read_pdu_header(s, &header))
 
  339  WLog_DBG(TAG, header.common.ptype == PTYPE_BIND_ACK ? 
"Receiving BindAck PDU" 
  340                                                      : 
"Receiving AlterContextResp PDU");
 
  342  rpc->max_recv_frag = header.bind_ack.max_xmit_frag;
 
  343  rpc->max_xmit_frag = header.bind_ack.max_recv_frag;
 
  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);
 
  352  buffer.cbBuffer = header.common.auth_length;
 
  353  buffer.pvBuffer = malloc(buffer.cbBuffer);
 
  354  if (!buffer.pvBuffer)
 
  356  memcpy(buffer.pvBuffer, auth_data, buffer.cbBuffer);
 
  357  credssp_auth_take_input_buffer(rpc->auth, &buffer);
 
  359  if (credssp_auth_authenticate(rpc->auth) < 0)
 
  364  rts_free_pdu_header(&header, FALSE);
 
  375int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
 
  388  connection = rpc->VirtualConnection;
 
  389  WINPR_ASSERT(connection);
 
  391  inChannel = connection->DefaultInChannel;
 
  392  WINPR_ASSERT(inChannel);
 
  394  WLog_DBG(TAG, 
"Sending RpcAuth3 PDU");
 
  396  sbuffer = credssp_auth_get_output_buffer(rpc->auth);
 
  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;
 
  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);
 
  421  WINPR_ASSERT(offset <= UINT16_MAX);
 
  422  auth_3_pdu.header.frag_length = (UINT16)offset;
 
  424  buffer = Stream_New(NULL, auth_3_pdu.header.frag_length);
 
  429  if (!rts_write_pdu_auth3(buffer, &auth_3_pdu))
 
  432  clientCall = rpc_client_call_new(auth_3_pdu.header.call_id, 0);
 
  434  if (ArrayList_Append(rpc->client->ClientCallList, clientCall))
 
  436    Stream_SealLength(buffer);
 
  437    status = rpc_in_channel_send_pdu(inChannel, Stream_Buffer(buffer), Stream_Length(buffer));
 
  441  Stream_Free(buffer, TRUE);
 
  442  return (status > 0) ? 1 : -1;
 
  445enum RPC_BIND_STATE rpc_bind_state(rdpRpc* rpc)
 
  451  complete = credssp_auth_is_complete(rpc->auth);
 
  452  have_token = credssp_auth_have_output_token(rpc->auth);
 
  454  return complete ? (have_token ? RPC_BIND_STATE_LAST_LEG : RPC_BIND_STATE_COMPLETE)
 
  455                  : RPC_BIND_STATE_INCOMPLETE;
 
  458BYTE rpc_auth_pkg_to_security_provider(
const char* name)
 
  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;
 
  469    return RPC_C_AUTHN_NONE;