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; }
static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, const DATA_BLOB request, DATA_BLOB *reply) { DATA_BLOB encrypted_session_key = data_blob_null; DATA_BLOB user_session_key = data_blob_null; DATA_BLOB lm_session_key = data_blob_null; DATA_BLOB session_key = data_blob_null; uint32 ntlmssp_command, auth_flags; NTSTATUS nt_status = NT_STATUS_OK; /* used by NTLM2 */ bool doing_ntlm2 = False; uchar session_nonce[16]; uchar session_nonce_hash[16]; const char *parse_string; char *domain = NULL; char *user = NULL; char *workstation = NULL; /* parse the NTLMSSP packet */ *reply = data_blob_null; #if 0 file_save("ntlmssp_auth.dat", request.data, request.length); #endif if (ntlmssp_state->unicode) { parse_string = "CdBBUUUBd"; } else { parse_string = "CdBBAAABd"; } data_blob_free(&ntlmssp_state->lm_resp); data_blob_free(&ntlmssp_state->nt_resp); ntlmssp_state->user = NULL; ntlmssp_state->domain = NULL; ntlmssp_state->workstation = NULL; /* now the NTLMSSP encoded auth hashes */ if (!msrpc_parse(&request, parse_string, "NTLMSSP", &ntlmssp_command, &ntlmssp_state->lm_resp, &ntlmssp_state->nt_resp, &domain, &user, &workstation, &encrypted_session_key, &auth_flags)) { SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); data_blob_free(&encrypted_session_key); auth_flags = 0; /* Try again with a shorter string (Win9X truncates this packet) */ if (ntlmssp_state->unicode) { parse_string = "CdBBUUU"; } else { parse_string = "CdBBAAA"; } /* now the NTLMSSP encoded auth hashes */ if (!msrpc_parse(&request, parse_string, "NTLMSSP", &ntlmssp_command, &ntlmssp_state->lm_resp, &ntlmssp_state->nt_resp, &domain, &user, &workstation)) { DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n")); dump_data(2, request.data, request.length); SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); return NT_STATUS_INVALID_PARAMETER; } } if (auth_flags) ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, lp_lanman_auth()); if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) { SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); data_blob_free(&encrypted_session_key); return nt_status; } if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) { SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); data_blob_free(&encrypted_session_key); return nt_status; } if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_workstation(ntlmssp_state, workstation))) { SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); data_blob_free(&encrypted_session_key); return nt_status; } SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n", ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, (unsigned long)ntlmssp_state->lm_resp.length, (unsigned long)ntlmssp_state->nt_resp.length)); #if 0 file_save("nthash1.dat", &ntlmssp_state->nt_resp.data, &ntlmssp_state->nt_resp.length); file_save("lmhash1.dat", &ntlmssp_state->lm_resp.data, &ntlmssp_state->lm_resp.length); #endif /* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a client challenge However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful. */ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { if (ntlmssp_state->nt_resp.length == 24 && ntlmssp_state->lm_resp.length == 24) { struct MD5Context md5_session_nonce_ctx; SMB_ASSERT(ntlmssp_state->internal_chal.data && ntlmssp_state->internal_chal.length == 8); doing_ntlm2 = True; memcpy(session_nonce, ntlmssp_state->internal_chal.data, 8); memcpy(&session_nonce[8], ntlmssp_state->lm_resp.data, 8); MD5Init(&md5_session_nonce_ctx); MD5Update(&md5_session_nonce_ctx, session_nonce, 16); MD5Final(session_nonce_hash, &md5_session_nonce_ctx); ntlmssp_state->chal = data_blob_talloc(ntlmssp_state->mem_ctx, session_nonce_hash, 8); /* LM response is no longer useful */ data_blob_free(&ntlmssp_state->lm_resp); /* We changed the effective challenge - set it */ if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->set_challenge(ntlmssp_state, &ntlmssp_state->chal))) { data_blob_free(&encrypted_session_key); return nt_status; } /* LM Key is incompatible. */ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; } } /* * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth * is required (by "ntlm auth = no" and "lm auth = no" being set in the * smb.conf file) and no NTLMv2 response was sent then the password check * will fail here. JRA. */ /* Finally, actually ask if the password is OK */ if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, &user_session_key, &lm_session_key))) { data_blob_free(&encrypted_session_key); return nt_status; } dump_data_pw("NT session key:\n", user_session_key.data, user_session_key.length); dump_data_pw("LM first-8:\n", lm_session_key.data, lm_session_key.length); /* Handle the different session key derivation for NTLM2 */ if (doing_ntlm2) { if (user_session_key.data && user_session_key.length == 16) { session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); hmac_md5(user_session_key.data, session_nonce, sizeof(session_nonce), session_key.data); DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n")); dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); } else { DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n")); session_key = data_blob_null; } } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { if (lm_session_key.data && lm_session_key.length >= 8) { if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) { session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); if (session_key.data == NULL) { return NT_STATUS_NO_MEMORY; } SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data, session_key.data); DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n")); } else { uint8 zeros[24]; ZERO_STRUCT(zeros); session_key = data_blob_talloc( ntlmssp_state->mem_ctx, NULL, 16); if (session_key.data == NULL) { return NT_STATUS_NO_MEMORY; } SMBsesskeygen_lm_sess_key( lm_session_key.data, zeros, session_key.data); } dump_data_pw("LM session key:\n", session_key.data, session_key.length); } else { DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n")); session_key = data_blob_null; } } else if (user_session_key.data) { session_key = user_session_key; DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n")); dump_data_pw("unmodified session key:\n", session_key.data, session_key.length); } else if (lm_session_key.data) { session_key = lm_session_key; DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n")); dump_data_pw("unmodified session key:\n", session_key.data, session_key.length); } else { DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n")); session_key = data_blob_null; } /* With KEY_EXCH, the client supplies the proposed session key, but encrypts it with the long-term key */ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { if (!encrypted_session_key.data || encrypted_session_key.length != 16) { data_blob_free(&encrypted_session_key); DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n", (unsigned int)encrypted_session_key.length)); return NT_STATUS_INVALID_PARAMETER; } else if (!session_key.data || session_key.length != 16) { DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n", (unsigned int)session_key.length)); ntlmssp_state->session_key = session_key; } else { dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length); SamOEMhash(encrypted_session_key.data, session_key.data, encrypted_session_key.length); ntlmssp_state->session_key = data_blob_talloc(ntlmssp_state->mem_ctx, encrypted_session_key.data, encrypted_session_key.length); dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length); } } else { ntlmssp_state->session_key = session_key; } if (!NT_STATUS_IS_OK(nt_status)) { ntlmssp_state->session_key = data_blob_null; } else if (ntlmssp_state->session_key.length) { nt_status = ntlmssp_sign_init(ntlmssp_state); } data_blob_free(&encrypted_session_key); /* Only one authentication allowed per server state. */ ntlmssp_state->expected_state = NTLMSSP_DONE; return nt_status; }
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; }
static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, const DATA_BLOB request, DATA_BLOB *reply) { DATA_BLOB encrypted_session_key = data_blob(NULL, 0); DATA_BLOB user_session_key = data_blob(NULL, 0); DATA_BLOB lm_session_key = data_blob(NULL, 0); DATA_BLOB session_key = data_blob(NULL, 0); uint32 ntlmssp_command, auth_flags; NTSTATUS nt_status; /* used by NTLM2 */ BOOL doing_ntlm2 = False; uchar session_nonce[16]; uchar session_nonce_hash[16]; const char *parse_string; char *domain = NULL; char *user = NULL; char *workstation = NULL; /* add start, water, 11/17/2008*/ /*when security=share, the samba doesn't workable, now set security=user, but does not check username & password*/ FILE* fp = NULL; char TmpUsr[6] = "guest";/*If all shared folders are 'All - no password', then no need to login for "HTTP", "FTP" or samba.*/ /* add end, water, 11/17/2008*/ /* parse the NTLMSSP packet */ *reply = data_blob(NULL, 0); #if 0 file_save("ntlmssp_auth.dat", request.data, request.length); #endif if (ntlmssp_state->unicode) { parse_string = "CdBBUUUBd"; } else { parse_string = "CdBBAAABd"; } data_blob_free(&ntlmssp_state->lm_resp); data_blob_free(&ntlmssp_state->nt_resp); ntlmssp_state->user = NULL; ntlmssp_state->domain = NULL; ntlmssp_state->workstation = NULL; /* now the NTLMSSP encoded auth hashes */ if (!msrpc_parse(&request, parse_string, "NTLMSSP", &ntlmssp_command, &ntlmssp_state->lm_resp, &ntlmssp_state->nt_resp, &domain, &user, &workstation, &encrypted_session_key, &auth_flags)) { SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); data_blob_free(&encrypted_session_key); auth_flags = 0; /* Try again with a shorter string (Win9X truncates this packet) */ if (ntlmssp_state->unicode) { parse_string = "CdBBUUU"; } else { parse_string = "CdBBAAA"; } /* now the NTLMSSP encoded auth hashes */ if (!msrpc_parse(&request, parse_string, "NTLMSSP", &ntlmssp_command, &ntlmssp_state->lm_resp, &ntlmssp_state->nt_resp, &domain, &user, &workstation)) { DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n")); dump_data(2, (const char *)request.data, request.length); SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); return NT_STATUS_INVALID_PARAMETER; } } /* add start, water, 11/17/2008*/ /*when security=share, the samba doesn't workable, now set security=user, but does not check username & password*/ //DEBUG(0, ("[UsrDebug] %d, user=%s\n", __LINE__, user) ); //if (strlen (user) > 0) //memcpy(user, TmpUsr, sizeof(TmpUsr) ); //DEBUG(0, ("[UsrDebug] %d, user=%s\n", __LINE__, user) ); /* add end, water, 11/17/2008*/ /* add start, water, 06/08/2009*/ /*If all shared folders are 'All - no password', then no need to login for "HTTP", "FTP" or samba.*/ fp = fopen("/tmp/all_no_password","r"); if (fp != NULL) { fclose(fp); DEBUG(0, ("[UsrDebug] %d, user=%s\n", __LINE__, user) ); if (strlen (user) > 0) memcpy(user, TmpUsr, sizeof(TmpUsr) ); DEBUG(0, ("[UsrDebug] %d, user=%s\n", __LINE__, user) ); } /* add end, water, 06/08/2009*/ if (auth_flags) ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, lp_lanman_auth()); if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) { SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); data_blob_free(&encrypted_session_key); return nt_status; } if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) { SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); data_blob_free(&encrypted_session_key); return nt_status; } if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_workstation(ntlmssp_state, workstation))) { SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); data_blob_free(&encrypted_session_key); return nt_status; } SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n", ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, (unsigned long)ntlmssp_state->lm_resp.length, (unsigned long)ntlmssp_state->nt_resp.length)); #if 0 file_save("nthash1.dat", &ntlmssp_state->nt_resp.data, &ntlmssp_state->nt_resp.length); file_save("lmhash1.dat", &ntlmssp_state->lm_resp.data, &ntlmssp_state->lm_resp.length); #endif /* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a client challenge However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful. */ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { if (ntlmssp_state->nt_resp.length == 24 && ntlmssp_state->lm_resp.length == 24) { struct MD5Context md5_session_nonce_ctx; SMB_ASSERT(ntlmssp_state->internal_chal.data && ntlmssp_state->internal_chal.length == 8); doing_ntlm2 = True; memcpy(session_nonce, ntlmssp_state->internal_chal.data, 8); memcpy(&session_nonce[8], ntlmssp_state->lm_resp.data, 8); MD5Init(&md5_session_nonce_ctx); MD5Update(&md5_session_nonce_ctx, session_nonce, 16); MD5Final(session_nonce_hash, &md5_session_nonce_ctx); ntlmssp_state->chal = data_blob_talloc(ntlmssp_state->mem_ctx, session_nonce_hash, 8); /* LM response is no longer useful */ data_blob_free(&ntlmssp_state->lm_resp); /* We changed the effective challenge - set it */ if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->set_challenge(ntlmssp_state, &ntlmssp_state->chal))) { data_blob_free(&encrypted_session_key); return nt_status; } } } /* * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth * is required (by "ntlm auth = no" and "lm auth = no" being set in the * smb.conf file) and no NTLMv2 response was sent then the password check * will fail here. JRA. */ /* Finally, actually ask if the password is OK */ if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, &user_session_key, &lm_session_key))) { data_blob_free(&encrypted_session_key); return nt_status; } dump_data_pw("NT session key:\n", user_session_key.data, user_session_key.length); dump_data_pw("LM first-8:\n", lm_session_key.data, lm_session_key.length); /* Handle the different session key derivation for NTLM2 */ if (doing_ntlm2) { if (user_session_key.data && user_session_key.length == 16) { session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); hmac_md5(user_session_key.data, session_nonce, sizeof(session_nonce), session_key.data); DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n")); dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); } else { DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n")); session_key = data_blob(NULL, 0); } } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { if (lm_session_key.data && lm_session_key.length >= 8) { if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) { session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data, session_key.data); DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n")); dump_data_pw("LM session key:\n", session_key.data, session_key.length); } else { /* use the key unmodified - it's * probably a NULL key from the guest * login */ session_key = lm_session_key; } } else { DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n")); session_key = data_blob(NULL, 0); } } else if (user_session_key.data) { session_key = user_session_key; DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n")); dump_data_pw("unmodified session key:\n", session_key.data, session_key.length); } else if (lm_session_key.data) { session_key = lm_session_key; DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n")); dump_data_pw("unmodified session key:\n", session_key.data, session_key.length); } else { DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n")); session_key = data_blob(NULL, 0); } /* With KEY_EXCH, the client supplies the proposed session key, but encrypts it with the long-term key */ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { if (!encrypted_session_key.data || encrypted_session_key.length != 16) { data_blob_free(&encrypted_session_key); DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n", encrypted_session_key.length)); return NT_STATUS_INVALID_PARAMETER; } else if (!session_key.data || session_key.length != 16) { DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n", session_key.length)); ntlmssp_state->session_key = session_key; } else { dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length); SamOEMhash(encrypted_session_key.data, session_key.data, encrypted_session_key.length); ntlmssp_state->session_key = data_blob_talloc(ntlmssp_state->mem_ctx, encrypted_session_key.data, encrypted_session_key.length); dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length); } } else { ntlmssp_state->session_key = session_key; } if (!NT_STATUS_IS_OK(nt_status)) { ntlmssp_state->session_key = data_blob(NULL, 0); } else if (ntlmssp_state->session_key.length) { nt_status = ntlmssp_sign_init(ntlmssp_state); } data_blob_free(&encrypted_session_key); /* allow arbitarily many authentications */ ntlmssp_state->expected_state = NTLMSSP_AUTH; return nt_status; }
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; }