diff options
Diffstat (limited to 'source4/auth/auth_sam.c')
-rw-r--r-- | source4/auth/auth_sam.c | 194 |
1 files changed, 143 insertions, 51 deletions
diff --git a/source4/auth/auth_sam.c b/source4/auth/auth_sam.c index 028fda74fe..6f61820ae5 100644 --- a/source4/auth/auth_sam.c +++ b/source4/auth/auth_sam.c @@ -33,17 +33,14 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, TALLOC_CTX *mem_ctx, - SAM_ACCOUNT *sampass, + const char *username, + uint16 acct_flags, + const uint8 lm_pw[16], const uint8 nt_pw[16], const auth_usersupplied_info *user_info, DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key) { - uint16 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 (acct_flags & 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; @@ -53,9 +50,6 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, } } - lm_pw = pdb_get_lanman_passwd(sampass); - nt_pw = pdb_get_nt_passwd(sampass); - 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, @@ -72,49 +66,51 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, ****************************************************************************/ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, - SAM_ACCOUNT *sampass, + const char *username, + uint16 acct_flags, + struct ldb_message **msgs, const auth_usersupplied_info *user_info) { - uint16 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))); + DEBUG(4,("sam_account_ok: Checking SMB password for user %s\n", username)); /* 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))); + if (acct_flags & ACB_DISABLED) { + DEBUG(1,("sam_account_ok: Account for user '%s' was disabled.\n", username)); 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))); + if (acct_flags & ACB_AUTOLOCK) { + DEBUG(1,("sam_account_ok: Account for user %s was locked out.\n", username)); 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) { - DEBUG(1,("sam_account_ok: Account for user '%s' has expired.\n", pdb_get_username(sampass))); + 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)); return NT_STATUS_ACCOUNT_EXPIRED; } - if (!(pdb_get_acct_ctrl(sampass) & ACB_PWNOEXP)) { + 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", pdb_get_username(sampass))); + 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", pdb_get_username(sampass))); + 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)); return NT_STATUS_PASSWORD_EXPIRED; } @@ -144,19 +140,19 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, 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))); +#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; } - if (acct_ctrl & ACB_SVRTRUST) { - DEBUG(2,("sam_account_ok: Server trust account %s denied by server\n", pdb_get_username(sampass))); + if (acct_flags & ACB_SVRTRUST) { + DEBUG(2,("sam_account_ok: Server trust account %s denied by server\n", username)); 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))); + if (acct_flags & ACB_WSTRUST) { + DEBUG(4,("sam_account_ok: Wksta trust account %s denied by server\n", username)); return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; } @@ -175,60 +171,156 @@ 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 ldb_message **msgs; + void *sam_ctx; + uint16 acct_flags; + char *username = user_info->internal_username.str; BOOL ret; NTSTATUS nt_status; DATA_BLOB user_sess_key = data_blob(NULL, 0); DATA_BLOB lm_sess_key = data_blob(NULL, 0); + const uint8 *lm_pwd, *nt_pwd; + const char *unicodePwd; + struct samr_Hash lmPwdHash_u, ntPwdHash_u; + struct samr_Hash *lmPwdHash, *ntPwdHash; + uint_t num_lm, num_nt; if (!user_info || !auth_context) { return NT_STATUS_UNSUCCESSFUL; } - - /* 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; + + sam_ctx = samdb_connect(); + if (sam_ctx == NULL) { + return NT_STATUS_INVALID_SYSTEM_SERVICE; } - - /* get the account information */ - - become_root(); - ret = pdb_getsampwnam(sampass, user_info->internal_username.str); - unbecome_root(); - - if (ret == False) { - DEBUG(3,("check_sam_security: Couldn't find user '%s' in passdb file.\n", user_info->internal_username.str)); - pdb_free_sam(&sampass); + /* pull all the user attributes */ + ret = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, NULL, + "(&(sAMAccountName=%s)(objectclass=user))", + username); + + if (ret == 0) { + DEBUG(3,("check_sam_security: Couldn't find user [%s] in passdb file.\n", + username)); return NT_STATUS_NO_SUCH_USER; } + if (ret > 1) { + DEBUG(1,("Found %d records matching user [%s]\n", ret, username)); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + acct_flags = samdb_result_acct_flags(msgs[0], "sAMAcctFlags"); + /* 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))); + if (acct_flags & ACB_AUTOLOCK) { + DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", + username)); return NT_STATUS_ACCOUNT_LOCKED_OUT; } - nt_status = sam_password_ok(auth_context, mem_ctx, sampass, + unicodePwd = samdb_result_string(msgs[0], "unicodePwd", NULL); + + if (unicodePwd) { + BOOL lm_hash_ok; + /* compute the new nt and lm hashes */ + lm_hash_ok = E_deshash(unicodePwd, lmPwdHash_u.hash); + E_md4hash(unicodePwd, ntPwdHash_u.hash); + + if (lm_hash_ok) { + lm_pwd = lmPwdHash_u.hash; + } else { + lm_pwd = NULL; + } + + nt_pwd = ntPwdHash_u.hash; + + } else { + num_lm = samdb_result_hashes(mem_ctx, msgs[0], "lmPwdHash", &lmPwdHash); + if (num_lm == 0) { + lm_pwd = NULL; + } else if (num_lm > 1) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } else { + lm_pwd = lmPwdHash[0].hash; + } + + num_nt = samdb_result_hashes(mem_ctx, msgs[0], "ntPwdHash", &ntPwdHash); + if (num_nt == 0) { + nt_pwd = NULL; + } else if (num_nt > 1) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } else { + nt_pwd = ntPwdHash[0].hash; + } + } + + nt_status = sam_password_ok(auth_context, mem_ctx, + username, acct_flags, + lm_pwd, nt_pwd, user_info, &user_sess_key, &lm_sess_key); if (!NT_STATUS_IS_OK(nt_status)) { - pdb_free_sam(&sampass); return nt_status; } - nt_status = sam_account_ok(mem_ctx, sampass, user_info); + nt_status = sam_account_ok(mem_ctx, username, acct_flags, msgs, user_info); if (!NT_STATUS_IS_OK(nt_status)) { - pdb_free_sam(&sampass); return nt_status; } - if (!NT_STATUS_IS_OK(nt_status = make_server_info_sam(server_info, sampass))) { + 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))); return nt_status; } + { + struct ldb_message **group_msgs; + char *dn = msgs[0]->dn; + int group_ret; + const char *group_attrs[3] = { "sAMAccountType", "objectSid", NULL }; + /* find list of sids */ + struct dom_sid **groupSIDs = NULL; + struct dom_sid *user_sid; + struct dom_sid *group_sid; + const char *sidstr; + int i; + + group_ret = samdb_search(sam_ctx, + mem_ctx, NULL, &group_msgs, group_attrs, + "(&(member=%s)(sAMAccountType=*))", + dn); + + if (!(groupSIDs = talloc_realloc_p((*server_info)->mem_ctx, groupSIDs, + struct dom_sid *, group_ret))) { + talloc_destroy((*server_info)->mem_ctx); + return NT_STATUS_NO_MEMORY; + } + + /* Need to unroll some nested groups, but not aliases */ + for (i = 0; i < group_ret; i++) { + sidstr = ldb_msg_find_string(group_msgs[i], "objectSid", NULL); + groupSIDs[i] = dom_sid_parse_talloc((*server_info)->mem_ctx, sidstr); + } + + sidstr = ldb_msg_find_string(msgs[0], "objectSid", NULL); + user_sid = dom_sid_parse_talloc((*server_info)->mem_ctx, sidstr); + group_sid = dom_sid_parse_talloc((*server_info)->mem_ctx, sidstr); + group_sid->sub_auths[group_sid->num_auths-1] + = samdb_result_uint(msgs[0], "primaryGroupID", 0); + + if (!NT_STATUS_IS_OK(nt_status = create_nt_user_token((*server_info)->mem_ctx, + user_sid, group_sid, + group_ret, groupSIDs, + 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); + return nt_status; + } + } + + (*server_info)->guest = False; + (*server_info)->user_session_key = user_sess_key; (*server_info)->lm_session_key = lm_sess_key; |