diff options
Diffstat (limited to 'source3')
32 files changed, 2216 insertions, 1139 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index f582bd8e19..ea15da5ca3 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -398,7 +398,7 @@ WINBINDD_OBJ1 = \ nsswitch/winbindd_cm.o NECESSARY_BECAUSE_SAMBA_DEPENDENCIES_ARE_SO_BROKEN_OBJ = \ - libsmb/domain_client_validate.o \ + libsmb/domain_client_validate.o smbd/auth_util.o \ rpc_client/cli_netlogon.o rpc_client/cli_login.o WINBINDD_OBJ = \ diff --git a/source3/auth/auth.c b/source3/auth/auth.c index 4bdbdf5555..4d1a566833 100644 --- a/source3/auth/auth.c +++ b/source3/auth/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); -} diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index bcd41bacdb..f20da19607 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -29,7 +29,7 @@ BOOL global_machine_password_needs_changing = False; ****************************************************************************/ NTSTATUS check_domain_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info *server_info) + auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; char *p, *pserver; diff --git a/source3/auth/auth_rhosts.c b/source3/auth/auth_rhosts.c index 9f5f1e10e5..9c07e48a9b 100644 --- a/source3/auth/auth_rhosts.c +++ b/source3/auth/auth_rhosts.c @@ -131,11 +131,11 @@ static BOOL check_user_equiv(const char *user, const char *remote, const char *e /**************************************************************************** check for a possible hosts equiv or rhosts entry for the user ****************************************************************************/ -static BOOL check_hosts_equiv(char *user) /* should be const... */ + +static BOOL check_hosts_equiv(struct passwd *pass) { char *fname = NULL; pstring rhostsfile; - struct passwd *pass = Get_Pwnam(user); if (!pass) return(False); @@ -149,15 +149,15 @@ static BOOL check_hosts_equiv(char *user) /* should be const... */ } if (lp_use_rhosts()) - { - char *home = pass->pw_dir; - if (home) { - slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); - if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) - return(True); - } - } - + { + char *home = pass->pw_dir; + if (home) { + slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); + if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) + return(True); + } + } + return(False); } @@ -166,15 +166,21 @@ static BOOL check_hosts_equiv(char *user) /* should be const... */ ****************************************************************************/ NTSTATUS check_rhosts_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info *server_info) + auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - - become_root(); - if (check_hosts_equiv(user_info->unix_username.str)) { - nt_status = NT_STATUS_OK; + struct passwd *pass = Get_Pwnam(user_info->internal_username.str); + + if (pass) { + become_root(); + if (check_hosts_equiv(pass)) { + nt_status = NT_STATUS_OK; + make_server_info_pw(server_info, pass); + } + unbecome_root(); + } else { + nt_status = NT_STATUS_NO_SUCH_USER; } - unbecome_root(); return nt_status; } diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c index 84ca8d03be..d4283429ce 100644 --- a/source3/auth/auth_sam.c +++ b/source3/auth/auth_sam.c @@ -26,53 +26,65 @@ /**************************************************************************** core of smb password checking routine. ****************************************************************************/ -static BOOL smb_pwd_check_ntlmv1(const uchar *password, +static BOOL smb_pwd_check_ntlmv1(DATA_BLOB nt_response, const uchar *part_passwd, - const uchar *c8, - char user_sess_key[16]) + DATA_BLOB sec_blob, + uint8 user_sess_key[16]) { - /* Finish the encryption of part_passwd. */ - uchar p24[24]; - - if (part_passwd == NULL) { - DEBUG(10,("No password set - DISALLOWING access\n")); - /* No password set - always false ! */ - return False; - } + /* Finish the encryption of part_passwd. */ + uchar p24[24]; + + if (part_passwd == NULL) { + DEBUG(10,("No password set - DISALLOWING access\n")); + /* No password set - always false ! */ + return False; + } + + if (sec_blob.length != 8) { + DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challange size (%d)\n", sec_blob.length)); + return False; + } + + if (nt_response.length != 24) { + DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", nt_response.length)); + return False; + } - SMBOWFencrypt(part_passwd, c8, p24); + SMBOWFencrypt(part_passwd, sec_blob.data, p24); if (user_sess_key != NULL) { SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key); } - - - + + + #if DEBUG_PASSWORD DEBUG(100,("Part password (P16) was |")); dump_data(100, part_passwd, 16); DEBUG(100,("Password from client was |")); - dump_data(100, password, 24); + dump_data(100, nt_response.data, nt_response.length); DEBUG(100,("Given challenge was |")); - dump_data(100, c8, 8); + dump_data(100, sec_blob.data, sec_blob.length); DEBUG(100,("Value from encryption was |")); dump_data(100, p24, 24); #endif - return (memcmp(p24, password, 24) == 0); + return (memcmp(p24, nt_response.data, 24) == 0); } /**************************************************************************** core of smb password checking routine. ****************************************************************************/ -static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, +static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, const uchar *part_passwd, - const uchar *c8, + const DATA_BLOB sec_blob, const char *user, const char *domain, - char user_sess_key[16]) + uint8 user_sess_key[16]) { /* Finish the encryption of part_passwd. */ uchar kr[16]; - uchar resp[16]; + uchar value_from_encryption[16]; + uchar client_response[16]; + DATA_BLOB client_key_data; if (part_passwd == NULL) { @@ -81,25 +93,42 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, return False; } + if (ntv2_response.length < 16) { + /* We MUST have more than 16 bytes, or the stuff below will go + crazy... */ + DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", + ntv2_response.length)); + return False; + } + + client_key_data = data_blob(ntv2_response.data+16, ntv2_response.length-16); + memcpy(client_response, ntv2_response.data, ntv2_response.length); + + if (!client_key_data.data) { + return False; + } + ntv2_owf_gen(part_passwd, user, domain, kr); - SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, (char *)resp); + SMBOWFencrypt_ntv2(kr, sec_blob, client_key_data, (char *)value_from_encryption); if (user_sess_key != NULL) { - SMBsesskeygen_ntv2(kr, resp, user_sess_key); + SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key); } #if DEBUG_PASSWORD DEBUG(100,("Part password (P16) was |")); dump_data(100, part_passwd, 16); DEBUG(100,("Password from client was |")); - dump_data(100, password, pwd_len); + dump_data(100, ntv2_response.data, ntv2_response.length); + DEBUG(100,("Variable data from client was |")); + dump_data(100, ntv2_response.data, ntv2_response.length); DEBUG(100,("Given challenge was |")); - dump_data(100, c8, 8); + dump_data(100, sec_blob.data, sec_blob.length); DEBUG(100,("Value from encryption was |")); - dump_data(100, resp, 16); + dump_data(100, value_from_encryption, 16); #endif - - return (memcmp(resp, password, 16) == 0); + data_blob_clear_free(&client_key_data); + return (memcmp(value_from_encryption, client_response, 16) == 0); } @@ -107,11 +136,12 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ -NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, char user_sess_key[16]) +NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, uint8 user_sess_key[16]) { const uint8 *nt_pw, *lm_pw; uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); - + uint32 ntlmssp_flags; + if (!user_info || !sampass) return NT_STATUS_LOGON_FAILURE; @@ -119,12 +149,12 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use { if (lp_null_passwords()) { - DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", sampass->username)); + DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", pdb_get_username(sampass))); return(NT_STATUS_OK); } else { - DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", sampass->username)); + DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", pdb_get_username(sampass))); return(NT_STATUS_LOGON_FAILURE); } } @@ -132,61 +162,84 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use nt_pw = pdb_get_nt_passwd(sampass); lm_pw = pdb_get_lanman_passwd(sampass); - if (nt_pw != NULL && user_info->nt_resp.len > 0) { - if ((user_info->nt_resp.len > 24 )) { + ntlmssp_flags = user_info->ntlmssp_flags; + + if (nt_pw == NULL) { + DEBUG(3,("smb_password_ok: NO NT password stored for user %s.\n", + pdb_get_username(sampass))); + /* No return, we want to check the LM hash below in this case */ + ntlmssp_flags &= (~(NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2)); + } + + if (ntlmssp_flags & NTLMSSP_NEGOTIATE_NTLM2) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n")); - if (smb_pwd_check_ntlmv2( user_info->nt_resp.buffer, - user_info->nt_resp.len, + if (smb_pwd_check_ntlmv2( user_info->nt_resp, nt_pw, - user_info->chal, user_info->smb_username.str, - user_info->requested_domain.str, + user_info->sec_blob, user_info->smb_name.str, + user_info->client_domain.str, user_sess_key)) { return NT_STATUS_OK; } else { - DEBUG(4,("smb_password_ok: NTLMv2 password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; + DEBUG(3,("smb_password_ok: NTLMv2 password check failed\n")); + return NT_STATUS_WRONG_PASSWORD; } - - } else if (lp_ntlm_auth() && (user_info->nt_resp.len == 24)) { + } else if (ntlmssp_flags & NTLMSSP_NEGOTIATE_NTLM) { + if (lp_ntlm_auth()) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ - DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); - if (smb_pwd_check_ntlmv1(user_info->nt_resp.buffer, - nt_pw, user_info->chal, - user_sess_key)) - { - return NT_STATUS_OK; + DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); + if (smb_pwd_check_ntlmv1(user_info->nt_resp, + nt_pw, user_info->sec_blob, + user_sess_key)) + { + return NT_STATUS_OK; + } else { + DEBUG(3,("smb_password_ok: NT MD4 password check failed for user %s\n",pdb_get_username(sampass))); + return NT_STATUS_WRONG_PASSWORD; + } } else { - DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; + DEBUG(2,("smb_password_ok: NTLMv1 passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); + /* No return, we want to check the LM hash below in this case */ } - } else { - return NT_STATUS_LOGON_FAILURE; - } } - if (lm_pw != NULL && user_info->lm_resp.len == 24) { - if (lp_lanman_auth()) { - DEBUG(4,("smb_password_ok: Checking LM password\n")); - if (smb_pwd_check_ntlmv1(user_info->lm_resp.buffer, - lm_pw, user_info->chal, - user_sess_key)) - { - return NT_STATUS_OK; - } else { - DEBUG(4,("smb_password_ok: LM password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; - } + if (lm_pw == NULL) { + DEBUG(3,("smb_password_ok: NO LanMan password set for user %s (and no NT password supplied)\n",pdb_get_username(sampass))); + ntlmssp_flags &= (~NTLMSSP_NEGOTIATE_OEM); + } + + if (ntlmssp_flags & NTLMSSP_NEGOTIATE_OEM) { + + if (user_info->lm_resp.length != 24) { + DEBUG(2,("smb_password_ok: invalid LanMan password length (%d) for user %s\n", + user_info->nt_resp.length, pdb_get_username(sampass))); } + + if (!lp_lanman_auth()) { + DEBUG(3,("smb_password_ok: Lanman passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); + return NT_STATUS_LOGON_FAILURE; + } + + DEBUG(4,("smb_password_ok: Checking LM password\n")); + if (smb_pwd_check_ntlmv1(user_info->lm_resp, + lm_pw, user_info->sec_blob, + user_sess_key)) + { + return NT_STATUS_OK; + } else { + DEBUG(4,("smb_password_ok: LM password check failed for user %s\n",pdb_get_username(sampass))); + return NT_STATUS_WRONG_PASSWORD; + } } - /* Should not be reached */ - return NT_STATUS_LOGON_FAILURE; + /* Should not be reached, but if they send nothing... */ + DEBUG(3,("smb_password_ok: NEITHER LanMan nor NT password supplied for user %s\n",pdb_get_username(sampass))); + return NT_STATUS_WRONG_PASSWORD; } /**************************************************************************** @@ -290,33 +343,58 @@ SMB hash supplied in the user_info structure return an NT_STATUS constant. ****************************************************************************/ -NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { SAM_ACCOUNT *sampass=NULL; BOOL ret; NTSTATUS nt_status; + uint8 user_sess_key[16]; + const uint8* lm_hash; pdb_init_sam(&sampass); /* get the account information */ become_root(); - ret = pdb_getsampwnam(sampass, user_info->unix_username.str); + ret = pdb_getsampwnam(sampass, user_info->internal_username.str); unbecome_root(); if (ret == False) { - DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->unix_username.str)); + DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->internal_username.str)); pdb_free_sam(&sampass); return NT_STATUS_NO_SUCH_USER; } - nt_status = sam_password_ok(sampass, user_info, (char *)(server_info->session_key)); + nt_status = sam_password_ok(sampass, user_info, user_sess_key); - if NT_STATUS_IS_OK(nt_status) { - nt_status = sam_account_ok(sampass, user_info); + if (!NT_STATUS_IS_OK(nt_status)) { + pdb_free_sam(&sampass); + return nt_status; } - pdb_free_sam(&sampass); + nt_status = sam_account_ok(sampass, user_info); + + if (!NT_STATUS_IS_OK(nt_status)) { + pdb_free_sam(&sampass); + return nt_status; + } + + if (!make_server_info_sam(server_info, sampass)) { + DEBUG(0,("failed to malloc memory for server_info\n")); + return NT_STATUS_NO_MEMORY; + } + + lm_hash = pdb_get_lanman_passwd((*server_info)->sam_account); + if (lm_hash) { + memcpy((*server_info)->first_8_lm_hash, lm_hash, 8); + } + + memcpy((*server_info)->session_key, user_sess_key, sizeof(user_sess_key)); + return nt_status; } + + + + diff --git a/source3/auth/auth_server.c b/source3/auth/auth_server.c index 520417e3e0..ddbc284d50 100644 --- a/source3/auth/auth_server.c +++ b/source3/auth/auth_server.c @@ -115,7 +115,7 @@ struct cli_state *server_cryptkey(void) - Validate a password with the password server. ****************************************************************************/ -NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { struct cli_state *cli; static unsigned char badpass[24]; @@ -134,8 +134,8 @@ NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_ser if(badpass[0] == 0) memset(badpass, 0x1f, sizeof(badpass)); - if((user_info->nt_resp.len == sizeof(badpass)) && - !memcmp(badpass, user_info->nt_resp.buffer, sizeof(badpass))) { + if((user_info->nt_resp.length == sizeof(badpass)) && + !memcmp(badpass, user_info->nt_resp.data, sizeof(badpass))) { /* * Very unlikely, our random bad password is the same as the users * password. @@ -206,11 +206,11 @@ use this machine as the password server.\n")); * not guest enabled, we can try with the real password. */ - if (!cli_session_setup(cli, user_info->smb_username.str, - (char *)user_info->lm_resp.buffer, - user_info->lm_resp.len, - (char *)user_info->nt_resp.buffer, - user_info->nt_resp.len, + if (!cli_session_setup(cli, user_info->smb_name.str, + (char *)user_info->lm_resp.data, + user_info->lm_resp.length, + (char *)user_info->nt_resp.data, + user_info->nt_resp.length, user_info->domain.str)) { DEBUG(1,("password server %s rejected the password\n", cli->desthost)); /* Make this cli_nt_error() when the conversion is in */ @@ -227,5 +227,16 @@ use this machine as the password server.\n")); cli_ulogoff(cli); + if NT_STATUS_IS_OK(nt_status) { + struct passwd *pass = Get_Pwnam(user_info->internal_username.str); + if (pass) { + if (!make_server_info_pw(server_info, pass)) { + nt_status = NT_STATUS_NO_MEMORY; + } + } else { + nt_status = NT_STATUS_NO_SUCH_USER; + } + } + return(nt_status); } diff --git a/source3/auth/auth_unix.c b/source3/auth/auth_unix.c index 29a2a6eafb..d456da1fdf 100644 --- a/source3/auth/auth_unix.c +++ b/source3/auth/auth_unix.c @@ -82,22 +82,27 @@ check if a username/password is OK assuming the password in PLAIN TEXT ****************************************************************************/ -NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status; struct passwd *pass = NULL; become_root(); - - pass = Get_Pwnam(user_info->unix_username.str); + pass = Get_Pwnam(user_info->internal_username.str); nt_status = pass_check(pass, - pass ? pass->pw_name : user_info->unix_username.str, - user_info->plaintext_password.str, - user_info->plaintext_password.len, + pass ? pass->pw_name : user_info->internal_username.str, + (char *)user_info->plaintext_password.data, + user_info->plaintext_password.length-1, lp_update_encrypted() ? update_smbpassword_file : NULL, True); + + if NT_STATUS_IS_OK(nt_status) { + if (pass) { + make_server_info_pw(server_info, pass); + } + } unbecome_root(); diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index d3b9aa7001..297c482af5 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -25,6 +25,8 @@ /* Data to do lanman1/2 password challenge. */ static unsigned char saved_challenge[8]; static BOOL challenge_sent=False; +extern fstring remote_machine; +extern pstring global_myname; /******************************************************************* Get the next challenge value - no repeats. @@ -64,7 +66,7 @@ BOOL last_challenge(unsigned char *challenge) Create a UNIX user on demand. ****************************************************************************/ -static int smb_create_user(char *unix_user, char *homedir) +static int smb_create_user(const char *unix_user, const char *homedir) { pstring add_script; int ret; @@ -100,40 +102,560 @@ static int smb_delete_user(char *unix_user) Add and Delete UNIX users on demand, based on NTSTATUS codes. ****************************************************************************/ -void smb_user_control(char *unix_user, NTSTATUS nt_status) +void smb_user_control(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info, NTSTATUS nt_status) { struct passwd *pwd=NULL; if (NT_STATUS_IS_OK(nt_status)) { - /* - * User validated ok against Domain controller. - * If the admin wants us to try and create a UNIX - * user on the fly, do so. - */ - if(lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) - smb_create_user(unix_user, NULL); - - if(lp_adduser_script() && pwd) { - SMB_STRUCT_STAT st; + if (!(server_info->sam_fill_level & SAM_FILL_UNIX)) { + /* - * Also call smb_create_user if the users home directory - * doesn't exist. Used with winbindd to allow the script to - * create the home directory for a user mapped with winbindd. + * User validated ok against Domain controller. + * If the admin wants us to try and create a UNIX + * user on the fly, do so. */ + + if(lp_adduser_script() && !(pwd = Get_Pwnam(user_info->internal_username.str))) { + smb_create_user(user_info->internal_username.str, NULL); + } + } else { + if(lp_adduser_script()) { + SMB_STRUCT_STAT st; + const char *home_dir = pdb_get_homedir(server_info->sam_account); + /* + * Also call smb_create_user if the users home directory + * doesn't exist. Used with winbindd to allow the script to + * create the home directory for a user mapped with winbindd. + */ - if (pwd->pw_dir && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT)) - smb_create_user(unix_user, pwd->pw_dir); + if (home_dir && + (sys_stat(home_dir, &st) == -1) && (errno == ENOENT)) { + smb_create_user(user_info->internal_username.str, home_dir); + } + } } - - } else if (NT_STATUS_V(nt_status) == NT_STATUS_V(NT_STATUS_NO_SUCH_USER)) { + } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) { /* * User failed to validate ok against Domain controller. * If the failure was "user doesn't exist" and admin * wants us to try and delete that UNIX user on the fly, * do so. */ - if(lp_deluser_script() && smb_getpwnam(unix_user,True)) - smb_delete_user(unix_user); + if (lp_deluser_script()) { + smb_delete_user(user_info->internal_username.str); + } + } +} + +/**************************************************************************** + Create an auth_usersupplied_data structure +****************************************************************************/ + +BOOL make_user_info(auth_usersupplied_info **user_info, + char *smb_name, char *internal_username, + char *client_domain, char *domain, + char *wksta_name, DATA_BLOB sec_blob, + DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, + DATA_BLOB plaintext, + uint32 ntlmssp_flags, BOOL encrypted) +{ + + DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name)); + + *user_info = malloc(sizeof(**user_info)); + if (!user_info) { + DEBUG(0,("malloc failed for user_info (size %d)\n", sizeof(*user_info))); + return False; + } + + ZERO_STRUCTP(*user_info); + + DEBUG(5,("makeing strings for %s's user_info struct\n", internal_username)); + + (*user_info)->smb_name.str = strdup(smb_name); + if ((*user_info)->smb_name.str) { + (*user_info)->smb_name.len = strlen(smb_name); + } else { + free_user_info(user_info); + return False; + } + + (*user_info)->internal_username.str = strdup(internal_username); + if ((*user_info)->internal_username.str) { + (*user_info)->internal_username.len = strlen(internal_username); + } else { + free_user_info(user_info); + return False; + } + + (*user_info)->domain.str = strdup(domain); + if ((*user_info)->domain.str) { + (*user_info)->domain.len = strlen(domain); + } else { + free_user_info(user_info); + return False; + } + + (*user_info)->client_domain.str = strdup(client_domain); + if ((*user_info)->client_domain.str) { + (*user_info)->client_domain.len = strlen(client_domain); + } else { + free_user_info(user_info); + return False; + } + + (*user_info)->wksta_name.str = strdup(wksta_name); + if ((*user_info)->wksta_name.str) { + (*user_info)->wksta_name.len = strlen(wksta_name); + } else { + free_user_info(user_info); + return False; } + + DEBUG(5,("makeing blobs for %s's user_info struct\n", internal_username)); + + (*user_info)->sec_blob = data_blob(sec_blob.data, sec_blob.length); + (*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); + + (*user_info)->encrypted = encrypted; + (*user_info)->ntlmssp_flags = ntlmssp_flags; + + DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name)); + + return True; } + +/**************************************************************************** + Create an auth_usersupplied_data structure after appropriate mapping. +****************************************************************************/ + +BOOL make_user_info_map(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + char *wksta_name, DATA_BLOB sec_blob, + DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, + DATA_BLOB plaintext, + uint32 ntlmssp_flags, BOOL encrypted) +{ + char *domain; + fstring internal_username; + fstrcpy(internal_username, smb_name); + map_username(internal_username); + + if (lp_allow_trusted_domains()) { + domain = client_domain; + } else { + domain = lp_workgroup(); + } + + return make_user_info(user_info, + smb_name, internal_username, + client_domain, domain, + wksta_name, sec_blob, + lm_pwd, nt_pwd, + plaintext, + ntlmssp_flags, encrypted); + +} + +/**************************************************************************** + Create an auth_usersupplied_data, making the DATA_BLOBs here. + Decrupt and encrypt the passwords. +****************************************************************************/ + +BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + char *wksta_name, uchar chal[8], + uchar *lm_network_pwd, int lm_pwd_len, + uchar *nt_network_pwd, int nt_pwd_len) +{ + BOOL ret; + DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); + 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 ntlmssp_flags = 0; + + if (lm_pwd_len) + ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; + if (nt_pwd_len) + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; + + ret = make_user_info_map(user_info, + smb_name, client_domain, + wksta_name, sec_blob, + nt_blob, lm_blob, + plaintext_blob, + ntlmssp_flags, True); + + data_blob_free(&lm_blob); + data_blob_free(&nt_blob); + return ret; +} + +/**************************************************************************** + Create an auth_usersupplied_data, making the DATA_BLOBs here. + Decrupt and encrypt the passwords. +****************************************************************************/ + +BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + char *wksta_name, + uchar *lm_interactive_pwd, int lm_pwd_len, + uchar *nt_interactive_pwd, int nt_pwd_len, + uchar *dc_sess_key) +{ + char nt_pwd[16]; + char lm_pwd[16]; + unsigned char local_lm_response[24]; + unsigned char local_nt_response[24]; + unsigned char key[16]; + uint8 chal[8]; + uint32 ntlmssp_flags = 0; + + generate_random_buffer(chal, 8, False); + + memset(key, 0, 16); + memcpy(key, dc_sess_key, 8); + + memcpy(lm_pwd, lm_interactive_pwd, 16); + memcpy(nt_pwd, nt_interactive_pwd, 16); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("key:")); + dump_data(100, (char *)key, 16); + + DEBUG(100,("lm owf password:")); + dump_data(100, lm_pwd, 16); + + DEBUG(100,("nt owf password:")); + dump_data(100, nt_pwd, 16); +#endif + + SamOEMhash((uchar *)lm_pwd, key, 16); + SamOEMhash((uchar *)nt_pwd, key, 16); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("decrypt of lm owf password:")); + dump_data(100, lm_pwd, 16); + + DEBUG(100,("decrypt of nt owf password:")); + dump_data(100, nt_pwd, 16); +#endif + + generate_random_buffer(chal, 8, False); + SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response); + SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response); + + /* Password info parinoia */ + ZERO_STRUCT(lm_pwd); + ZERO_STRUCT(nt_pwd); + ZERO_STRUCT(key); + + { + BOOL ret; + DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); + 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); + + ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_NTLM; + ret = make_user_info_map(user_info, + smb_name, client_domain, + wksta_name, sec_blob, + local_nt_blob, + local_lm_blob, + plaintext_blob, + ntlmssp_flags, True); + + data_blob_free(&local_lm_blob); + data_blob_free(&local_nt_blob); + return ret; + } +} + +/**************************************************************************** + Create an auth_usersupplied_data structure +****************************************************************************/ + +BOOL make_user_info_for_winbind(auth_usersupplied_info **user_info, + char *username, + char *domain, + char *password) +{ + unsigned char local_lm_response[24]; + unsigned char local_nt_response[24]; + char chal[8]; + DATA_BLOB local_lm_blob; + DATA_BLOB local_nt_blob; + DATA_BLOB plaintext_blob; + uint32 ntlmssp_flags = 0; + + /* + * Not encrypted - do so. + */ + + DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n")); + + generate_random_buffer(chal, 8, False); + + if (*password) { + SMBencrypt( (uchar *)password, chal, local_lm_response); + + /* This encrypts the lm_pwd feild, which actualy contains the password + rather than the nt_pwd field becouse that contains nothing */ + + /* 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 */ + + SMBNTencrypt((uchar *)password, chal, local_nt_response); + + local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response)); + local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); + plaintext_blob = data_blob(password, strlen(password)+1); + if ((!local_lm_blob.data) || (!local_nt_blob.data)|| (!plaintext_blob.data)) { + data_blob_free(&local_lm_blob); + data_blob_free(&local_nt_blob); + data_blob_clear_free(&plaintext_blob); + return False; + } + ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_NTLM; + } else { + local_lm_blob = data_blob(NULL, 0); + local_nt_blob = data_blob(NULL, 0); + plaintext_blob = data_blob(NULL, 0); + } + + { + BOOL ret; + DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); + + if (!sec_blob.data) { + return False; + } + + ret = make_user_info(user_info, + username, username, + domain, domain, + global_myname, sec_blob, + local_nt_blob, + local_lm_blob, + plaintext_blob, + ntlmssp_flags, False); + + data_blob_free(&local_lm_blob); + data_blob_free(&local_nt_blob); + data_blob_clear_free(&plaintext_blob); + return ret; + } +} + +/**************************************************************************** + Create an auth_usersupplied_data, making the DATA_BLOBs here. + Decrupt and encrypt the passwords. +****************************************************************************/ + +BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + uchar chal[8], + uchar *lm_network_pwd, int lm_pwd_len, + uchar *nt_network_pwd, int nt_pwd_len) +{ + BOOL ret; + DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); + 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 ntlmssp_flags = 0; + + if (lm_pwd_len) + ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; + if (nt_pwd_len) + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; + + ret = make_user_info(user_info, + smb_name, smb_name, + client_domain, client_domain, + global_myname, sec_blob, + nt_blob, lm_blob, + plaintext_blob, + ntlmssp_flags, True); + + data_blob_free(&lm_blob); + data_blob_free(&nt_blob); + return ret; +} + +/**************************************************************************** + Create an auth_usersupplied_data structure +****************************************************************************/ + +BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + DATA_BLOB lm_resp, DATA_BLOB nt_resp, + DATA_BLOB plaintext_password, + BOOL encrypted) +{ + uchar chal[8]; + + DATA_BLOB local_lm_blob; + DATA_BLOB local_nt_blob; + DATA_BLOB sec_blob; + BOOL ret = False; + uint32 ntlmssp_flags = 0; + + if (encrypted) { + DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); + if (!last_challenge(chal)) { + DEBUG(0,("Encrypted login but no challange set!\n")); + return False; + } + sec_blob = data_blob(chal, 8); + + if (lm_resp.length == 24) { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; + } + if (nt_resp.length == 0) { + } else if (nt_resp.length == 24) { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; + } else { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2; + } + + return make_user_info_map(user_info, smb_name, + client_domain, + remote_machine, sec_blob, + lm_resp, + nt_resp, + no_plaintext_blob, + ntlmssp_flags, encrypted); + } + + generate_random_buffer(chal, 8, False); + + sec_blob = data_blob(chal, 8); + + /* + * Not encrypted - do so. + */ + + DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n")); + + if (plaintext_password.data) { + unsigned char local_lm_response[24]; + + SMBencrypt( (uchar *)plaintext_password.data, chal, local_lm_response); + local_lm_blob = data_blob(local_lm_response, 24); + + /* We can't do an NT hash here, as the password needs to be case insensitive */ + local_nt_blob = data_blob(NULL, 0); + + ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM; + } else { + local_lm_blob = data_blob(NULL, 0); + local_nt_blob = data_blob(NULL, 0); + } + + ret = make_user_info_map(user_info, smb_name, + client_domain, + remote_machine, + sec_blob, + local_lm_blob, + local_nt_blob, + plaintext_password, + ntlmssp_flags, encrypted); + + data_blob_free(&local_lm_blob); + return ret; +} + +BOOL make_server_info(auth_serversupplied_info **server_info) +{ + *server_info = malloc(sizeof(**server_info)); + if (!*server_info) { + DEBUG(0,("make_server_info_sam: malloc failed!\n")); + return False; + } + ZERO_STRUCTP(*server_info); + return True; +} + +BOOL make_server_info_sam(auth_serversupplied_info **server_info, SAM_ACCOUNT *sampass) +{ + if (!make_server_info(server_info)) { + return False; + } + + (*server_info)->sam_fill_level = SAM_FILL_ALL; + (*server_info)->sam_account = sampass; + + DEBUG(5,("make_server_info_sam: made sever info for user %s\n", + pdb_get_username((*server_info)->sam_account))); + return True; +} + +BOOL make_server_info_pw(auth_serversupplied_info **server_info, struct passwd *pwd) +{ + SAM_ACCOUNT *sampass = NULL; + if (!pdb_init_sam_pw(&sampass, pwd)) { + return False; + } + return make_server_info_sam(server_info, sampass); +} + +void free_user_info(auth_usersupplied_info **user_info) +{ + DEBUG(5,("attempting to free (and zero) a user_info structure\n")); + if (*user_info != NULL) { + if ((*user_info)->smb_name.str) { + DEBUG(10,("structure was created for %s\n", (*user_info)->smb_name.str)); + } + SAFE_FREE((*user_info)->smb_name.str); + SAFE_FREE((*user_info)->internal_username.str); + SAFE_FREE((*user_info)->client_domain.str); + SAFE_FREE((*user_info)->domain.str); + data_blob_free(&(*user_info)->sec_blob); + 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)->plaintext_password); + ZERO_STRUCT(**user_info); + } + SAFE_FREE(*user_info); +} + +/*************************************************************************** + Clear out a server_info struct that has been allocated +***************************************************************************/ +void free_server_info(auth_serversupplied_info **server_info) +{ + if (*server_info != NULL) { + pdb_free_sam(&(*server_info)->sam_account); + + /* call pam_end here, unless we know we are keeping it */ + SAFE_FREE((*server_info)->group_rids); + + ZERO_STRUCT(**server_info); + } + SAFE_FREE(*server_info); +} + +/*************************************************************************** + Make a server_info struct for a guest user +***************************************************************************/ +void make_server_info_guest(auth_serversupplied_info **server_info) +{ + struct passwd *pass = sys_getpwnam(lp_guestaccount(-1)); + + if (pass) { + make_server_info_pw(server_info, pass); + } +} + diff --git a/source3/include/auth.h b/source3/include/auth.h index 9e99600e98..427cb8b489 100644 --- a/source3/include/auth.h +++ b/source3/include/auth.h @@ -35,58 +35,44 @@ typedef struct unicode_string uchar *unistr; } AUTH_UNISTR; -/* AUTH_BUFFER - 8-bit byte buffer */ -typedef struct auth_buffer -{ - int len; - uint8 *buffer; -} AUTH_BUFFER; - -typedef struct net_password -{ - AUTH_BUFFER lm_resp; - AUTH_BUFFER nt_resp; -} auth_net_password; - typedef struct interactive_password { OWF_INFO lm_owf; /* LM OWF Password */ OWF_INFO nt_owf; /* NT OWF Password */ } auth_interactive_password; -typedef struct plaintext_password -{ - AUTH_STR password; -} auth_plaintext_password; - typedef struct usersupplied_info { - AUTH_BUFFER lm_resp; - AUTH_BUFFER nt_resp; + DATA_BLOB lm_resp; + DATA_BLOB nt_resp; auth_interactive_password * interactive_password; - AUTH_STR plaintext_password; + DATA_BLOB plaintext_password; - uint8 chal[8]; + BOOL encrypted; + + uint32 ntlmssp_flags; + + DATA_BLOB sec_blob; - AUTH_STR requested_domain; /* domain name string */ + AUTH_STR client_domain; /* domain name string */ AUTH_STR domain; /* domain name after mapping */ - AUTH_STR unix_username; /* username after mapping */ - AUTH_STR smb_username; /* username before mapping */ + AUTH_STR internal_username; /* username after mapping */ + AUTH_STR smb_name; /* username before mapping */ AUTH_STR wksta_name; /* workstation name (netbios calling name) unicode string */ } auth_usersupplied_info; +#define SAM_FILL_NAME 0x01 +#define SAM_FILL_INFO3 0x02 +#define SAM_FILL_SAM 0x04 +#define SAM_FILL_UNIX 0x08 +#define SAM_FILL_ALL (SAM_FILL_NAME | SAM_FILL_INFO3 | SAM_FILL_SAM | SAM_FILL_UNIX) + typedef struct serversupplied_info { - AUTH_STR full_name; - AUTH_STR unix_user; - BOOL guest; - uid_t unix_uid; - gid_t unix_gid; - /* This groups info is needed for when we become_user() for this uid */ int n_groups; gid_t *groups; @@ -98,6 +84,11 @@ typedef struct serversupplied_info uchar session_key[16]; + uint8 first_8_lm_hash[8]; + + uint32 sam_fill_level; /* How far is this structure filled? */ + + SAM_ACCOUNT *sam_account; } auth_serversupplied_info; #endif /* _SMBAUTH_H_ */ diff --git a/source3/include/smb.h b/source3/include/smb.h index dea5bb66df..0e48b4c6c0 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -591,8 +591,8 @@ typedef struct sam_passwd pstring unknown_str ; /* don't know what this is, yet. */ pstring munged_dial ; /* munged path name and dial-back tel number */ - uid_t uid; /* this is actually the unix uid_t */ - gid_t gid; /* this is actually the unix gid_t */ + uid_t *uid; /* this is a pointer to the unix uid_t */ + gid_t *gid; /* this is a pointer to the unix gid_t */ uint32 user_rid; /* Primary User ID */ uint32 group_rid; /* Primary Group ID */ diff --git a/source3/libsmb/domain_client_validate.c b/source3/libsmb/domain_client_validate.c index 26a727b1f1..20db1ee4d6 100644 --- a/source3/libsmb/domain_client_validate.c +++ b/source3/libsmb/domain_client_validate.c @@ -271,7 +271,7 @@ static BOOL find_connect_pdc(struct cli_state *pcli, ************************************************************************/ NTSTATUS domain_client_validate(const auth_usersupplied_info *user_info, - auth_serversupplied_info *server_info, + auth_serversupplied_info **server_info, char *server, unsigned char *trust_passwd, time_t last_change_time) { @@ -282,6 +282,7 @@ NTSTATUS domain_client_validate(const auth_usersupplied_info *user_info, uint32 smb_uid_low; BOOL connected_ok = False; NTSTATUS status; + struct passwd *pass; /* * Check that the requested domain is not our own machine name. @@ -330,34 +331,48 @@ NTSTATUS domain_client_validate(const auth_usersupplied_info *user_info, if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("domain_client_validate: unable to validate password " "for user %s in domain %s to Domain controller %s. " - "Error was %s.\n", user_info->smb_username.str, + "Error was %s.\n", user_info->smb_name.str, user_info->domain.str, cli.srv_name_slash, get_nt_error_msg(status))); - } + } else { - /* - * Here, if we really want it, we have lots of info about the user - * in info3. - */ + /* + * Here, if we really want it, we have lots of info about the user + * in info3. + */ + + pass = Get_Pwnam(user_info->internal_username.str); + if (pass) { + make_server_info_pw(server_info, pass); + if (!server_info) { + status = NT_STATUS_NO_MEMORY; + } + } else { + status = NT_STATUS_NO_SUCH_USER; + } + } /* Store the user group information in the server_info returned to the caller. */ - - if ((server_info->group_rids = malloc(info3.num_groups2 * - sizeof(uint32))) == NULL) { - DEBUG(1, ("out of memory allocating rid group membership\n")); - status = NT_STATUS_NO_MEMORY; - } else { - int i; - - server_info->n_rids = info3.num_groups2; - - for (i = 0; i < server_info->n_rids; i++) { - server_info->group_rids[i] = info3.gids[i].g_rid; - DEBUG(5, ("** adding group rid 0x%x\n", - info3.gids[i].g_rid)); - } - } + + if (NT_STATUS_IS_OK(status)) { + if (((*server_info)->group_rids = malloc(info3.num_groups2 * + sizeof(uint32))) == NULL) { + DEBUG(1, ("out of memory allocating rid group membership\n")); + status = NT_STATUS_NO_MEMORY; + free_server_info(server_info); + } else { + int i; + + (*server_info)->n_rids = info3.num_groups2; + + for (i = 0; i < (*server_info)->n_rids; i++) { + (*server_info)->group_rids[i] = info3.gids[i].g_rid; + DEBUG(5, ("** adding group rid 0x%x\n", + info3.gids[i].g_rid)); + } + } + } #if 0 /* diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c index 2868b02ed9..c1c4750e05 100644 --- a/source3/libsmb/smbencrypt.c +++ b/source3/libsmb/smbencrypt.c @@ -216,27 +216,27 @@ BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[ /* Does the md5 encryption from the NT hash for NTLMv2. */ void SMBOWFencrypt_ntv2(const uchar kr[16], - const uchar * srv_chal, int srv_chal_len, - const uchar * cli_chal, int cli_chal_len, + const DATA_BLOB srv_chal, + const DATA_BLOB cli_chal, char resp_buf[16]) { HMACMD5Context ctx; hmac_md5_init_limK_to_64(kr, 16, &ctx); - hmac_md5_update(srv_chal, srv_chal_len, &ctx); - hmac_md5_update(cli_chal, cli_chal_len, &ctx); + hmac_md5_update(srv_chal.data, srv_chal.length, &ctx); + hmac_md5_update(cli_chal.data, cli_chal.length, &ctx); hmac_md5_final((unsigned char *)resp_buf, &ctx); #ifdef DEBUG_PASSWORD DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n")); - dump_data(100, srv_chal, srv_chal_len); - dump_data(100, cli_chal, cli_chal_len); + dump_data(100, srv_chal.data, srv_chal.length); + dump_data(100, cli_chal.data, cli_chal.length); dump_data(100, resp_buf, 16); #endif } void SMBsesskeygen_ntv2(const uchar kr[16], - const uchar * nt_resp, char sess_key[16]) + const uchar * nt_resp, uint8 sess_key[16]) { HMACMD5Context ctx; @@ -251,7 +251,7 @@ void SMBsesskeygen_ntv2(const uchar kr[16], } void SMBsesskeygen_ntv1(const uchar kr[16], - const uchar * nt_resp, char sess_key[16]) + const uchar * nt_resp, uint8 sess_key[16]) { mdfour((unsigned char *)sess_key, kr, 16); diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 5cf819a19d..59623b9f04 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -60,12 +60,8 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) unsigned char trust_passwd[16]; time_t last_change_time; - unsigned char local_lm_response[24]; - unsigned char local_nt_response[24]; - - auth_usersupplied_info user_info; - auth_serversupplied_info server_info; - AUTH_STR theirdomain, smb_username, wksta_name; + auth_usersupplied_info *user_info; + auth_serversupplied_info *server_info; DEBUG(3, ("[%5d]: pam auth %s\n", state->pid, state->request.data.auth.user)); @@ -82,37 +78,10 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) passlen = strlen(state->request.data.auth.pass); - ZERO_STRUCT(user_info); - ZERO_STRUCT(theirdomain); - ZERO_STRUCT(smb_username); - ZERO_STRUCT(wksta_name); - - theirdomain.str = name_domain; - theirdomain.len = strlen(theirdomain.str); - - user_info.requested_domain = theirdomain; - user_info.domain = theirdomain; - - user_info.smb_username.str = name_user; - user_info.smb_username.len = strlen(name_user); - - user_info.unix_username.str = name_user; - user_info.unix_username.len = strlen(name_user); - - user_info.wksta_name.str = global_myname; - user_info.wksta_name.len = strlen(user_info.wksta_name.str); - - user_info.wksta_name = wksta_name; - - generate_random_buffer( user_info.chal, 8, False); - if (state->request.data.auth.pass[0]) { - SMBencrypt((uchar *)state->request.data.auth.pass, user_info.chal, local_lm_response); - user_info.lm_resp.buffer = (uint8 *)local_lm_response; - user_info.lm_resp.len = 24; - SMBNTencrypt((uchar *)state->request.data.auth.pass, user_info.chal, local_nt_response); - user_info.nt_resp.buffer = (uint8 *)local_nt_response; - user_info.nt_resp.len = 24; + make_user_info_for_winbind(&user_info, + name_user, name_domain, + state->request.data.auth.pass); } else { return WINBINDD_ERROR; } @@ -137,11 +106,11 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) for each authentication performed. This can theoretically be optimised to use an already open IPC$ connection. */ - result = domain_client_validate(&user_info, &server_info, + result = domain_client_validate(user_info, &server_info, auth_dc, trust_passwd, last_change_time); - free_serversupplied_info(&server_info); /* No info needed */ + free_server_info(&server_info); /* No info needed */ return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } @@ -154,9 +123,8 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) fstring name_domain, name_user, auth_dc; unsigned char trust_passwd[16]; time_t last_change_time; - auth_usersupplied_info user_info; - auth_serversupplied_info server_info; - AUTH_STR theirdomain, smb_username, wksta_name; + auth_usersupplied_info *user_info; + auth_serversupplied_info *server_info; DEBUG(3, ("[%5d]: pam auth crap %s\n", state->pid, state->request.data.auth_crap.user)); @@ -166,36 +134,11 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) parse_domain_user(state->request.data.auth_crap.user, name_domain, name_user); - ZERO_STRUCT(user_info); - ZERO_STRUCT(theirdomain); - ZERO_STRUCT(smb_username); - ZERO_STRUCT(wksta_name); + make_user_info_winbind_crap(&user_info, name_user, + name_domain, state->request.data.auth_crap.chal, + (uchar *)state->request.data.auth_crap.lm_resp, 24, + (uchar *)state->request.data.auth_crap.nt_resp, 24); - theirdomain.str = name_domain; - theirdomain.len = strlen(theirdomain.str); - - user_info.requested_domain = theirdomain; - user_info.domain = theirdomain; - - user_info.smb_username.str = name_user; - user_info.smb_username.len = strlen(name_user); - - user_info.unix_username.str = name_user; - user_info.unix_username.len = strlen(name_user); - - user_info.wksta_name.str = global_myname; - user_info.wksta_name.len = strlen(user_info.wksta_name.str); - - user_info.wksta_name = wksta_name; - - memcpy(user_info.chal, state->request.data.auth_crap.chal, 8); - - user_info.lm_resp.buffer = (uchar *)state->request.data.auth_crap.lm_resp; - user_info.nt_resp.buffer = (uchar *)state->request.data.auth_crap.nt_resp; - - user_info.lm_resp.len = 24; - user_info.nt_resp.len = 24; - /* * Get the machine account password for our primary domain */ @@ -216,11 +159,11 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) for each authentication performed. This can theoretically be optimised to use an already open IPC$ connection. */ - result = domain_client_validate(&user_info, &server_info, + result = domain_client_validate(user_info, &server_info, auth_dc, trust_passwd, last_change_time); - free_serversupplied_info(&server_info); /* No info needed */ + free_server_info(&server_info); /* No info needed */ return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 6a96426a9f..05d448f963 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -135,8 +135,9 @@ BOOL pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, struct passwd *pwd) pdb_set_username(*new_sam_acct, pwd->pw_name); pdb_set_fullname(*new_sam_acct, pwd->pw_gecos); - pdb_set_uid(*new_sam_acct, pwd->pw_uid); - pdb_set_gid(*new_sam_acct, pwd->pw_gid); + + pdb_set_uid(*new_sam_acct, &pwd->pw_uid); + pdb_set_gid(*new_sam_acct, &pwd->pw_gid); pdb_set_user_rid(*new_sam_acct, pdb_uid_to_user_rid(pwd->pw_uid)); pdb_set_group_rid(*new_sam_acct, pdb_gid_to_group_rid(pwd->pw_gid)); @@ -186,6 +187,9 @@ static BOOL pdb_free_sam_contents(SAM_ACCOUNT *user) SAFE_FREE(user->nt_pw); SAFE_FREE(user->lm_pw); + + SAFE_FREE(user->uid); + SAFE_FREE(user->gid); return True; } @@ -1113,20 +1117,20 @@ uint32 pdb_get_group_rid (const SAM_ACCOUNT *sampass) return (-1); } -uid_t pdb_get_uid (const SAM_ACCOUNT *sampass) +uid_t *pdb_get_uid (const SAM_ACCOUNT *sampass) { if (sampass) return (sampass->uid); else - return ((uid_t)-1); + return (NULL); } -gid_t pdb_get_gid (const SAM_ACCOUNT *sampass) +gid_t *pdb_get_gid (const SAM_ACCOUNT *sampass) { if (sampass) return (sampass->gid); else - return ((gid_t)-1); + return (NULL); } const char* pdb_get_username (const SAM_ACCOUNT *sampass) @@ -1330,22 +1334,62 @@ BOOL pdb_set_logons_divs (SAM_ACCOUNT *sampass, uint16 hours) return True; } -BOOL pdb_set_uid (SAM_ACCOUNT *sampass, uid_t uid) +/********************************************************************* + Set the user's UNIX uid, as a pointer to malloc'ed memory. + ********************************************************************/ + +BOOL pdb_set_uid (SAM_ACCOUNT *sampass, const uid_t *uid) { if (!sampass) return False; + + if (!uid) { + /* Allow setting to NULL */ + SAFE_FREE(sampass->uid); + return True; + } + + if (sampass->uid!=NULL) + DEBUG(4,("pdb_set_nt_passwd: uid non NULL overwritting ?\n")); + else + sampass->uid=(uid_t *)malloc(sizeof(uid_t)); + + if (sampass->uid==NULL) + return False; + + *sampass->uid = *uid; - sampass->uid = uid; return True; + } -BOOL pdb_set_gid (SAM_ACCOUNT *sampass, gid_t gid) +/********************************************************************* + Set the user's UNIX gid, as a pointer to malloc'ed memory. + ********************************************************************/ + +BOOL pdb_set_gid (SAM_ACCOUNT *sampass, const gid_t *gid) { if (!sampass) return False; + + if (!gid) { + /* Allow setting to NULL */ + SAFE_FREE(sampass->gid); + return True; + } + + if (sampass->gid!=NULL) + DEBUG(4,("pdb_set_nt_passwd: gid non NULL overwritting ?\n")); + else + sampass->gid=(gid_t *)malloc(sizeof(gid_t)); + + if (sampass->gid==NULL) + return False; + + *sampass->gid = *gid; - sampass->gid = gid; return True; + } BOOL pdb_set_user_rid (SAM_ACCOUNT *sampass, uint32 rid) diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index 8524275f12..e190be99a5 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -1135,12 +1135,22 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno))); ********************************************************************/ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampass) { + uid_t *uid; + gid_t *gid; + if (sampass == NULL) return False; + uid = pdb_get_uid(sampass); + gid = pdb_get_gid(sampass); + + if (!uid || !gid) { + DEBUG(0,("build_sam_pass: Failing attempt to store user without a UNIX uid or gid. \n")); + return False; + } ZERO_STRUCTP(smb_pw); - smb_pw->smb_userid=pdb_get_uid(sampass); + smb_pw->smb_userid=*uid; smb_pw->smb_name=pdb_get_username(sampass); smb_pw->smb_passwd=pdb_get_lanman_passwd(sampass); @@ -1149,12 +1159,12 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas smb_pw->acct_ctrl=pdb_get_acct_ctrl(sampass); smb_pw->pass_last_set_time=pdb_get_pass_last_set_time(sampass); - if (smb_pw->smb_userid != pdb_user_rid_to_uid(pdb_get_user_rid(sampass))) { + if (*uid != pdb_user_rid_to_uid(pdb_get_user_rid(sampass))) { DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n")); return False; } - if (pdb_get_gid(sampass) != pdb_group_rid_to_gid(pdb_get_group_rid(sampass))) { + if (*gid != pdb_group_rid_to_gid(pdb_get_group_rid(sampass))) { DEBUG(0,("build_sam_pass: Failing attempt to store user with non-gid based primary group RID. \n")); return False; } @@ -1184,14 +1194,15 @@ static BOOL build_sam_account(SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw return False; } + pdb_set_uid (sam_pass, &pwfile->pw_uid); + pdb_set_gid (sam_pass, &pwfile->pw_gid); + /* FIXME!! This doesn't belong here. Should be set in net_sam_logon() --jerry */ + pstrcpy(samlogon_user, pw_buf->smb_name); - sam_logon_in_ssb = True; - pdb_set_uid (sam_pass, pwfile->pw_uid); - pdb_set_gid (sam_pass, pwfile->pw_gid); pdb_set_fullname(sam_pass, pwfile->pw_gecos); pdb_set_user_rid(sam_pass, pdb_uid_to_user_rid (pwfile->pw_uid)); diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 9b5f7379f5..e4e33d257f 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -927,7 +927,7 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in, int action; NTSTATUS nt_status; pstring driverpath; - fstring null_pw; + DATA_BLOB null_pw; files_struct *fsp = NULL; BOOL bad_path; SMB_STRUCT_STAT st; @@ -943,10 +943,10 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in, /* connect to the print$ share under the same account as the user connected to the rpc pipe */ /* Null password is ok - we are already an authenticated user... */ - *null_pw = '\0'; + null_pw = data_blob(NULL, 0); become_root(); - conn = make_connection("print$", null_pw, 0, "A:", user->vuid, &nt_status); + conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status); unbecome_root(); if (conn == NULL) { @@ -1230,7 +1230,7 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, pstring new_dir; pstring old_name; pstring new_name; - fstring null_pw; + DATA_BLOB null_pw; connection_struct *conn; NTSTATUS nt_status; int ver = 0; @@ -1252,8 +1252,8 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, /* connect to the print$ share under the same account as the user connected to the rpc pipe */ /* Null password is ok - we are already an authenticated user... */ - *null_pw = '\0'; - conn = make_connection("print$", null_pw, 0, "A:", user->vuid, &nt_status); + null_pw = data_blob(NULL, 0); + conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status); if (conn == NULL) { DEBUG(0,("move_driver_to_download_area: Unable to connect\n")); diff --git a/source3/rpc_client/cli_login.c b/source3/rpc_client/cli_login.c index 0f54d5512c..eaedb1613a 100644 --- a/source3/rpc_client/cli_login.c +++ b/source3/rpc_client/cli_login.c @@ -169,14 +169,14 @@ NTSTATUS cli_nt_login_network(struct cli_state *cli, /* Create the structure needed for SAM logon. */ init_id_info2(&ctr->auth.id2, user_info->domain.str, 0, smb_userid_low, 0, - user_info->smb_username.str, + user_info->smb_name.str, /* Send our cleint's workstaion name if we have it, otherwise ours */ ((user_info->wksta_name.len > 0) ? user_info->wksta_name.str : cli->clnt_name_slash), - user_info->chal, - user_info->lm_resp.buffer, user_info->lm_resp.len, - user_info->nt_resp.buffer, user_info->nt_resp.len); + user_info->sec_blob.data, + user_info->lm_resp.data, user_info->lm_resp.length, + user_info->nt_resp.data, user_info->nt_resp.length); /* Send client sam-logon request - update credentials on success. */ return cli_net_sam_logon(cli, ctr, user_info3); diff --git a/source3/rpc_parse/parse_net.c b/source3/rpc_parse/parse_net.c index 2f0dd1eb62..c546213173 100644 --- a/source3/rpc_parse/parse_net.c +++ b/source3/rpc_parse/parse_net.c @@ -1193,7 +1193,7 @@ static BOOL smb_io_sam_info(char *desc, DOM_SAM_INFO *sam, prs_struct *ps, int d void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr, SAM_ACCOUNT *sampw, uint16 logon_count, uint16 bad_pw_count, uint32 num_groups, DOM_GID *gids, - uint32 user_flgs, char *sess_key, + uint32 user_flgs, uchar *sess_key, char *logon_srv, char *logon_dom, DOM_SID *dom_sid, char *other_sids) { diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 0f2b672d38..26054117fb 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -484,123 +484,6 @@ NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOF return r_u->status; } -/************************************************************************* - _net_logon_any: Use the new authentications subsystem to log in. - *************************************************************************/ - -static NTSTATUS _net_logon_any(NET_ID_INFO_CTR *ctr, char *user, char *domain, char *workstation, char *sess_key) -{ - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - - unsigned char local_lm_response[24]; - unsigned char local_nt_response[24]; - - auth_usersupplied_info user_info; - auth_serversupplied_info server_info; - AUTH_STR ourdomain, theirdomain, smb_username, wksta_name; - - DEBUG(5, ("_net_logon_any: entered with user %s and domain %s\n", user, domain)); - - ZERO_STRUCT(user_info); - ZERO_STRUCT(server_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 = user; - smb_username.len = strlen(smb_username.str); - - user_info.unix_username = smb_username; /* For the time-being */ - user_info.smb_username = smb_username; - - user_info.wksta_name.str = workstation; - user_info.wksta_name.len = strlen(workstation); - - user_info.wksta_name = wksta_name; - - DEBUG(10,("_net_logon_any: Attempting validation level %d.\n", ctr->switch_value)); - switch (ctr->switch_value) { - case NET_LOGON_TYPE: - /* Standard challange/response authenticaion */ - - user_info.lm_resp.buffer = (uint8 *)ctr->auth.id2.lm_chal_resp.buffer; - user_info.lm_resp.len = ctr->auth.id2.lm_chal_resp.str_str_len; - user_info.nt_resp.buffer = (uint8 *)ctr->auth.id2.nt_chal_resp.buffer; - user_info.nt_resp.len = ctr->auth.id2.nt_chal_resp.str_str_len; - memcpy(user_info.chal, ctr->auth.id2.lm_chal, 8); - break; - case INTERACTIVE_LOGON_TYPE: - /* 'Interactive' autheticaion, supplies the password in its MD4 form, encrypted - with the session key. We will convert this to challange/responce for the - auth subsystem to chew on */ - { - char nt_pwd[16]; - char lm_pwd[16]; - unsigned char key[16]; - - memset(key, 0, 16); - memcpy(key, sess_key, 8); - - memcpy(lm_pwd, ctr->auth.id1.lm_owf.data, 16); - memcpy(nt_pwd, ctr->auth.id1.nt_owf.data, 16); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("key:")); - dump_data(100, (char *)key, 16); - - DEBUG(100,("lm owf password:")); - dump_data(100, lm_pwd, 16); - - DEBUG(100,("nt owf password:")); - dump_data(100, nt_pwd, 16); -#endif - - SamOEMhash((uchar *)lm_pwd, key, 16); - SamOEMhash((uchar *)nt_pwd, key, 16); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("decrypt of lm owf password:")); - dump_data(100, lm_pwd, 16); - - DEBUG(100,("decrypt of nt owf password:")); - dump_data(100, nt_pwd, 16); -#endif - - generate_random_buffer(user_info.chal, 8, False); - SMBOWFencrypt((const unsigned char *)lm_pwd, user_info.chal, local_lm_response); - SMBOWFencrypt((const unsigned char *)nt_pwd, user_info.chal, local_nt_response); - user_info.lm_resp.buffer = (uint8 *)local_lm_response; - user_info.lm_resp.len = 24; - user_info.nt_resp.buffer = (uint8 *)local_nt_response; - user_info.nt_resp.len = 24; - break; - } - default: - DEBUG(2,("SAM Logon: unsupported switch value\n")); - return NT_STATUS_INVALID_INFO_CLASS; - } /* end switch */ - - nt_status = check_password(&user_info, &server_info); - - DEBUG(5, ("_net_logon_any: exited with status %s\n", - get_nt_error_msg(nt_status))); - - free_serversupplied_info(&server_info); /* No info needed */ - - return nt_status; -} - - /************************************************************************* _net_sam_logon @@ -610,15 +493,16 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * { NTSTATUS status = NT_STATUS_OK; NET_USER_INFO_3 *usr_info = NULL; + NET_ID_INFO_CTR *ctr = q_u->sam_id.ctr; DOM_CRED srv_cred; SAM_ACCOUNT *sampass = NULL; UNISTR2 *uni_samlogon_user = NULL; UNISTR2 *uni_samlogon_domain = NULL; UNISTR2 *uni_samlogon_workstation = NULL; fstring nt_username, nt_domain, nt_workstation; - - BOOL ret; - + auth_usersupplied_info *user_info; + auth_serversupplied_info *server_info; + usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3)); if (!usr_info) return NT_STATUS_NO_MEMORY; @@ -647,16 +531,17 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * switch (q_u->sam_id.logon_level) { case INTERACTIVE_LOGON_TYPE: - uni_samlogon_user = &q_u->sam_id.ctr->auth.id1.uni_user_name; - uni_samlogon_domain = &q_u->sam_id.ctr->auth.id1.uni_domain_name; - uni_samlogon_workstation = &q_u->sam_id.ctr->auth.id1.uni_wksta_name; + uni_samlogon_user = &ctr->auth.id1.uni_user_name; + uni_samlogon_domain = &ctr->auth.id1.uni_domain_name; + + uni_samlogon_workstation = &ctr->auth.id1.uni_wksta_name; DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. ", lp_workgroup())); break; case NET_LOGON_TYPE: - uni_samlogon_user = &q_u->sam_id.ctr->auth.id2.uni_user_name; - uni_samlogon_domain = &q_u->sam_id.ctr->auth.id2.uni_domain_name; - uni_samlogon_workstation = &q_u->sam_id.ctr->auth.id2.uni_wksta_name; + uni_samlogon_user = &ctr->auth.id2.uni_user_name; + uni_samlogon_domain = &ctr->auth.id2.uni_domain_name; + uni_samlogon_workstation = &ctr->auth.id2.uni_wksta_name; DEBUG(3,("SAM Logon (Network). Domain:[%s]. ", lp_workgroup())); break; @@ -678,29 +563,51 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * * Convert to a UNIX username. */ - map_username(nt_username); + DEBUG(5,("Attempting validation level %d for unmapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username)); - DEBUG(10,("Attempting validation level %d for mapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username)); + switch (ctr->switch_value) { + case NET_LOGON_TYPE: + /* Standard challange/response authenticaion */ + make_user_info_netlogon_network(&user_info, + nt_username, nt_domain, + nt_workstation, ctr->auth.id2.lm_chal, + ctr->auth.id2.lm_chal_resp.buffer, + ctr->auth.id2.lm_chal_resp.str_str_len, + ctr->auth.id2.nt_chal_resp.buffer, + ctr->auth.id2.nt_chal_resp.str_str_len); + break; + case INTERACTIVE_LOGON_TYPE: + /* 'Interactive' autheticaion, supplies the password in its MD4 form, encrypted + with the session key. We will convert this to challange/responce for the + auth subsystem to chew on */ + { + make_user_info_netlogon_interactive(&user_info, + nt_username, nt_domain, + nt_workstation, + ctr->auth.id1.lm_owf.data, 16, + ctr->auth.id1.lm_owf.data, 16, + p->dc.sess_key); + break; + } + default: + DEBUG(2,("SAM Logon: unsupported switch value\n")); + return NT_STATUS_INVALID_INFO_CLASS; + } /* end switch */ + + status = check_password(user_info, &server_info); - status = _net_logon_any(q_u->sam_id.ctr, nt_username, nt_domain, nt_workstation, (char *)p->dc.sess_key); + free_user_info(&user_info); + + DEBUG(5, ("_net_sam_logon: exiting with status %s\n", + get_nt_error_msg(status))); /* Check account and password */ - if (NT_STATUS_IS_ERR(status)) + if (NT_STATUS_IS_ERR(status)) { + free_server_info(&server_info); return status; - - pdb_init_sam(&sampass); - - /* get the account information */ - become_root(); - ret = pdb_getsampwnam(sampass, nt_username); - unbecome_root(); - - if (ret == False) { - pdb_free_sam(&sampass); - return NT_STATUS_NO_SUCH_USER; } - + /* This is the point at which, if the login was successful, that the SAM Local Security Authority should record that the user is logged in to the domain. */ @@ -748,12 +655,14 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * num_gids, /* uint32 num_groups */ gids , /* DOM_GID *gids */ 0x20 , /* uint32 user_flgs (?) */ - NULL, /* char sess_key[16] */ + NULL, /* uchar sess_key[16] */ my_name , /* char *logon_srv */ my_workgroup, /* char *logon_dom */ &global_sam_sid, /* DOM_SID *dom_sid */ NULL); /* char *other_sids */ } - pdb_free_sam(&sampass); + free_server_info(&server_info); return status; } + + diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 6f3c050519..21de4d3d2b 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -269,10 +269,16 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm fstring domain; fstring wks; BOOL guest_user = False; - SAM_ACCOUNT *sampass = NULL; uchar null_smb_passwd[16]; + const uchar *smb_passwd_ptr = NULL; + auth_usersupplied_info *user_info; + auth_serversupplied_info *server_info; + + uid_t *puid; + uid_t *pgid; + DEBUG(5,("api_pipe_ntlmssp_verify: checking user details\n")); memset(p->user_name, '\0', sizeof(p->user_name)); @@ -336,14 +342,6 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm } else { - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - fstrcpy(pipe_user_name, user_name); - (void)map_username(pipe_user_name); - /* * Do the length checking only if user is not NULL. */ @@ -362,41 +360,28 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm } if(!guest_user) { + NTSTATUS nt_status; - become_root(); - - p->ntlmssp_auth_validated = - NT_STATUS_IS_OK(pass_check_smb_with_chal(pipe_user_name, NULL, - domain, wks, - (uchar*)p->challenge, - lm_owf, lm_pw_len, - nt_owf, nt_pw_len)); - if (!p->ntlmssp_auth_validated) { - DEBUG(1,("api_pipe_ntlmssp_verify: User %s\\%s from machine %s \ -failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name )); - unbecome_root(); + if (!make_user_info_netlogon_network(&user_info, + user_name, domain, wks, (uchar*)p->challenge, + lm_owf, lm_pw_len, + nt_owf, nt_pw_len)) { + DEBUG(0,("make_user_info_netlogon_network failed! Failing authenticaion.\n")); return False; } - pdb_init_sam(&sampass); - - if(!pdb_getsampwnam(sampass, pipe_user_name)) { - DEBUG(1,("api_pipe_ntlmssp_verify: Cannot find user %s in smb passwd database.\n", - pipe_user_name)); - pdb_free_sam(&sampass); - unbecome_root(); - return False; - } + nt_status = check_password(user_info, &server_info); + + free_user_info(&user_info); - unbecome_root(); + p->ntlmssp_auth_validated = NT_STATUS_IS_OK(nt_status); - if(!pdb_get_nt_passwd(sampass)) { - DEBUG(1,("Account for user '%s' has no NT password hash.\n", pipe_user_name)); - pdb_free_sam(&sampass); + if (!p->ntlmssp_auth_validated) { + DEBUG(1,("api_pipe_ntlmssp_verify: User %s\\%s from machine %s \ +failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name )); + free_server_info(&server_info); return False; - } - - smb_passwd_ptr = pdb_get_lanman_passwd(sampass); + } } /* @@ -405,7 +390,7 @@ failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name { uchar p24[24]; - NTLMSSPOWFencrypt(smb_passwd_ptr, lm_owf, p24); + NTLMSSPOWFencrypt(server_info->first_8_lm_hash, lm_owf, p24); { unsigned char j = 0; int ind; @@ -447,8 +432,17 @@ failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name * Store the UNIX credential data (uid/gid pair) in the pipe structure. */ - p->pipe_user.uid = pdb_get_uid(sampass); - p->pipe_user.gid = pdb_get_gid(sampass); + puid = pdb_get_uid(server_info->sam_account); + pgid = pdb_get_gid(server_info->sam_account); + + if (!puid || !pgid) { + DEBUG(0,("Attempted authenticated pipe with invalid user. No uid/gid in SAM_ACCOUNT\n")); + free_server_info(&server_info); + return False; + } + + p->pipe_user.uid = *puid; + p->pipe_user.gid = *pgid; /* Set up pipe user group membership. */ initialise_groups(pipe_user_name, p->pipe_user.uid, p->pipe_user.gid); @@ -461,7 +455,7 @@ failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name p->ntlmssp_auth_validated = True; - pdb_free_sam(&sampass); + pdb_free_sam(&server_info->sam_account); return True; } diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index 44e44cfa3a..7369c9d37d 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -1574,7 +1574,7 @@ NTSTATUS _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDE { SEC_DESC *psd = NULL; size_t sd_size; - fstring null_pw; + DATA_BLOB null_pw; pstring filename; pstring qualname; files_struct *fsp = NULL; @@ -1594,12 +1594,12 @@ NTSTATUS _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDE unistr2_to_ascii(qualname, &q_u->uni_qual_name, sizeof(qualname)); /* Null password is ok - we are already an authenticated user... */ - *null_pw = '\0'; + null_pw = data_blob(NULL, 0); get_current_user(&user, p); become_root(); - conn = make_connection(qualname, null_pw, 0, "A:", user.vuid, &nt_status); + conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status); unbecome_root(); if (conn == NULL) { @@ -1678,7 +1678,7 @@ NTSTATUS _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC * SRV_R_NET_FILE_SET_SECDESC *r_u) { BOOL ret; - fstring null_pw; + DATA_BLOB null_pw; pstring filename; pstring qualname; files_struct *fsp = NULL; @@ -1698,12 +1698,12 @@ NTSTATUS _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC * unistr2_to_ascii(qualname, &q_u->uni_qual_name, sizeof(qualname)); /* Null password is ok - we are already an authenticated user... */ - *null_pw = '\0'; + null_pw = data_blob(NULL, 0); get_current_user(&user, p); become_root(); - conn = make_connection(qualname, null_pw, 0, "A:", user.vuid, &nt_status); + conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status); unbecome_root(); if (conn == NULL) { 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); -} diff --git a/source3/smbd/auth_domain.c b/source3/smbd/auth_domain.c index bcd41bacdb..f20da19607 100644 --- a/source3/smbd/auth_domain.c +++ b/source3/smbd/auth_domain.c @@ -29,7 +29,7 @@ BOOL global_machine_password_needs_changing = False; ****************************************************************************/ NTSTATUS check_domain_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info *server_info) + auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; char *p, *pserver; diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c index 9f5f1e10e5..9c07e48a9b 100644 --- a/source3/smbd/auth_rhosts.c +++ b/source3/smbd/auth_rhosts.c @@ -131,11 +131,11 @@ static BOOL check_user_equiv(const char *user, const char *remote, const char *e /**************************************************************************** check for a possible hosts equiv or rhosts entry for the user ****************************************************************************/ -static BOOL check_hosts_equiv(char *user) /* should be const... */ + +static BOOL check_hosts_equiv(struct passwd *pass) { char *fname = NULL; pstring rhostsfile; - struct passwd *pass = Get_Pwnam(user); if (!pass) return(False); @@ -149,15 +149,15 @@ static BOOL check_hosts_equiv(char *user) /* should be const... */ } if (lp_use_rhosts()) - { - char *home = pass->pw_dir; - if (home) { - slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); - if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) - return(True); - } - } - + { + char *home = pass->pw_dir; + if (home) { + slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); + if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) + return(True); + } + } + return(False); } @@ -166,15 +166,21 @@ static BOOL check_hosts_equiv(char *user) /* should be const... */ ****************************************************************************/ NTSTATUS check_rhosts_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info *server_info) + auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - - become_root(); - if (check_hosts_equiv(user_info->unix_username.str)) { - nt_status = NT_STATUS_OK; + struct passwd *pass = Get_Pwnam(user_info->internal_username.str); + + if (pass) { + become_root(); + if (check_hosts_equiv(pass)) { + nt_status = NT_STATUS_OK; + make_server_info_pw(server_info, pass); + } + unbecome_root(); + } else { + nt_status = NT_STATUS_NO_SUCH_USER; } - unbecome_root(); return nt_status; } diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c index 520417e3e0..ddbc284d50 100644 --- a/source3/smbd/auth_server.c +++ b/source3/smbd/auth_server.c @@ -115,7 +115,7 @@ struct cli_state *server_cryptkey(void) - Validate a password with the password server. ****************************************************************************/ -NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { struct cli_state *cli; static unsigned char badpass[24]; @@ -134,8 +134,8 @@ NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_ser if(badpass[0] == 0) memset(badpass, 0x1f, sizeof(badpass)); - if((user_info->nt_resp.len == sizeof(badpass)) && - !memcmp(badpass, user_info->nt_resp.buffer, sizeof(badpass))) { + if((user_info->nt_resp.length == sizeof(badpass)) && + !memcmp(badpass, user_info->nt_resp.data, sizeof(badpass))) { /* * Very unlikely, our random bad password is the same as the users * password. @@ -206,11 +206,11 @@ use this machine as the password server.\n")); * not guest enabled, we can try with the real password. */ - if (!cli_session_setup(cli, user_info->smb_username.str, - (char *)user_info->lm_resp.buffer, - user_info->lm_resp.len, - (char *)user_info->nt_resp.buffer, - user_info->nt_resp.len, + if (!cli_session_setup(cli, user_info->smb_name.str, + (char *)user_info->lm_resp.data, + user_info->lm_resp.length, + (char *)user_info->nt_resp.data, + user_info->nt_resp.length, user_info->domain.str)) { DEBUG(1,("password server %s rejected the password\n", cli->desthost)); /* Make this cli_nt_error() when the conversion is in */ @@ -227,5 +227,16 @@ use this machine as the password server.\n")); cli_ulogoff(cli); + if NT_STATUS_IS_OK(nt_status) { + struct passwd *pass = Get_Pwnam(user_info->internal_username.str); + if (pass) { + if (!make_server_info_pw(server_info, pass)) { + nt_status = NT_STATUS_NO_MEMORY; + } + } else { + nt_status = NT_STATUS_NO_SUCH_USER; + } + } + return(nt_status); } diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 84ca8d03be..d4283429ce 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -26,53 +26,65 @@ /**************************************************************************** core of smb password checking routine. ****************************************************************************/ -static BOOL smb_pwd_check_ntlmv1(const uchar *password, +static BOOL smb_pwd_check_ntlmv1(DATA_BLOB nt_response, const uchar *part_passwd, - const uchar *c8, - char user_sess_key[16]) + DATA_BLOB sec_blob, + uint8 user_sess_key[16]) { - /* Finish the encryption of part_passwd. */ - uchar p24[24]; - - if (part_passwd == NULL) { - DEBUG(10,("No password set - DISALLOWING access\n")); - /* No password set - always false ! */ - return False; - } + /* Finish the encryption of part_passwd. */ + uchar p24[24]; + + if (part_passwd == NULL) { + DEBUG(10,("No password set - DISALLOWING access\n")); + /* No password set - always false ! */ + return False; + } + + if (sec_blob.length != 8) { + DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challange size (%d)\n", sec_blob.length)); + return False; + } + + if (nt_response.length != 24) { + DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", nt_response.length)); + return False; + } - SMBOWFencrypt(part_passwd, c8, p24); + SMBOWFencrypt(part_passwd, sec_blob.data, p24); if (user_sess_key != NULL) { SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key); } - - - + + + #if DEBUG_PASSWORD DEBUG(100,("Part password (P16) was |")); dump_data(100, part_passwd, 16); DEBUG(100,("Password from client was |")); - dump_data(100, password, 24); + dump_data(100, nt_response.data, nt_response.length); DEBUG(100,("Given challenge was |")); - dump_data(100, c8, 8); + dump_data(100, sec_blob.data, sec_blob.length); DEBUG(100,("Value from encryption was |")); dump_data(100, p24, 24); #endif - return (memcmp(p24, password, 24) == 0); + return (memcmp(p24, nt_response.data, 24) == 0); } /**************************************************************************** core of smb password checking routine. ****************************************************************************/ -static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, +static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, const uchar *part_passwd, - const uchar *c8, + const DATA_BLOB sec_blob, const char *user, const char *domain, - char user_sess_key[16]) + uint8 user_sess_key[16]) { /* Finish the encryption of part_passwd. */ uchar kr[16]; - uchar resp[16]; + uchar value_from_encryption[16]; + uchar client_response[16]; + DATA_BLOB client_key_data; if (part_passwd == NULL) { @@ -81,25 +93,42 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, return False; } + if (ntv2_response.length < 16) { + /* We MUST have more than 16 bytes, or the stuff below will go + crazy... */ + DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", + ntv2_response.length)); + return False; + } + + client_key_data = data_blob(ntv2_response.data+16, ntv2_response.length-16); + memcpy(client_response, ntv2_response.data, ntv2_response.length); + + if (!client_key_data.data) { + return False; + } + ntv2_owf_gen(part_passwd, user, domain, kr); - SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, (char *)resp); + SMBOWFencrypt_ntv2(kr, sec_blob, client_key_data, (char *)value_from_encryption); if (user_sess_key != NULL) { - SMBsesskeygen_ntv2(kr, resp, user_sess_key); + SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key); } #if DEBUG_PASSWORD DEBUG(100,("Part password (P16) was |")); dump_data(100, part_passwd, 16); DEBUG(100,("Password from client was |")); - dump_data(100, password, pwd_len); + dump_data(100, ntv2_response.data, ntv2_response.length); + DEBUG(100,("Variable data from client was |")); + dump_data(100, ntv2_response.data, ntv2_response.length); DEBUG(100,("Given challenge was |")); - dump_data(100, c8, 8); + dump_data(100, sec_blob.data, sec_blob.length); DEBUG(100,("Value from encryption was |")); - dump_data(100, resp, 16); + dump_data(100, value_from_encryption, 16); #endif - - return (memcmp(resp, password, 16) == 0); + data_blob_clear_free(&client_key_data); + return (memcmp(value_from_encryption, client_response, 16) == 0); } @@ -107,11 +136,12 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ -NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, char user_sess_key[16]) +NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, uint8 user_sess_key[16]) { const uint8 *nt_pw, *lm_pw; uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); - + uint32 ntlmssp_flags; + if (!user_info || !sampass) return NT_STATUS_LOGON_FAILURE; @@ -119,12 +149,12 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use { if (lp_null_passwords()) { - DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", sampass->username)); + DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", pdb_get_username(sampass))); return(NT_STATUS_OK); } else { - DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", sampass->username)); + DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", pdb_get_username(sampass))); return(NT_STATUS_LOGON_FAILURE); } } @@ -132,61 +162,84 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use nt_pw = pdb_get_nt_passwd(sampass); lm_pw = pdb_get_lanman_passwd(sampass); - if (nt_pw != NULL && user_info->nt_resp.len > 0) { - if ((user_info->nt_resp.len > 24 )) { + ntlmssp_flags = user_info->ntlmssp_flags; + + if (nt_pw == NULL) { + DEBUG(3,("smb_password_ok: NO NT password stored for user %s.\n", + pdb_get_username(sampass))); + /* No return, we want to check the LM hash below in this case */ + ntlmssp_flags &= (~(NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2)); + } + + if (ntlmssp_flags & NTLMSSP_NEGOTIATE_NTLM2) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n")); - if (smb_pwd_check_ntlmv2( user_info->nt_resp.buffer, - user_info->nt_resp.len, + if (smb_pwd_check_ntlmv2( user_info->nt_resp, nt_pw, - user_info->chal, user_info->smb_username.str, - user_info->requested_domain.str, + user_info->sec_blob, user_info->smb_name.str, + user_info->client_domain.str, user_sess_key)) { return NT_STATUS_OK; } else { - DEBUG(4,("smb_password_ok: NTLMv2 password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; + DEBUG(3,("smb_password_ok: NTLMv2 password check failed\n")); + return NT_STATUS_WRONG_PASSWORD; } - - } else if (lp_ntlm_auth() && (user_info->nt_resp.len == 24)) { + } else if (ntlmssp_flags & NTLMSSP_NEGOTIATE_NTLM) { + if (lp_ntlm_auth()) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ - DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); - if (smb_pwd_check_ntlmv1(user_info->nt_resp.buffer, - nt_pw, user_info->chal, - user_sess_key)) - { - return NT_STATUS_OK; + DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); + if (smb_pwd_check_ntlmv1(user_info->nt_resp, + nt_pw, user_info->sec_blob, + user_sess_key)) + { + return NT_STATUS_OK; + } else { + DEBUG(3,("smb_password_ok: NT MD4 password check failed for user %s\n",pdb_get_username(sampass))); + return NT_STATUS_WRONG_PASSWORD; + } } else { - DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; + DEBUG(2,("smb_password_ok: NTLMv1 passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); + /* No return, we want to check the LM hash below in this case */ } - } else { - return NT_STATUS_LOGON_FAILURE; - } } - if (lm_pw != NULL && user_info->lm_resp.len == 24) { - if (lp_lanman_auth()) { - DEBUG(4,("smb_password_ok: Checking LM password\n")); - if (smb_pwd_check_ntlmv1(user_info->lm_resp.buffer, - lm_pw, user_info->chal, - user_sess_key)) - { - return NT_STATUS_OK; - } else { - DEBUG(4,("smb_password_ok: LM password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; - } + if (lm_pw == NULL) { + DEBUG(3,("smb_password_ok: NO LanMan password set for user %s (and no NT password supplied)\n",pdb_get_username(sampass))); + ntlmssp_flags &= (~NTLMSSP_NEGOTIATE_OEM); + } + + if (ntlmssp_flags & NTLMSSP_NEGOTIATE_OEM) { + + if (user_info->lm_resp.length != 24) { + DEBUG(2,("smb_password_ok: invalid LanMan password length (%d) for user %s\n", + user_info->nt_resp.length, pdb_get_username(sampass))); } + + if (!lp_lanman_auth()) { + DEBUG(3,("smb_password_ok: Lanman passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); + return NT_STATUS_LOGON_FAILURE; + } + + DEBUG(4,("smb_password_ok: Checking LM password\n")); + if (smb_pwd_check_ntlmv1(user_info->lm_resp, + lm_pw, user_info->sec_blob, + user_sess_key)) + { + return NT_STATUS_OK; + } else { + DEBUG(4,("smb_password_ok: LM password check failed for user %s\n",pdb_get_username(sampass))); + return NT_STATUS_WRONG_PASSWORD; + } } - /* Should not be reached */ - return NT_STATUS_LOGON_FAILURE; + /* Should not be reached, but if they send nothing... */ + DEBUG(3,("smb_password_ok: NEITHER LanMan nor NT password supplied for user %s\n",pdb_get_username(sampass))); + return NT_STATUS_WRONG_PASSWORD; } /**************************************************************************** @@ -290,33 +343,58 @@ SMB hash supplied in the user_info structure return an NT_STATUS constant. ****************************************************************************/ -NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { SAM_ACCOUNT *sampass=NULL; BOOL ret; NTSTATUS nt_status; + uint8 user_sess_key[16]; + const uint8* lm_hash; pdb_init_sam(&sampass); /* get the account information */ become_root(); - ret = pdb_getsampwnam(sampass, user_info->unix_username.str); + ret = pdb_getsampwnam(sampass, user_info->internal_username.str); unbecome_root(); if (ret == False) { - DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->unix_username.str)); + DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->internal_username.str)); pdb_free_sam(&sampass); return NT_STATUS_NO_SUCH_USER; } - nt_status = sam_password_ok(sampass, user_info, (char *)(server_info->session_key)); + nt_status = sam_password_ok(sampass, user_info, user_sess_key); - if NT_STATUS_IS_OK(nt_status) { - nt_status = sam_account_ok(sampass, user_info); + if (!NT_STATUS_IS_OK(nt_status)) { + pdb_free_sam(&sampass); + return nt_status; } - pdb_free_sam(&sampass); + nt_status = sam_account_ok(sampass, user_info); + + if (!NT_STATUS_IS_OK(nt_status)) { + pdb_free_sam(&sampass); + return nt_status; + } + + if (!make_server_info_sam(server_info, sampass)) { + DEBUG(0,("failed to malloc memory for server_info\n")); + return NT_STATUS_NO_MEMORY; + } + + lm_hash = pdb_get_lanman_passwd((*server_info)->sam_account); + if (lm_hash) { + memcpy((*server_info)->first_8_lm_hash, lm_hash, 8); + } + + memcpy((*server_info)->session_key, user_sess_key, sizeof(user_sess_key)); + return nt_status; } + + + + diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c index 29a2a6eafb..d456da1fdf 100644 --- a/source3/smbd/auth_unix.c +++ b/source3/smbd/auth_unix.c @@ -82,22 +82,27 @@ check if a username/password is OK assuming the password in PLAIN TEXT ****************************************************************************/ -NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) +NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status; struct passwd *pass = NULL; become_root(); - - pass = Get_Pwnam(user_info->unix_username.str); + pass = Get_Pwnam(user_info->internal_username.str); nt_status = pass_check(pass, - pass ? pass->pw_name : user_info->unix_username.str, - user_info->plaintext_password.str, - user_info->plaintext_password.len, + pass ? pass->pw_name : user_info->internal_username.str, + (char *)user_info->plaintext_password.data, + user_info->plaintext_password.length-1, lp_update_encrypted() ? update_smbpassword_file : NULL, True); + + if NT_STATUS_IS_OK(nt_status) { + if (pass) { + make_server_info_pw(server_info, pass); + } + } unbecome_root(); diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index d3b9aa7001..297c482af5 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -25,6 +25,8 @@ /* Data to do lanman1/2 password challenge. */ static unsigned char saved_challenge[8]; static BOOL challenge_sent=False; +extern fstring remote_machine; +extern pstring global_myname; /******************************************************************* Get the next challenge value - no repeats. @@ -64,7 +66,7 @@ BOOL last_challenge(unsigned char *challenge) Create a UNIX user on demand. ****************************************************************************/ -static int smb_create_user(char *unix_user, char *homedir) +static int smb_create_user(const char *unix_user, const char *homedir) { pstring add_script; int ret; @@ -100,40 +102,560 @@ static int smb_delete_user(char *unix_user) Add and Delete UNIX users on demand, based on NTSTATUS codes. ****************************************************************************/ -void smb_user_control(char *unix_user, NTSTATUS nt_status) +void smb_user_control(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info, NTSTATUS nt_status) { struct passwd *pwd=NULL; if (NT_STATUS_IS_OK(nt_status)) { - /* - * User validated ok against Domain controller. - * If the admin wants us to try and create a UNIX - * user on the fly, do so. - */ - if(lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) - smb_create_user(unix_user, NULL); - - if(lp_adduser_script() && pwd) { - SMB_STRUCT_STAT st; + if (!(server_info->sam_fill_level & SAM_FILL_UNIX)) { + /* - * Also call smb_create_user if the users home directory - * doesn't exist. Used with winbindd to allow the script to - * create the home directory for a user mapped with winbindd. + * User validated ok against Domain controller. + * If the admin wants us to try and create a UNIX + * user on the fly, do so. */ + + if(lp_adduser_script() && !(pwd = Get_Pwnam(user_info->internal_username.str))) { + smb_create_user(user_info->internal_username.str, NULL); + } + } else { + if(lp_adduser_script()) { + SMB_STRUCT_STAT st; + const char *home_dir = pdb_get_homedir(server_info->sam_account); + /* + * Also call smb_create_user if the users home directory + * doesn't exist. Used with winbindd to allow the script to + * create the home directory for a user mapped with winbindd. + */ - if (pwd->pw_dir && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT)) - smb_create_user(unix_user, pwd->pw_dir); + if (home_dir && + (sys_stat(home_dir, &st) == -1) && (errno == ENOENT)) { + smb_create_user(user_info->internal_username.str, home_dir); + } + } } - - } else if (NT_STATUS_V(nt_status) == NT_STATUS_V(NT_STATUS_NO_SUCH_USER)) { + } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) { /* * User failed to validate ok against Domain controller. * If the failure was "user doesn't exist" and admin * wants us to try and delete that UNIX user on the fly, * do so. */ - if(lp_deluser_script() && smb_getpwnam(unix_user,True)) - smb_delete_user(unix_user); + if (lp_deluser_script()) { + smb_delete_user(user_info->internal_username.str); + } + } +} + +/**************************************************************************** + Create an auth_usersupplied_data structure +****************************************************************************/ + +BOOL make_user_info(auth_usersupplied_info **user_info, + char *smb_name, char *internal_username, + char *client_domain, char *domain, + char *wksta_name, DATA_BLOB sec_blob, + DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, + DATA_BLOB plaintext, + uint32 ntlmssp_flags, BOOL encrypted) +{ + + DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name)); + + *user_info = malloc(sizeof(**user_info)); + if (!user_info) { + DEBUG(0,("malloc failed for user_info (size %d)\n", sizeof(*user_info))); + return False; + } + + ZERO_STRUCTP(*user_info); + + DEBUG(5,("makeing strings for %s's user_info struct\n", internal_username)); + + (*user_info)->smb_name.str = strdup(smb_name); + if ((*user_info)->smb_name.str) { + (*user_info)->smb_name.len = strlen(smb_name); + } else { + free_user_info(user_info); + return False; + } + + (*user_info)->internal_username.str = strdup(internal_username); + if ((*user_info)->internal_username.str) { + (*user_info)->internal_username.len = strlen(internal_username); + } else { + free_user_info(user_info); + return False; + } + + (*user_info)->domain.str = strdup(domain); + if ((*user_info)->domain.str) { + (*user_info)->domain.len = strlen(domain); + } else { + free_user_info(user_info); + return False; + } + + (*user_info)->client_domain.str = strdup(client_domain); + if ((*user_info)->client_domain.str) { + (*user_info)->client_domain.len = strlen(client_domain); + } else { + free_user_info(user_info); + return False; + } + + (*user_info)->wksta_name.str = strdup(wksta_name); + if ((*user_info)->wksta_name.str) { + (*user_info)->wksta_name.len = strlen(wksta_name); + } else { + free_user_info(user_info); + return False; } + + DEBUG(5,("makeing blobs for %s's user_info struct\n", internal_username)); + + (*user_info)->sec_blob = data_blob(sec_blob.data, sec_blob.length); + (*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); + + (*user_info)->encrypted = encrypted; + (*user_info)->ntlmssp_flags = ntlmssp_flags; + + DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name)); + + return True; } + +/**************************************************************************** + Create an auth_usersupplied_data structure after appropriate mapping. +****************************************************************************/ + +BOOL make_user_info_map(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + char *wksta_name, DATA_BLOB sec_blob, + DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, + DATA_BLOB plaintext, + uint32 ntlmssp_flags, BOOL encrypted) +{ + char *domain; + fstring internal_username; + fstrcpy(internal_username, smb_name); + map_username(internal_username); + + if (lp_allow_trusted_domains()) { + domain = client_domain; + } else { + domain = lp_workgroup(); + } + + return make_user_info(user_info, + smb_name, internal_username, + client_domain, domain, + wksta_name, sec_blob, + lm_pwd, nt_pwd, + plaintext, + ntlmssp_flags, encrypted); + +} + +/**************************************************************************** + Create an auth_usersupplied_data, making the DATA_BLOBs here. + Decrupt and encrypt the passwords. +****************************************************************************/ + +BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + char *wksta_name, uchar chal[8], + uchar *lm_network_pwd, int lm_pwd_len, + uchar *nt_network_pwd, int nt_pwd_len) +{ + BOOL ret; + DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); + 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 ntlmssp_flags = 0; + + if (lm_pwd_len) + ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; + if (nt_pwd_len) + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; + + ret = make_user_info_map(user_info, + smb_name, client_domain, + wksta_name, sec_blob, + nt_blob, lm_blob, + plaintext_blob, + ntlmssp_flags, True); + + data_blob_free(&lm_blob); + data_blob_free(&nt_blob); + return ret; +} + +/**************************************************************************** + Create an auth_usersupplied_data, making the DATA_BLOBs here. + Decrupt and encrypt the passwords. +****************************************************************************/ + +BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + char *wksta_name, + uchar *lm_interactive_pwd, int lm_pwd_len, + uchar *nt_interactive_pwd, int nt_pwd_len, + uchar *dc_sess_key) +{ + char nt_pwd[16]; + char lm_pwd[16]; + unsigned char local_lm_response[24]; + unsigned char local_nt_response[24]; + unsigned char key[16]; + uint8 chal[8]; + uint32 ntlmssp_flags = 0; + + generate_random_buffer(chal, 8, False); + + memset(key, 0, 16); + memcpy(key, dc_sess_key, 8); + + memcpy(lm_pwd, lm_interactive_pwd, 16); + memcpy(nt_pwd, nt_interactive_pwd, 16); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("key:")); + dump_data(100, (char *)key, 16); + + DEBUG(100,("lm owf password:")); + dump_data(100, lm_pwd, 16); + + DEBUG(100,("nt owf password:")); + dump_data(100, nt_pwd, 16); +#endif + + SamOEMhash((uchar *)lm_pwd, key, 16); + SamOEMhash((uchar *)nt_pwd, key, 16); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("decrypt of lm owf password:")); + dump_data(100, lm_pwd, 16); + + DEBUG(100,("decrypt of nt owf password:")); + dump_data(100, nt_pwd, 16); +#endif + + generate_random_buffer(chal, 8, False); + SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response); + SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response); + + /* Password info parinoia */ + ZERO_STRUCT(lm_pwd); + ZERO_STRUCT(nt_pwd); + ZERO_STRUCT(key); + + { + BOOL ret; + DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); + 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); + + ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_NTLM; + ret = make_user_info_map(user_info, + smb_name, client_domain, + wksta_name, sec_blob, + local_nt_blob, + local_lm_blob, + plaintext_blob, + ntlmssp_flags, True); + + data_blob_free(&local_lm_blob); + data_blob_free(&local_nt_blob); + return ret; + } +} + +/**************************************************************************** + Create an auth_usersupplied_data structure +****************************************************************************/ + +BOOL make_user_info_for_winbind(auth_usersupplied_info **user_info, + char *username, + char *domain, + char *password) +{ + unsigned char local_lm_response[24]; + unsigned char local_nt_response[24]; + char chal[8]; + DATA_BLOB local_lm_blob; + DATA_BLOB local_nt_blob; + DATA_BLOB plaintext_blob; + uint32 ntlmssp_flags = 0; + + /* + * Not encrypted - do so. + */ + + DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n")); + + generate_random_buffer(chal, 8, False); + + if (*password) { + SMBencrypt( (uchar *)password, chal, local_lm_response); + + /* This encrypts the lm_pwd feild, which actualy contains the password + rather than the nt_pwd field becouse that contains nothing */ + + /* 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 */ + + SMBNTencrypt((uchar *)password, chal, local_nt_response); + + local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response)); + local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); + plaintext_blob = data_blob(password, strlen(password)+1); + if ((!local_lm_blob.data) || (!local_nt_blob.data)|| (!plaintext_blob.data)) { + data_blob_free(&local_lm_blob); + data_blob_free(&local_nt_blob); + data_blob_clear_free(&plaintext_blob); + return False; + } + ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_NTLM; + } else { + local_lm_blob = data_blob(NULL, 0); + local_nt_blob = data_blob(NULL, 0); + plaintext_blob = data_blob(NULL, 0); + } + + { + BOOL ret; + DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); + + if (!sec_blob.data) { + return False; + } + + ret = make_user_info(user_info, + username, username, + domain, domain, + global_myname, sec_blob, + local_nt_blob, + local_lm_blob, + plaintext_blob, + ntlmssp_flags, False); + + data_blob_free(&local_lm_blob); + data_blob_free(&local_nt_blob); + data_blob_clear_free(&plaintext_blob); + return ret; + } +} + +/**************************************************************************** + Create an auth_usersupplied_data, making the DATA_BLOBs here. + Decrupt and encrypt the passwords. +****************************************************************************/ + +BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + uchar chal[8], + uchar *lm_network_pwd, int lm_pwd_len, + uchar *nt_network_pwd, int nt_pwd_len) +{ + BOOL ret; + DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); + 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 ntlmssp_flags = 0; + + if (lm_pwd_len) + ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; + if (nt_pwd_len) + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; + + ret = make_user_info(user_info, + smb_name, smb_name, + client_domain, client_domain, + global_myname, sec_blob, + nt_blob, lm_blob, + plaintext_blob, + ntlmssp_flags, True); + + data_blob_free(&lm_blob); + data_blob_free(&nt_blob); + return ret; +} + +/**************************************************************************** + Create an auth_usersupplied_data structure +****************************************************************************/ + +BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, + char *smb_name, + char *client_domain, + DATA_BLOB lm_resp, DATA_BLOB nt_resp, + DATA_BLOB plaintext_password, + BOOL encrypted) +{ + uchar chal[8]; + + DATA_BLOB local_lm_blob; + DATA_BLOB local_nt_blob; + DATA_BLOB sec_blob; + BOOL ret = False; + uint32 ntlmssp_flags = 0; + + if (encrypted) { + DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); + if (!last_challenge(chal)) { + DEBUG(0,("Encrypted login but no challange set!\n")); + return False; + } + sec_blob = data_blob(chal, 8); + + if (lm_resp.length == 24) { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; + } + if (nt_resp.length == 0) { + } else if (nt_resp.length == 24) { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; + } else { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2; + } + + return make_user_info_map(user_info, smb_name, + client_domain, + remote_machine, sec_blob, + lm_resp, + nt_resp, + no_plaintext_blob, + ntlmssp_flags, encrypted); + } + + generate_random_buffer(chal, 8, False); + + sec_blob = data_blob(chal, 8); + + /* + * Not encrypted - do so. + */ + + DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n")); + + if (plaintext_password.data) { + unsigned char local_lm_response[24]; + + SMBencrypt( (uchar *)plaintext_password.data, chal, local_lm_response); + local_lm_blob = data_blob(local_lm_response, 24); + + /* We can't do an NT hash here, as the password needs to be case insensitive */ + local_nt_blob = data_blob(NULL, 0); + + ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM; + } else { + local_lm_blob = data_blob(NULL, 0); + local_nt_blob = data_blob(NULL, 0); + } + + ret = make_user_info_map(user_info, smb_name, + client_domain, + remote_machine, + sec_blob, + local_lm_blob, + local_nt_blob, + plaintext_password, + ntlmssp_flags, encrypted); + + data_blob_free(&local_lm_blob); + return ret; +} + +BOOL make_server_info(auth_serversupplied_info **server_info) +{ + *server_info = malloc(sizeof(**server_info)); + if (!*server_info) { + DEBUG(0,("make_server_info_sam: malloc failed!\n")); + return False; + } + ZERO_STRUCTP(*server_info); + return True; +} + +BOOL make_server_info_sam(auth_serversupplied_info **server_info, SAM_ACCOUNT *sampass) +{ + if (!make_server_info(server_info)) { + return False; + } + + (*server_info)->sam_fill_level = SAM_FILL_ALL; + (*server_info)->sam_account = sampass; + + DEBUG(5,("make_server_info_sam: made sever info for user %s\n", + pdb_get_username((*server_info)->sam_account))); + return True; +} + +BOOL make_server_info_pw(auth_serversupplied_info **server_info, struct passwd *pwd) +{ + SAM_ACCOUNT *sampass = NULL; + if (!pdb_init_sam_pw(&sampass, pwd)) { + return False; + } + return make_server_info_sam(server_info, sampass); +} + +void free_user_info(auth_usersupplied_info **user_info) +{ + DEBUG(5,("attempting to free (and zero) a user_info structure\n")); + if (*user_info != NULL) { + if ((*user_info)->smb_name.str) { + DEBUG(10,("structure was created for %s\n", (*user_info)->smb_name.str)); + } + SAFE_FREE((*user_info)->smb_name.str); + SAFE_FREE((*user_info)->internal_username.str); + SAFE_FREE((*user_info)->client_domain.str); + SAFE_FREE((*user_info)->domain.str); + data_blob_free(&(*user_info)->sec_blob); + 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)->plaintext_password); + ZERO_STRUCT(**user_info); + } + SAFE_FREE(*user_info); +} + +/*************************************************************************** + Clear out a server_info struct that has been allocated +***************************************************************************/ +void free_server_info(auth_serversupplied_info **server_info) +{ + if (*server_info != NULL) { + pdb_free_sam(&(*server_info)->sam_account); + + /* call pam_end here, unless we know we are keeping it */ + SAFE_FREE((*server_info)->group_rids); + + ZERO_STRUCT(**server_info); + } + SAFE_FREE(*server_info); +} + +/*************************************************************************** + Make a server_info struct for a guest user +***************************************************************************/ +void make_server_info_guest(auth_serversupplied_info **server_info) +{ + struct passwd *pass = sys_getpwnam(lp_guestaccount(-1)); + + if (pass) { + make_server_info_pw(server_info, pass); + } +} + diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e8f40f1fa3..01eabfda5e 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -197,10 +197,11 @@ has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, - char *domain,BOOL guest, char *full_name) +int register_vuid(auth_serversupplied_info *server_info, char *smb_name, BOOL guest) { user_struct *vuser = NULL; + uid_t *puid; + gid_t *pgid; /* Ensure no vuid gets registered in share level security. */ if(lp_security() == SEC_SHARE) @@ -217,8 +218,14 @@ int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, ZERO_STRUCTP(vuser); - DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)uid, (unsigned int)gid, - unix_name, requested_name, domain, guest )); + puid = pdb_get_uid(server_info->sam_account); + pgid = pdb_get_gid(server_info->sam_account); + + if (!puid || !pgid) { + DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT\n")); + free(vuser); + return UID_FIELD_INVALID; + } /* Allocate a free vuid. Yes this is a linear search... :-) */ while( get_valid_user_struct(next_vuid) != NULL ) { @@ -231,13 +238,19 @@ int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid )); vuser->vuid = next_vuid; - vuser->uid = uid; - vuser->gid = gid; + vuser->uid = *puid; + vuser->gid = *pgid; vuser->guest = guest; - fstrcpy(vuser->user.unix_name,unix_name); - fstrcpy(vuser->user.smb_name,requested_name); - fstrcpy(vuser->user.domain,domain); - fstrcpy(vuser->user.full_name, full_name); + fstrcpy(vuser->user.unix_name, pdb_get_username(server_info->sam_account)); + fstrcpy(vuser->user.smb_name, smb_name); + fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account)); + fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account)); + + DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", + (unsigned int)vuser->uid, + (unsigned int)vuser->gid, + vuser->user.unix_name, vuser->user.smb_name, vuser->user.domain, guest )); + DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,vuser->user.full_name)); vuser->n_groups = 0; @@ -332,7 +345,7 @@ BOOL user_ok(char *user,int snum) /**************************************************************************** validate a group username entry. Return the username or NULL ****************************************************************************/ -static char *validate_group(char *group,char *password,int pwlen,int snum) +static char *validate_group(char *group, DATA_BLOB password,int snum) { #ifdef HAVE_NETGROUP { @@ -341,7 +354,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) while (getnetgrent(&host, &user, &domain)) { if (user) { if (user_ok(user, snum) && - password_ok(user,password,pwlen)) { + password_ok(user,password)) { endnetgrent(); return(user); } @@ -396,7 +409,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) static fstring name; fstrcpy(name,member); if (user_ok(name,snum) && - password_ok(name,password,pwlen)) { + password_ok(name,password)) { endgrent(); return(&name[0]); } @@ -419,7 +432,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) Note this is *NOT* used when logging on using sessionsetup_and_X. ****************************************************************************/ -BOOL authorise_login(int snum,char *user,char *password, int pwlen, +BOOL authorise_login(int snum,char *user, DATA_BLOB password, BOOL *guest,BOOL *force,uint16 vuid) { BOOL ok = False; @@ -427,7 +440,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, #if DEBUG_PASSWORD DEBUG(100,("authorise_login: checking authorisation on user=%s pass=%s\n", - user,password)); + user,password.data)); #endif *guest = False; @@ -472,7 +485,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, /* check for a previously registered guest username */ if (!ok && (vuser != 0) && vuser->guest) { if (user_ok(vuser->user.unix_name,snum) && - password_ok(vuser->user.unix_name, password, pwlen)) { + password_ok(vuser->user.unix_name, password)) { fstrcpy(user, vuser->user.unix_name); vuser->guest = False; DEBUG(3,("authorise_login: ACCEPTED: given password with registered user %s\n", user)); @@ -494,7 +507,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, if (!user_ok(user2,snum)) continue; - if (password_ok(user2,password, pwlen)) { + if (password_ok(user2,password)) { ok = True; fstrcpy(user,user2); DEBUG(3,("authorise_login: ACCEPTED: session list username (%s) \ @@ -526,7 +539,7 @@ and given password ok\n", user)); for (auser=strtok(user_list,LIST_SEP); auser && !ok; auser = strtok(NULL,LIST_SEP)) { if (*auser == '@') { - auser = validate_group(auser+1,password,pwlen,snum); + auser = validate_group(auser+1,password,snum); if (auser) { ok = True; fstrcpy(user,auser); @@ -536,7 +549,7 @@ and given password ok (%s)\n", user)); } else { fstring user2; fstrcpy(user2,auser); - if (user_ok(user2,snum) && password_ok(user2,password,pwlen)) { + if (user_ok(user2,snum) && password_ok(user2,password)) { ok = True; fstrcpy(user,user2); DEBUG(3,("authorise_login: ACCEPTED: user list username \ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index ca7bcb9c5f..b60738d23d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -159,14 +159,16 @@ int reply_tcon(connection_struct *conn, int pwlen=0; NTSTATUS nt_status; char *p; - + DATA_BLOB password_blob; + START_PROFILE(SMBtcon); *service = *password = *dev = 0; p = smb_buf(inbuf)+1; p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1; - p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1; + pwlen = srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1; + p += pwlen; p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1; p = strrchr_m(service,'\\'); @@ -174,7 +176,9 @@ int reply_tcon(connection_struct *conn, pstrcpy(service, p+1); } - conn = make_connection(service,password,pwlen,dev,vuid,&nt_status); + password_blob = data_blob(password, pwlen+1); + + conn = make_connection(service,password_blob,dev,vuid,&nt_status); if (!conn) { END_PROFILE(SMBtcon); @@ -200,16 +204,17 @@ int reply_tcon(connection_struct *conn, int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { fstring service; - pstring password; + DATA_BLOB password; pstring devicename; NTSTATUS nt_status; uint16 vuid = SVAL(inbuf,smb_uid); int passlen = SVAL(inbuf,smb_vwv3); pstring path; char *p, *q; - START_PROFILE(SMBtconX); - - *service = *password = *devicename = 0; + extern BOOL global_encrypted_passwords_negotiated; + START_PROFILE(SMBtconX); + + *service = *devicename = 0; /* we might have to close an old one */ if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) { @@ -220,17 +225,17 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return ERROR_DOS(ERRDOS,ERRbuftoosmall); } - memcpy(password,smb_buf(inbuf),passlen); - password[passlen]=0; + if (global_encrypted_passwords_negotiated) { + password = data_blob(smb_buf(inbuf),passlen); + } else { + password = data_blob(smb_buf(inbuf),passlen+1); + /* Ensure correct termination */ + password.data[passlen]=0; + } + p = smb_buf(inbuf) + passlen; p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE); - if (passlen != 24) { - if (strequal(password," ")) - *password = 0; - passlen = strlen(password); - } - /* * the service name can be either: \\server\share * or share directly like on the DELL PowerVault 705 @@ -250,7 +255,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt DEBUG(4,("Got device type %s\n",devicename)); - conn = make_connection(service,password,passlen,devicename,vuid,&nt_status); + conn = make_connection(service,password,devicename,vuid,&nt_status); if (!conn) { END_PROFILE(SMBtconX); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 37f4610b9d..f6296201ae 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -79,7 +79,7 @@ BOOL set_current_service(connection_struct *conn,BOOL do_chdir) Add a home service. Returns the new service number or -1 if fail. ****************************************************************************/ -int add_home_service(char *service, char *homedir) +int add_home_service(const char *service, const char *homedir) { int iHomeService; int iService; @@ -320,8 +320,8 @@ static void set_admin_user(connection_struct *conn) Make a connection to a service. ****************************************************************************/ -connection_struct *make_connection(char *service,char *password, - int pwlen, char *dev,uint16 vuid, NTSTATUS *status) +connection_struct *make_connection(char *service, DATA_BLOB password, + char *dev,uint16 vuid, NTSTATUS *status) { int snum; struct passwd *pass = NULL; @@ -361,7 +361,7 @@ connection_struct *make_connection(char *service,char *password, if (validated_username(vuid)) { fstring unix_username; fstrcpy(unix_username,validated_username(vuid)); - return(make_connection(unix_username,password,pwlen,dev,vuid,status)); + return(make_connection(unix_username,password,dev,vuid,status)); } } else { /* Security = share. Try with current_user_info.smb_name @@ -370,7 +370,7 @@ connection_struct *make_connection(char *service,char *password, fstring unix_username; fstrcpy(unix_username,current_user_info.smb_name); map_username(unix_username); - return(make_connection(unix_username,password,pwlen,dev,vuid,status)); + return(make_connection(unix_username,password,dev,vuid,status)); } } } @@ -387,7 +387,7 @@ connection_struct *make_connection(char *service,char *password, /* shall we let them in? */ - if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) { + if (!authorise_login(snum,user,password,&guest,&force,vuid)) { DEBUG( 2, ( "Invalid username/password for %s [%s]\n", service, user ) ); *status = NT_STATUS_WRONG_PASSWORD; return NULL; diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 2d9f624b80..5331127cb5 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -264,14 +264,16 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, DATA_BLOB auth; char *workgroup, *user, *machine; DATA_BLOB lmhash, nthash, sess_key; + DATA_BLOB plaintext_password = data_blob(NULL, 0); + DATA_BLOB sec_blob; uint32 ntlmssp_command, neg_flags; NTSTATUS nt_status; int sess_vuid; - gid_t gid; - uid_t uid; - char *full_name; char *p; - const struct passwd *pw; + char chal[8]; + + auth_usersupplied_info *user_info = NULL; + auth_serversupplied_info *server_info = NULL; if (!spnego_parse_auth(blob1, &auth)) { #if 0 @@ -305,36 +307,40 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, file_save("lmhash1.dat", lmhash.data, lmhash.length); #endif - nt_status = pass_check_smb(user, user, - workgroup, machine, - lmhash.data, - lmhash.length, - nthash.data, - nthash.length); - - data_blob_free(&nthash); + if (!last_challenge(chal)) { + DEBUG(0,("Encrypted login but no challange set!\n")); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + sec_blob = data_blob(chal, 8); + if (!sec_blob.data) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + if (!make_user_info_map(&user_info, + user, workgroup, + machine, sec_blob, + lmhash, nthash, + plaintext_password, + neg_flags, True)) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + nt_status = check_password(user_info, &server_info); + + free_user_info(&user_info); + data_blob_free(&lmhash); - + + data_blob_free(&nthash); + if (!NT_STATUS_IS_OK(nt_status)) { - return ERROR_NT(nt_status); + return ERROR_NT(nt_status_squash(nt_status)); } - /* the password is good - let them in */ - pw = smb_getpwnam(user,False); - if (!pw) { - DEBUG(1,("Username %s is invalid on this system\n",user)); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - gid = pw->pw_gid; - uid = pw->pw_uid; - full_name = pw->pw_gecos; - - sess_vuid = register_vuid(uid,gid,user,user,workgroup,False, full_name); + sess_vuid = register_vuid(server_info, user, False); - free(user); - free(workgroup); - free(machine); - + free_server_info(&server_info); + if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -360,30 +366,16 @@ reply to a session setup spnego anonymous packet static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize) { - char *user; int sess_vuid; - gid_t gid; - uid_t uid; - char *full_name; char *p; - const struct passwd *pw; + auth_serversupplied_info *server_info = NULL; DEBUG(3,("Got anonymous request\n")); - user = lp_guestaccount(-1); - - /* the password is good - let them in */ - pw = smb_getpwnam(user,False); - if (!pw) { - DEBUG(1,("Guest username %s is invalid on this system\n",user)); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - gid = pw->pw_gid; - uid = pw->pw_uid; - full_name = pw->pw_gecos; - - sess_vuid = register_vuid(uid,gid,user,user,lp_workgroup(),True,full_name); - + make_server_info_guest(&server_info); + sess_vuid = register_vuid(server_info, lp_guestaccount(-1), False); + free_server_info(&server_info); + if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -414,7 +406,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,cha extern uint32 global_client_caps; int ret; - DEBUG(3,("Doing spego session setup\n")); + DEBUG(3,("Doing spnego session setup\n")); if (global_client_caps == 0) { global_client_caps = IVAL(inbuf,smb_vwv10); @@ -464,16 +456,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, int length,int bufsize) { int sess_vuid; - gid_t gid; - uid_t uid; - char* full_name; int smb_bufsize; - int smb_apasslen = 0; - pstring smb_apasswd; - int smb_ntpasslen = 0; - pstring smb_ntpasswd; + DATA_BLOB lm_resp; + DATA_BLOB nt_resp; + DATA_BLOB plaintext_password; pstring user; - pstring orig_user; fstring domain; fstring native_os; fstring native_lanman; @@ -486,9 +473,18 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, extern fstring remote_machine; extern userdom_struct current_user_info; extern int max_send; + + auth_usersupplied_info *user_info = NULL; + auth_serversupplied_info *server_info = NULL; + BOOL doencrypt = global_encrypted_passwords_negotiated; + START_PROFILE(SMBsesssetupX); + ZERO_STRUCT(lm_resp); + ZERO_STRUCT(nt_resp); + ZERO_STRUCT(plaintext_password); + DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2))); /* a SPNEGO session setup has 12 command words, whereas a normal @@ -503,28 +499,35 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(NT_STATUS_UNSUCCESSFUL); } - *smb_apasswd = *smb_ntpasswd = 0; - smb_bufsize = SVAL(inbuf,smb_vwv2); - + if (Protocol < PROTOCOL_NT1) { - smb_apasslen = SVAL(inbuf,smb_vwv7); - if (smb_apasslen > MAX_PASS_LEN) { + uint16 passlen1 = SVAL(inbuf,smb_vwv7); + if (passlen1 > MAX_PASS_LEN) { return ERROR_DOS(ERRDOS,ERRbuftoosmall); } - memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); - srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE); - - if (!doencrypt && (lp_security() != SEC_SERVER)) { - smb_apasslen = strlen(smb_apasswd); + if (doencrypt) { + lm_resp = data_blob(smb_buf(inbuf), passlen1); + } else { + plaintext_password = data_blob(smb_buf(inbuf), passlen1+1); + if (!plaintext_password.data) { + DEBUG(0,("reply_sesssetup_and_X: malloc failed for plaintext_password!\n")); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } else { + /* Ensure null termination */ + plaintext_password.data[passlen1] = 0; + } } + + srvstr_pull(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), -1, STR_TERMINATE); + } else { uint16 passlen1 = SVAL(inbuf,smb_vwv7); uint16 passlen2 = SVAL(inbuf,smb_vwv8); enum remote_arch_types ra_type = get_remote_arch(); char *p = smb_buf(inbuf); - + if(global_client_caps == 0) global_client_caps = IVAL(inbuf,smb_vwv11); @@ -539,16 +542,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } } - if (passlen1 != 24 && passlen2 < 24) - doencrypt = False; - if (passlen1 > MAX_PASS_LEN) { return ERROR_DOS(ERRDOS,ERRbuftoosmall); } - + passlen1 = MIN(passlen1, MAX_PASS_LEN); passlen2 = MIN(passlen2, MAX_PASS_LEN); - + if (!doencrypt) { /* both Win95 and WinNT stuff up the password lengths for non-encrypting systems. Uggh. @@ -591,23 +591,20 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, passlen1 = 1; } } - + /* Save the lanman2 password and the NT md4 password. */ - smb_apasslen = passlen1; - memcpy(smb_apasswd,p,smb_apasslen); - - smb_ntpasslen = passlen2; - memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); - - if (smb_apasslen != 24 || !doencrypt) { - /* trim the password */ - smb_apasslen = strlen(smb_apasswd); - - /* wfwg sometimes uses a space instead of a null */ - if (strequal(smb_apasswd," ")) { - smb_apasslen = 0; - *smb_apasswd = 0; - } + + if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) { + doencrypt = False; + } + + if (doencrypt) { + lm_resp = data_blob(p, passlen1); + nt_resp = data_blob(p+passlen1, passlen2); + } else { + plaintext_password = data_blob(p, passlen1+1); + /* Ensure null termination */ + plaintext_password.data[passlen1] = 0; } p += passlen1 + passlen2; @@ -630,15 +627,29 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - if (lp_security() == SEC_SHARE) { - /* in share level we should ignore any passwords */ - smb_ntpasslen = 0; - smb_apasslen = 0; + DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, remote_machine)); + + /* If no username is sent use the guest account */ + if (!*user) { + pstrcpy(user,lp_guestaccount(-1)); guest = True; } + pstrcpy(current_user_info.smb_name,user); + + reload_services(True); + + if (lp_security() == SEC_SHARE) { + /* in share level we should ignore any passwords */ + + data_blob_free(&lm_resp); + data_blob_free(&nt_resp); + data_blob_free(&plaintext_password); - DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",user, domain, remote_machine)); + guest = True; + map_username(user); + add_session_user(user); + } if (done_sesssetup && lp_restrict_anonymous()) { /* tests show that even if browsing is done over @@ -649,106 +660,61 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, * only deny connections that have no session * information. If a domain has been provided, then * it's not a purely anonymous connection. AAB */ - if (!*user && !*smb_apasswd && !*domain) { + if (!*user && !*domain) { DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n")); + + data_blob_free(&lm_resp); + data_blob_free(&nt_resp); + data_blob_free(&plaintext_password); + END_PROFILE(SMBsesssetupX); return ERROR_DOS(ERRDOS,ERRnoaccess); } } - - /* If no username is sent use the guest account */ - if (!*user) { - pstrcpy(user,lp_guestaccount(-1)); - guest = True; - } - - pstrcpy(current_user_info.smb_name,user); - - reload_services(True); - - /* - * Save the username before mapping. We will use - * the original username sent to us for security=server - * and security=domain checking. - */ - - pstrcpy( orig_user, user); - - /* - * Always try the "DOMAIN\user" lookup first, as this is the most - * specific case. If this fails then try the simple "user" lookup. - * But don't do this for guests, as this is always a local user. - */ if (!guest) { - pstring dom_user; - - /* Work out who's who */ - - slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s", - domain, lp_winbind_separator(), user); - - if (sys_getpwnam(dom_user) != NULL) { - pstrcpy(user, dom_user); - DEBUG(3,("Using unix username %s\n", dom_user)); + NTSTATUS nt_status; + if (!make_user_info_for_reply(&user_info, + user, domain, + lm_resp, nt_resp, + plaintext_password, doencrypt)) { + return ERROR_NT(NT_STATUS_NO_MEMORY); } - /* - * Pass the user through the NT -> unix user mapping - * function. - */ + nt_status = check_password(user_info, &server_info); - (void)map_username(user); + free_user_info(&user_info); - /* - * Do any UNIX username case mangling. - */ - smb_getpwnam(user, True); - } - - add_session_user(user); - - if (!guest) { - NTSTATUS nt_status; - nt_status = pass_check_smb(orig_user, user, - domain, remote_machine, - (unsigned char *)smb_apasswd, - smb_apasslen, - (unsigned char *)smb_ntpasswd, - smb_ntpasslen); - - if NT_STATUS_IS_OK(nt_status) { - - } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { - if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || - (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { - DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); - pstrcpy(user,lp_guestaccount(-1)); - guest = True; - } else { - /* Match WinXP and don't give the game away */ - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { - if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { - pstrcpy(user,lp_guestaccount(-1)); - DEBUG(3,("Registered username %s for guest access\n",user)); - guest = True; - } else { + data_blob_free(&lm_resp); + data_blob_free(&nt_resp); + data_blob_free(&plaintext_password); + + if (!NT_STATUS_IS_OK(nt_status)) { + if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { + if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || + (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { + DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); + pstrcpy(user,lp_guestaccount(-1)); + guest = True; + + } + } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { + if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { + pstrcpy(user,lp_guestaccount(-1)); + DEBUG(3,("Registered username %s for guest access\n",user)); + guest = True; + } /* Match WinXP and don't give the game away */ return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - } else { - return ERROR_NT(nt_status); + + if (!guest) { + free_server_info(&server_info); + return ERROR_NT(nt_status_squash(nt_status)); + } } } - if (!strequal(user,lp_guestaccount(-1)) && - lp_servicenumber(user) < 0) { - add_home_service(user,get_user_home_dir(user)); - } - - /* it's ok - setup a reply */ if (Protocol < PROTOCOL_NT1) { set_message(outbuf,3,0,True); @@ -763,30 +729,26 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, /* perhaps grab OS version here?? */ } - /* Set the correct uid in the outgoing and incoming packets - We will use this on future requests to determine which - user we should become. - */ - { - const struct passwd *pw = smb_getpwnam(user,False); - if (!pw) { - DEBUG(1,("Username %s is invalid on this system\n",user)); - END_PROFILE(SMBsesssetupX); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + if (guest) { + SSVAL(outbuf,smb_vwv2,1); + free_server_info(&server_info); + make_server_info_guest(&server_info); + } else { + const char *home_dir = pdb_get_homedir(server_info->sam_account); + const char *username = pdb_get_username(server_info->sam_account); + if ((home_dir && *home_dir) + && (lp_servicenumber(username) < 0)) { + add_home_service(username, home_dir); } - gid = pw->pw_gid; - uid = pw->pw_uid; - full_name = pw->pw_gecos; } - - if (guest) - SSVAL(outbuf,smb_vwv2,1); - + /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - - sess_vuid = register_vuid(uid,gid,user,orig_user,domain,guest, full_name); - + + sess_vuid = register_vuid(server_info, user, guest); + + free_server_info(&server_info); + if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } |