void credssp_ntlmssp_init(rdpCredssp* credssp) { NTLMSSP *ntlmssp = credssp->ntlmssp; rdpSettings *settings = credssp->transport->settings; ntlmssp_set_password(ntlmssp, settings->password); ntlmssp_set_username(ntlmssp, settings->username); if (settings->domain != NULL) { if (strlen(settings->domain) > 0) { ntlmssp_set_domain(ntlmssp, settings->domain); } } else { ntlmssp_set_domain(ntlmssp, NULL); } ntlmssp_generate_client_challenge(ntlmssp); ntlmssp_generate_random_session_key(ntlmssp); ntlmssp_generate_exported_session_key(ntlmssp); ntlmssp->ntlm_v2 = 0; }
void test_ntlmssp_compute_lm_v2_response(void) { int i; char *p; NTLMSSP* ntlmssp; int lm_v2_response_good; char password[] = "password"; char username[] = "username"; char domain[] = "win7"; char server_challenge[8] = "\x26\x6e\xcd\x75\xaa\x41\xe7\x6f"; char lm_client_challenge[8] = "\x47\xa2\xe5\xcf\x27\xf7\x3c\x43"; char expected_lm_v2_response[24] = "\xa0\x98\x01\x10\x19\xbb\x5d\x00\xf6\xbe\x00\x33\x90\x20\x34\xb3\x47\xa2\xe5\xcf\x27\xf7\x3c\x43"; ntlmssp = ntlmssp_client_new(); ntlmssp_set_password(ntlmssp, password); ntlmssp_set_username(ntlmssp, username); ntlmssp_set_domain(ntlmssp, domain); memcpy(ntlmssp->server_challenge, server_challenge, 8); memcpy(ntlmssp->client_challenge, lm_client_challenge, 8); ntlmssp_compute_lm_v2_response(ntlmssp); p = (char*) ntlmssp->lm_challenge_response.data; lm_v2_response_good = 1; for (i = 0; i < 24; i++) { if (p[i] != expected_lm_v2_response[i]) lm_v2_response_good = 0; } CU_ASSERT(lm_v2_response_good == 1); }
void test_ntlmssp_compute_ntlm_v2_hash(void) { int i; NTLMSSP* ntlmssp; int ntlm_v2_hash_good; char ntlm_v2_hash[16]; char username[] = "User"; char password[] = "Password"; char domain[] = "Domain"; char expected_ntlm_v2_hash[16] = "\x0c\x86\x8a\x40\x3b\xfd\x7a\x93\xa3\x00\x1e\xf2\x2e\xf0\x2e\x3f"; ntlmssp = ntlmssp_client_new(); ntlmssp_set_password(ntlmssp, password); ntlmssp_set_username(ntlmssp, username); ntlmssp_set_domain(ntlmssp, domain); ntlmssp_compute_ntlm_v2_hash(ntlmssp, ntlm_v2_hash); ntlm_v2_hash_good = 1; for (i = 0; i < 16; i++) { if (ntlm_v2_hash[i] != expected_ntlm_v2_hash[i]) ntlm_v2_hash_good = 0; } CU_ASSERT(ntlm_v2_hash_good == 1); }
static NTSTATUS gensec_ntlmssp3_client_start(struct gensec_security *gensec_security) { NTSTATUS nt_status; struct gensec_ntlmssp_context *gensec_ntlmssp; const char *user, *domain; const char *password; nt_status = gensec_ntlmssp_start(gensec_security); NT_STATUS_NOT_OK_RETURN(nt_status); gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data, struct gensec_ntlmssp_context); nt_status = ntlmssp_client_start(gensec_ntlmssp, lp_netbios_name(), lp_workgroup(), lp_client_ntlmv2_auth(), &gensec_ntlmssp->ntlmssp_state); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } cli_credentials_get_ntlm_username_domain(gensec_security->credentials, gensec_ntlmssp, &user, &domain); if (!user || !domain) { return NT_STATUS_NO_MEMORY; } nt_status = ntlmssp_set_username(gensec_ntlmssp->ntlmssp_state, user); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } nt_status = ntlmssp_set_domain(gensec_ntlmssp->ntlmssp_state, domain); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } password = cli_credentials_get_password(gensec_security->credentials); if (!password) { return NT_STATUS_NO_MEMORY; } nt_status = ntlmssp_set_password(gensec_ntlmssp->ntlmssp_state, password); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) { gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; } if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SIGN) { gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; } if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SEAL) { gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; } return NT_STATUS_OK; }
static NTSTATUS ntlm_auth_start_ntlmssp_client(NTLMSSP_STATE **client_ntlmssp_state) { NTSTATUS status; if ( (opt_username == NULL) || (opt_domain == NULL) ) { status = NT_STATUS_UNSUCCESSFUL; DEBUG(1, ("Need username and domain for NTLMSSP\n")); return NT_STATUS_INVALID_PARAMETER; } status = ntlmssp_client_start(client_ntlmssp_state); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not start NTLMSSP client: %s\n", nt_errstr(status))); ntlmssp_end(client_ntlmssp_state); return status; } status = ntlmssp_set_username(*client_ntlmssp_state, opt_username); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not set username: %s\n", nt_errstr(status))); ntlmssp_end(client_ntlmssp_state); return status; } status = ntlmssp_set_domain(*client_ntlmssp_state, opt_domain); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not set domain: %s\n", nt_errstr(status))); ntlmssp_end(client_ntlmssp_state); return status; } status = ntlmssp_set_password(*client_ntlmssp_state, opt_password); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not set password: %s\n", nt_errstr(status))); ntlmssp_end(client_ntlmssp_state); return status; } return NT_STATUS_OK; }
int credssp_ntlmssp_client_init(rdpCredssp* credssp) { freerdp* instance; NTLMSSP* ntlmssp = credssp->ntlmssp; rdpSettings* settings = credssp->transport->settings; instance = (freerdp*) settings->instance; if ((settings->password == NULL) || (settings->username == NULL)) { if (instance->Authenticate) { boolean proceed = instance->Authenticate(instance, &settings->username, &settings->password, &settings->domain); if (!proceed) return 0; } } if (settings->ntlm_version == 2) ntlmssp->ntlm_v2 = 1; ntlmssp_set_password(ntlmssp, settings->password); ntlmssp_set_username(ntlmssp, settings->username); if (ntlmssp->ntlm_v2) { ntlmssp_set_workstation(ntlmssp, "WORKSTATION"); } if (settings->domain != NULL) { if (strlen(settings->domain) > 0) ntlmssp_set_domain(ntlmssp, settings->domain); } else { ntlmssp_set_domain(ntlmssp, NULL); } ntlmssp_generate_client_challenge(ntlmssp); ntlmssp_generate_random_session_key(ntlmssp); ntlmssp_generate_exported_session_key(ntlmssp); return 1; }
void test_ntlmssp_compute_ntlm_hash(void) { int i; NTLMSSP *ntlmssp; int ntlm_hash_good; char ntlm_hash[16]; char password[] = "Password"; char expected_ntlm_hash[16] = "\xa4\xf4\x9c\x40\x65\x10\xbd\xca\xb6\x82\x4e\xe7\xc3\x0f\xd8\x52"; ntlmssp = ntlmssp_new(); ntlmssp_set_password(ntlmssp, password); ntlmssp_compute_ntlm_hash(&ntlmssp->password, ntlm_hash); ntlm_hash_good = 1; for (i = 0; i < 16; i++) { if (ntlm_hash[i] != expected_ntlm_hash[i]) ntlm_hash_good = 0; } CU_ASSERT(ntlm_hash_good == 1); }
/* perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can we fit on one socket??) */ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads) { DATA_BLOB msg1 = data_blob_null; DATA_BLOB blob = data_blob_null; DATA_BLOB blob_in = data_blob_null; DATA_BLOB blob_out = data_blob_null; struct berval cred, *scred = NULL; int rc; NTSTATUS nt_status; ADS_STATUS status; int turn = 1; uint32 features = 0; struct ntlmssp_state *ntlmssp_state; if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) { return ADS_ERROR_NT(nt_status); } ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN; if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, ads->auth.user_name))) { return ADS_ERROR_NT(nt_status); } if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, ads->auth.realm))) { return ADS_ERROR_NT(nt_status); } if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, ads->auth.password))) { return ADS_ERROR_NT(nt_status); } switch (ads->ldap.wrap_type) { case ADS_SASLWRAP_TYPE_SEAL: features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL; break; case ADS_SASLWRAP_TYPE_SIGN: if (ads->auth.flags & ADS_AUTH_SASL_FORCE) { features = NTLMSSP_FEATURE_SIGN; } else { /* * windows servers are broken with sign only, * so we need to use seal here too */ features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL; ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL; } break; case ADS_SASLWRAP_TYPE_PLAIN: break; } ntlmssp_want_feature(ntlmssp_state, features); blob_in = data_blob_null; do { nt_status = ntlmssp_update(ntlmssp_state, blob_in, &blob_out); data_blob_free(&blob_in); if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) && blob_out.length) { if (turn == 1) { /* and wrap it in a SPNEGO wrapper */ msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out); } else { /* wrap it in SPNEGO */ msg1 = spnego_gen_auth(blob_out); } data_blob_free(&blob_out); cred.bv_val = (char *)msg1.data; cred.bv_len = msg1.length; scred = NULL; rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred); data_blob_free(&msg1); if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) { if (scred) { ber_bvfree(scred); } ntlmssp_end(&ntlmssp_state); return ADS_ERROR(rc); } if (scred) { blob = data_blob(scred->bv_val, scred->bv_len); ber_bvfree(scred); } else { blob = data_blob_null; } } else { ntlmssp_end(&ntlmssp_state); data_blob_free(&blob_out); return ADS_ERROR_NT(nt_status); } if ((turn == 1) && (rc == LDAP_SASL_BIND_IN_PROGRESS)) { DATA_BLOB tmp_blob = data_blob_null; /* the server might give us back two challenges */ if (!spnego_parse_challenge(blob, &blob_in, &tmp_blob)) { ntlmssp_end(&ntlmssp_state); data_blob_free(&blob); DEBUG(3,("Failed to parse challenges\n")); return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); } data_blob_free(&tmp_blob); } else if (rc == LDAP_SASL_BIND_IN_PROGRESS) { if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP, &blob_in)) { ntlmssp_end(&ntlmssp_state); data_blob_free(&blob); DEBUG(3,("Failed to parse auth response\n")); return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); } } data_blob_free(&blob); data_blob_free(&blob_out); turn++; } while (rc == LDAP_SASL_BIND_IN_PROGRESS && !NT_STATUS_IS_OK(nt_status)); /* we have a reference conter on ntlmssp_state, if we are signing then the state will be kept by the signing engine */ if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) { ads->ldap.out.max_unwrapped = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED - NTLMSSP_SIG_SIZE; ads->ldap.out.sig_size = NTLMSSP_SIG_SIZE; ads->ldap.in.min_wrapped = ads->ldap.out.sig_size; ads->ldap.in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED; status = ads_setup_sasl_wrapping(ads, &ads_sasl_ntlmssp_ops, ntlmssp_state); if (!ADS_ERR_OK(status)) { DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n", ads_errstr(status))); ntlmssp_end(&ntlmssp_state); return status; } } else { ntlmssp_end(&ntlmssp_state); } return ADS_ERROR(rc); }
void test_ntlmssp_compute_ntlm_v2_response(void) { int i; char* p; NTLMSSP* ntlmssp; int session_base_key_good; int lm_challenge_response_good; int nt_challenge_response_good; char password[] = "password"; char username[] = "username"; char domain[] = "win7"; char timestamp[8] = "\xc3\x83\xa2\x1c\x6c\xb0\xcb\x01"; char client_challenge[8] = "\x47\xa2\xe5\xcf\x27\xf7\x3c\x43"; char server_challenge[8] = "\x26\x6e\xcd\x75\xaa\x41\xe7\x6f"; char target_info_data[68] = "\x02\x00\x08\x00\x57\x00\x49\x00\x4e\x00\x37\x00" "\x01\x00\x08\x00\x57\x00\x49\x00\x4e\x00\x37\x00" "\x04\x00\x08\x00\x77\x00\x69\x00\x6e\x00\x37\x00" "\x03\x00\x08\x00\x77\x00\x69\x00\x6e\x00\x37\x00" "\x07\x00\x08\x00\xa9\x8d\x9b\x1a\x6c\xb0\xcb\x01" "\x00\x00\x00\x00\x00\x00\x00\x00"; char expected_nt_challenge_response[112] = "\x01\x4a\xd0\x8c\x24\xb4\x90\x74\x39\x68\xe8\xbd\x0d\x2b\x70\x10" "\x01\x01\x00\x00\x00\x00\x00\x00\xc3\x83\xa2\x1c\x6c\xb0\xcb\x01" "\x47\xa2\xe5\xcf\x27\xf7\x3c\x43\x00\x00\x00\x00\x02\x00\x08\x00" "\x57\x00\x49\x00\x4e\x00\x37\x00\x01\x00\x08\x00\x57\x00\x49\x00" "\x4e\x00\x37\x00\x04\x00\x08\x00\x77\x00\x69\x00\x6e\x00\x37\x00" "\x03\x00\x08\x00\x77\x00\x69\x00\x6e\x00\x37\x00\x07\x00\x08\x00" "\xa9\x8d\x9b\x1a\x6c\xb0\xcb\x01\x00\x00\x00\x00\x00\x00\x00\x00"; char expected_lm_challenge_response[24] = "\xa0\x98\x01\x10\x19\xbb\x5d\x00\xf6\xbe\x00\x33\x90\x20\x34\xb3" "\x47\xa2\xe5\xcf\x27\xf7\x3c\x43"; char expected_session_base_key[16] = "\x6e\xf1\x6b\x79\x88\xf2\x3d\x7e\x54\x2a\x1a\x38\x4e\xa0\x6b\x52"; ntlmssp = ntlmssp_client_new(); ntlmssp_set_password(ntlmssp, password); ntlmssp_set_username(ntlmssp, username); ntlmssp_set_domain(ntlmssp, domain); ntlmssp->av_pairs->Timestamp.value = xzalloc(8); ntlmssp->av_pairs->Timestamp.length = 8; memcpy(ntlmssp->timestamp, timestamp, 8); memcpy(ntlmssp->server_challenge, server_challenge, 8); memcpy(ntlmssp->client_challenge, client_challenge, 8); ntlmssp->target_info.data = target_info_data; ntlmssp->target_info.length = sizeof(target_info_data); ntlmssp_compute_lm_v2_response(ntlmssp); ntlmssp_compute_ntlm_v2_response(ntlmssp); session_base_key_good = 1; p = (char*) ntlmssp->session_base_key; for (i = 0; i < 16; i++) { if (p[i] != expected_session_base_key[i]) session_base_key_good = 0; } CU_ASSERT(session_base_key_good == 1); lm_challenge_response_good = 1; p = (char*) ntlmssp->lm_challenge_response.data; for (i = 0; i < 24; i++) { if (p[i] != expected_lm_challenge_response[i]) lm_challenge_response_good = 0; } CU_ASSERT(lm_challenge_response_good == 1); nt_challenge_response_good = 1; p = (char*) ntlmssp->nt_challenge_response.data; for (i = 0; i < 84; i++) { if (p[i] != expected_nt_challenge_response[i]) nt_challenge_response_good = 0; } CU_ASSERT(nt_challenge_response_good == 1); }
static BOOL rpc_pipe_bind(struct cli_state *cli, int pipe_idx, const char *my_name) { RPC_IFACE abstract; RPC_IFACE transfer; prs_struct rpc_out; prs_struct rdata; uint32 rpc_call_id; char buffer[MAX_PDU_FRAG_LEN]; if ( (pipe_idx < 0) || (pipe_idx >= PI_MAX_PIPES) ) return False; DEBUG(5,("Bind RPC Pipe[%x]: %s\n", cli->nt_pipe_fnum, pipe_names[pipe_idx].client_pipe)); if (!valid_pipe_name(pipe_idx, &abstract, &transfer)) return False; prs_init(&rpc_out, 0, cli->mem_ctx, MARSHALL); /* * Use the MAX_PDU_FRAG_LEN buffer to store the bind request. */ prs_give_memory( &rpc_out, buffer, sizeof(buffer), False); rpc_call_id = get_rpc_call_id(); if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { NTSTATUS nt_status; fstring password; DEBUG(5, ("NTLMSSP authenticated pipe selected\n")); nt_status = ntlmssp_client_start(&cli->ntlmssp_pipe_state); if (!NT_STATUS_IS_OK(nt_status)) return False; /* Currently the NTLMSSP code does not implement NTLM2 correctly for signing or sealing */ cli->ntlmssp_pipe_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; nt_status = ntlmssp_set_username(cli->ntlmssp_pipe_state, cli->user_name); if (!NT_STATUS_IS_OK(nt_status)) return False; nt_status = ntlmssp_set_domain(cli->ntlmssp_pipe_state, cli->domain); if (!NT_STATUS_IS_OK(nt_status)) return False; if (cli->pwd.null_pwd) { nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, NULL); if (!NT_STATUS_IS_OK(nt_status)) return False; } else { pwd_get_cleartext(&cli->pwd, password); nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, password); if (!NT_STATUS_IS_OK(nt_status)) return False; } if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) { cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; } if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) { cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; } } else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { cli->auth_info.seq_num = 0; } /* Marshall the outgoing data. */ create_rpc_bind_req(cli, &rpc_out, rpc_call_id, &abstract, &transfer, global_myname(), cli->domain); /* Initialize the incoming data struct. */ prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); /* send data on \PIPE\. receive a response */ if (rpc_api_pipe(cli, &rpc_out, &rdata, RPC_BINDACK)) { RPC_HDR_BA hdr_ba; DEBUG(5, ("rpc_pipe_bind: rpc_api_pipe returned OK.\n")); if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rdata, 0)) { DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n")); prs_mem_free(&rdata); return False; } if(!check_bind_response(&hdr_ba, pipe_idx, &transfer)) { DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n")); prs_mem_free(&rdata); return False; } cli->max_xmit_frag = hdr_ba.bba.max_tsize; cli->max_recv_frag = hdr_ba.bba.max_rsize; /* * If we're doing NTLMSSP auth we need to send a reply to * the bind-ack to complete the 3-way challenge response * handshake. */ if ((cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) && !rpc_send_auth_reply(cli, &rdata, rpc_call_id)) { DEBUG(0,("rpc_pipe_bind: rpc_send_auth_reply failed.\n")); prs_mem_free(&rdata); return False; } prs_mem_free(&rdata); return True; } return False; }
/* perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can we fit on one socket??) */ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads) { DATA_BLOB msg1 = data_blob(NULL, 0); DATA_BLOB blob = data_blob(NULL, 0); DATA_BLOB blob_in = data_blob(NULL, 0); DATA_BLOB blob_out = data_blob(NULL, 0); struct berval cred, *scred = NULL; int rc; NTSTATUS nt_status; int turn = 1; struct ntlmssp_state *ntlmssp_state; if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) { return ADS_ERROR_NT(nt_status); } ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN; if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, ads->auth.user_name))) { return ADS_ERROR_NT(nt_status); } if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, ads->auth.realm))) { return ADS_ERROR_NT(nt_status); } if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, ads->auth.password))) { return ADS_ERROR_NT(nt_status); } blob_in = data_blob(NULL, 0); do { nt_status = ntlmssp_update(ntlmssp_state, blob_in, &blob_out); data_blob_free(&blob_in); if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) && blob_out.length) { if (turn == 1) { /* and wrap it in a SPNEGO wrapper */ msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out); } else { /* wrap it in SPNEGO */ msg1 = spnego_gen_auth(blob_out); } data_blob_free(&blob_out); cred.bv_val = (char *)msg1.data; cred.bv_len = msg1.length; scred = NULL; rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred); data_blob_free(&msg1); if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) { if (scred) { ber_bvfree(scred); } ntlmssp_end(&ntlmssp_state); return ADS_ERROR(rc); } if (scred) { blob = data_blob(scred->bv_val, scred->bv_len); ber_bvfree(scred); } else { blob = data_blob(NULL, 0); } } else { ntlmssp_end(&ntlmssp_state); data_blob_free(&blob_out); return ADS_ERROR_NT(nt_status); } if ((turn == 1) && (rc == LDAP_SASL_BIND_IN_PROGRESS)) { DATA_BLOB tmp_blob = data_blob(NULL, 0); /* the server might give us back two challenges */ if (!spnego_parse_challenge(blob, &blob_in, &tmp_blob)) { ntlmssp_end(&ntlmssp_state); data_blob_free(&blob); DEBUG(3,("Failed to parse challenges\n")); return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); } data_blob_free(&tmp_blob); } else if (rc == LDAP_SASL_BIND_IN_PROGRESS) { if (!spnego_parse_auth_response(blob, nt_status, &blob_in)) { ntlmssp_end(&ntlmssp_state); data_blob_free(&blob); DEBUG(3,("Failed to parse auth response\n")); return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); } } data_blob_free(&blob); data_blob_free(&blob_out); turn++; } while (rc == LDAP_SASL_BIND_IN_PROGRESS && !NT_STATUS_IS_OK(nt_status)); /* we have a reference conter on ntlmssp_state, if we are signing then the state will be kept by the signing engine */ ntlmssp_end(&ntlmssp_state); return ADS_ERROR(rc); }
tbool rpch_in_send_bind(rdpRpch* rpch) { STREAM* ntlm_stream = stream_new(0xFFFF); STREAM* pdu; int bytes; rpcconn_bind_hdr_t* bind_pdu; LLOGLN(10, ("rpch_in_send_bind:")); rpch->ntlmssp = ntlmssp_new(); rpch->ntlmssp->ntlm_v2 = true; ntlmssp_set_username(rpch->ntlmssp, rpch->settings->tsg_username); ntlmssp_set_password(rpch->ntlmssp, rpch->settings->tsg_password); ntlmssp_set_domain(rpch->ntlmssp, rpch->settings->tsg_domain); ntlmssp_set_workstation(rpch->ntlmssp, "WORKSTATION"); /* TODO insert proper w.name */ ntlmssp_send(rpch->ntlmssp, ntlm_stream); bind_pdu = (rpcconn_bind_hdr_t*) xmalloc(sizeof(rpcconn_bind_hdr_t)); bind_pdu->rpc_vers = 5; bind_pdu->rpc_vers_minor = 0; bind_pdu->PTYPE = PTYPE_BIND; bind_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_PENDING_CANCEL | PFC_CONC_MPX; bind_pdu->packed_drep[0] = 0x10; bind_pdu->packed_drep[1] = 0x00; bind_pdu->packed_drep[2] = 0x00; bind_pdu->packed_drep[3] = 0x00; bytes = (int) (ntlm_stream->p - ntlm_stream->data); bind_pdu->frag_length = 124 + bytes; bind_pdu->auth_length = bytes; bind_pdu->call_id = 2; bind_pdu->max_xmit_frag = 0x0FF8; bind_pdu->max_recv_frag = 0x0FF8; bind_pdu->assoc_group_id = 0; bind_pdu->p_context_elem.n_context_elem = 2; bind_pdu->p_context_elem.reserved = 0; bind_pdu->p_context_elem.reserved2 = 0; bind_pdu->p_context_elem.p_cont_elem = (p_cont_elem_t*) xmalloc(sizeof(p_cont_elem_t) * bind_pdu->p_context_elem.n_context_elem); bind_pdu->p_context_elem.p_cont_elem[0].p_cont_id = 0; bind_pdu->p_context_elem.p_cont_elem[0].n_transfer_syn = 1; bind_pdu->p_context_elem.p_cont_elem[0].reserved = 0; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.time_low = 0x44e265dd; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.time_mid = 0x7daf; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.time_hi_and_version = 0x42cd; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.clock_seq_hi_and_reserved = 0x85; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.clock_seq_low = 0x60; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[0] = 0x3c; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[1] = 0xdb; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[2] = 0x6e; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[3] = 0x7a; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[4] = 0x27; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[5] = 0x29; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_version = 0x00030001; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes = xmalloc(sizeof(p_syntax_id_t)); bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.time_low = 0x8a885d04; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.time_mid = 0x1ceb; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.time_hi_and_version = 0x11c9; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.clock_seq_hi_and_reserved = 0x9f; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.clock_seq_low = 0xe8; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[0] = 0x08; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[1] = 0x00; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[2] = 0x2b; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[3] = 0x10; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[4] = 0x48; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[5] = 0x60; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_version = 0x00000002; bind_pdu->p_context_elem.p_cont_elem[1].p_cont_id = 1; bind_pdu->p_context_elem.p_cont_elem[1].n_transfer_syn = 1; bind_pdu->p_context_elem.p_cont_elem[1].reserved = 0; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.time_low = 0x44e265dd; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.time_mid = 0x7daf; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.time_hi_and_version = 0x42cd; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.clock_seq_hi_and_reserved = 0x85; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.clock_seq_low = 0x60; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[0] = 0x3c; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[1] = 0xdb; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[2] = 0x6e; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[3] = 0x7a; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[4] = 0x27; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[5] = 0x29; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_version = 0x00030001; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes = xmalloc(sizeof(p_syntax_id_t)); bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.time_low = 0x6cb71c2c; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.time_mid = 0x9812; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.time_hi_and_version = 0x4540; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.clock_seq_hi_and_reserved = 0x03; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.clock_seq_low = 0x00; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[0] = 0x00; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[1] = 0x00; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[2] = 0x00; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[3] = 0x00; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[4] = 0x00; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[5] = 0x00; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_version = 0x00000001; bind_pdu->auth_verifier.auth_pad = NULL; /* align(4); size_is(auth_pad_length) p*/ bind_pdu->auth_verifier.auth_type = 0x0a; /* :01 which authent service */ bind_pdu->auth_verifier.auth_level = 0x05; /* :01 which level within service */ bind_pdu->auth_verifier.auth_pad_length = 0x00; /* :01 */ bind_pdu->auth_verifier.auth_reserved = 0x00; /* :01 reserved, m.b.z. */ bind_pdu->auth_verifier.auth_context_id = 0x00000000; /* :04 */ bind_pdu->auth_verifier.auth_value = xmalloc(bind_pdu->auth_length); /* credentials; size_is(auth_length) p*/; memcpy(bind_pdu->auth_verifier.auth_value, ntlm_stream->data, bind_pdu->auth_length); stream_free(ntlm_stream); pdu = stream_new(bind_pdu->frag_length); stream_write(pdu, bind_pdu, 24); stream_write(pdu, &bind_pdu->p_context_elem, 4); stream_write(pdu, bind_pdu->p_context_elem.p_cont_elem, 24); stream_write(pdu, bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes, 20); stream_write(pdu, bind_pdu->p_context_elem.p_cont_elem + 1, 24); stream_write(pdu, bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes, 20); if (bind_pdu->auth_verifier.auth_pad_length > 0) { stream_write(pdu, bind_pdu->auth_verifier.auth_pad, bind_pdu->auth_verifier.auth_pad_length); } stream_write(pdu, &bind_pdu->auth_verifier.auth_type, 8); /* assumed that uint8 pointer is 32bit long (4 bytes) */ stream_write(pdu, bind_pdu->auth_verifier.auth_value, bind_pdu->auth_length); rpch_in_write(rpch, pdu->data, pdu->p - pdu->data); /* TODO there are some alocatad memory */ xfree(bind_pdu); return true; }
tbool rpch_in_connect_http(rdpRpch* rpch) { rdpTls* tls_in = rpch->tls_in; rdpSettings* settings = rpch->settings; rdpRpchHTTP* http_in = rpch->http_in; NTLMSSP* http_in_ntlmssp = http_in->ntht; STREAM* ntlmssp_stream; STREAM* http_stream; int decoded_ntht_length; int encoded_ntht_length = 0; int bytes; uint8* decoded_ntht_data; uint8* encoded_ntht_data = NULL; char* ntlm_text; LLOGLN(10, ("rpch_in_connect_http:")); ntlmssp_stream = stream_new(0xFFFF); http_stream = stream_new(0xFFFF); ntlmssp_set_username(http_in_ntlmssp, settings->tsg_username); ntlmssp_set_password(http_in_ntlmssp, settings->tsg_password); ntlmssp_set_domain(http_in_ntlmssp, settings->tsg_domain); ntlmssp_set_workstation(http_in_ntlmssp, "WORKSTATION"); /* TODO insert proper w.name */ LLOGLN(10, ("rpch_in_connect_http: tsg_username %s tsg_password %s tsg_domain %s", settings->tsg_username, settings->tsg_password, settings->tsg_domain)); ntlmssp_send(http_in_ntlmssp, ntlmssp_stream); decoded_ntht_length = (int) (ntlmssp_stream->p - ntlmssp_stream->data); decoded_ntht_data = (uint8*) xmalloc(decoded_ntht_length); ntlmssp_stream->p = ntlmssp_stream->data; stream_read(ntlmssp_stream, decoded_ntht_data, decoded_ntht_length); stream_clear(ntlmssp_stream); ntlmssp_stream->p = ntlmssp_stream->data; crypto_base64_encode(decoded_ntht_data, decoded_ntht_length, &encoded_ntht_data, &encoded_ntht_length); stream_write(http_stream, "RPC_IN_DATA /rpc/rpcproxy.dll?localhost:3388 HTTP/1.1\n", 54); stream_write(http_stream, "Accept: application/rpc\n", 24); stream_write(http_stream, "Cache-Control: no-cache\n", 24); stream_write(http_stream, "Connection: Keep-Alive\n", 23); stream_write(http_stream, "Content-Length: 0\n", 18); stream_write(http_stream, "User-Agent: MSRPC\n", 18); stream_write(http_stream, "Host: ", 6); stream_write(http_stream, settings->tsg_server, strlen(settings->tsg_server)); stream_write(http_stream, "\n", 1); stream_write(http_stream, "Pragma: ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, SessionId=33ad20ac-7469-4f63-946d-113eac21a23c\n", 110); stream_write(http_stream, "Authorization: NTLM ", 20); stream_write(http_stream, encoded_ntht_data, encoded_ntht_length); stream_write(http_stream, "\n\n", 2); LLOGLN(10, ("rpch_in_connect_http: sending\n%s", http_stream->data)); DEBUG_RPCH("\nSend:\n%s\n", http_stream->data); bytes = (int) (http_stream->p - http_stream->data); tls_write(tls_in, http_stream->data, bytes); stream_clear(http_stream); http_stream->p = http_stream->data; xfree(decoded_ntht_data); encoded_ntht_length = -1; xfree(encoded_ntht_data); encoded_ntht_data = NULL; http_in->contentLength = 0; LLOGLN(10, ("rpch_in_connect_http: 1")); stream_free(http_stream); http_stream = read_http(tls_in, NULL, true); if (http_stream == NULL) { LLOGLN(0, ("rpch_in_connect_http: error http_stream is nil")); return false; } ntlm_text = strstr((char*)(http_stream->data), "NTLM "); if (ntlm_text != NULL) { encoded_ntht_data = (uint8*)(ntlm_text + 5); encoded_ntht_length = 0; while (encoded_ntht_data[encoded_ntht_length] != '\r' && encoded_ntht_data[encoded_ntht_length] != '\n') { encoded_ntht_length++; } } LLOGLN(0, ("rpch_in_connect_http: encoded_ntht_length %d encoded_ntht_data %s", encoded_ntht_length, encoded_ntht_data)); if (encoded_ntht_length < 1) /* No NTLM data was found */ { LLOGLN(0, ("rpch_in_connect_http: error encoded_ntht_length < 1")); return false; } http_stream->p = http_stream->data; crypto_base64_decode(encoded_ntht_data, encoded_ntht_length, &decoded_ntht_data, &decoded_ntht_length); stream_write(ntlmssp_stream, decoded_ntht_data, decoded_ntht_length); ntlmssp_stream->p = ntlmssp_stream->data; xfree(decoded_ntht_data); ntlmssp_recv(http_in_ntlmssp, ntlmssp_stream); stream_clear(ntlmssp_stream); ntlmssp_stream->p = ntlmssp_stream->data; ntlmssp_send(http_in_ntlmssp, ntlmssp_stream); decoded_ntht_length = (int) (ntlmssp_stream->p - ntlmssp_stream->data); decoded_ntht_data = (uint8*) xmalloc(decoded_ntht_length); ntlmssp_stream->p = ntlmssp_stream->data; stream_read(ntlmssp_stream, decoded_ntht_data, decoded_ntht_length); stream_clear(ntlmssp_stream); ntlmssp_stream->p = ntlmssp_stream->data; crypto_base64_encode(decoded_ntht_data, decoded_ntht_length, &encoded_ntht_data, &encoded_ntht_length); stream_write(http_stream, "RPC_IN_DATA /rpc/rpcproxy.dll?localhost:3388 HTTP/1.1\n", 54); stream_write(http_stream, "Accept: application/rpc\n", 24); stream_write(http_stream, "Cache-Control: no-cache\n", 24); stream_write(http_stream, "Connection: Keep-Alive\n", 23); stream_write(http_stream, "Content-Length: 1073741824\n", 27); stream_write(http_stream, "User-Agent: MSRPC\n", 18); stream_write(http_stream, "Host: ", 6); stream_write(http_stream, settings->tsg_server, strlen(settings->tsg_server)); stream_write(http_stream, "\n", 1); stream_write(http_stream, "Pragma: ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, SessionId=33ad20ac-7469-4f63-946d-113eac21a23c\n", 110); stream_write(http_stream, "Authorization: NTLM ", 20); stream_write(http_stream, encoded_ntht_data, encoded_ntht_length); stream_write(http_stream, "\n\n", 2); http_in->contentLength = 1073741824; http_in->remContentLength = 1073741824; DEBUG_RPCH("\nSend:\n%s\n", http_stream->data); tls_write(tls_in, http_stream->data, http_stream->p - http_stream->data); stream_clear(http_stream); http_stream->p = http_stream->data; xfree(decoded_ntht_data); xfree(encoded_ntht_data); /* At this point IN connection is ready to send CONN/B1 and start with sending data */ http_in->state = RPCH_HTTP_SENDING; LLOGLN(10, ("rpch_in_connect_http: out")); return true; }