データ構造 | |
struct | ntlmssp_callbacks |
Callbacks for NTLMSSP - for both client and server operating modes [詳細] | |
関数 | |
static NTSTATUS | ntlmssp_client_initial (struct ntlmssp_state *ntlmssp_state, DATA_BLOB reply, DATA_BLOB *next_request) |
Next state function for the Initial packet | |
static NTSTATUS | ntlmssp_server_negotiate (struct ntlmssp_state *ntlmssp_state, const DATA_BLOB request, DATA_BLOB *reply) |
Next state function for the Negotiate packet | |
static NTSTATUS | ntlmssp_client_challenge (struct ntlmssp_state *ntlmssp_state, const DATA_BLOB reply, DATA_BLOB *next_request) |
Next state function for the Challenge Packet. | |
static NTSTATUS | ntlmssp_server_auth (struct ntlmssp_state *ntlmssp_state, const DATA_BLOB request, DATA_BLOB *reply) |
Next state function for the Authenticate packet | |
void | debug_ntlmssp_flags (uint32 neg_flags) |
Print out the NTLMSSP flags for debugging | |
static const uint8 * | get_challenge (const struct ntlmssp_state *ntlmssp_state) |
Default challenge generation code. | |
static BOOL | may_set_challenge (const struct ntlmssp_state *ntlmssp_state) |
Default 'we can set the challenge to anything we like' implementation | |
static NTSTATUS | set_challenge (struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge) |
Default 'we can set the challenge to anything we like' implementation | |
NTSTATUS | ntlmssp_set_username (NTLMSSP_STATE *ntlmssp_state, const char *user) |
Set a username on an NTLMSSP context - ensures it is talloc()ed | |
NTSTATUS | ntlmssp_set_hashes (NTLMSSP_STATE *ntlmssp_state, const unsigned char lm_hash[16], const unsigned char nt_hash[16]) |
Store NT and LM hashes on an NTLMSSP context - ensures they are talloc()ed | |
NTSTATUS | ntlmssp_set_password (NTLMSSP_STATE *ntlmssp_state, const char *password) |
Converts a password to the hashes on an NTLMSSP context. | |
NTSTATUS | ntlmssp_set_domain (NTLMSSP_STATE *ntlmssp_state, const char *domain) |
Set a domain on an NTLMSSP context - ensures it is talloc()ed | |
NTSTATUS | ntlmssp_set_workstation (NTLMSSP_STATE *ntlmssp_state, const char *workstation) |
Set a workstation on an NTLMSSP context - ensures it is talloc()ed | |
NTSTATUS | ntlmssp_store_response (NTLMSSP_STATE *ntlmssp_state, DATA_BLOB response) |
Store a DATA_BLOB containing an NTLMSSP response, for use later. | |
void | ntlmssp_want_feature_list (NTLMSSP_STATE *ntlmssp_state, char *feature_list) |
Request features for the NTLMSSP negotiation | |
void | ntlmssp_want_feature (NTLMSSP_STATE *ntlmssp_state, uint32 feature) |
Request a feature for the NTLMSSP negotiation | |
NTSTATUS | ntlmssp_update (NTLMSSP_STATE *ntlmssp_state, const DATA_BLOB in, DATA_BLOB *out) |
Next state function for the NTLMSSP state machine | |
void | ntlmssp_end (NTLMSSP_STATE **ntlmssp_state) |
End an NTLMSSP state machine | |
static const char * | ntlmssp_target_name (struct ntlmssp_state *ntlmssp_state, uint32 neg_flags, uint32 *chal_flags) |
Determine correct target name flags for reply, given server role and negotiated flags | |
static void | ntlmssp_handle_neg_flags (struct ntlmssp_state *ntlmssp_state, uint32 neg_flags, BOOL allow_lm) |
DATA_BLOB | ntlmssp_weaken_keys (NTLMSSP_STATE *ntlmssp_state, TALLOC_CTX *mem_ctx) |
Weaken NTLMSSP keys to cope with down-level clients and servers. | |
NTSTATUS | ntlmssp_server_start (NTLMSSP_STATE **ntlmssp_state) |
Create an NTLMSSP state machine | |
NTSTATUS | ntlmssp_client_start (NTLMSSP_STATE **ntlmssp_state) |
static NTSTATUS ntlmssp_client_initial | ( | struct ntlmssp_state * | ntlmssp_state, | |
DATA_BLOB | reply, | |||
DATA_BLOB * | next_request | |||
) | [static] |
Next state function for the Initial packet
ntlmssp_state | NTLMSSP State | |
request | The request, as a DATA_BLOB. reply.data must be NULL | |
request | The reply, as an allocated DATA_BLOB, caller to free. |
参照先 ntlmssp_state::expected_state・ntlmssp_state::get_domain・ntlmssp_state::get_global_myname・msrpc_gen()・ntlmssp_state::neg_flags・NTLMSSP_CHALLENGE・NTLMSSP_NEGOTIATE・ntlmssp_state::unicode・ntlmssp_state::use_ntlmv2.
00956 { 00957 if (ntlmssp_state->unicode) { 00958 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; 00959 } else { 00960 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM; 00961 } 00962 00963 if (ntlmssp_state->use_ntlmv2) { 00964 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; 00965 } 00966 00967 /* generate the ntlmssp negotiate packet */ 00968 msrpc_gen(next_request, "CddAA", 00969 "NTLMSSP", 00970 NTLMSSP_NEGOTIATE, 00971 ntlmssp_state->neg_flags, 00972 ntlmssp_state->get_domain(), 00973 ntlmssp_state->get_global_myname()); 00974 00975 ntlmssp_state->expected_state = NTLMSSP_CHALLENGE; 00976 00977 return NT_STATUS_MORE_PROCESSING_REQUIRED; 00978 }
static NTSTATUS ntlmssp_server_negotiate | ( | struct ntlmssp_state * | ntlmssp_state, | |
const DATA_BLOB | request, | |||
DATA_BLOB * | reply | |||
) | [static] |
Next state function for the Negotiate packet
ntlmssp_state | NTLMSSP State | |
request | The request, as a DATA_BLOB | |
request | The reply, as an allocated DATA_BLOB, caller to free. |
参照先 ntlmssp_state::chal・data_blob_::data・data_blob()・data_blob_free()・data_blob_talloc()・debug_ntlmssp_flags()・dump_data()・ntlmssp_state::expected_state・file_save()・ntlmssp_state::get_challenge・ntlmssp_state::get_global_myname・get_mydnsdomname()・get_mydnsfullname()・ntlmssp_state::internal_chal・data_blob_::length・ntlmssp_state::may_set_challenge・ntlmssp_state::mem_ctx・msrpc_gen()・msrpc_parse()・ntlmssp_state::neg_flags・NTLMSSP_AUTH・NTLMSSP_CHALLENGE・ntlmssp_handle_neg_flags()・ntlmssp_target_name()・strlower_m()・ntlmssp_state::unicode.
00514 { 00515 DATA_BLOB struct_blob; 00516 fstring dnsname, dnsdomname; 00517 uint32 neg_flags = 0; 00518 uint32 ntlmssp_command, chal_flags; 00519 const uint8 *cryptkey; 00520 const char *target_name; 00521 00522 /* parse the NTLMSSP packet */ 00523 #if 0 00524 file_save("ntlmssp_negotiate.dat", request.data, request.length); 00525 #endif 00526 00527 if (request.length) { 00528 if ((request.length < 16) || !msrpc_parse(&request, "Cdd", 00529 "NTLMSSP", 00530 &ntlmssp_command, 00531 &neg_flags)) { 00532 DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate of length %u\n", 00533 (unsigned int)request.length)); 00534 dump_data(2, (const char *)request.data, request.length); 00535 return NT_STATUS_INVALID_PARAMETER; 00536 } 00537 debug_ntlmssp_flags(neg_flags); 00538 } 00539 00540 ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, lp_lanman_auth()); 00541 00542 /* Ask our caller what challenge they would like in the packet */ 00543 cryptkey = ntlmssp_state->get_challenge(ntlmssp_state); 00544 00545 /* Check if we may set the challenge */ 00546 if (!ntlmssp_state->may_set_challenge(ntlmssp_state)) { 00547 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; 00548 } 00549 00550 /* The flags we send back are not just the negotiated flags, 00551 * they are also 'what is in this packet'. Therfore, we 00552 * operate on 'chal_flags' from here on 00553 */ 00554 00555 chal_flags = ntlmssp_state->neg_flags; 00556 00557 /* get the right name to fill in as 'target' */ 00558 target_name = ntlmssp_target_name(ntlmssp_state, 00559 neg_flags, &chal_flags); 00560 if (target_name == NULL) 00561 return NT_STATUS_INVALID_PARAMETER; 00562 00563 ntlmssp_state->chal = data_blob_talloc(ntlmssp_state->mem_ctx, cryptkey, 8); 00564 ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state->mem_ctx, cryptkey, 8); 00565 00566 00567 /* This should be a 'netbios domain -> DNS domain' mapping */ 00568 dnsdomname[0] = '\0'; 00569 get_mydnsdomname(dnsdomname); 00570 strlower_m(dnsdomname); 00571 00572 dnsname[0] = '\0'; 00573 get_mydnsfullname(dnsname); 00574 00575 /* This creates the 'blob' of names that appears at the end of the packet */ 00576 if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) 00577 { 00578 msrpc_gen(&struct_blob, "aaaaa", 00579 NTLMSSP_NAME_TYPE_DOMAIN, target_name, 00580 NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->get_global_myname(), 00581 NTLMSSP_NAME_TYPE_DOMAIN_DNS, dnsdomname, 00582 NTLMSSP_NAME_TYPE_SERVER_DNS, dnsname, 00583 0, ""); 00584 } else { 00585 struct_blob = data_blob(NULL, 0); 00586 } 00587 00588 { 00589 /* Marshel the packet in the right format, be it unicode or ASCII */ 00590 const char *gen_string; 00591 if (ntlmssp_state->unicode) { 00592 gen_string = "CdUdbddB"; 00593 } else { 00594 gen_string = "CdAdbddB"; 00595 } 00596 00597 msrpc_gen(reply, gen_string, 00598 "NTLMSSP", 00599 NTLMSSP_CHALLENGE, 00600 target_name, 00601 chal_flags, 00602 cryptkey, 8, 00603 0, 0, 00604 struct_blob.data, struct_blob.length); 00605 } 00606 00607 data_blob_free(&struct_blob); 00608 00609 ntlmssp_state->expected_state = NTLMSSP_AUTH; 00610 00611 return NT_STATUS_MORE_PROCESSING_REQUIRED; 00612 }
static NTSTATUS ntlmssp_client_challenge | ( | struct ntlmssp_state * | ntlmssp_state, | |
const DATA_BLOB | reply, | |||
DATA_BLOB * | next_request | |||
) | [static] |
Next state function for the Challenge Packet.
Generate an auth packet.
ntlmssp_state | NTLMSSP State | |
request | The request, as a DATA_BLOB. reply.data must be NULL | |
request | The reply, as an allocated DATA_BLOB, caller to free. |
参照先 ntlmssp_state::chal・data_blob_::data・data_blob()・data_blob_free()・data_blob_talloc()・debug_ntlmssp_flags()・ntlmssp_state::domain・dump_data()・dump_data_pw()・ntlmssp_state::expected_state・generate_random_buffer()・ntlmssp_state::get_global_myname・hmac_md5()・data_blob_::length・ntlmssp_state::lm_hash・ntlmssp_state::lm_resp・MD5Final()・MD5Init()・MD5Update()・ntlmssp_state::mem_ctx・msrpc_gen()・msrpc_parse()・ntlmssp_state::neg_flags・nt_errstr()・ntlmssp_state::nt_hash・ntlmssp_state::nt_resp・NTLMSSP_AUTH・NTLMSSP_DONE・ntlmssp_handle_neg_flags()・ntlmssp_sign_init()・SamOEMhash()・ntlmssp_state::server_domain・ntlmssp_state::session_key・SMBencrypt_hash()・SMBNTencrypt_hash()・SMBNTLMv2encrypt_hash()・SMBsesskeygen_lm_sess_key()・SMBsesskeygen_ntv1()・talloc_strdup()・ntlmssp_state::unicode・ntlmssp_state::use_ntlmv2・ntlmssp_state::user.
00991 { 00992 uint32 chal_flags, ntlmssp_command, unkn1, unkn2; 00993 DATA_BLOB server_domain_blob; 00994 DATA_BLOB challenge_blob; 00995 DATA_BLOB struct_blob = data_blob(NULL, 0); 00996 char *server_domain; 00997 const char *chal_parse_string; 00998 const char *auth_gen_string; 00999 DATA_BLOB lm_response = data_blob(NULL, 0); 01000 DATA_BLOB nt_response = data_blob(NULL, 0); 01001 DATA_BLOB session_key = data_blob(NULL, 0); 01002 DATA_BLOB encrypted_session_key = data_blob(NULL, 0); 01003 NTSTATUS nt_status = NT_STATUS_OK; 01004 01005 if (!msrpc_parse(&reply, "CdBd", 01006 "NTLMSSP", 01007 &ntlmssp_command, 01008 &server_domain_blob, 01009 &chal_flags)) { 01010 DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n")); 01011 dump_data(2, (const char *)reply.data, reply.length); 01012 01013 return NT_STATUS_INVALID_PARAMETER; 01014 } 01015 01016 data_blob_free(&server_domain_blob); 01017 01018 DEBUG(3, ("Got challenge flags:\n")); 01019 debug_ntlmssp_flags(chal_flags); 01020 01021 ntlmssp_handle_neg_flags(ntlmssp_state, chal_flags, lp_client_lanman_auth()); 01022 01023 if (ntlmssp_state->unicode) { 01024 if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { 01025 chal_parse_string = "CdUdbddB"; 01026 } else { 01027 chal_parse_string = "CdUdbdd"; 01028 } 01029 auth_gen_string = "CdBBUUUBd"; 01030 } else { 01031 if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { 01032 chal_parse_string = "CdAdbddB"; 01033 } else { 01034 chal_parse_string = "CdAdbdd"; 01035 } 01036 01037 auth_gen_string = "CdBBAAABd"; 01038 } 01039 01040 DEBUG(3, ("NTLMSSP: Set final flags:\n")); 01041 debug_ntlmssp_flags(ntlmssp_state->neg_flags); 01042 01043 if (!msrpc_parse(&reply, chal_parse_string, 01044 "NTLMSSP", 01045 &ntlmssp_command, 01046 &server_domain, 01047 &chal_flags, 01048 &challenge_blob, 8, 01049 &unkn1, &unkn2, 01050 &struct_blob)) { 01051 DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n")); 01052 dump_data(2, (const char *)reply.data, reply.length); 01053 return NT_STATUS_INVALID_PARAMETER; 01054 } 01055 01056 ntlmssp_state->server_domain = talloc_strdup(ntlmssp_state->mem_ctx, 01057 server_domain); 01058 01059 SAFE_FREE(server_domain); 01060 if (challenge_blob.length != 8) { 01061 data_blob_free(&struct_blob); 01062 return NT_STATUS_INVALID_PARAMETER; 01063 } 01064 01065 if (!ntlmssp_state->nt_hash || !ntlmssp_state->lm_hash) { 01066 static const uchar zeros[16] = { 0, }; 01067 /* do nothing - blobs are zero length */ 01068 01069 /* session key is all zeros */ 01070 session_key = data_blob_talloc(ntlmssp_state->mem_ctx, zeros, 16); 01071 01072 /* not doing NLTM2 without a password */ 01073 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; 01074 } else if (ntlmssp_state->use_ntlmv2) { 01075 01076 if (!struct_blob.length) { 01077 /* be lazy, match win2k - we can't do NTLMv2 without it */ 01078 DEBUG(1, ("Server did not provide 'target information', required for NTLMv2\n")); 01079 return NT_STATUS_INVALID_PARAMETER; 01080 } 01081 01082 /* TODO: if the remote server is standalone, then we should replace 'domain' 01083 with the server name as supplied above */ 01084 01085 if (!SMBNTLMv2encrypt_hash(ntlmssp_state->user, 01086 ntlmssp_state->domain, 01087 ntlmssp_state->nt_hash, &challenge_blob, 01088 &struct_blob, 01089 &lm_response, &nt_response, &session_key)) { 01090 data_blob_free(&challenge_blob); 01091 data_blob_free(&struct_blob); 01092 return NT_STATUS_NO_MEMORY; 01093 } 01094 } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { 01095 struct MD5Context md5_session_nonce_ctx; 01096 uchar session_nonce[16]; 01097 uchar session_nonce_hash[16]; 01098 uchar user_session_key[16]; 01099 01100 lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); 01101 generate_random_buffer(lm_response.data, 8); 01102 memset(lm_response.data+8, 0, 16); 01103 01104 memcpy(session_nonce, challenge_blob.data, 8); 01105 memcpy(&session_nonce[8], lm_response.data, 8); 01106 01107 MD5Init(&md5_session_nonce_ctx); 01108 MD5Update(&md5_session_nonce_ctx, challenge_blob.data, 8); 01109 MD5Update(&md5_session_nonce_ctx, lm_response.data, 8); 01110 MD5Final(session_nonce_hash, &md5_session_nonce_ctx); 01111 01112 DEBUG(5, ("NTLMSSP challenge set by NTLM2\n")); 01113 DEBUG(5, ("challenge is: \n")); 01114 dump_data(5, (const char *)session_nonce_hash, 8); 01115 01116 nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); 01117 SMBNTencrypt_hash(ntlmssp_state->nt_hash, 01118 session_nonce_hash, 01119 nt_response.data); 01120 01121 session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); 01122 01123 SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, NULL, user_session_key); 01124 hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data); 01125 dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); 01126 } else { 01127 /* lanman auth is insecure, it may be disabled */ 01128 if (lp_client_lanman_auth()) { 01129 lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); 01130 SMBencrypt_hash(ntlmssp_state->lm_hash,challenge_blob.data, 01131 lm_response.data); 01132 } 01133 01134 nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); 01135 SMBNTencrypt_hash(ntlmssp_state->nt_hash,challenge_blob.data, 01136 nt_response.data); 01137 01138 session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); 01139 if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 01140 && lp_client_lanman_auth()) { 01141 SMBsesskeygen_lm_sess_key(ntlmssp_state->lm_hash, lm_response.data, 01142 session_key.data); 01143 dump_data_pw("LM session key\n", session_key.data, session_key.length); 01144 } else { 01145 SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, NULL, session_key.data); 01146 dump_data_pw("NT session key:\n", session_key.data, session_key.length); 01147 } 01148 } 01149 data_blob_free(&struct_blob); 01150 01151 /* Key exchange encryptes a new client-generated session key with 01152 the password-derived key */ 01153 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { 01154 /* Make up a new session key */ 01155 uint8 client_session_key[16]; 01156 generate_random_buffer(client_session_key, sizeof(client_session_key)); 01157 01158 /* Encrypt the new session key with the old one */ 01159 encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key)); 01160 dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length); 01161 SamOEMhash(encrypted_session_key.data, session_key.data, encrypted_session_key.length); 01162 dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length); 01163 01164 /* Mark the new session key as the 'real' session key */ 01165 data_blob_free(&session_key); 01166 session_key = data_blob_talloc(ntlmssp_state->mem_ctx, client_session_key, sizeof(client_session_key)); 01167 } 01168 01169 /* this generates the actual auth packet */ 01170 if (!msrpc_gen(next_request, auth_gen_string, 01171 "NTLMSSP", 01172 NTLMSSP_AUTH, 01173 lm_response.data, lm_response.length, 01174 nt_response.data, nt_response.length, 01175 ntlmssp_state->domain, 01176 ntlmssp_state->user, 01177 ntlmssp_state->get_global_myname(), 01178 encrypted_session_key.data, encrypted_session_key.length, 01179 ntlmssp_state->neg_flags)) { 01180 01181 return NT_STATUS_NO_MEMORY; 01182 } 01183 01184 data_blob_free(&encrypted_session_key); 01185 01186 data_blob_free(&ntlmssp_state->chal); 01187 01188 ntlmssp_state->session_key = session_key; 01189 01190 ntlmssp_state->chal = challenge_blob; 01191 ntlmssp_state->lm_resp = lm_response; 01192 ntlmssp_state->nt_resp = nt_response; 01193 01194 ntlmssp_state->expected_state = NTLMSSP_DONE; 01195 01196 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_sign_init(ntlmssp_state))) { 01197 DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n", nt_errstr(nt_status))); 01198 } 01199 01200 return nt_status; 01201 }
static NTSTATUS ntlmssp_server_auth | ( | struct ntlmssp_state * | ntlmssp_state, | |
const DATA_BLOB | request, | |||
DATA_BLOB * | reply | |||
) | [static] |
Next state function for the Authenticate packet
ntlmssp_state | NTLMSSP State | |
request | The request, as a DATA_BLOB | |
request | The reply, as an allocated DATA_BLOB, caller to free. |
参照先 data_blob_::data・data_blob()・data_blob_free()・data_blob_talloc()・ntlmssp_state::domain・dump_data()・dump_data_pw()・file_save()・hmac_md5()・data_blob_::length・ntlmssp_state::lm_resp・MD5Final()・MD5Init()・MD5Update()・msrpc_parse()・ntlmssp_state::nt_resp・NTLMSSP_DONE・ntlmssp_handle_neg_flags()・ntlmssp_set_domain()・ntlmssp_set_username()・ntlmssp_set_workstation()・ntlmssp_sign_init()・SamOEMhash()・ntlmssp_state::session_key・SMBsesskeygen_lm_sess_key()・ntlmssp_state::unicode・ntlmssp_state::user・ntlmssp_state::workstation.
00625 { 00626 DATA_BLOB encrypted_session_key = data_blob(NULL, 0); 00627 DATA_BLOB user_session_key = data_blob(NULL, 0); 00628 DATA_BLOB lm_session_key = data_blob(NULL, 0); 00629 DATA_BLOB session_key = data_blob(NULL, 0); 00630 uint32 ntlmssp_command, auth_flags; 00631 NTSTATUS nt_status = NT_STATUS_OK; 00632 00633 /* used by NTLM2 */ 00634 BOOL doing_ntlm2 = False; 00635 00636 uchar session_nonce[16]; 00637 uchar session_nonce_hash[16]; 00638 00639 const char *parse_string; 00640 char *domain = NULL; 00641 char *user = NULL; 00642 char *workstation = NULL; 00643 00644 /* parse the NTLMSSP packet */ 00645 *reply = data_blob(NULL, 0); 00646 00647 #if 0 00648 file_save("ntlmssp_auth.dat", request.data, request.length); 00649 #endif 00650 00651 if (ntlmssp_state->unicode) { 00652 parse_string = "CdBBUUUBd"; 00653 } else { 00654 parse_string = "CdBBAAABd"; 00655 } 00656 00657 data_blob_free(&ntlmssp_state->lm_resp); 00658 data_blob_free(&ntlmssp_state->nt_resp); 00659 00660 ntlmssp_state->user = NULL; 00661 ntlmssp_state->domain = NULL; 00662 ntlmssp_state->workstation = NULL; 00663 00664 /* now the NTLMSSP encoded auth hashes */ 00665 if (!msrpc_parse(&request, parse_string, 00666 "NTLMSSP", 00667 &ntlmssp_command, 00668 &ntlmssp_state->lm_resp, 00669 &ntlmssp_state->nt_resp, 00670 &domain, 00671 &user, 00672 &workstation, 00673 &encrypted_session_key, 00674 &auth_flags)) { 00675 SAFE_FREE(domain); 00676 SAFE_FREE(user); 00677 SAFE_FREE(workstation); 00678 data_blob_free(&encrypted_session_key); 00679 auth_flags = 0; 00680 00681 /* Try again with a shorter string (Win9X truncates this packet) */ 00682 if (ntlmssp_state->unicode) { 00683 parse_string = "CdBBUUU"; 00684 } else { 00685 parse_string = "CdBBAAA"; 00686 } 00687 00688 /* now the NTLMSSP encoded auth hashes */ 00689 if (!msrpc_parse(&request, parse_string, 00690 "NTLMSSP", 00691 &ntlmssp_command, 00692 &ntlmssp_state->lm_resp, 00693 &ntlmssp_state->nt_resp, 00694 &domain, 00695 &user, 00696 &workstation)) { 00697 DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n")); 00698 dump_data(2, (const char *)request.data, request.length); 00699 SAFE_FREE(domain); 00700 SAFE_FREE(user); 00701 SAFE_FREE(workstation); 00702 00703 return NT_STATUS_INVALID_PARAMETER; 00704 } 00705 } 00706 00707 if (auth_flags) 00708 ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, lp_lanman_auth()); 00709 00710 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) { 00711 SAFE_FREE(domain); 00712 SAFE_FREE(user); 00713 SAFE_FREE(workstation); 00714 data_blob_free(&encrypted_session_key); 00715 return nt_status; 00716 } 00717 00718 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) { 00719 SAFE_FREE(domain); 00720 SAFE_FREE(user); 00721 SAFE_FREE(workstation); 00722 data_blob_free(&encrypted_session_key); 00723 return nt_status; 00724 } 00725 00726 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_workstation(ntlmssp_state, workstation))) { 00727 SAFE_FREE(domain); 00728 SAFE_FREE(user); 00729 SAFE_FREE(workstation); 00730 data_blob_free(&encrypted_session_key); 00731 return nt_status; 00732 } 00733 00734 SAFE_FREE(domain); 00735 SAFE_FREE(user); 00736 SAFE_FREE(workstation); 00737 00738 DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n", 00739 ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, (unsigned long)ntlmssp_state->lm_resp.length, (unsigned long)ntlmssp_state->nt_resp.length)); 00740 00741 #if 0 00742 file_save("nthash1.dat", &ntlmssp_state->nt_resp.data, &ntlmssp_state->nt_resp.length); 00743 file_save("lmhash1.dat", &ntlmssp_state->lm_resp.data, &ntlmssp_state->lm_resp.length); 00744 #endif 00745 00746 /* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a 00747 client challenge 00748 00749 However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful. 00750 */ 00751 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { 00752 if (ntlmssp_state->nt_resp.length == 24 && ntlmssp_state->lm_resp.length == 24) { 00753 struct MD5Context md5_session_nonce_ctx; 00754 SMB_ASSERT(ntlmssp_state->internal_chal.data && ntlmssp_state->internal_chal.length == 8); 00755 00756 doing_ntlm2 = True; 00757 00758 memcpy(session_nonce, ntlmssp_state->internal_chal.data, 8); 00759 memcpy(&session_nonce[8], ntlmssp_state->lm_resp.data, 8); 00760 00761 MD5Init(&md5_session_nonce_ctx); 00762 MD5Update(&md5_session_nonce_ctx, session_nonce, 16); 00763 MD5Final(session_nonce_hash, &md5_session_nonce_ctx); 00764 00765 ntlmssp_state->chal = data_blob_talloc(ntlmssp_state->mem_ctx, session_nonce_hash, 8); 00766 00767 /* LM response is no longer useful */ 00768 data_blob_free(&ntlmssp_state->lm_resp); 00769 00770 /* We changed the effective challenge - set it */ 00771 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->set_challenge(ntlmssp_state, &ntlmssp_state->chal))) { 00772 data_blob_free(&encrypted_session_key); 00773 return nt_status; 00774 } 00775 00776 /* LM Key is incompatible. */ 00777 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; 00778 } 00779 } 00780 00781 /* 00782 * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth 00783 * is required (by "ntlm auth = no" and "lm auth = no" being set in the 00784 * smb.conf file) and no NTLMv2 response was sent then the password check 00785 * will fail here. JRA. 00786 */ 00787 00788 /* Finally, actually ask if the password is OK */ 00789 00790 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, 00791 &user_session_key, &lm_session_key))) { 00792 data_blob_free(&encrypted_session_key); 00793 return nt_status; 00794 } 00795 00796 dump_data_pw("NT session key:\n", user_session_key.data, user_session_key.length); 00797 dump_data_pw("LM first-8:\n", lm_session_key.data, lm_session_key.length); 00798 00799 /* Handle the different session key derivation for NTLM2 */ 00800 if (doing_ntlm2) { 00801 if (user_session_key.data && user_session_key.length == 16) { 00802 session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); 00803 hmac_md5(user_session_key.data, session_nonce, 00804 sizeof(session_nonce), session_key.data); 00805 DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n")); 00806 dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); 00807 00808 } else { 00809 DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n")); 00810 session_key = data_blob(NULL, 0); 00811 } 00812 } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { 00813 if (lm_session_key.data && lm_session_key.length >= 8) { 00814 if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) { 00815 session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); 00816 if (session_key.data == NULL) { 00817 return NT_STATUS_NO_MEMORY; 00818 } 00819 SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data, 00820 session_key.data); 00821 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n")); 00822 } else { 00823 static const uint8 zeros[24] = { 0, }; 00824 session_key = data_blob_talloc( 00825 ntlmssp_state->mem_ctx, NULL, 16); 00826 if (session_key.data == NULL) { 00827 return NT_STATUS_NO_MEMORY; 00828 } 00829 SMBsesskeygen_lm_sess_key( 00830 lm_session_key.data, zeros, 00831 session_key.data); 00832 } 00833 dump_data_pw("LM session key:\n", session_key.data, 00834 session_key.length); 00835 } else { 00836 DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n")); 00837 session_key = data_blob(NULL, 0); 00838 } 00839 } else if (user_session_key.data) { 00840 session_key = user_session_key; 00841 DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n")); 00842 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length); 00843 } else if (lm_session_key.data) { 00844 session_key = lm_session_key; 00845 DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n")); 00846 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length); 00847 } else { 00848 DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n")); 00849 session_key = data_blob(NULL, 0); 00850 } 00851 00852 /* With KEY_EXCH, the client supplies the proposed session key, 00853 but encrypts it with the long-term key */ 00854 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { 00855 if (!encrypted_session_key.data || encrypted_session_key.length != 16) { 00856 data_blob_free(&encrypted_session_key); 00857 DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n", 00858 (unsigned int)encrypted_session_key.length)); 00859 return NT_STATUS_INVALID_PARAMETER; 00860 } else if (!session_key.data || session_key.length != 16) { 00861 DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n", 00862 (unsigned int)session_key.length)); 00863 ntlmssp_state->session_key = session_key; 00864 } else { 00865 dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length); 00866 SamOEMhash(encrypted_session_key.data, 00867 session_key.data, 00868 encrypted_session_key.length); 00869 ntlmssp_state->session_key = data_blob_talloc(ntlmssp_state->mem_ctx, 00870 encrypted_session_key.data, 00871 encrypted_session_key.length); 00872 dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, 00873 encrypted_session_key.length); 00874 } 00875 } else { 00876 ntlmssp_state->session_key = session_key; 00877 } 00878 00879 if (!NT_STATUS_IS_OK(nt_status)) { 00880 ntlmssp_state->session_key = data_blob(NULL, 0); 00881 } else if (ntlmssp_state->session_key.length) { 00882 nt_status = ntlmssp_sign_init(ntlmssp_state); 00883 } 00884 00885 data_blob_free(&encrypted_session_key); 00886 00887 /* Only one authentication allowed per server state. */ 00888 ntlmssp_state->expected_state = NTLMSSP_DONE; 00889 00890 return nt_status; 00891 }
void debug_ntlmssp_flags | ( | uint32 | neg_flags | ) |
Print out the NTLMSSP flags for debugging
neg_flags | The flags from the packet |
参照元 ntlmssp_client_challenge()・ntlmssp_server_negotiate()・ntlmssp_sign_init().
00062 { 00063 DEBUG(3,("Got NTLMSSP neg_flags=0x%08x\n", neg_flags)); 00064 00065 if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) 00066 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_UNICODE\n")); 00067 if (neg_flags & NTLMSSP_NEGOTIATE_OEM) 00068 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_OEM\n")); 00069 if (neg_flags & NTLMSSP_REQUEST_TARGET) 00070 DEBUGADD(4, (" NTLMSSP_REQUEST_TARGET\n")); 00071 if (neg_flags & NTLMSSP_NEGOTIATE_SIGN) 00072 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_SIGN\n")); 00073 if (neg_flags & NTLMSSP_NEGOTIATE_SEAL) 00074 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_SEAL\n")); 00075 if (neg_flags & NTLMSSP_NEGOTIATE_DATAGRAM_STYLE) 00076 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_DATAGRAM_STYLE\n")); 00077 if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 00078 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_LM_KEY\n")); 00079 if (neg_flags & NTLMSSP_NEGOTIATE_NETWARE) 00080 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NETWARE\n")); 00081 if (neg_flags & NTLMSSP_NEGOTIATE_NTLM) 00082 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NTLM\n")); 00083 if (neg_flags & NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED) 00084 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED\n")); 00085 if (neg_flags & NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED) 00086 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED\n")); 00087 if (neg_flags & NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL) 00088 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n")); 00089 if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) 00090 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n")); 00091 if (neg_flags & NTLMSSP_CHAL_ACCEPT_RESPONSE) 00092 DEBUGADD(4, (" NTLMSSP_CHAL_ACCEPT_RESPONSE\n")); 00093 if (neg_flags & NTLMSSP_CHAL_NON_NT_SESSION_KEY) 00094 DEBUGADD(4, (" NTLMSSP_CHAL_NON_NT_SESSION_KEY\n")); 00095 if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2) 00096 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NTLM2\n")); 00097 if (neg_flags & NTLMSSP_CHAL_TARGET_INFO) 00098 DEBUGADD(4, (" NTLMSSP_CHAL_TARGET_INFO\n")); 00099 if (neg_flags & NTLMSSP_NEGOTIATE_128) 00100 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_128\n")); 00101 if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) 00102 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_KEY_EXCH\n")); 00103 if (neg_flags & NTLMSSP_NEGOTIATE_56) 00104 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_56\n")); 00105 }
static const uint8* get_challenge | ( | const struct ntlmssp_state * | ntlmssp_state | ) | [static] |
Default challenge generation code.
参照先 ntlmssp_state::chal・generate_random_buffer().
参照元 ntlmssp_server_start()・reply_lanman1()・reply_lanman2()・reply_nt1()・test_lm_ntlm_broken()・test_lmv2_ntlmv2_broken()・test_ntlm_in_both()・test_ntlm_in_lm().
00113 { 00114 static uchar chal[8]; 00115 generate_random_buffer(chal, sizeof(chal)); 00116 00117 return chal; 00118 }
static BOOL may_set_challenge | ( | const struct ntlmssp_state * | ntlmssp_state | ) | [static] |
Default 'we can set the challenge to anything we like' implementation
static NTSTATUS set_challenge | ( | struct ntlmssp_state * | ntlmssp_state, | |
DATA_BLOB * | challenge | |||
) | [static] |
Default 'we can set the challenge to anything we like' implementation
Does not actually do anything, as the value is always in the structure anyway.
参照先 data_blob_::length.
00138 { 00139 SMB_ASSERT(challenge->length == 8); 00140 return NT_STATUS_OK; 00141 }
NTSTATUS ntlmssp_set_username | ( | NTLMSSP_STATE * | ntlmssp_state, | |
const char * | user | |||
) |
Set a username on an NTLMSSP context - ensures it is talloc()ed
参照先 ntlmssp_state::mem_ctx・talloc_strdup()・ntlmssp_state::user.
参照元 ads_sasl_spnego_ntlmssp_bind()・cli_rpc_pipe_open_ntlmssp_internal()・cli_session_setup_ntlmssp()・do_ntlm_auth_with_hashes()・ntlm_auth_start_ntlmssp_client()・ntlmssp_server_auth().
00149 { 00150 ntlmssp_state->user = talloc_strdup(ntlmssp_state->mem_ctx, user ? user : "" ); 00151 if (!ntlmssp_state->user) { 00152 return NT_STATUS_NO_MEMORY; 00153 } 00154 return NT_STATUS_OK; 00155 }
NTSTATUS ntlmssp_set_hashes | ( | NTLMSSP_STATE * | ntlmssp_state, | |
const unsigned char | lm_hash[16], | |||
const unsigned char | nt_hash[16] | |||
) |
Store NT and LM hashes on an NTLMSSP context - ensures they are talloc()ed
参照先 ntlmssp_state::lm_hash・ntlmssp_state::mem_ctx・ntlmssp_state::nt_hash.
参照元 do_ntlm_auth_with_hashes()・ntlmssp_set_password().
00164 { 00165 ntlmssp_state->lm_hash = (unsigned char *) 00166 TALLOC_MEMDUP(ntlmssp_state->mem_ctx, lm_hash, 16); 00167 ntlmssp_state->nt_hash = (unsigned char *) 00168 TALLOC_MEMDUP(ntlmssp_state->mem_ctx, nt_hash, 16); 00169 if (!ntlmssp_state->lm_hash || !ntlmssp_state->nt_hash) { 00170 TALLOC_FREE(ntlmssp_state->lm_hash); 00171 TALLOC_FREE(ntlmssp_state->nt_hash); 00172 return NT_STATUS_NO_MEMORY; 00173 } 00174 return NT_STATUS_OK; 00175 }
NTSTATUS ntlmssp_set_password | ( | NTLMSSP_STATE * | ntlmssp_state, | |
const char * | password | |||
) |
Converts a password to the hashes on an NTLMSSP context.
参照先 E_deshash()・E_md4hash()・ntlmssp_state::lm_hash・ntlmssp_state::nt_hash・ntlmssp_set_hashes().
参照元 ads_sasl_spnego_ntlmssp_bind()・cli_rpc_pipe_open_ntlmssp_internal()・cli_session_setup_ntlmssp()・ntlm_auth_start_ntlmssp_client().
00182 { 00183 if (!password) { 00184 ntlmssp_state->lm_hash = NULL; 00185 ntlmssp_state->nt_hash = NULL; 00186 } else { 00187 unsigned char lm_hash[16]; 00188 unsigned char nt_hash[16]; 00189 00190 E_deshash(password, lm_hash); 00191 E_md4hash(password, nt_hash); 00192 return ntlmssp_set_hashes(ntlmssp_state, lm_hash, nt_hash); 00193 } 00194 return NT_STATUS_OK; 00195 }
NTSTATUS ntlmssp_set_domain | ( | NTLMSSP_STATE * | ntlmssp_state, | |
const char * | domain | |||
) |
Set a domain on an NTLMSSP context - ensures it is talloc()ed
参照先 ntlmssp_state::domain・ntlmssp_state::mem_ctx・talloc_strdup().
参照元 ads_sasl_spnego_ntlmssp_bind()・cli_rpc_pipe_open_ntlmssp_internal()・cli_session_setup_ntlmssp()・do_ntlm_auth_with_hashes()・ntlm_auth_start_ntlmssp_client()・ntlmssp_server_auth().
00202 { 00203 ntlmssp_state->domain = talloc_strdup(ntlmssp_state->mem_ctx, domain ? domain : "" ); 00204 if (!ntlmssp_state->domain) { 00205 return NT_STATUS_NO_MEMORY; 00206 } 00207 return NT_STATUS_OK; 00208 }
NTSTATUS ntlmssp_set_workstation | ( | NTLMSSP_STATE * | ntlmssp_state, | |
const char * | workstation | |||
) |
Set a workstation on an NTLMSSP context - ensures it is talloc()ed
参照先 ntlmssp_state::mem_ctx・talloc_strdup()・ntlmssp_state::workstation.
00215 { 00216 ntlmssp_state->workstation = talloc_strdup(ntlmssp_state->mem_ctx, workstation); 00217 if (!ntlmssp_state->workstation) { 00218 return NT_STATUS_NO_MEMORY; 00219 } 00220 return NT_STATUS_OK; 00221 }
NTSTATUS ntlmssp_store_response | ( | NTLMSSP_STATE * | ntlmssp_state, | |
DATA_BLOB | response | |||
) |
Store a DATA_BLOB containing an NTLMSSP response, for use later.
This copies the data blob
参照先 data_blob_::data・data_blob_talloc()・data_blob_::length・ntlmssp_state::mem_ctx・ntlmssp_state::stored_response.
00230 { 00231 ntlmssp_state->stored_response = data_blob_talloc(ntlmssp_state->mem_ctx, 00232 response.data, response.length); 00233 return NT_STATUS_OK; 00234 }
void ntlmssp_want_feature_list | ( | NTLMSSP_STATE * | ntlmssp_state, | |
char * | feature_list | |||
) |
Request features for the NTLMSSP negotiation
ntlmssp_state | NTLMSSP state | |
feature_list | List of space seperated features requested from NTLMSSP. |
参照先 in_list()・ntlmssp_state::neg_flags.
参照元 manage_client_ntlmssp_request()・manage_squid_ntlmssp_request().
00243 { 00244 /* 00245 * We need to set this to allow a later SetPassword 00246 * via the SAMR pipe to succeed. Strange.... We could 00247 * also add NTLMSSP_NEGOTIATE_SEAL here. JRA. 00248 */ 00249 if (in_list("NTLMSSP_FEATURE_SESSION_KEY", feature_list, True)) { 00250 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; 00251 } 00252 if (in_list("NTLMSSP_FEATURE_SIGN", feature_list, True)) { 00253 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; 00254 } 00255 if(in_list("NTLMSSP_FEATURE_SEAL", feature_list, True)) { 00256 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; 00257 } 00258 }
void ntlmssp_want_feature | ( | NTLMSSP_STATE * | ntlmssp_state, | |
uint32 | feature | |||
) |
Request a feature for the NTLMSSP negotiation
ntlmssp_state | NTLMSSP state | |
feature | Bit flag specifying the requested feature |
参照元 cli_session_setup_ntlmssp().
00267 { 00268 /* As per JRA's comment above */ 00269 if (feature & NTLMSSP_FEATURE_SESSION_KEY) { 00270 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; 00271 } 00272 if (feature & NTLMSSP_FEATURE_SIGN) { 00273 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; 00274 } 00275 if (feature & NTLMSSP_FEATURE_SEAL) { 00276 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; 00277 } 00278 }
NTSTATUS ntlmssp_update | ( | NTLMSSP_STATE * | ntlmssp_state, | |
const DATA_BLOB | in, | |||
DATA_BLOB * | out | |||
) |
Next state function for the NTLMSSP state machine
ntlmssp_state | NTLMSSP State | |
in | The packet in from the NTLMSSP partner, as a DATA_BLOB | |
out | The reply, as an allocated DATA_BLOB, caller to free. |
参照先 data_blob_::data・data_blob()・dump_data()・ntlmssp_state::expected_state・data_blob_::length・msrpc_parse()・NTLMSSP_CLIENT・NTLMSSP_DONE・NTLMSSP_INITIAL・NTLMSSP_NEGOTIATE・NTLMSSP_SERVER・ntlmssp_state::role・ntlmssp_state::stored_response.
参照元 ads_sasl_spnego_ntlmssp_bind()・auth_ntlmssp_update()・cli_session_setup_ntlmssp()・create_ntlmssp_auth_rpc_bind_req()・create_spnego_ntlmssp_auth_rpc_bind_req()・do_ntlm_auth_with_hashes()・manage_client_ntlmssp_init()・manage_client_ntlmssp_request()・manage_client_ntlmssp_targ()・manage_gss_spnego_request()・manage_squid_ntlmssp_request()・rpc_finish_auth3_bind()・rpc_finish_spnego_ntlmssp_bind().
00291 { 00292 DATA_BLOB input; 00293 uint32 ntlmssp_command; 00294 int i; 00295 00296 if (ntlmssp_state->expected_state == NTLMSSP_DONE) { 00297 /* Called update after negotiations finished. */ 00298 DEBUG(1, ("Called NTLMSSP after state machine was 'done'\n")); 00299 return NT_STATUS_INVALID_PARAMETER; 00300 } 00301 00302 *out = data_blob(NULL, 0); 00303 00304 if (!in.length && ntlmssp_state->stored_response.length) { 00305 input = ntlmssp_state->stored_response; 00306 00307 /* we only want to read the stored response once - overwrite it */ 00308 ntlmssp_state->stored_response = data_blob(NULL, 0); 00309 } else { 00310 input = in; 00311 } 00312 00313 if (!input.length) { 00314 switch (ntlmssp_state->role) { 00315 case NTLMSSP_CLIENT: 00316 ntlmssp_command = NTLMSSP_INITIAL; 00317 break; 00318 case NTLMSSP_SERVER: 00319 /* 'datagram' mode - no neg packet */ 00320 ntlmssp_command = NTLMSSP_NEGOTIATE; 00321 break; 00322 } 00323 } else { 00324 if (!msrpc_parse(&input, "Cd", 00325 "NTLMSSP", 00326 &ntlmssp_command)) { 00327 DEBUG(1, ("Failed to parse NTLMSSP packet, could not extract NTLMSSP command\n")); 00328 dump_data(2, (const char *)input.data, input.length); 00329 return NT_STATUS_INVALID_PARAMETER; 00330 } 00331 } 00332 00333 if (ntlmssp_command != ntlmssp_state->expected_state) { 00334 DEBUG(1, ("got NTLMSSP command %u, expected %u\n", ntlmssp_command, ntlmssp_state->expected_state)); 00335 return NT_STATUS_INVALID_PARAMETER; 00336 } 00337 00338 for (i=0; ntlmssp_callbacks[i].fn; i++) { 00339 if (ntlmssp_callbacks[i].role == ntlmssp_state->role 00340 && ntlmssp_callbacks[i].ntlmssp_command == ntlmssp_command) { 00341 return ntlmssp_callbacks[i].fn(ntlmssp_state, input, out); 00342 } 00343 } 00344 00345 DEBUG(1, ("failed to find NTLMSSP callback for NTLMSSP mode %u, command %u\n", 00346 ntlmssp_state->role, ntlmssp_command)); 00347 00348 return NT_STATUS_INVALID_PARAMETER; 00349 }
void ntlmssp_end | ( | NTLMSSP_STATE ** | ntlmssp_state | ) |
End an NTLMSSP state machine
ntlmssp_state | NTLMSSP State, free()ed by this function |
参照先 data_blob_free()・ntlmssp_state::mem_ctx.
参照元 ads_sasl_spnego_ntlmssp_bind()・auth_ntlmssp_end()・cli_ntlmssp_auth_free()・cli_session_setup_ntlmssp()・do_ntlm_auth_with_hashes()・manage_client_ntlmssp_init()・manage_client_ntlmssp_request()・manage_client_ntlmssp_targ()・manage_gss_spnego_client_request()・manage_gss_spnego_request()・manage_squid_ntlmssp_request()・ntlm_auth_start_ntlmssp_client().
00358 { 00359 TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx; 00360 00361 (*ntlmssp_state)->ref_count--; 00362 00363 if ((*ntlmssp_state)->ref_count == 0) { 00364 data_blob_free(&(*ntlmssp_state)->chal); 00365 data_blob_free(&(*ntlmssp_state)->lm_resp); 00366 data_blob_free(&(*ntlmssp_state)->nt_resp); 00367 00368 talloc_destroy(mem_ctx); 00369 } 00370 00371 *ntlmssp_state = NULL; 00372 return; 00373 }
static const char* ntlmssp_target_name | ( | struct ntlmssp_state * | ntlmssp_state, | |
uint32 | neg_flags, | |||
uint32 * | chal_flags | |||
) | [static] |
Determine correct target name flags for reply, given server role and negotiated flags
ntlmssp_state | NTLMSSP State | |
neg_flags | The flags from the packet | |
chal_flags | The flags to be set in the reply packet |
参照先 ntlmssp_state::get_domain・ntlmssp_state::get_global_myname・ROLE_STANDALONE・ntlmssp_state::server_role.
参照元 ntlmssp_server_negotiate().
00387 { 00388 if (neg_flags & NTLMSSP_REQUEST_TARGET) { 00389 *chal_flags |= NTLMSSP_CHAL_TARGET_INFO; 00390 *chal_flags |= NTLMSSP_REQUEST_TARGET; 00391 if (ntlmssp_state->server_role == ROLE_STANDALONE) { 00392 *chal_flags |= NTLMSSP_TARGET_TYPE_SERVER; 00393 return ntlmssp_state->get_global_myname(); 00394 } else { 00395 *chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN; 00396 return ntlmssp_state->get_domain(); 00397 }; 00398 } else { 00399 return ""; 00400 } 00401 }
static void ntlmssp_handle_neg_flags | ( | struct ntlmssp_state * | ntlmssp_state, | |
uint32 | neg_flags, | |||
BOOL | allow_lm | |||
) | [static] |
参照先 ntlmssp_state::neg_flags・ntlmssp_state::unicode・ntlmssp_state::use_ntlmv2.
参照元 ntlmssp_client_challenge()・ntlmssp_server_auth()・ntlmssp_server_negotiate().
00404 { 00405 if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) { 00406 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; 00407 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_OEM; 00408 ntlmssp_state->unicode = True; 00409 } else { 00410 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE; 00411 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM; 00412 ntlmssp_state->unicode = False; 00413 } 00414 00415 if ((neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) && allow_lm) { 00416 /* other end forcing us to use LM */ 00417 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY; 00418 ntlmssp_state->use_ntlmv2 = False; 00419 } else { 00420 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; 00421 } 00422 00423 if (!(neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) { 00424 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_ALWAYS_SIGN; 00425 } 00426 00427 if (!(neg_flags & NTLMSSP_NEGOTIATE_NTLM2)) { 00428 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; 00429 } 00430 00431 if (!(neg_flags & NTLMSSP_NEGOTIATE_128)) { 00432 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128; 00433 } 00434 00435 if (!(neg_flags & NTLMSSP_NEGOTIATE_56)) { 00436 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_56; 00437 } 00438 00439 if (!(neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) { 00440 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH; 00441 } 00442 00443 if (!(neg_flags & NTLMSSP_NEGOTIATE_SIGN)) { 00444 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN; 00445 } 00446 00447 if (!(neg_flags & NTLMSSP_NEGOTIATE_SEAL)) { 00448 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SEAL; 00449 } 00450 00451 /* Woop Woop - unknown flag for Windows compatibility... 00452 What does this really do ? JRA. */ 00453 if (!(neg_flags & NTLMSSP_UNKNOWN_02000000)) { 00454 ntlmssp_state->neg_flags &= ~NTLMSSP_UNKNOWN_02000000; 00455 } 00456 00457 if ((neg_flags & NTLMSSP_REQUEST_TARGET)) { 00458 ntlmssp_state->neg_flags |= NTLMSSP_REQUEST_TARGET; 00459 } 00460 }
DATA_BLOB ntlmssp_weaken_keys | ( | NTLMSSP_STATE * | ntlmssp_state, | |
TALLOC_CTX * | mem_ctx | |||
) |
Weaken NTLMSSP keys to cope with down-level clients and servers.
We probably should have some parameters to control this, but as it only occours for LM_KEY connections, and this is controlled by the client lanman auth/lanman auth parameters, it isn't too bad.
参照先 data_blob_::data・data_blob_talloc()・data_blob_::length・ntlmssp_state::neg_flags・ntlmssp_state::session_key.
参照元 ntlmssp_sign_init().
00471 { 00472 DATA_BLOB weakened_key = data_blob_talloc(mem_ctx, 00473 ntlmssp_state->session_key.data, 00474 ntlmssp_state->session_key.length); 00475 00476 /* Nothing to weaken. We certainly don't want to 'extend' the length... */ 00477 if (weakened_key.length < 16) { 00478 /* perhaps there was no key? */ 00479 return weakened_key; 00480 } 00481 00482 /* Key weakening not performed on the master key for NTLM2 00483 and does not occour for NTLM1. Therefore we only need 00484 to do this for the LM_KEY. 00485 */ 00486 00487 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { 00488 /* LM key doesn't support 128 bit crypto, so this is 00489 * the best we can do. If you negotiate 128 bit, but 00490 * not 56, you end up with 40 bit... */ 00491 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) { 00492 weakened_key.data[7] = 0xa0; 00493 } else { /* forty bits */ 00494 weakened_key.data[5] = 0xe5; 00495 weakened_key.data[6] = 0x38; 00496 weakened_key.data[7] = 0xb0; 00497 } 00498 weakened_key.length = 8; 00499 } 00500 return weakened_key; 00501 }
NTSTATUS ntlmssp_server_start | ( | NTLMSSP_STATE ** | ntlmssp_state | ) |
Create an NTLMSSP state machine
ntlmssp_state | NTLMSSP State, allocated by this function |
参照先 get_challenge()・global_myname・lp_workgroup()・may_set_challenge()・NTLMSSP_NEGOTIATE・NTLMSSP_SERVER・ROLE_DOMAIN_MEMBER・set_challenge()・talloc_init().
参照元 auth_ntlmssp_start()・ntlm_auth_start_ntlmssp_server().
00900 { 00901 TALLOC_CTX *mem_ctx; 00902 00903 mem_ctx = talloc_init("NTLMSSP context"); 00904 00905 *ntlmssp_state = TALLOC_ZERO_P(mem_ctx, NTLMSSP_STATE); 00906 if (!*ntlmssp_state) { 00907 DEBUG(0,("ntlmssp_server_start: talloc failed!\n")); 00908 talloc_destroy(mem_ctx); 00909 return NT_STATUS_NO_MEMORY; 00910 } 00911 00912 (*ntlmssp_state)->role = NTLMSSP_SERVER; 00913 00914 (*ntlmssp_state)->mem_ctx = mem_ctx; 00915 (*ntlmssp_state)->get_challenge = get_challenge; 00916 (*ntlmssp_state)->set_challenge = set_challenge; 00917 (*ntlmssp_state)->may_set_challenge = may_set_challenge; 00918 00919 (*ntlmssp_state)->get_global_myname = global_myname; 00920 (*ntlmssp_state)->get_domain = lp_workgroup; 00921 (*ntlmssp_state)->server_role = ROLE_DOMAIN_MEMBER; /* a good default */ 00922 00923 (*ntlmssp_state)->expected_state = NTLMSSP_NEGOTIATE; 00924 00925 (*ntlmssp_state)->ref_count = 1; 00926 00927 (*ntlmssp_state)->neg_flags = 00928 NTLMSSP_NEGOTIATE_128 | 00929 NTLMSSP_NEGOTIATE_56 | 00930 NTLMSSP_UNKNOWN_02000000 | 00931 NTLMSSP_NEGOTIATE_ALWAYS_SIGN | 00932 NTLMSSP_NEGOTIATE_NTLM | 00933 NTLMSSP_NEGOTIATE_NTLM2 | 00934 NTLMSSP_NEGOTIATE_KEY_EXCH | 00935 NTLMSSP_NEGOTIATE_SIGN | 00936 NTLMSSP_NEGOTIATE_SEAL; 00937 00938 return NT_STATUS_OK; 00939 }
NTSTATUS ntlmssp_client_start | ( | NTLMSSP_STATE ** | ntlmssp_state | ) |
参照先 global_myname・lp_workgroup()・NTLMSSP_CLIENT・NTLMSSP_INITIAL・talloc_init().
参照元 ads_sasl_spnego_ntlmssp_bind()・cli_rpc_pipe_open_ntlmssp_internal()・cli_session_setup_ntlmssp()・do_ntlm_auth_with_hashes()・ntlm_auth_start_ntlmssp_client().
01204 { 01205 TALLOC_CTX *mem_ctx; 01206 01207 mem_ctx = talloc_init("NTLMSSP Client context"); 01208 01209 *ntlmssp_state = TALLOC_ZERO_P(mem_ctx, NTLMSSP_STATE); 01210 if (!*ntlmssp_state) { 01211 DEBUG(0,("ntlmssp_client_start: talloc failed!\n")); 01212 talloc_destroy(mem_ctx); 01213 return NT_STATUS_NO_MEMORY; 01214 } 01215 01216 (*ntlmssp_state)->role = NTLMSSP_CLIENT; 01217 01218 (*ntlmssp_state)->mem_ctx = mem_ctx; 01219 01220 (*ntlmssp_state)->get_global_myname = global_myname; 01221 (*ntlmssp_state)->get_domain = lp_workgroup; 01222 01223 (*ntlmssp_state)->unicode = True; 01224 01225 (*ntlmssp_state)->use_ntlmv2 = lp_client_ntlmv2_auth(); 01226 01227 (*ntlmssp_state)->expected_state = NTLMSSP_INITIAL; 01228 01229 (*ntlmssp_state)->ref_count = 1; 01230 01231 (*ntlmssp_state)->neg_flags = 01232 NTLMSSP_NEGOTIATE_128 | 01233 NTLMSSP_NEGOTIATE_ALWAYS_SIGN | 01234 NTLMSSP_NEGOTIATE_NTLM | 01235 NTLMSSP_NEGOTIATE_NTLM2 | 01236 NTLMSSP_NEGOTIATE_KEY_EXCH | 01237 NTLMSSP_REQUEST_TARGET; 01238 01239 return NT_STATUS_OK; 01240 }