NTSTATUS check_sam_security(const DATA_BLOB *challenge, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { struct samu *sampass=NULL; bool ret; NTSTATUS nt_status; NTSTATUS update_login_attempts_status; DATA_BLOB user_sess_key = data_blob_null; DATA_BLOB lm_sess_key = data_blob_null; bool updated_badpw = False; const char *username; const uint8_t *nt_pw; const uint8_t *lm_pw; uint32_t acct_ctrl; /* the returned struct gets kept on the server_info, by means of a steal further down */ sampass = samu_new(mem_ctx); if (sampass == NULL) { return NT_STATUS_NO_MEMORY; } /* get the account information */ become_root(); ret = pdb_getsampwnam(sampass, user_info->mapped.account_name); unbecome_root(); if (ret == False) { DEBUG(3,("check_sam_security: Couldn't find user '%s' in " "passdb.\n", user_info->mapped.account_name)); TALLOC_FREE(sampass); return NT_STATUS_NO_SUCH_USER; } acct_ctrl = pdb_get_acct_ctrl(sampass); username = pdb_get_username(sampass); nt_pw = pdb_get_nt_passwd(sampass); lm_pw = pdb_get_lanman_passwd(sampass); /* Quit if the account was locked out. */ if (acct_ctrl & ACB_AUTOLOCK) { DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", username)); TALLOC_FREE(sampass); return NT_STATUS_ACCOUNT_LOCKED_OUT; } nt_status = sam_password_ok(mem_ctx, username, acct_ctrl, challenge, lm_pw, nt_pw, 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(nt_status)) { bool increment_bad_pw_count = false; if (NT_STATUS_EQUAL(nt_status,NT_STATUS_WRONG_PASSWORD) && (acct_ctrl & ACB_NORMAL) && NT_STATUS_IS_OK(update_login_attempts_status)) { increment_bad_pw_count = need_to_increment_bad_pw_count( challenge, sampass, user_info); } if (increment_bad_pw_count) { pdb_increment_bad_password_count(sampass); updated_badpw = True; } else { pdb_update_bad_password_count(sampass, &updated_badpw); } if (updated_badpw){ NTSTATUS status; become_root(); status = pdb_update_sam_account(sampass); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to modify entry: %s\n", nt_errstr(status))); } } goto done; } /* * We must only reset the bad password count if the login was * successful, including checking account policies */ nt_status = sam_account_ok(mem_ctx, sampass, user_info); if (!NT_STATUS_IS_OK(nt_status)) { goto done; } if ((acct_ctrl & ACB_NORMAL) && (pdb_get_bad_password_count(sampass) > 0)){ NTSTATUS status; pdb_set_bad_password_count(sampass, 0, PDB_CHANGED); pdb_set_bad_password_time(sampass, 0, PDB_CHANGED); become_root(); status = pdb_update_sam_account(sampass); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to modify entry: %s\n", nt_errstr(status))); } } become_root(); nt_status = make_server_info_sam(mem_ctx, sampass, server_info); unbecome_root(); TALLOC_FREE(sampass); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status))); goto done; } (*server_info)->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); (*server_info)->nss_token |= user_info->was_mapped; done: TALLOC_FREE(sampass); data_blob_free(&user_sess_key); data_blob_free(&lm_sess_key); return nt_status; }
static NTSTATUS check_sam_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { struct samu *sampass=NULL; BOOL ret; NTSTATUS nt_status; 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, because the returned struct gets kept on the server_info */ if ( !(sampass = samu_new( NULL )) ) { return NT_STATUS_NO_MEMORY; } /* get the account information */ become_root(); ret = pdb_getsampwnam(sampass, user_info->internal_username); unbecome_root(); 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; } /* 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)) { 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)) { TALLOC_FREE(sampass); data_blob_free(&user_sess_key); data_blob_free(&lm_sess_key); return nt_status; } 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; } (*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); (*server_info)->was_mapped |= user_info->was_mapped; return nt_status; }
NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, char *ntuser, char *ntdomain, char *username, struct passwd *pw, struct PAC_LOGON_INFO *logon_info, bool mapped_to_guest, bool username_was_mapped, DATA_BLOB *session_key, struct auth_session_info **session_info) { NTSTATUS status; struct auth_serversupplied_info *server_info; if (mapped_to_guest) { status = make_server_info_guest(mem_ctx, &server_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("make_server_info_guest failed: %s!\n", nt_errstr(status))); return status; } } else if (logon_info) { /* pass the unmapped username here since map_username() will be called again in make_server_info_info3() */ status = make_server_info_info3(mem_ctx, ntuser, ntdomain, &server_info, &logon_info->info3); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("make_server_info_info3 failed: %s!\n", nt_errstr(status))); return status; } } else { /* * We didn't get a PAC, we have to make up the user * ourselves. Try to ask the pdb backend to provide * SID consistency with ntlmssp session setup */ struct samu *sampass; /* The stupid make_server_info_XX functions here don't take a talloc context. */ struct auth_serversupplied_info *tmp = NULL; sampass = samu_new(talloc_tos()); if (sampass == NULL) { return NT_STATUS_NO_MEMORY; } if (pdb_getsampwnam(sampass, username)) { DEBUG(10, ("found user %s in passdb, calling " "make_server_info_sam\n", username)); status = make_server_info_sam(&tmp, sampass); } else { /* * User not in passdb, make it up artificially */ DEBUG(10, ("didn't find user %s in passdb, calling " "make_server_info_pw\n", username)); status = make_server_info_pw(&tmp, username, pw); } TALLOC_FREE(sampass); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("make_server_info_[sam|pw] failed: %s!\n", nt_errstr(status))); return status; } /* make_server_info_pw does not set the domain. Without this * we end up with the local netbios name in substitutions for * %D. */ if (server_info->info3 != NULL) { server_info->info3->base.domain.string = talloc_strdup(server_info->info3, ntdomain); } } server_info->nss_token |= username_was_mapped; status = create_local_token(mem_ctx, server_info, session_key, ntuser, session_info); talloc_free(server_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("failed to create local token: %s\n", nt_errstr(status))); return status; } return NT_STATUS_OK; }