diff options
Diffstat (limited to 'source3/smbd/auth.c')
-rw-r--r-- | source3/smbd/auth.c | 263 |
1 files changed, 118 insertions, 145 deletions
diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index 4bdbdf5555..4d1a566833 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -50,183 +50,160 @@ static BOOL check_domain_match(char *user, char *domain) This functions does NOT need to be in a become_root()/unbecome_root() pair as it makes the calls itself when needed. + + The return value takes precedence over the contents of the server_info + struct. When the return is other than NT_STATUS_NOPROBLEMO the contents + of that structure is undefined. + ****************************************************************************/ NTSTATUS check_password(const auth_usersupplied_info *user_info, - auth_serversupplied_info *server_info) + auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; BOOL done_pam = False; - - DEBUG(3, ("check_password: Checking password for smb user %s\\%s@%s with the new password interface\n", - user_info->smb_username.str, user_info->requested_domain.str, user_info->wksta_name.str)); - if (!check_domain_match(user_info->smb_username.str, user_info->domain.str)) { + + DEBUG(3, ("check_password: Checking password for unmapped user %s\\%s@%s with the new password interface\n", + user_info->smb_name.str, user_info->client_domain.str, user_info->wksta_name.str)); + + /* This needs to be sorted: If it doesn't match, what should we do? */ + if (!check_domain_match(user_info->smb_name.str, user_info->domain.str)) { return NT_STATUS_LOGON_FAILURE; } if (!NT_STATUS_IS_OK(nt_status)) { nt_status = check_rhosts_security(user_info, server_info); + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG(7, ("check_password: Password (rhosts) for user %s suceeded\n", user_info->smb_name.str)); + } else { + DEBUG(5, ("check_password: Password (rhosts)for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + + } } if ((lp_security() == SEC_DOMAIN) && !NT_STATUS_IS_OK(nt_status)) { nt_status = check_domain_security(user_info, server_info); + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG(7, ("check_password: Password (domain) for user %s suceeded\n", user_info->smb_name.str)); + } else { + DEBUG(5, ("check_password: Password (domain) for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + + } } if ((lp_security() == SEC_SERVER) && !NT_STATUS_IS_OK(nt_status)) { nt_status = check_server_security(user_info, server_info); + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG(7, ("check_password: Password (server) for user %s suceeded\n", user_info->smb_name.str)); + } else { + DEBUG(5, ("check_password: Password (server) for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + + } } if (lp_security() >= SEC_SERVER) { - smb_user_control(user_info->unix_username.str, nt_status); + smb_user_control(user_info, *server_info, nt_status); } if (!NT_STATUS_IS_OK(nt_status)) { - if ((user_info->plaintext_password.len > 0) - && (!lp_plaintext_to_smbpasswd())) { + if (user_info->encrypted || lp_plaintext_to_smbpasswd()) { + nt_status = check_smbpasswd_security(user_info, server_info); + } else { nt_status = check_unix_security(user_info, server_info); done_pam = True; - } else { - nt_status = check_smbpasswd_security(user_info, server_info); } + + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG(7, ("check_password: Password (unix/smbpasswd) for user %s suceeded\n", user_info->smb_name.str)); + } else { + DEBUG(5, ("check_password: Password (unix/smbpasswd) for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + + } } + if (NT_STATUS_IS_OK(nt_status) && !done_pam) { /* We might not be root if we are an RPC call */ become_root(); - nt_status = smb_pam_accountcheck(user_info->unix_username.str); + nt_status = smb_pam_accountcheck(pdb_get_username((*server_info)->sam_account)); unbecome_root(); - } + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG(5, ("check_password: PAM Account for user %s suceeded\n", user_info->smb_name.str)); + } else { + DEBUG(3, ("check_password: PAM Account for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + + } + } + if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("check_password: Password for smb user %s suceeded\n", user_info->smb_username.str)); + DEBUG(5, ("check_password: Password for smb user %s suceeded\n", user_info->smb_name.str)); } else { - DEBUG(3, ("check_password: Password for smb user %s FAILED with error %s\n", user_info->smb_username.str, get_nt_error_msg(nt_status))); - + DEBUG(3, ("check_password: Password for smb user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); + ZERO_STRUCTP(server_info); } + return nt_status; } /**************************************************************************** - COMPATABILITY INTERFACES: - ***************************************************************************/ - -/**************************************************************************** -check if a username/password is OK assuming the password is a 24 byte -SMB hash -return True if the password is correct, False otherwise + Squash an NT_STATUS return in line with requirements for unauthenticated + connections. (session setups in particular) ****************************************************************************/ -NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, - char *domain, char* workstation, - uchar chal[8], - uchar *lm_pwd, int lm_pwd_len, - uchar *nt_pwd, int nt_pwd_len) +NTSTATUS nt_status_squash(NTSTATUS nt_status) { - - auth_usersupplied_info user_info; - auth_serversupplied_info server_info; - AUTH_STR ourdomain, theirdomain, unix_username, smb_username, - wksta_name; - NTSTATUS result; + if NT_STATUS_IS_OK(nt_status) { + return nt_status; + } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { + /* Match WinXP and don't give the game away */ + return NT_STATUS_LOGON_FAILURE; - ZERO_STRUCT(user_info); - ZERO_STRUCT(ourdomain); - ZERO_STRUCT(theirdomain); - ZERO_STRUCT(smb_username); - ZERO_STRUCT(wksta_name); - - ourdomain.str = lp_workgroup(); - ourdomain.len = strlen(ourdomain.str); - - theirdomain.str = domain; - theirdomain.len = strlen(theirdomain.str); - - user_info.requested_domain = theirdomain; - user_info.domain = ourdomain; - - smb_username.str = smb_user; - smb_username.len = strlen(smb_username.str); - - /* If unix user is NULL, use smb user */ - - unix_username.str = unix_user ? unix_user : smb_user; - unix_username.len = strlen(unix_username.str); - - user_info.unix_username = unix_username; - user_info.smb_username = smb_username; - - wksta_name.str = workstation; - wksta_name.len = strlen(workstation); - - user_info.wksta_name = wksta_name; - - memcpy(user_info.chal, chal, 8); - - if ((lm_pwd_len >= 24 || nt_pwd_len >= 24) || - (lp_encrypted_passwords() && (lm_pwd_len == 0) && lp_null_passwords())) { - /* if 24 bytes long assume it is an encrypted password */ - - user_info.lm_resp.buffer = (uint8 *)lm_pwd; - user_info.lm_resp.len = lm_pwd_len; - user_info.nt_resp.buffer = (uint8 *)nt_pwd; - user_info.nt_resp.len = nt_pwd_len; - + } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { + /* Match WinXP and don't give the game away */ + return NT_STATUS_LOGON_FAILURE; } else { - unsigned char local_lm_response[24]; - unsigned char local_nt_response[24]; - - /* - * Not encrypted - do so. - */ - - DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n")); - - if (lm_pwd_len > 0) { - SMBencrypt( (uchar *)lm_pwd, user_info.chal, local_lm_response); - user_info.lm_resp.buffer = (uint8 *)local_lm_response; - user_info.lm_resp.len = 24; - - - /* WATCH OUT. This doesn't work if the incoming password is incorrectly cased. - We might want to add a check here and only do an LM in that case */ + return nt_status; + } +} - /* This encrypts the lm_pwd feild, which actualy contains the password - rather than the nt_pwd field becouse that contains nothing */ - SMBNTencrypt((uchar *)lm_pwd, user_info.chal, local_nt_response); - user_info.nt_resp.buffer = (uint8 *)local_nt_response; - user_info.nt_resp.len = 24; - } - - user_info.plaintext_password.str = (char *)lm_pwd; - user_info.plaintext_password.len = lm_pwd_len; - } - result = check_password(&user_info, &server_info); +/**************************************************************************** + COMPATABILITY INTERFACES: + ***************************************************************************/ - free_serversupplied_info(&server_info); /* No info needed */ +/**************************************************************************** +check if a username/password is OK assuming the password is a 24 byte +SMB hash +return True if the password is correct, False otherwise +****************************************************************************/ - return result; -} +static NTSTATUS pass_check_smb(char *smb_name, + char *domain, + DATA_BLOB lm_pwd, + DATA_BLOB nt_pwd, + DATA_BLOB plaintext_password, + BOOL encrypted) -NTSTATUS pass_check_smb(char *smb_user, char *unix_user, - char *domain, char *workstation, - uchar *lm_pwd, int lm_pwd_len, - uchar *nt_pwd, int nt_pwd_len) { - uchar chal[8]; - - if (!last_challenge(chal)) { - generate_random_buffer( chal, 8, False); - } - - return pass_check_smb_with_chal(smb_user, unix_user, - domain, workstation, chal, - lm_pwd, lm_pwd_len, - nt_pwd, nt_pwd_len); - + NTSTATUS nt_status; + auth_usersupplied_info *user_info = NULL; + auth_serversupplied_info *server_info = NULL; + + make_user_info_for_reply(&user_info, smb_name, + domain, + lm_pwd, + nt_pwd, + plaintext_password, + encrypted); + + nt_status = check_password(user_info, &server_info); + free_user_info(&user_info); + free_server_info(&server_info); + return nt_status; } /**************************************************************************** @@ -234,36 +211,32 @@ check if a username/password pair is OK either via the system password database or the encrypted SMB password database return True if the password is correct, False otherwise ****************************************************************************/ -BOOL password_ok(char *user, char *password, int pwlen) +BOOL password_ok(char *smb_name, DATA_BLOB password_blob) { - extern fstring remote_machine; - /* - * This hack must die! But until I rewrite the rest of samba - * it must stay - abartlet 2001-08-03 - */ - - if ((pwlen == 0) && !lp_null_passwords()) { - DEBUG(4,("Null passwords not allowed.\n")); - return False; - } - - /* The password could be either NTLM or plain LM. Try NTLM first, but fall-through as - required. */ - if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, remote_machine, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen))) { - return True; - } + DATA_BLOB null_password = data_blob(NULL, 0); + extern BOOL global_encrypted_passwords_negotiated; - if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, remote_machine, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0))) { - return True; + if (global_encrypted_passwords_negotiated) { + /* + * The password could be either NTLM or plain LM. Try NTLM first, + * but fall-through as required. + * NTLMv2 makes no sense here. + */ + if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, password_blob, null_password, global_encrypted_passwords_negotiated))) { + return True; + } + + if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), password_blob, null_password, null_password, global_encrypted_passwords_negotiated))) { + return True; + } + } else { + if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, null_password, password_blob, global_encrypted_passwords_negotiated))) { + return True; + } } return False; } -/* Free a auth_serversupplied_info structure */ -void free_serversupplied_info(auth_serversupplied_info *server_info) -{ - SAFE_FREE(server_info->group_rids); -} |