static NTSTATUS sam_password_ok(const struct auth_context *auth_context, TALLOC_CTX *mem_ctx, struct samu *sampass, const auth_usersupplied_info *user_info, DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key) { 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", 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; } } 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, username, user_info->smb_name, user_info->client_domain, lm_pw, nt_pw, user_sess_key, lm_sess_key); }
static int print_sam_info (struct samu *sam_pwent, bool verbosity, bool smbpwdstyle) { uid_t uid; time_t tmp; /* TODO: check if entry is a user or a workstation */ if (!sam_pwent) return -1; if (verbosity) { char temp[44]; const uint8_t *hours; printf ("Unix username: %s\n", pdb_get_username(sam_pwent)); printf ("NT username: %s\n", pdb_get_nt_username(sam_pwent)); printf ("Account Flags: %s\n", pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent), NEW_PW_FORMAT_SPACE_PADDED_LEN)); printf ("User SID: %s\n", sid_string_tos(pdb_get_user_sid(sam_pwent))); printf ("Primary Group SID: %s\n", sid_string_tos(pdb_get_group_sid(sam_pwent))); printf ("Full Name: %s\n", pdb_get_fullname(sam_pwent)); printf ("Home Directory: %s\n", pdb_get_homedir(sam_pwent)); printf ("HomeDir Drive: %s\n", pdb_get_dir_drive(sam_pwent)); printf ("Logon Script: %s\n", pdb_get_logon_script(sam_pwent)); printf ("Profile Path: %s\n", pdb_get_profile_path(sam_pwent)); printf ("Domain: %s\n", pdb_get_domain(sam_pwent)); printf ("Account desc: %s\n", pdb_get_acct_desc(sam_pwent)); printf ("Workstations: %s\n", pdb_get_workstations(sam_pwent)); printf ("Munged dial: %s\n", pdb_get_munged_dial(sam_pwent)); tmp = pdb_get_logon_time(sam_pwent); printf ("Logon time: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_logoff_time(sam_pwent); printf ("Logoff time: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_kickoff_time(sam_pwent); printf ("Kickoff time: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_pass_last_set_time(sam_pwent); printf ("Password last set: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_pass_can_change_time(sam_pwent); printf ("Password can change: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_pass_must_change_time(sam_pwent); printf ("Password must change: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_bad_password_time(sam_pwent); printf ("Last bad password : %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); printf ("Bad password count : %d\n", pdb_get_bad_password_count(sam_pwent)); hours = pdb_get_hours(sam_pwent); pdb_sethexhours(temp, hours); printf ("Logon hours : %s\n", temp); } else if (smbpwdstyle) { char lm_passwd[33]; char nt_passwd[33]; uid = nametouid(pdb_get_username(sam_pwent)); pdb_sethexpwd(lm_passwd, pdb_get_lanman_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent)); pdb_sethexpwd(nt_passwd, pdb_get_nt_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent)); printf("%s:%lu:%s:%s:%s:LCT-%08X:\n", pdb_get_username(sam_pwent), (unsigned long)uid, lm_passwd, nt_passwd, pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent),NEW_PW_FORMAT_SPACE_PADDED_LEN), (uint32_t)convert_time_t_to_uint32_t(pdb_get_pass_last_set_time(sam_pwent))); } else { uid = nametouid(pdb_get_username(sam_pwent)); printf ("%s:%lu:%s\n", pdb_get_username(sam_pwent), (unsigned long)uid, pdb_get_fullname(sam_pwent)); } return 0; }
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; }
/* Helper function for adding a user to the db. */ static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl, const char *name, SAM_ACCOUNT *sampass, BOOL exist) { pstring err_str; pstring msg_str; const char *pass = NULL; int retval; err_str[0] = '\0'; msg_str[0] = '\0'; /* Get the authtok; if we don't have one, silently fail. */ retval = pam_get_item( pamh, PAM_AUTHTOK, (const void **) &pass ); if (retval != PAM_SUCCESS) { _log_err( LOG_ALERT , "pam_get_item returned error to pam_sm_authenticate" ); return PAM_AUTHTOK_RECOVER_ERR; } else if (pass == NULL) { return PAM_AUTHTOK_RECOVER_ERR; } /* Add the user to the db if they aren't already there. */ if (!exist) { retval = local_password_change( name, LOCAL_ADD_USER, pass, err_str, sizeof(err_str), msg_str, sizeof(msg_str) ); if (!retval && *err_str) { err_str[PSTRING_LEN-1] = '\0'; make_remark( pamh, ctrl, PAM_ERROR_MSG, err_str ); } else if (*msg_str) { msg_str[PSTRING_LEN-1] = '\0'; make_remark( pamh, ctrl, PAM_TEXT_INFO, msg_str ); } pass = NULL; return PAM_IGNORE; } else { /* Change the user's password IFF it's null. */ if ((pdb_get_lanman_passwd(sampass) == NULL) && (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ)) { retval = local_password_change( name, 0, pass, err_str, sizeof(err_str), msg_str, sizeof(msg_str) ); if (!retval && *err_str) { err_str[PSTRING_LEN-1] = '\0'; make_remark( pamh, ctrl, PAM_ERROR_MSG, err_str ); } else if (*msg_str) { msg_str[PSTRING_LEN-1] = '\0'; make_remark( pamh, ctrl, PAM_TEXT_INFO, msg_str ); } } } pass = NULL; return PAM_IGNORE; }
static BOOL samu_correct(struct samu *s1, struct samu *s2) { BOOL ret = True; uint32 s1_len, s2_len; const char *s1_buf, *s2_buf; const uint8 *d1_buf, *d2_buf; /* Check Unix username */ s1_buf = pdb_get_username(s1); s2_buf = pdb_get_username(s2); if (s2_buf == NULL && s1_buf != NULL) { DEBUG(0, ("Username is not set\n")); ret = False; } else if (s1_buf == NULL) { /* Do nothing */ } else if (strcmp(s1_buf,s2_buf)) { DEBUG(0, ("Username not written correctly, want %s, got \"%s\"\n", pdb_get_username(s1), pdb_get_username(s2))); ret = False; } /* Check NT username */ s1_buf = pdb_get_nt_username(s1); s2_buf = pdb_get_nt_username(s2); if (s2_buf == NULL && s1_buf != NULL) { DEBUG(0, ("NT Username is not set\n")); ret = False; } else if (s1_buf == NULL) { /* Do nothing */ } else if (strcmp(s1_buf, s2_buf)) { DEBUG(0, ("NT Username not written correctly, want \"%s\", got \"%s\"\n", pdb_get_nt_username(s1), pdb_get_nt_username(s2))); ret = False; } /* Check acct ctrl */ if (pdb_get_acct_ctrl(s1) != pdb_get_acct_ctrl(s2)) { DEBUG(0, ("Acct ctrl field not written correctly, want %d (0x%X), got %d (0x%X)\n", pdb_get_acct_ctrl(s1), pdb_get_acct_ctrl(s1), pdb_get_acct_ctrl(s2), pdb_get_acct_ctrl(s2))); ret = False; } /* Check NT password */ d1_buf = pdb_get_nt_passwd(s1); d2_buf = pdb_get_nt_passwd(s2); if (d2_buf == NULL && d1_buf != NULL) { DEBUG(0, ("NT password is not set\n")); ret = False; } else if (d1_buf == NULL) { /* Do nothing */ } else if (memcmp(d1_buf, d2_buf, NT_HASH_LEN)) { DEBUG(0, ("NT password not written correctly\n")); ret = False; } /* Check lanman password */ d1_buf = pdb_get_lanman_passwd(s1); d2_buf = pdb_get_lanman_passwd(s2); if (d2_buf == NULL && d1_buf != NULL) { DEBUG(0, ("Lanman password is not set\n")); } else if (d1_buf == NULL) { /* Do nothing */ } else if (memcmp(d1_buf, d2_buf, NT_HASH_LEN)) { DEBUG(0, ("Lanman password not written correctly\n")); ret = False; } /* Check password history */ d1_buf = pdb_get_pw_history(s1, &s1_len); d2_buf = pdb_get_pw_history(s2, &s2_len); if (d2_buf == NULL && d1_buf != NULL) { DEBUG(0, ("Password history is not set\n")); } else if (d1_buf == NULL) { /* Do nothing */ } else if (s1_len != s1_len) { DEBUG(0, ("Password history not written correctly, lengths differ, want %d, got %d\n", s1_len, s2_len)); ret = False; } else if (strncmp(s1_buf, s2_buf, s1_len)) { DEBUG(0, ("Password history not written correctly\n")); ret = False; } /* Check logon time */ if (pdb_get_logon_time(s1) != pdb_get_logon_time(s2)) { DEBUG(0, ("Logon time is not written correctly\n")); ret = False; } /* Check logoff time */ if (pdb_get_logoff_time(s1) != pdb_get_logoff_time(s2)) { DEBUG(0, ("Logoff time is not written correctly\n")); ret = False; } /* Check kickoff time */ if (pdb_get_kickoff_time(s1) != pdb_get_logoff_time(s2)) { DEBUG(0, ("Kickoff time is not written correctly\n")); ret = False; } /* Check bad password time */ if (pdb_get_bad_password_time(s1) != pdb_get_bad_password_time(s2)) { DEBUG(0, ("Bad password time is not written correctly\n")); ret = False; } /* Check password last set time */ if (pdb_get_pass_last_set_time(s1) != pdb_get_pass_last_set_time(s2)) { DEBUG(0, ("Password last set time is not written correctly\n")); ret = False; } /* Check password can change time */ if (pdb_get_pass_can_change_time(s1) != pdb_get_pass_can_change_time(s2)) { DEBUG(0, ("Password can change time is not written correctly\n")); ret = False; } /* Check password must change time */ if (pdb_get_pass_must_change_time(s1) != pdb_get_pass_must_change_time(s2)) { DEBUG(0, ("Password must change time is not written correctly\n")); ret = False; } /* Check logon divs */ if (pdb_get_logon_divs(s1) != pdb_get_logon_divs(s2)) { DEBUG(0, ("Logon divs not written correctly\n")); ret = False; } /* Check logon hours */ if (pdb_get_hours_len(s1) != pdb_get_hours_len(s2)) { DEBUG(0, ("Logon hours length not written correctly\n")); ret = False; } else if (pdb_get_hours_len(s1) != 0) { d1_buf = pdb_get_hours(s1); d2_buf = pdb_get_hours(s2); if (d2_buf == NULL && d2_buf != NULL) { DEBUG(0, ("Logon hours is not set\n")); ret = False; } else if (d1_buf == NULL) { /* Do nothing */ } else if (memcmp(d1_buf, d2_buf, MAX_HOURS_LEN)) { DEBUG(0, ("Logon hours is not written correctly\n")); ret = False; } } /* Check profile path */ s1_buf = pdb_get_profile_path(s1); s2_buf = pdb_get_profile_path(s2); if (s2_buf == NULL && s1_buf != NULL) { DEBUG(0, ("Profile path is not set\n")); ret = False; } else if (s1_buf == NULL) { /* Do nothing */ } else if (strcmp(s1_buf, s2_buf)) { DEBUG(0, ("Profile path is not written correctly\n")); ret = False; } /* Check home dir */ s1_buf = pdb_get_homedir(s1); s2_buf = pdb_get_homedir(s2); if (s2_buf == NULL && s1_buf != NULL) { DEBUG(0, ("Home dir is not set\n")); ret = False; } else if (s1_buf == NULL) { /* Do nothing */ } else if (strcmp(s1_buf, s2_buf)) { DEBUG(0, ("Home dir is not written correctly\n")); ret = False; } /* Check logon script */ s1_buf = pdb_get_logon_script(s1); s2_buf = pdb_get_logon_script(s2); if (s2_buf == NULL && s1_buf != NULL) { DEBUG(0, ("Logon script not set\n")); ret = False; } else if (s1_buf == NULL) { /* Do nothing */ } else if (strcmp(s1_buf, s2_buf)) { DEBUG(0, ("Logon script is not written correctly\n")); ret = False; } /* TODO Check user and group sids */ return ret; }