static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, struct samu *sampass, const auth_usersupplied_info *user_info) { uint32 acct_ctrl = pdb_get_acct_ctrl(sampass); char *workstation_list; time_t kickoff_time; DEBUG(4,("sam_account_ok: Checking SMB password for user %s\n",pdb_get_username(sampass))); /* Quit if the account was disabled. */ if (acct_ctrl & ACB_DISABLED) { 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,("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; } if (!(pdb_get_acct_ctrl(sampass) & ACB_PWNOEXP) && !(pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ)) { 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" * for a user account. */ if (((acct_ctrl & (ACB_WSTRUST|ACB_SVRTRUST)) == 0) && (last_set_time == 0)) { 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,("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; } } /* 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) { 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; while (next_token(&s, tok, ",", sizeof(tok))) { 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) return NT_STATUS_INVALID_WORKSTATION; } if (acct_ctrl & ACB_DOMTRUST) { DEBUG(2,("sam_account_ok: Domain trust account %s denied by server\n", pdb_get_username(sampass))); return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; } if (acct_ctrl & ACB_SVRTRUST) { 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) { 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; }
/**************************************************************************** Do a specific test for a SAM_ACCOUNT being valid for this connection (ie not disabled, expired and the like). ****************************************************************************/ _PUBLIC_ NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx, uint32_t logon_parameters, struct ldb_dn *domain_dn, struct ldb_message *msg, const char *logon_workstation, const char *name_for_logs, bool allow_domain_trust, bool password_change) { uint16_t acct_flags; const char *workstation_list; NTTIME acct_expiry; NTTIME must_change_time; NTTIME now; DEBUG(4,("authsam_account_ok: Checking SMB password for user %s\n", name_for_logs)); acct_flags = samdb_result_acct_flags(sam_ctx, mem_ctx, msg, domain_dn); acct_expiry = samdb_result_account_expires(msg); /* Check for when we must change this password, taking the * userAccountControl flags into account */ must_change_time = samdb_result_force_password_change(sam_ctx, mem_ctx, domain_dn, msg); workstation_list = ldb_msg_find_attr_as_string(msg, "userWorkstations", NULL); /* Quit if the account was disabled. */ if (acct_flags & ACB_DISABLED) { DEBUG(2,("authsam_account_ok: Account for user '%s' was disabled.\n", name_for_logs)); return NT_STATUS_ACCOUNT_DISABLED; } /* Quit if the account was locked out. */ if (acct_flags & ACB_AUTOLOCK) { DEBUG(2,("authsam_account_ok: Account for user %s was locked out.\n", name_for_logs)); return NT_STATUS_ACCOUNT_LOCKED_OUT; } /* Test account expire time */ unix_to_nt_time(&now, time(NULL)); if (now > acct_expiry) { DEBUG(2,("authsam_account_ok: Account for user '%s' has expired.\n", name_for_logs)); DEBUG(3,("authsam_account_ok: Account expired at '%s'.\n", nt_time_string(mem_ctx, acct_expiry))); return NT_STATUS_ACCOUNT_EXPIRED; } /* check for immediate expiry "must change at next logon" (but not if this is a password change request) */ if ((must_change_time == 0) && !password_change) { DEBUG(2,("sam_account_ok: Account for user '%s' password must change!.\n", name_for_logs)); return NT_STATUS_PASSWORD_MUST_CHANGE; } /* check for expired password (but not if this is a password change request) */ if ((must_change_time < now) && !password_change) { DEBUG(2,("sam_account_ok: Account for user '%s' password expired!.\n", name_for_logs)); DEBUG(2,("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. */ if (logon_workstation && workstation_list && *workstation_list) { bool invalid_ws = true; int i; const char **workstations = (const char **)str_list_make(mem_ctx, workstation_list, ","); for (i = 0; workstations && workstations[i]; i++) { DEBUG(10,("sam_account_ok: checking for workstation match '%s' and '%s'\n", workstations[i], logon_workstation)); if (strequal(workstations[i], logon_workstation)) { invalid_ws = false; break; } } talloc_free(workstations); if (invalid_ws) { return NT_STATUS_INVALID_WORKSTATION; } } if (!logon_hours_ok(msg, name_for_logs)) { return NT_STATUS_INVALID_LOGON_HOURS; } if (!allow_domain_trust) { if (acct_flags & ACB_DOMTRUST) { DEBUG(2,("sam_account_ok: Domain trust account %s denied by server\n", name_for_logs)); return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; } } if (!(logon_parameters & MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT)) { if (acct_flags & ACB_SVRTRUST) { DEBUG(2,("sam_account_ok: Server trust account %s denied by server\n", name_for_logs)); return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; } } if (!(logon_parameters & MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT)) { /* TODO: this fails with current solaris client. We need to work with Gordon to work out why */ if (acct_flags & ACB_WSTRUST) { DEBUG(4,("sam_account_ok: Wksta trust account %s denied by server\n", name_for_logs)); return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; } } return NT_STATUS_OK; }