diff options
Diffstat (limited to 'source4/auth')
-rw-r--r-- | source4/auth/auth_sam.c | 129 |
1 files changed, 100 insertions, 29 deletions
diff --git a/source4/auth/auth_sam.c b/source4/auth/auth_sam.c index 681907e74a..d7e4e97826 100644 --- a/source4/auth/auth_sam.c +++ b/source4/auth/auth_sam.c @@ -40,17 +40,20 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, { if (acct_flags & ACB_PWNOTREQ) { if (lp_null_passwords()) { - DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", username)); + 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)); + DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", + username)); return NT_STATUS_LOGON_FAILURE; } } 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, + &user_info->lm_interactive_pwd, + &user_info->nt_interactive_pwd, username, user_info->smb_name.str, user_info->client_domain.str, @@ -66,12 +69,12 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, const char *username, uint16 acct_flags, - struct ldb_message **msgs, + NTTIME *acct_expiry, + NTTIME *must_change_time, + NTTIME *last_set_time, + const char *workstation_list, const auth_usersupplied_info *user_info) { - char *workstation_list; - time_t kickoff_time; - DEBUG(4,("sam_account_ok: Checking SMB password for user %s\n", username)); /* Quit if the account was disabled. */ @@ -86,41 +89,37 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, return NT_STATUS_ACCOUNT_LOCKED_OUT; } -#if 0 /* Test account expire time */ - kickoff_time = pdb_get_kickoff_time(sampass); - if (kickoff_time != 0 && time(NULL) > kickoff_time) { + if (!nt_time_is_zero(acct_expiry) && time(NULL) > nt_time_to_unix(acct_expiry)) { DEBUG(1,("sam_account_ok: Account for user '%s' has expired.\n", username)); - DEBUG(3,("sam_account_ok: Account expired at '%ld' unix time.\n", (long)kickoff_time)); + DEBUG(3,("sam_account_ok: Account expired at '%s'.\n", + nt_time_string(mem_ctx, acct_expiry))); return NT_STATUS_ACCOUNT_EXPIRED; } if (!(acct_flags & ACB_PWNOEXP)) { - time_t must_change_time = pdb_get_pass_must_change_time(sampass); - time_t last_set_time = pdb_get_pass_last_set_time(sampass); /* check for immediate expiry "must change at next logon" */ - if (must_change_time == 0 && last_set_time != 0) { - DEBUG(1,("sam_account_ok: Account for user '%s' password must change!.\n", username)); + if (nt_time_is_zero(must_change_time) && !nt_time_is_zero(last_set_time)) { + DEBUG(1,("sam_account_ok: Account for user '%s' password must change!.\n", + username)); return NT_STATUS_PASSWORD_MUST_CHANGE; } /* check for expired password */ - if (must_change_time < time(NULL) && must_change_time != 0) { - DEBUG(1,("sam_account_ok: Account for user '%s' password expired!.\n", username)); - DEBUG(1,("sam_account_ok: Password expired at '%s' (%ld) unix time.\n", timestring(mem_ctx, must_change_time), (long)must_change_time)); + if (!nt_time_is_zero(must_change_time) && nt_time_to_unix(must_change_time) < time(NULL)) { + DEBUG(1,("sam_account_ok: Account for user '%s' password expired!.\n", + username)); + DEBUG(1,("sam_account_ok: Password expired at '%s' unix time.\n", + nt_time_string(mem_ctx, must_change_time))); return NT_STATUS_PASSWORD_EXPIRED; } } /* 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) { + if (workstation_list && *workstation_list) { BOOL invalid_ws = True; const char *s = workstation_list; @@ -129,6 +128,7 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, while (next_token(&s, tok, ",", sizeof(tok))) { DEBUG(10,("sam_account_ok: 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)) { invalid_ws = False; break; @@ -138,7 +138,7 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, if (invalid_ws) return NT_STATUS_INVALID_WORKSTATION; } -#endif + if (acct_flags & ACB_DOMTRUST) { DEBUG(2,("sam_account_ok: Domain trust account %s denied by server\n", username)); return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; @@ -170,10 +170,20 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, auth_serversupplied_info **server_info) { struct ldb_message **msgs; + struct ldb_message **msgs_domain; void *sam_ctx; - uint16 acct_flags; char *username = user_info->internal_username.str; - BOOL ret; + uint16 acct_flags; + const char *workstation_list; + NTTIME acct_expiry; + NTTIME must_change_time; + NTTIME last_set_time; + + uint_t ret; + uint_t ret_domain; + + const char *domain_dn; + NTSTATUS nt_status; DATA_BLOB user_sess_key = data_blob(NULL, 0); DATA_BLOB lm_sess_key = data_blob(NULL, 0); @@ -183,6 +193,19 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, struct samr_Hash *lmPwdHash, *ntPwdHash; uint_t num_lm, num_nt; + struct dom_sid *domain_sid; + + const char *attrs[] = {"unicodePwd", "lmPwdHash", "ntPwdHash", + "sAMAcctFlags", + "pwdLastSet", + "accountExpires", + "objectSid", + "userWorkstations", + NULL, + }; + + const char *domain_attrs[] = {NULL}; + if (!user_info || !auth_context) { return NT_STATUS_UNSUCCESSFUL; } @@ -191,28 +214,59 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } - /* pull all the user attributes */ - ret = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, NULL, + /* pull the user attributes */ + ret = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs, "(&(sAMAccountName=%s)(objectclass=user))", username); if (ret == 0) { DEBUG(3,("check_sam_security: Couldn't find user [%s] in passdb file.\n", username)); + samdb_close(sam_ctx); return NT_STATUS_NO_SUCH_USER; } if (ret > 1) { DEBUG(1,("Found %d records matching user [%s]\n", ret, username)); + samdb_close(sam_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } + domain_sid = dom_sid_parse_talloc(mem_ctx, samdb_result_string(msgs[0], "objectSid", NULL)); + if (!domain_sid) { + samdb_close(sam_ctx); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + sid_split_rid(domain_sid, NULL); + + /* find the domain's DN */ + ret_domain = samdb_search(sam_ctx, mem_ctx, NULL, &msgs_domain, domain_attrs, + "(&(objectSid=%s)(objectclass=domain))", + dom_sid_string(mem_ctx, domain_sid)); + + if (ret_domain == 0) { + DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n", + dom_sid_string(mem_ctx, domain_sid))); + samdb_close(sam_ctx); + return NT_STATUS_NO_SUCH_USER; + } + + if (ret_domain > 1) { + DEBUG(1,("Found %d records matching domain [%s]\n", ret, dom_sid_string(mem_ctx, domain_sid))); + samdb_close(sam_ctx); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + domain_dn = msgs_domain[0]->dn; + acct_flags = samdb_result_acct_flags(msgs[0], "sAMAcctFlags"); /* Quit if the account was locked out. */ if (acct_flags & ACB_AUTOLOCK) { DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", username)); + samdb_close(sam_ctx); return NT_STATUS_ACCOUNT_LOCKED_OUT; } @@ -258,17 +312,32 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, user_info, &user_sess_key, &lm_sess_key); if (!NT_STATUS_IS_OK(nt_status)) { + samdb_close(sam_ctx); return nt_status; } - nt_status = sam_account_ok(mem_ctx, username, acct_flags, msgs, user_info); + acct_expiry = samdb_result_nttime(msgs[0], "accountExpires", 0); + must_change_time = samdb_result_force_pwd_change(sam_ctx, mem_ctx, + domain_dn, msgs[0], "pwdLastSet"); + last_set_time = samdb_result_nttime(msgs[0], "pwdLastSet", 0); + + workstation_list = samdb_result_string(msgs[0], "userWorkstations", NULL); + + nt_status = sam_account_ok(mem_ctx, username, acct_flags, + &acct_expiry, + &must_change_time, + &last_set_time, + workstation_list, + user_info); if (!NT_STATUS_IS_OK(nt_status)) { + samdb_close(sam_ctx); return nt_status; } if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info, username))) { DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status))); + samdb_close(sam_ctx); return nt_status; } @@ -292,6 +361,7 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, if (!(groupSIDs = talloc_realloc_p((*server_info)->mem_ctx, groupSIDs, struct dom_sid *, group_ret))) { talloc_destroy((*server_info)->mem_ctx); + samdb_close(sam_ctx); return NT_STATUS_NO_MEMORY; } @@ -313,6 +383,7 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, False, &(*server_info)->ptok))) { DEBUG(1,("check_sam_security: create_nt_user_token failed with '%s'\n", nt_errstr(nt_status))); free_server_info(server_info); + samdb_close(sam_ctx); return nt_status; } } |