diff options
author | Andrew Bartlett <abartlet@samba.org> | 2004-04-03 15:41:32 +0000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2004-04-03 15:41:32 +0000 |
commit | c2ff214772ac1934731938b3804d37e514e45c32 (patch) | |
tree | 6e7219577a7f1d2ad3e573bc220e07d99ec3708e /source3 | |
parent | c2699d25462e8684bded32adada78addf88b6df5 (diff) | |
download | samba-c2ff214772ac1934731938b3804d37e514e45c32.tar.gz samba-c2ff214772ac1934731938b3804d37e514e45c32.tar.bz2 samba-c2ff214772ac1934731938b3804d37e514e45c32.zip |
Fix most of bug #169.
For a (very) long time, we have had a bug in Samba were an NTLMv2-only
PDC would fail, because it converted the password into NTLM format for
checking.
This patch performs the direct comparison required for interactive
logons to function in this situation. It also removes the 'auth flags', which
simply where not ever used.
Natrually, this plays with the size of structures, so rebuild, rebuild
rebuild...
Andrew Bartlett
(This used to be commit 9598593bcf2d877b1d08cd6a7323ee0bc160d4ba)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/auth/auth_ntlmssp.c | 20 | ||||
-rw-r--r-- | source3/auth/auth_sam.c | 3 | ||||
-rw-r--r-- | source3/auth/auth_util.c | 167 | ||||
-rw-r--r-- | source3/include/auth.h | 24 | ||||
-rw-r--r-- | source3/libsmb/ntlm_check.c | 43 | ||||
-rw-r--r-- | source3/utils/ntlm_auth.c | 1 |
6 files changed, 136 insertions, 122 deletions
diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c index a5ce101e5e..498a7b1a39 100644 --- a/source3/auth/auth_ntlmssp.c +++ b/source3/auth/auth_ntlmssp.c @@ -78,21 +78,9 @@ static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *nt_session_key, DATA_BLOB *lm_session_key) { AUTH_NTLMSSP_STATE *auth_ntlmssp_state = ntlmssp_state->auth_context; - uint32 auth_flags = AUTH_FLAG_NONE; auth_usersupplied_info *user_info = NULL; - DATA_BLOB plaintext_password = data_blob(NULL, 0); NTSTATUS nt_status; - if (auth_ntlmssp_state->ntlmssp_state->lm_resp.length) { - auth_flags |= AUTH_FLAG_LM_RESP; - } - - if (auth_ntlmssp_state->ntlmssp_state->nt_resp.length == 24) { - auth_flags |= AUTH_FLAG_NTLM_RESP; - } else if (auth_ntlmssp_state->ntlmssp_state->nt_resp.length > 24) { - auth_flags |= AUTH_FLAG_NTLMv2_RESP; - } - /* the client has given us its machine name (which we otherwise would not get on port 445). we need to possibly reload smb.conf if smb.conf includes depend on the machine name */ @@ -108,10 +96,10 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, auth_ntlmssp_state->ntlmssp_state->user, auth_ntlmssp_state->ntlmssp_state->domain, auth_ntlmssp_state->ntlmssp_state->workstation, - auth_ntlmssp_state->ntlmssp_state->lm_resp, - auth_ntlmssp_state->ntlmssp_state->nt_resp, - plaintext_password, - auth_flags, True); + auth_ntlmssp_state->ntlmssp_state->lm_resp.data ? &auth_ntlmssp_state->ntlmssp_state->lm_resp : NULL, + auth_ntlmssp_state->ntlmssp_state->nt_resp.data ? &auth_ntlmssp_state->ntlmssp_state->nt_resp : NULL, + NULL, NULL, NULL, + True); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c index b35cc78d6b..5efc51b21a 100644 --- a/source3/auth/auth_sam.c +++ b/source3/auth/auth_sam.c @@ -57,7 +57,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, nt_pw = pdb_get_nt_passwd(sampass); return ntlm_password_check(mem_ctx, &auth_context->challenge, - &user_info->lm_resp, &user_info->nt_resp, + &user_info->lm_resp, &user_info->nt_resp, + &user_info->lm_interactive_pwd, &user_info->nt_interactive_pwd, username, user_info->smb_name.str, user_info->client_domain.str, diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index f62cc2fb9e..9df5873983 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -124,9 +124,10 @@ static NTSTATUS make_user_info(auth_usersupplied_info **user_info, const char *client_domain, const char *domain, const char *wksta_name, - DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, - DATA_BLOB plaintext, - uint32 auth_flags, BOOL encrypted) + DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd, + DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd, + DATA_BLOB *plaintext, + BOOL encrypted) { DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name)); @@ -183,12 +184,19 @@ static NTSTATUS make_user_info(auth_usersupplied_info **user_info, DEBUG(5,("making blobs for %s's user_info struct\n", internal_username)); - (*user_info)->lm_resp = data_blob(lm_pwd.data, lm_pwd.length); - (*user_info)->nt_resp = data_blob(nt_pwd.data, nt_pwd.length); - (*user_info)->plaintext_password = data_blob(plaintext.data, plaintext.length); + if (lm_pwd) + (*user_info)->lm_resp = data_blob(lm_pwd->data, lm_pwd->length); + if (nt_pwd) + (*user_info)->nt_resp = data_blob(nt_pwd->data, nt_pwd->length); + if (lm_interactive_pwd) + (*user_info)->lm_interactive_pwd = data_blob(lm_interactive_pwd->data, lm_interactive_pwd->length); + if (nt_interactive_pwd) + (*user_info)->nt_interactive_pwd = data_blob(nt_interactive_pwd->data, nt_interactive_pwd->length); + + if (plaintext) + (*user_info)->plaintext_password = data_blob(plaintext->data, plaintext->length); (*user_info)->encrypted = encrypted; - (*user_info)->auth_flags = auth_flags; DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name)); @@ -203,9 +211,10 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const char *wksta_name, - DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, - DATA_BLOB plaintext, - uint32 ntlmssp_flags, BOOL encrypted) + DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd, + DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd, + DATA_BLOB *plaintext, + BOOL encrypted) { const char *domain; fstring internal_username; @@ -233,8 +242,10 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info, /* we know that it is a trusted domain (and we are allowing them) or it is our domain */ return make_user_info(user_info, smb_name, internal_username, - client_domain, domain, wksta_name, lm_pwd, nt_pwd, - plaintext, ntlmssp_flags, encrypted); + client_domain, domain, wksta_name, + lm_pwd, nt_pwd, + lm_interactive_pwd, nt_interactive_pwd, + plaintext, encrypted); } /**************************************************************************** @@ -253,23 +264,14 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, NTSTATUS nt_status; DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len); DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len); - DATA_BLOB plaintext_blob = data_blob(NULL, 0); - uint32 auth_flags = AUTH_FLAG_NONE; - - if (lm_pwd_len) - auth_flags |= AUTH_FLAG_LM_RESP; - if (nt_pwd_len == 24) { - auth_flags |= AUTH_FLAG_NTLM_RESP; - } else if (nt_pwd_len != 0) { - auth_flags |= AUTH_FLAG_NTLMv2_RESP; - } nt_status = make_user_info_map(user_info, - smb_name, client_domain, - wksta_name, - lm_blob, nt_blob, - plaintext_blob, - auth_flags, True); + smb_name, client_domain, + wksta_name, + lm_pwd_len ? &lm_blob : NULL, + nt_pwd_len ? &nt_blob : NULL, + NULL, NULL, NULL, + True); ret = NT_STATUS_IS_OK(nt_status) ? True : False; @@ -297,7 +299,6 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; unsigned char key[16]; - uint32 auth_flags = AUTH_FLAG_NONE; ZERO_STRUCT(key); memcpy(key, dc_sess_key, 8); @@ -316,8 +317,11 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, dump_data(100, nt_pwd, sizeof(nt_pwd)); #endif - SamOEMhash((uchar *)lm_pwd, key, sizeof(lm_pwd)); - SamOEMhash((uchar *)nt_pwd, key, sizeof(nt_pwd)); + if (lm_interactive_pwd) + SamOEMhash((uchar *)lm_pwd, key, sizeof(lm_pwd)); + + if (nt_interactive_pwd) + SamOEMhash((uchar *)nt_pwd, key, sizeof(nt_pwd)); #ifdef DEBUG_PASSWORD DEBUG(100,("decrypt of lm owf password:")); @@ -327,37 +331,51 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, dump_data(100, nt_pwd, sizeof(nt_pwd)); #endif - SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response); - SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response); + if (lm_interactive_pwd) + SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response); + + if (nt_interactive_pwd) + SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response); /* Password info paranoia */ - ZERO_STRUCT(lm_pwd); - ZERO_STRUCT(nt_pwd); ZERO_STRUCT(key); { BOOL ret; NTSTATUS nt_status; - DATA_BLOB local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response)); - DATA_BLOB local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); - DATA_BLOB plaintext_blob = data_blob(NULL, 0); + DATA_BLOB local_lm_blob; + DATA_BLOB local_nt_blob; - if (lm_interactive_pwd) - auth_flags |= AUTH_FLAG_LM_RESP; - if (nt_interactive_pwd) - auth_flags |= AUTH_FLAG_NTLM_RESP; + DATA_BLOB lm_interactive_blob; + DATA_BLOB nt_interactive_blob; + + if (lm_interactive_pwd) { + local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response)); + lm_interactive_blob = data_blob(lm_pwd, sizeof(lm_pwd)); + ZERO_STRUCT(lm_pwd); + } + + if (nt_interactive_pwd) { + local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); + nt_interactive_blob = data_blob(nt_pwd, sizeof(nt_pwd)); + ZERO_STRUCT(nt_pwd); + } nt_status = make_user_info_map(user_info, smb_name, client_domain, wksta_name, - local_lm_blob, - local_nt_blob, - plaintext_blob, - auth_flags, True); - + lm_interactive_pwd ? &local_lm_blob : NULL, + nt_interactive_pwd ? &local_nt_blob : NULL, + lm_interactive_pwd ? &lm_interactive_blob : NULL, + nt_interactive_pwd ? &nt_interactive_blob : NULL, + NULL, + True); + ret = NT_STATUS_IS_OK(nt_status) ? True : False; data_blob_free(&local_lm_blob); data_blob_free(&local_nt_blob); + data_blob_free(&lm_interactive_blob); + data_blob_free(&nt_interactive_blob); return ret; } } @@ -377,7 +395,6 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, DATA_BLOB local_lm_blob; DATA_BLOB local_nt_blob; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - uint32 auth_flags = AUTH_FLAG_NONE; /* * Not encrypted - do so. @@ -400,7 +417,6 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, case insensitive */ local_nt_blob = data_blob(NULL, 0); - auth_flags = (AUTH_FLAG_PLAINTEXT | AUTH_FLAG_LM_RESP); } else { local_lm_blob = data_blob(NULL, 0); local_nt_blob = data_blob(NULL, 0); @@ -409,10 +425,11 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, ret = make_user_info_map(user_info, smb_name, client_domain, get_remote_machine_name(), - local_lm_blob, - local_nt_blob, - plaintext_password, - auth_flags, False); + local_lm_blob.data ? &local_lm_blob : NULL, + local_nt_blob.data ? &local_nt_blob : NULL, + NULL, NULL, + plaintext_password.data ? &plaintext_password : NULL, + False); data_blob_free(&local_lm_blob); return NT_STATUS_IS_OK(ret) ? True : False; @@ -427,27 +444,13 @@ NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info, const char *client_domain, DATA_BLOB lm_resp, DATA_BLOB nt_resp) { - uint32 auth_flags = AUTH_FLAG_NONE; - - DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); - - if (lm_resp.length == 24) { - auth_flags |= AUTH_FLAG_LM_RESP; - } - if (nt_resp.length == 0) { - } else if (nt_resp.length == 24) { - auth_flags |= AUTH_FLAG_NTLM_RESP; - } else { - auth_flags |= AUTH_FLAG_NTLMv2_RESP; - } - return make_user_info_map(user_info, smb_name, - client_domain, - get_remote_machine_name(), - lm_resp, - nt_resp, - no_plaintext_blob, - auth_flags, True); + client_domain, + get_remote_machine_name(), + lm_resp.data ? &lm_resp : NULL, + nt_resp.data ? &nt_resp : NULL, + NULL, NULL, NULL, + True); } /**************************************************************************** @@ -456,19 +459,16 @@ NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info, BOOL make_user_info_guest(auth_usersupplied_info **user_info) { - DATA_BLOB lm_blob = data_blob(NULL, 0); - DATA_BLOB nt_blob = data_blob(NULL, 0); - DATA_BLOB plaintext_blob = data_blob(NULL, 0); - uint32 auth_flags = AUTH_FLAG_NONE; NTSTATUS nt_status; nt_status = make_user_info(user_info, - "","", - "","", - "", - nt_blob, lm_blob, - plaintext_blob, - auth_flags, True); + "","", + "","", + "", + NULL, NULL, + NULL, NULL, + NULL, + True); return NT_STATUS_IS_OK(nt_status) ? True : False; } @@ -1307,7 +1307,8 @@ void free_user_info(auth_usersupplied_info **user_info) SAFE_FREE((*user_info)->wksta_name.str); data_blob_free(&(*user_info)->lm_resp); data_blob_free(&(*user_info)->nt_resp); - SAFE_FREE((*user_info)->interactive_password); + data_blob_clear_free(&(*user_info)->lm_interactive_pwd); + data_blob_clear_free(&(*user_info)->nt_interactive_pwd); data_blob_clear_free(&(*user_info)->plaintext_password); ZERO_STRUCT(**user_info); } diff --git a/source3/include/auth.h b/source3/include/auth.h index ecf4d539d8..8f52512e6a 100644 --- a/source3/include/auth.h +++ b/source3/include/auth.h @@ -27,37 +27,17 @@ typedef struct normal_string char *str; } AUTH_STR; -/* AUTH_UNISTR - unicode string or buffer */ -typedef struct unicode_string -{ - int len; - uchar *unistr; -} AUTH_UNISTR; - -typedef struct interactive_password -{ - OWF_INFO lm_owf; /* LM OWF Password */ - OWF_INFO nt_owf; /* NT OWF Password */ -} auth_interactive_password; - -#define AUTH_FLAG_NONE 0x000000 -#define AUTH_FLAG_PLAINTEXT 0x000001 -#define AUTH_FLAG_LM_RESP 0x000002 -#define AUTH_FLAG_NTLM_RESP 0x000004 -#define AUTH_FLAG_NTLMv2_RESP 0x000008 - typedef struct auth_usersupplied_info { DATA_BLOB lm_resp; DATA_BLOB nt_resp; - auth_interactive_password * interactive_password; + DATA_BLOB lm_interactive_pwd; + DATA_BLOB nt_interactive_pwd; DATA_BLOB plaintext_password; BOOL encrypted; - uint32 auth_flags; - AUTH_STR client_domain; /* domain name string */ AUTH_STR domain; /* domain name after mapping */ AUTH_STR internal_username; /* username after mapping */ diff --git a/source3/libsmb/ntlm_check.c b/source3/libsmb/ntlm_check.c index bc291b5128..a7764f9e98 100644 --- a/source3/libsmb/ntlm_check.c +++ b/source3/libsmb/ntlm_check.c @@ -170,6 +170,8 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, const DATA_BLOB *challenge, const DATA_BLOB *lm_response, const DATA_BLOB *nt_response, + const DATA_BLOB *lm_interactive_pwd, + const DATA_BLOB *nt_interactive_pwd, const char *username, const char *client_username, const char *client_domain, @@ -183,6 +185,47 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, username)); } + if (nt_interactive_pwd && nt_interactive_pwd->length && nt_pw) { + if (nt_interactive_pwd->length != 16) { + DEBUG(3,("ntlm_password_check: Interactive logon: Invalid NT password length (%d) supplied for user %s\n", (int)nt_interactive_pwd->length, + username)); + return NT_STATUS_WRONG_PASSWORD; + } + + if (memcmp(nt_interactive_pwd->data, nt_pw, 16) == 0) { + if (user_sess_key) { + *user_sess_key = data_blob(NULL, 16); + SMBsesskeygen_ntv1(nt_pw, NULL, user_sess_key->data); + } + return NT_STATUS_OK; + } else { + DEBUG(3,("ntlm_password_check: Interactive logon: NT password check failed for user %s\n", + username)); + return NT_STATUS_WRONG_PASSWORD; + } + + } else if (lm_interactive_pwd && lm_interactive_pwd->length && lm_pw) { + if (lm_interactive_pwd->length != 16) { + DEBUG(3,("ntlm_password_check: Interactive logon: Invalid LANMAN password length (%d) supplied for user %s\n", (int)lm_interactive_pwd->length, + username)); + return NT_STATUS_WRONG_PASSWORD; + } + + if (!lp_lanman_auth()) { + DEBUG(3,("ntlm_password_check: Interactive logon: only LANMAN password supplied for user %s, and LM passwords are disabled!\n", + username)); + return NT_STATUS_WRONG_PASSWORD; + } + + if (memcmp(lm_interactive_pwd->data, lm_pw, 16) == 0) { + return NT_STATUS_OK; + } else { + DEBUG(3,("ntlm_password_check: Interactive logon: LANMAN password check failed for user %s\n", + username)); + return NT_STATUS_WRONG_PASSWORD; + } + } + /* Check for cleartext netlogon. Used by Exchange 5.5. */ if (challenge->length == sizeof(zeros) && (memcmp(challenge->data, zeros, challenge->length) == 0 )) { diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 2213a9bae3..e33bca363b 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -366,6 +366,7 @@ static NTSTATUS local_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *n &ntlmssp_state->chal, &ntlmssp_state->lm_resp, &ntlmssp_state->nt_resp, + NULL, NULL, ntlmssp_state->user, ntlmssp_state->user, ntlmssp_state->domain, |