X-Git-Url: http://git.samba.org/samba.git/?p=tprouty%2Fsamba.git;a=blobdiff_plain;f=source%2Fauth%2Fauth_sam.c;h=94e4ec414b60fdf80e024f29d93464e12253e8df;hp=634afc633dbbb7e42c7ab433cf683a690c0503c8;hb=7433dba78bda27cd6366a49b0efc10a387439ccd;hpb=e4e44cf3b18231ec5d7326fb42edec741caa147b diff --git a/source/auth/auth_sam.c b/source/auth/auth_sam.c index 634afc633d..94e4ec414b 100644 --- a/source/auth/auth_sam.c +++ b/source/auth/auth_sam.c @@ -3,7 +3,8 @@ Password and authentication handling Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Luke Kenneth Casson Leighton 1996-2000 - Copyright (C) Andrew Bartlett 2001 + Copyright (C) Andrew Bartlett 2001-2003 + Copyright (C) Gerald Carter 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,297 +26,95 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH -/**************************************************************************** -core of smb password checking routine. -****************************************************************************/ -static BOOL smb_pwd_check_ntlmv1(const DATA_BLOB *nt_response, - const uchar *part_passwd, - const 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; - } - - if (sec_blob->length != 8) { - DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challenge 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, 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 |\n")); - dump_data(100, part_passwd, 16); - DEBUGADD(100,("Password from client was |\n")); - dump_data(100, nt_response->data, nt_response->length); - DEBUGADD(100,("Given challenge was |\n")); - dump_data(100, sec_blob->data, sec_blob->length); - DEBUGADD(100,("Value from encryption was |\n")); - dump_data(100, p24, 24); -#endif - return (memcmp(p24, nt_response->data, 24) == 0); -} - - -/**************************************************************************** -core of smb password checking routine. (NTLMv2, LMv2) - -Note: The same code works with both NTLMv2 and LMv2. -****************************************************************************/ -static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB *ntv2_response, - const uchar *part_passwd, - const DATA_BLOB *sec_blob, - const char *user, const char *domain, - uint8 user_sess_key[16]) -{ - /* Finish the encryption of part_passwd. */ - uchar kr[16]; - uchar value_from_encryption[16]; - uchar client_response[16]; - DATA_BLOB client_key_data; - - if (part_passwd == NULL) - { - DEBUG(10,("No password set - DISALLOWING access\n")); - /* No password set - always False */ - return False; - } - - if (ntv2_response->length < 24) { - /* We MUST have more than 16 bytes, or the stuff below will go - crazy. No known implementation sends less than the 24 bytes - for LMv2, let alone NTLMv2. */ - DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect password length (%d)\n", - ntv2_response->length)); - return False; - } - - client_key_data = data_blob(ntv2_response->data+16, ntv2_response->length-16); - /* - todo: should we be checking this for anything? We can't for LMv2, - but for NTLMv2 it is meant to contain the current time etc. - */ - - memcpy(client_response, ntv2_response->data, sizeof(client_response)); - - if (!ntv2_owf_gen(part_passwd, user, domain, kr)) { - return False; - } - - SMBOWFencrypt_ntv2(kr, sec_blob, &client_key_data, value_from_encryption); - if (user_sess_key != NULL) - { - SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key); - } - -#if DEBUG_PASSWORD - DEBUG(100,("Part password (P16) was |\n")); - dump_data(100, part_passwd, 16); - DEBUGADD(100,("Password from client was |\n")); - dump_data(100, ntv2_response->data, ntv2_response->length); - DEBUGADD(100,("Variable data from client was |\n")); - dump_data(100, client_key_data.data, client_key_data.length); - DEBUGADD(100,("Given challenge was |\n")); - dump_data(100, sec_blob->data, sec_blob->length); - DEBUGADD(100,("Value from encryption was |\n")); - dump_data(100, value_from_encryption, 16); -#endif - data_blob_clear_free(&client_key_data); - return (memcmp(value_from_encryption, client_response, 16) == 0); -} - - /**************************************************************************** Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ + static NTSTATUS sam_password_ok(const struct auth_context *auth_context, TALLOC_CTX *mem_ctx, - SAM_ACCOUNT *sampass, + struct samu *sampass, const auth_usersupplied_info *user_info, - uint8 user_sess_key[16]) + DATA_BLOB *user_sess_key, + DATA_BLOB *lm_sess_key) { - uint16 acct_ctrl; - const uint8 *nt_pw, *lm_pw; - uint32 auth_flags; + uint32 acct_ctrl; + const uint8 *lm_pw, *nt_pw; + const char *username = pdb_get_username(sampass); acct_ctrl = pdb_get_acct_ctrl(sampass); - if (acct_ctrl & ACB_PWNOTREQ) - { - if (lp_null_passwords()) - { - 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", pdb_get_username(sampass))); - return(NT_STATUS_LOGON_FAILURE); + if (acct_ctrl & ACB_PWNOTREQ) { + if (lp_null_passwords()) { + DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", username)); + return NT_STATUS_OK; + } else { + DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", username)); + return NT_STATUS_LOGON_FAILURE; } } - auth_flags = user_info->auth_flags; + lm_pw = pdb_get_lanman_passwd(sampass); + nt_pw = pdb_get_nt_passwd(sampass); - if (IS_SAM_DEFAULT(sampass, PDB_NTPASSWD)) { - DEBUG(3,("sam_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 */ - auth_flags &= (~(AUTH_FLAG_NTLMv2_RESP | AUTH_FLAG_NTLM_RESP)); - } - - if (auth_flags & AUTH_FLAG_NTLMv2_RESP) { - nt_pw = pdb_get_nt_passwd(sampass); - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - DEBUG(4,("sam_password_ok: Checking NTLMv2 password with domain [%s]\n", user_info->client_domain.str)); - if (smb_pwd_check_ntlmv2( &user_info->nt_resp, - nt_pw, &auth_context->challenge, - user_info->smb_name.str, - user_info->client_domain.str, - user_sess_key)) - { - return NT_STATUS_OK; - } + return ntlm_password_check(mem_ctx, &auth_context->challenge, + &user_info->lm_resp, &user_info->nt_resp, + &user_info->lm_interactive_pwd, &user_info->nt_interactive_pwd, + username, + user_info->smb_name, + user_info->client_domain, + lm_pw, nt_pw, user_sess_key, lm_sess_key); +} - DEBUG(4,("sam_password_ok: Checking NTLMv2 password without a domain\n")); - if (smb_pwd_check_ntlmv2( &user_info->nt_resp, - nt_pw, &auth_context->challenge, - user_info->smb_name.str, - "", - user_sess_key)) - { - return NT_STATUS_OK; - } else { - DEBUG(3,("sam_password_ok: NTLMv2 password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; - } - } else if (auth_flags & AUTH_FLAG_NTLM_RESP) { - if (lp_ntlm_auth()) { - nt_pw = pdb_get_nt_passwd(sampass); - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - DEBUG(4,("sam_password_ok: Checking NT MD4 password\n")); - if (smb_pwd_check_ntlmv1(&user_info->nt_resp, - nt_pw, &auth_context->challenge, - user_sess_key)) - { - return NT_STATUS_OK; - } else { - DEBUG(3,("sam_password_ok: NT MD4 password check failed for user %s\n",pdb_get_username(sampass))); - return NT_STATUS_WRONG_PASSWORD; - } - } else { - DEBUG(2,("sam_password_ok: NTLMv1 passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); - /* no return, becouse we might pick up LMv2 in the LM feild */ - } +/**************************************************************************** + Check if a user is allowed to logon at this time. Note this is the + servers local time, as logon hours are just specified as a weekly + bitmask. +****************************************************************************/ + +static BOOL logon_hours_ok(struct samu *sampass) +{ + /* In logon hours first bit is Sunday from 12AM to 1AM */ + const uint8 *hours; + struct tm *utctime; + time_t lasttime; + uint8 bitmask, bitpos; + + hours = pdb_get_hours(sampass); + if (!hours) { + DEBUG(5,("logon_hours_ok: No hours restrictions for user %s\n",pdb_get_username(sampass))); + return True; } - - if (auth_flags & AUTH_FLAG_LM_RESP) { - if (user_info->lm_resp.length != 24) { - DEBUG(2,("sam_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,("sam_password_ok: Lanman passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); - } else if (IS_SAM_DEFAULT(sampass, PDB_LMPASSWD)) { - DEBUG(3,("sam_password_ok: NO LanMan password set for user %s (and no NT password supplied)\n",pdb_get_username(sampass))); - } else { - lm_pw = pdb_get_lanman_passwd(sampass); - - DEBUG(4,("sam_password_ok: Checking LM password\n")); - if (smb_pwd_check_ntlmv1(&user_info->lm_resp, - lm_pw, &auth_context->challenge, - user_sess_key)) - { - return NT_STATUS_OK; - } - } - if (IS_SAM_DEFAULT(sampass, PDB_NTPASSWD)) { - DEBUG(4,("sam_password_ok: LM password check failed for user, no NT password %s\n",pdb_get_username(sampass))); - return NT_STATUS_WRONG_PASSWORD; - } - - nt_pw = pdb_get_nt_passwd(sampass); - - /* This is for 'LMv2' authentication. almost NTLMv2 but limited to 24 bytes. - - related to Win9X, legacy NAS pass-though authentication - */ - DEBUG(4,("sam_password_ok: Checking LMv2 password with domain %s\n", user_info->client_domain.str)); - if (smb_pwd_check_ntlmv2( &user_info->lm_resp, - nt_pw, &auth_context->challenge, - user_info->smb_name.str, - user_info->client_domain.str, - user_sess_key)) - { - return NT_STATUS_OK; - } + lasttime = time(NULL); + utctime = gmtime(&lasttime); - DEBUG(4,("sam_password_ok: Checking LMv2 password without a domain\n")); - if (smb_pwd_check_ntlmv2( &user_info->lm_resp, - nt_pw, &auth_context->challenge, - user_info->smb_name.str, - "", - user_sess_key)) - { - return NT_STATUS_OK; - } + /* find the corresponding byte and bit */ + bitpos = (utctime->tm_wday * 24 + utctime->tm_hour) % 168; + bitmask = 1 << (bitpos % 8); - /* Apparently NT accepts NT responses in the LM field - - I think this is related to Win9X pass-though authentication - */ - DEBUG(4,("sam_password_ok: Checking NT MD4 password in LM field\n")); - if (lp_ntlm_auth()) - { - if (smb_pwd_check_ntlmv1(&user_info->lm_resp, - nt_pw, &auth_context->challenge, - user_sess_key)) - { - return NT_STATUS_OK; - } - DEBUG(3,("sam_password_ok: LM password, NT MD4 password in LM field and LMv2 failed for user %s\n",pdb_get_username(sampass))); - return NT_STATUS_WRONG_PASSWORD; - } else { - DEBUG(3,("sam_password_ok: LM password and LMv2 failed for user %s, and NT MD4 password in LM field not permitted\n",pdb_get_username(sampass))); - return NT_STATUS_WRONG_PASSWORD; - } - + if (! (hours[bitpos/8] & bitmask)) { + DEBUG(1,("logon_hours_ok: Account for user %s not allowed to logon at this time (%s).\n", + pdb_get_username(sampass), + asctime(localtime(&lasttime)) )); + return False; } - - /* Should not be reached, but if they send nothing... */ - DEBUG(3,("sam_password_ok: NEITHER LanMan nor NT password supplied for user %s\n",pdb_get_username(sampass))); - return NT_STATUS_WRONG_PASSWORD; + + DEBUG(5,("logon_hours_ok: user %s allowed to logon at this time (%s)\n", + pdb_get_username(sampass), asctime(utctime) )); + + return True; } /**************************************************************************** - Do a specific test for a SAM_ACCOUNT being vaild for this connection + Do a specific test for a struct samu being vaild for this connection (ie not disabled, expired and the like). ****************************************************************************/ + static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, - SAM_ACCOUNT *sampass, + struct samu *sampass, const auth_usersupplied_info *user_info) { - uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); + uint32 acct_ctrl = pdb_get_acct_ctrl(sampass); char *workstation_list; time_t kickoff_time; @@ -323,16 +122,27 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, /* Quit if the account was disabled. */ if (acct_ctrl & ACB_DISABLED) { - DEBUG(1,("Account for user '%s' was disabled.\n", pdb_get_username(sampass))); + DEBUG(1,("sam_account_ok: Account for user '%s' was disabled.\n", pdb_get_username(sampass))); return NT_STATUS_ACCOUNT_DISABLED; } + /* Quit if the account was locked out. */ + if (acct_ctrl & ACB_AUTOLOCK) { + DEBUG(1,("sam_account_ok: Account for user %s was locked out.\n", pdb_get_username(sampass))); + return NT_STATUS_ACCOUNT_LOCKED_OUT; + } + + /* Quit if the account is not allowed to logon at this time. */ + if (! logon_hours_ok(sampass)) { + return NT_STATUS_INVALID_LOGON_HOURS; + } + /* Test account expire time */ kickoff_time = pdb_get_kickoff_time(sampass); if (kickoff_time != 0 && time(NULL) > kickoff_time) { - DEBUG(1,("Account for user '%s' has expried.\n", pdb_get_username(sampass))); - DEBUG(3,("Account expired at '%ld' unix time.\n", (long)kickoff_time)); + DEBUG(1,("sam_account_ok: Account for user '%s' has expired.\n", pdb_get_username(sampass))); + DEBUG(3,("sam_account_ok: Account expired at '%ld' unix time.\n", (long)kickoff_time)); return NT_STATUS_ACCOUNT_EXPIRED; } @@ -342,14 +152,14 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, /* check for immediate expiry "must change at next logon" */ if (must_change_time == 0 && last_set_time != 0) { - DEBUG(1,("Account for user '%s' password must change!.\n", pdb_get_username(sampass))); + DEBUG(1,("sam_account_ok: Account for user '%s' password must change!.\n", pdb_get_username(sampass))); return NT_STATUS_PASSWORD_MUST_CHANGE; } /* check for expired password */ if (must_change_time < time(NULL) && must_change_time != 0) { - DEBUG(1,("Account for user '%s' password expired!.\n", pdb_get_username(sampass))); - DEBUG(1,("Password expired at '%s' (%ld) unix time.\n", http_timestring(must_change_time), (long)must_change_time)); + DEBUG(1,("sam_account_ok: Account for user '%s' password expired!.\n", pdb_get_username(sampass))); + DEBUG(1,("sam_account_ok: Password expired at '%s' (%ld) unix time.\n", http_timestring(must_change_time), (long)must_change_time)); return NT_STATUS_PASSWORD_EXPIRED; } } @@ -357,22 +167,34 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, /* Test workstation. Workstation list is comma separated. */ workstation_list = talloc_strdup(mem_ctx, pdb_get_workstations(sampass)); - - if (!workstation_list) return NT_STATUS_NO_MEMORY; + if (!workstation_list) + return NT_STATUS_NO_MEMORY; if (*workstation_list) { BOOL invalid_ws = True; + fstring tok; const char *s = workstation_list; + + const char *machine_name = talloc_asprintf(mem_ctx, "%s$", user_info->wksta_name); + if (machine_name == NULL) + return NT_STATUS_NO_MEMORY; - fstring tok; while (next_token(&s, tok, ",", sizeof(tok))) { - DEBUG(10,("checking for workstation match %s and %s (len=%d)\n", - tok, user_info->wksta_name.str, user_info->wksta_name.len)); - if(strequal(tok, user_info->wksta_name.str)) { + DEBUG(10,("sam_account_ok: checking for workstation match %s and %s\n", + tok, user_info->wksta_name)); + if(strequal(tok, user_info->wksta_name)) { invalid_ws = False; break; } + if (tok[0] == '+') { + DEBUG(10,("sam_account_ok: checking for workstation %s in group: %s\n", + machine_name, tok + 1)); + if (user_in_group(machine_name, tok + 1)) { + invalid_ws = False; + break; + } + } } if (invalid_ws) @@ -385,19 +207,21 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, } if (acct_ctrl & ACB_SVRTRUST) { - DEBUG(2,("sam_account_ok: Server trust account %s denied by server\n", pdb_get_username(sampass))); - return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; + if (!(user_info->logon_parameters & MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT)) { + DEBUG(2,("sam_account_ok: Server trust account %s denied by server\n", pdb_get_username(sampass))); + return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; + } } - + if (acct_ctrl & ACB_WSTRUST) { - DEBUG(4,("sam_account_ok: Wksta trust account %s denied by server\n", pdb_get_username(sampass))); - return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; + if (!(user_info->logon_parameters & MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT)) { + DEBUG(2,("sam_account_ok: Wksta trust account %s denied by server\n", pdb_get_username(sampass))); + return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; + } } - return NT_STATUS_OK; } - /**************************************************************************** check if a username/password is OK assuming the password is a 24 byte SMB hash supplied in the user_info structure @@ -410,73 +234,133 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { - SAM_ACCOUNT *sampass=NULL; + struct samu *sampass=NULL; BOOL ret; NTSTATUS nt_status; - uint8 user_sess_key[16]; - const uint8* lm_hash; + NTSTATUS update_login_attempts_status; + DATA_BLOB user_sess_key = data_blob(NULL, 0); + DATA_BLOB lm_sess_key = data_blob(NULL, 0); + BOOL updated_autolock = False, updated_badpw = False; if (!user_info || !auth_context) { return NT_STATUS_UNSUCCESSFUL; } - /* Can't use the talloc version here, becouse the returned struct gets + /* Can't use the talloc version here, because the returned struct gets kept on the server_info */ - if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sampass))) { - return nt_status; + + if ( !(sampass = samu_new( NULL )) ) { + return NT_STATUS_NO_MEMORY; } /* get the account information */ become_root(); - ret = pdb_getsampwnam(sampass, user_info->internal_username.str); + ret = pdb_getsampwnam(sampass, user_info->internal_username); unbecome_root(); - if (ret == False) - { - DEBUG(3,("Couldn't find user '%s' in passdb file.\n", user_info->internal_username.str)); - pdb_free_sam(&sampass); + if (ret == False) { + DEBUG(3,("check_sam_security: Couldn't find user '%s' in " + "passdb.\n", user_info->internal_username)); + TALLOC_FREE(sampass); return NT_STATUS_NO_SUCH_USER; } - nt_status = sam_password_ok(auth_context, mem_ctx, sampass, user_info, user_sess_key); - + /* see if autolock flag needs to be updated */ + if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) + pdb_update_autolock_flag(sampass, &updated_autolock); + /* Quit if the account was locked out. */ + if (pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK) { + DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", pdb_get_username(sampass))); + return NT_STATUS_ACCOUNT_LOCKED_OUT; + } + + nt_status = sam_password_ok(auth_context, mem_ctx, sampass, + user_info, &user_sess_key, &lm_sess_key); + + /* Notify passdb backend of login success/failure. If not NT_STATUS_OK the backend doesn't like the login */ + update_login_attempts_status = pdb_update_login_attempts(sampass, NT_STATUS_IS_OK(nt_status)); + if (!NT_STATUS_IS_OK(update_login_attempts_status)) + nt_status = update_login_attempts_status; + if (!NT_STATUS_IS_OK(nt_status)) { - pdb_free_sam(&sampass); + if (NT_STATUS_EQUAL(nt_status,NT_STATUS_WRONG_PASSWORD) && + pdb_get_acct_ctrl(sampass) &ACB_NORMAL) { + pdb_increment_bad_password_count(sampass); + updated_badpw = True; + } else { + pdb_update_bad_password_count(sampass, + &updated_badpw); + } + if (updated_autolock || updated_badpw){ + become_root(); + if(!NT_STATUS_IS_OK(pdb_update_sam_account(sampass))) + DEBUG(1, ("Failed to modify entry.\n")); + unbecome_root(); + } + data_blob_free(&user_sess_key); + data_blob_free(&lm_sess_key); + TALLOC_FREE(sampass); return nt_status; } + if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) && + (pdb_get_bad_password_count(sampass) > 0)){ + pdb_set_bad_password_count(sampass, 0, PDB_CHANGED); + pdb_set_bad_password_time(sampass, 0, PDB_CHANGED); + updated_badpw = True; + } + + if (updated_autolock || updated_badpw){ + become_root(); + if(!NT_STATUS_IS_OK(pdb_update_sam_account(sampass))) + DEBUG(1, ("Failed to modify entry.\n")); + unbecome_root(); + } + nt_status = sam_account_ok(mem_ctx, sampass, user_info); if (!NT_STATUS_IS_OK(nt_status)) { - pdb_free_sam(&sampass); + TALLOC_FREE(sampass); + data_blob_free(&user_sess_key); + data_blob_free(&lm_sess_key); return nt_status; } - if (!NT_STATUS_IS_OK(nt_status = make_server_info_sam(server_info, sampass))) { + become_root(); + nt_status = make_server_info_sam(server_info, sampass); + unbecome_root(); + + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status))); + TALLOC_FREE(sampass); + data_blob_free(&user_sess_key); + data_blob_free(&lm_sess_key); return nt_status; } - 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)); + (*server_info)->user_session_key = + data_blob_talloc(*server_info, user_sess_key.data, + user_sess_key.length); + data_blob_free(&user_sess_key); + + (*server_info)->lm_session_key = + data_blob_talloc(*server_info, lm_sess_key.data, + lm_sess_key.length); + data_blob_free(&lm_sess_key); return nt_status; } /* module initialisation */ -NTSTATUS auth_init_sam(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +static NTSTATUS auth_init_sam_ignoredomain(struct auth_context *auth_context, const char *param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; } (*auth_method)->auth = check_sam_security; - (*auth_method)->name = "sam"; + (*auth_method)->name = "sam_ignoredomain"; return NT_STATUS_OK; } @@ -491,37 +375,55 @@ static NTSTATUS check_samstrict_security(const struct auth_context *auth_context const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { + BOOL is_local_name, is_my_domain; if (!user_info || !auth_context) { return NT_STATUS_LOGON_FAILURE; } - /* If we are a domain member, we must not - attempt to check the password locally, - unless it is one of our aliases. */ + is_local_name = is_myname(user_info->domain); + is_my_domain = strequal(user_info->domain, lp_workgroup()); + + /* check whether or not we service this domain/workgroup name */ - if (!is_myname(user_info->domain.str)) { - return NT_STATUS_NO_SUCH_USER; + switch ( lp_server_role() ) { + case ROLE_STANDALONE: + case ROLE_DOMAIN_MEMBER: + if ( !is_local_name ) { + DEBUG(6,("check_samstrict_security: %s is not one of my local names (%s)\n", + user_info->domain, (lp_server_role() == ROLE_DOMAIN_MEMBER + ? "ROLE_DOMAIN_MEMBER" : "ROLE_STANDALONE") )); + return NT_STATUS_NOT_IMPLEMENTED; + } + case ROLE_DOMAIN_PDC: + case ROLE_DOMAIN_BDC: + if ( !is_local_name && !is_my_domain ) { + DEBUG(6,("check_samstrict_security: %s is not one of my local names or domain name (DC)\n", + user_info->domain)); + return NT_STATUS_NOT_IMPLEMENTED; + } + default: /* name is ok */ + break; } return check_sam_security(auth_context, my_private_data, mem_ctx, user_info, server_info); } /* module initialisation */ -NTSTATUS auth_init_samstrict(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +static NTSTATUS auth_init_sam(struct auth_context *auth_context, const char *param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; } (*auth_method)->auth = check_samstrict_security; - (*auth_method)->name = "samstrict"; + (*auth_method)->name = "sam"; return NT_STATUS_OK; } NTSTATUS auth_sam_init(void) { - smb_register_auth(AUTH_INTERFACE_VERSION, "samstrict", auth_init_samstrict); smb_register_auth(AUTH_INTERFACE_VERSION, "sam", auth_init_sam); + smb_register_auth(AUTH_INTERFACE_VERSION, "sam_ignoredomain", auth_init_sam_ignoredomain); return NT_STATUS_OK; }