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 BOOL get_md4pw(char *md4pw, char *mach_acct) { SAM_ACCOUNT *sampass = NULL; const uint8 *pass; BOOL ret; uint32 acct_ctrl; #if 0 /* * Currently this code is redundent as we already have a filter * by hostname list. What this code really needs to do is to * get a hosts allowed/hosts denied list from the SAM database * on a per user basis, and make the access decision there. * I will leave this code here for now as a reminder to implement * this at a later date. JRA. */ if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(), client_name(), client_addr())) { DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct)); return False; } #endif /* 0 */ if(!NT_STATUS_IS_OK(pdb_init_sam(&sampass))) return False; /* JRA. This is ok as it is only used for generating the challenge. */ become_root(); ret=pdb_getsampwnam(sampass, mach_acct); unbecome_root(); if (ret==False) { DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct)); pdb_free_sam(&sampass); return False; } acct_ctrl = pdb_get_acct_ctrl(sampass); if (!(acct_ctrl & ACB_DISABLED) && ((acct_ctrl & ACB_DOMTRUST) || (acct_ctrl & ACB_WSTRUST) || (acct_ctrl & ACB_SVRTRUST)) && ((pass=pdb_get_nt_passwd(sampass)) != NULL)) { memcpy(md4pw, pass, 16); dump_data(5, md4pw, 16); pdb_free_sam(&sampass); return True; } DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct)); pdb_free_sam(&sampass); return False; }
/* Helper function for adding a user to the db. */ static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl, const char *name, struct samu *sampass, bool exist) { char *err_str = NULL; char *msg_str = NULL; const char *pass = NULL; int retval; TALLOC_CTX *frame = talloc_stackframe(); /* Get the authtok; if we don't have one, silently fail. */ retval = _pam_get_item( pamh, PAM_AUTHTOK, &pass ); if (retval != PAM_SUCCESS) { _log_err(pamh, LOG_ALERT , "pam_get_item returned error to pam_sm_authenticate" ); TALLOC_FREE(frame); return PAM_AUTHTOK_RECOVER_ERR; } /* Add the user to the db if they aren't already there. */ if (!exist) { retval = NT_STATUS_IS_OK(local_password_change(name, LOCAL_ADD_USER|LOCAL_SET_PASSWORD, pass, &err_str, &msg_str)); if (!retval && err_str) { make_remark(pamh, ctrl, PAM_ERROR_MSG, err_str ); } else if (msg_str) { make_remark(pamh, ctrl, PAM_TEXT_INFO, msg_str ); } pass = NULL; SAFE_FREE(err_str); SAFE_FREE(msg_str); TALLOC_FREE(frame); return PAM_IGNORE; } else { /* mimick 'update encrypted' as long as the 'no pw req' flag is not set */ if ( pdb_get_acct_ctrl(sampass) & ~ACB_PWNOTREQ ) { retval = NT_STATUS_IS_OK(local_password_change(name, LOCAL_SET_PASSWORD, pass, &err_str, &msg_str)); if (!retval && err_str) { make_remark(pamh, ctrl, PAM_ERROR_MSG, err_str ); } else if (msg_str) { make_remark(pamh, ctrl, PAM_TEXT_INFO, msg_str ); } } } SAFE_FREE(err_str); SAFE_FREE(msg_str); pass = NULL; TALLOC_FREE(frame); return PAM_IGNORE; }
/** * update the encrypted smbpasswd file from the plaintext username and password * * this ugly hack needs to die, but not quite yet, I think people still use it... **/ static BOOL update_smbpassword_file(const char *user, const char *password) { struct samu *sampass; BOOL ret; if ( !(sampass = samu_new( NULL )) ) { return False; } become_root(); ret = pdb_getsampwnam(sampass, user); unbecome_root(); if(ret == False) { DEBUG(0,("pdb_getsampwnam returned NULL\n")); TALLOC_FREE(sampass); return False; } /* * Remove the account disabled flag - we are updating the * users password from a login. */ if (!pdb_set_acct_ctrl(sampass, pdb_get_acct_ctrl(sampass) & ~ACB_DISABLED, PDB_CHANGED)) { TALLOC_FREE(sampass); return False; } if (!pdb_set_plaintext_passwd (sampass, password)) { TALLOC_FREE(sampass); return False; } /* Now write it into the file. */ become_root(); ret = NT_STATUS_IS_OK(pdb_update_sam_account (sampass)); unbecome_root(); if (ret) { DEBUG(3,("pdb_update_sam_account returned %d\n",ret)); } TALLOC_FREE(sampass); return ret; }
/* 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; }
bool pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext) { uchar new_lanman_p16[LM_HASH_LEN]; uchar new_nt_p16[NT_HASH_LEN]; if (!plaintext) return False; /* Calculate the MD4 hash (NT compatible) of the password */ E_md4hash(plaintext, new_nt_p16); if (!pdb_set_nt_passwd (sampass, new_nt_p16, PDB_CHANGED)) return False; if (!E_deshash(plaintext, new_lanman_p16)) { /* E_deshash returns false for 'long' passwords (> 14 DOS chars). This allows us to match Win2k, which does not store a LM hash for these passwords (which would reduce the effective password length to 14 */ if (!pdb_set_lanman_passwd (sampass, NULL, PDB_CHANGED)) return False; } else { if (!pdb_set_lanman_passwd (sampass, new_lanman_p16, PDB_CHANGED)) return False; } if (!pdb_set_plaintext_pw_only (sampass, plaintext, PDB_CHANGED)) return False; if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED)) return False; /* Store the password history. */ if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) { uchar *pwhistory; uint32 pwHistLen; pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); if (pwHistLen != 0){ uint32 current_history_len; /* We need to make sure we don't have a race condition here - the account policy history length can change between when the pw_history was first loaded into the struct samu struct and now.... JRA. */ pwhistory = (uchar *)pdb_get_pw_history(sampass, ¤t_history_len); if (current_history_len != pwHistLen) { /* After closing and reopening struct samu the history values will sync up. We can't do this here. */ /* current_history_len > pwHistLen is not a problem - we have more history than we need. */ if (current_history_len < pwHistLen) { /* Ensure we have space for the needed history. */ uchar *new_history = (uchar *)TALLOC(sampass, pwHistLen*PW_HISTORY_ENTRY_LEN); if (!new_history) { return False; } /* And copy it into the new buffer. */ if (current_history_len) { memcpy(new_history, pwhistory, current_history_len*PW_HISTORY_ENTRY_LEN); } /* Clearing out any extra space. */ memset(&new_history[current_history_len*PW_HISTORY_ENTRY_LEN], '\0', (pwHistLen-current_history_len)*PW_HISTORY_ENTRY_LEN); /* Finally replace it. */ pwhistory = new_history; } } if (pwhistory && pwHistLen){ /* Make room for the new password in the history list. */ if (pwHistLen > 1) { memmove(&pwhistory[PW_HISTORY_ENTRY_LEN], pwhistory, (pwHistLen -1)*PW_HISTORY_ENTRY_LEN ); } /* Create the new salt as the first part of the history entry. */ generate_random_buffer(pwhistory, PW_HISTORY_SALT_LEN); /* Generate the md5 hash of the salt+new password as the second part of the history entry. */ E_md5hash(pwhistory, new_nt_p16, &pwhistory[PW_HISTORY_SALT_LEN]); pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED); } else { DEBUG (10,("pdb_get_set.c: pdb_set_plaintext_passwd: pwhistory was NULL!\n")); } } else { /* Set the history length to zero. */ pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED); } } return True; }
static int set_machine_info(const char *machinename, const char *account_control, const char *machine_sid) { struct samu *sam_pwent = NULL; TALLOC_CTX *tosctx; uint32_t acb_flags; uint32_t not_settable; uint32_t new_flags; struct dom_sid m_sid; char *name; int len; bool ret; len = strlen(machinename); if (len == 0) { fprintf(stderr, "No machine name given\n"); return -1; } tosctx = talloc_tos(); if (!tosctx) { fprintf(stderr, "Out of memory!\n"); return -1; } sam_pwent = samu_new(tosctx); if (!sam_pwent) { return 1; } if (machinename[len-1] == '$') { name = talloc_strdup(sam_pwent, machinename); } else { name = talloc_asprintf(sam_pwent, "%s$", machinename); } if (!name) { fprintf(stderr, "Out of memory!\n"); TALLOC_FREE(sam_pwent); return -1; } if (!strlower_m(name)) { fprintf(stderr, "strlower_m %s failed\n", name); TALLOC_FREE(sam_pwent); return -1; } ret = pdb_getsampwnam(sam_pwent, name); if (!ret) { fprintf (stderr, "Username not found!\n"); TALLOC_FREE(sam_pwent); return -1; } if (account_control) { not_settable = ~(ACB_DISABLED); new_flags = pdb_decode_acct_ctrl(account_control); if (new_flags & not_settable) { fprintf(stderr, "Can only set [D] flags\n"); TALLOC_FREE(sam_pwent); return -1; } acb_flags = pdb_get_acct_ctrl(sam_pwent); pdb_set_acct_ctrl(sam_pwent, (acb_flags & not_settable) | new_flags, PDB_CHANGED); } if (machine_sid) { if (get_sid_from_cli_string(&m_sid, machine_sid)) { fprintf(stderr, "Failed to parse SID\n"); return -1; } pdb_set_user_sid(sam_pwent, &m_sid, PDB_CHANGED); } if (NT_STATUS_IS_OK(pdb_update_sam_account(sam_pwent))) { print_user_info(name, True, False); } else { fprintf (stderr, "Unable to modify entry!\n"); TALLOC_FREE(sam_pwent); return -1; } TALLOC_FREE(sam_pwent); return 0; }
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; }
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; }
void copy_id21_to_sam_passwd(const char *log_prefix, struct samu *to, struct samr_UserInfo21 *from) { time_t unix_time, stored_time; const char *old_string, *new_string; const char *l; if (from == NULL || to == NULL) { return; } if (log_prefix) { l = log_prefix; } else { l = "INFO_21"; } if (from->fields_present & SAMR_FIELD_LAST_LOGON) { unix_time = nt_time_to_unix(from->last_logon); stored_time = pdb_get_logon_time(to); DEBUG(10,("%s SAMR_FIELD_LAST_LOGON: %lu -> %lu\n", l, (long unsigned int)stored_time, (long unsigned int)unix_time)); if (stored_time != unix_time) { pdb_set_logon_time(to, unix_time, PDB_CHANGED); } } if (from->fields_present & SAMR_FIELD_LAST_LOGOFF) { unix_time = nt_time_to_unix(from->last_logoff); stored_time = pdb_get_logoff_time(to); DEBUG(10,("%s SAMR_FIELD_LAST_LOGOFF: %lu -> %lu\n", l, (long unsigned int)stored_time, (long unsigned int)unix_time)); if (stored_time != unix_time) { pdb_set_logoff_time(to, unix_time, PDB_CHANGED); } } if (from->fields_present & SAMR_FIELD_ACCT_EXPIRY) { unix_time = nt_time_to_unix(from->acct_expiry); stored_time = pdb_get_kickoff_time(to); DEBUG(10,("%s SAMR_FIELD_ACCT_EXPIRY: %lu -> %lu\n", l, (long unsigned int)stored_time, (long unsigned int)unix_time)); if (stored_time != unix_time) { pdb_set_kickoff_time(to, unix_time , PDB_CHANGED); } } if (from->fields_present & SAMR_FIELD_LAST_PWD_CHANGE) { unix_time = nt_time_to_unix(from->last_password_change); stored_time = pdb_get_pass_last_set_time(to); DEBUG(10,("%s SAMR_FIELD_LAST_PWD_CHANGE: %lu -> %lu\n", l, (long unsigned int)stored_time, (long unsigned int)unix_time)); if (stored_time != unix_time) { pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_ACCOUNT_NAME) && (from->account_name.string)) { old_string = pdb_get_username(to); new_string = from->account_name.string; DEBUG(10,("%s SAMR_FIELD_ACCOUNT_NAME: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_username(to, new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_FULL_NAME) && (from->full_name.string)) { old_string = pdb_get_fullname(to); new_string = from->full_name.string; DEBUG(10,("%s SAMR_FIELD_FULL_NAME: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_fullname(to, new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_HOME_DIRECTORY) && (from->home_directory.string)) { old_string = pdb_get_homedir(to); new_string = from->home_directory.string; DEBUG(10,("%s SAMR_FIELD_HOME_DIRECTORY: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_homedir(to, new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_HOME_DRIVE) && (from->home_drive.string)) { old_string = pdb_get_dir_drive(to); new_string = from->home_drive.string; DEBUG(10,("%s SAMR_FIELD_HOME_DRIVE: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_dir_drive(to, new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_LOGON_SCRIPT) && (from->logon_script.string)) { old_string = pdb_get_logon_script(to); new_string = from->logon_script.string; DEBUG(10,("%s SAMR_FIELD_LOGON_SCRIPT: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_logon_script(to , new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_PROFILE_PATH) && (from->profile_path.string)) { old_string = pdb_get_profile_path(to); new_string = from->profile_path.string; DEBUG(10,("%s SAMR_FIELD_PROFILE_PATH: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_profile_path(to , new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_DESCRIPTION) && (from->description.string)) { old_string = pdb_get_acct_desc(to); new_string = from->description.string; DEBUG(10,("%s SAMR_FIELD_DESCRIPTION: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_acct_desc(to, new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_WORKSTATIONS) && (from->workstations.string)) { old_string = pdb_get_workstations(to); new_string = from->workstations.string; DEBUG(10,("%s SAMR_FIELD_WORKSTATIONS: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_workstations(to , new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_COMMENT) && (from->comment.string)) { old_string = pdb_get_comment(to); new_string = from->comment.string; DEBUG(10,("%s SAMR_FIELD_COMMENT: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_comment(to, new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_PARAMETERS) && (from->parameters.array)) { char *newstr; DATA_BLOB mung; old_string = pdb_get_munged_dial(to); mung = data_blob_const(from->parameters.array, from->parameters.length); newstr = (mung.length == 0) ? NULL : base64_encode_data_blob(talloc_tos(), mung); DEBUG(10,("%s SAMR_FIELD_PARAMETERS: %s -> %s\n", l, old_string, newstr)); if (STRING_CHANGED_NC(old_string,newstr)) { pdb_set_munged_dial(to, newstr, PDB_CHANGED); } TALLOC_FREE(newstr); } if (from->fields_present & SAMR_FIELD_RID) { if (from->rid == 0) { DEBUG(10,("%s: Asked to set User RID to 0 !? Skipping change!\n", l)); } else if (from->rid != pdb_get_user_rid(to)) { DEBUG(10,("%s SAMR_FIELD_RID: %u -> %u NOT UPDATED!\n", l, pdb_get_user_rid(to), from->rid)); } } if (from->fields_present & SAMR_FIELD_PRIMARY_GID) { if (from->primary_gid == 0) { DEBUG(10,("%s: Asked to set Group RID to 0 !? Skipping change!\n", l)); } else if (from->primary_gid != pdb_get_group_rid(to)) { DEBUG(10,("%s SAMR_FIELD_PRIMARY_GID: %u -> %u\n", l, pdb_get_group_rid(to), from->primary_gid)); pdb_set_group_sid_from_rid(to, from->primary_gid, PDB_CHANGED); } } if (from->fields_present & SAMR_FIELD_ACCT_FLAGS) { DEBUG(10,("%s SAMR_FIELD_ACCT_FLAGS: %08X -> %08X\n", l, pdb_get_acct_ctrl(to), from->acct_flags)); if (from->acct_flags != pdb_get_acct_ctrl(to)) { /* You cannot autolock an unlocked account via * setuserinfo calls, so make sure to remove the * ACB_AUTOLOCK bit here - gd */ if ((from->acct_flags & ACB_AUTOLOCK) && !(pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) { from->acct_flags &= ~ACB_AUTOLOCK; } if (!(from->acct_flags & ACB_AUTOLOCK) && (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) { /* We're unlocking a previously locked user. Reset bad password counts. Patch from Jianliang Lu. <*****@*****.**> */ pdb_set_bad_password_count(to, 0, PDB_CHANGED); pdb_set_bad_password_time(to, 0, PDB_CHANGED); } pdb_set_acct_ctrl(to, from->acct_flags, PDB_CHANGED); } } if (from->fields_present & SAMR_FIELD_LOGON_HOURS) { char oldstr[44]; /* hours strings are 42 bytes. */ char newstr[44]; DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week): %08X -> %08X\n", l, pdb_get_logon_divs(to), from->logon_hours.units_per_week)); if (from->logon_hours.units_per_week != pdb_get_logon_divs(to)) { pdb_set_logon_divs(to, from->logon_hours.units_per_week, PDB_CHANGED); } DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week/8): %08X -> %08X\n", l, pdb_get_hours_len(to), from->logon_hours.units_per_week/8)); if (from->logon_hours.units_per_week/8 != pdb_get_hours_len(to)) { pdb_set_hours_len(to, from->logon_hours.units_per_week/8, PDB_CHANGED); } DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (bits): %s -> %s\n", l, pdb_get_hours(to), from->logon
bool pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext) { uchar new_lanman_p16[LM_HASH_LEN]; uchar new_nt_p16[NT_HASH_LEN]; uchar *pwhistory; uint32 pwHistLen; uint32 current_history_len; if (!plaintext) return False; /* Calculate the MD4 hash (NT compatible) of the password */ E_md4hash(plaintext, new_nt_p16); if (!pdb_set_nt_passwd (sampass, new_nt_p16, PDB_CHANGED)) return False; if (!E_deshash(plaintext, new_lanman_p16)) { /* E_deshash returns false for 'long' passwords (> 14 DOS chars). This allows us to match Win2k, which does not store a LM hash for these passwords (which would reduce the effective password length to 14 */ if (!pdb_set_lanman_passwd (sampass, NULL, PDB_CHANGED)) return False; } else { if (!pdb_set_lanman_passwd (sampass, new_lanman_p16, PDB_CHANGED)) return False; } if (!pdb_set_plaintext_pw_only (sampass, plaintext, PDB_CHANGED)) return False; if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED)) return False; if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) == 0) { /* * No password history for non-user accounts */ return true; } pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen); if (pwHistLen == 0) { /* Set the history length to zero. */ pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED); return true; } /* * We need to make sure we don't have a race condition here - * the account policy history length can change between when * the pw_history was first loaded into the struct samu struct * and now.... JRA. */ pwhistory = (uchar *)pdb_get_pw_history(sampass, ¤t_history_len); if ((current_history_len != 0) && (pwhistory == NULL)) { DEBUG(1, ("pdb_set_plaintext_passwd: pwhistory == NULL!\n")); return false; } if (current_history_len < pwHistLen) { /* * Ensure we have space for the needed history. This * also takes care of an account which did not have * any history at all so far, i.e. pwhistory==NULL */ uchar *new_history = talloc_zero_array( sampass, uchar, pwHistLen*PW_HISTORY_ENTRY_LEN); if (!new_history) { return False; } memcpy(new_history, pwhistory, current_history_len*PW_HISTORY_ENTRY_LEN); pwhistory = new_history; } /* * Make room for the new password in the history list. */ if (pwHistLen > 1) { memmove(&pwhistory[PW_HISTORY_ENTRY_LEN], pwhistory, (pwHistLen-1)*PW_HISTORY_ENTRY_LEN ); } /* * Fill the salt area with 0-s: this indicates that * a plain nt hash is stored in the has area. * The old format was to store a 16 byte salt and * then an md5hash of the nt_hash concatenated with * the salt. */ memset(pwhistory, 0, PW_HISTORY_SALT_LEN); /* * Store the plain nt hash in the second 16 bytes. * The old format was to store the md5 hash of * the salt+newpw. */ memcpy(&pwhistory[PW_HISTORY_SALT_LEN], new_nt_p16, SALTED_MD5_HASH_LEN); pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED); return True; }
NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx, struct samu *samu, const char *login_server, struct netr_SamInfo3 **_info3, struct extra_auth_info *extra) { struct netr_SamInfo3 *info3; const struct dom_sid *user_sid; const struct dom_sid *group_sid; struct dom_sid domain_sid; struct dom_sid *group_sids; uint32_t num_group_sids = 0; const char *tmp; gid_t *gids; NTSTATUS status; user_sid = pdb_get_user_sid(samu); group_sid = pdb_get_group_sid(samu); if (!user_sid || !group_sid) { DEBUG(1, ("Sam account is missing sids!\n")); return NT_STATUS_UNSUCCESSFUL; } info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); if (!info3) { return NT_STATUS_NO_MEMORY; } ZERO_STRUCT(domain_sid); status = SamInfo3_handle_sids(pdb_get_username(samu), user_sid, group_sid, info3, &domain_sid, extra); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); return status; } unix_to_nt_time(&info3->base.logon_time, pdb_get_logon_time(samu)); unix_to_nt_time(&info3->base.logoff_time, get_time_t_max()); unix_to_nt_time(&info3->base.kickoff_time, get_time_t_max()); unix_to_nt_time(&info3->base.last_password_change, pdb_get_pass_last_set_time(samu)); unix_to_nt_time(&info3->base.allow_password_change, pdb_get_pass_can_change_time(samu)); unix_to_nt_time(&info3->base.force_password_change, pdb_get_pass_must_change_time(samu)); tmp = pdb_get_username(samu); if (tmp) { info3->base.account_name.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.account_name.string); } tmp = pdb_get_fullname(samu); if (tmp) { info3->base.full_name.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.full_name.string); } tmp = pdb_get_logon_script(samu); if (tmp) { info3->base.logon_script.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.logon_script.string); } tmp = pdb_get_profile_path(samu); if (tmp) { info3->base.profile_path.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.profile_path.string); } tmp = pdb_get_homedir(samu); if (tmp) { info3->base.home_directory.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.home_directory.string); } tmp = pdb_get_dir_drive(samu); if (tmp) { info3->base.home_drive.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.home_drive.string); } info3->base.logon_count = pdb_get_logon_count(samu); info3->base.bad_password_count = pdb_get_bad_password_count(samu); info3->base.logon_domain.string = talloc_strdup(info3, pdb_get_domain(samu)); RET_NOMEM(info3->base.logon_domain.string); info3->base.domain_sid = dom_sid_dup(info3, &domain_sid); RET_NOMEM(info3->base.domain_sid); status = pdb_enum_group_memberships(mem_ctx, samu, &group_sids, &gids, &num_group_sids); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to get groups from sam account.\n")); TALLOC_FREE(info3); return status; } if (num_group_sids) { status = group_sids_to_info3(info3, group_sids, num_group_sids); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); return status; } } /* We don't need sids and gids after the conversion */ TALLOC_FREE(group_sids); TALLOC_FREE(gids); num_group_sids = 0; /* FIXME: should we add other flags ? */ info3->base.user_flags = NETLOGON_EXTRA_SIDS; if (login_server) { info3->base.logon_server.string = talloc_strdup(info3, login_server); RET_NOMEM(info3->base.logon_server.string); } info3->base.acct_flags = pdb_get_acct_ctrl(samu); *_info3 = info3; return NT_STATUS_OK; }
static int set_user_info (struct pdb_methods *in, const char *username, const char *fullname, const char *homedir, const char *acct_desc, const char *drive, const char *script, const char *profile, const char *account_control, const char *user_sid, const char *user_domain, const BOOL badpw, const BOOL hours) { BOOL updated_autolock = False, updated_badpw = False; struct samu *sam_pwent=NULL; BOOL ret; if ( (sam_pwent = samu_new( NULL )) == NULL ) { return 1; } ret = NT_STATUS_IS_OK(in->getsampwnam (in, sam_pwent, username)); if (ret==False) { fprintf (stderr, "Username not found!\n"); TALLOC_FREE(sam_pwent); return -1; } if (hours) { uint8 hours_array[MAX_HOURS_LEN]; uint32 hours_len; hours_len = pdb_get_hours_len(sam_pwent); memset(hours_array, 0xff, hours_len); pdb_set_hours(sam_pwent, hours_array, PDB_CHANGED); } if (!pdb_update_autolock_flag(sam_pwent, &updated_autolock)) { DEBUG(2,("pdb_update_autolock_flag failed.\n")); } if (!pdb_update_bad_password_count(sam_pwent, &updated_badpw)) { DEBUG(2,("pdb_update_bad_password_count failed.\n")); } if (fullname) pdb_set_fullname(sam_pwent, fullname, PDB_CHANGED); if (acct_desc) pdb_set_acct_desc(sam_pwent, acct_desc, PDB_CHANGED); if (homedir) pdb_set_homedir(sam_pwent, homedir, PDB_CHANGED); if (drive) pdb_set_dir_drive(sam_pwent,drive, PDB_CHANGED); if (script) pdb_set_logon_script(sam_pwent, script, PDB_CHANGED); if (profile) pdb_set_profile_path (sam_pwent, profile, PDB_CHANGED); if (user_domain) pdb_set_domain(sam_pwent, user_domain, PDB_CHANGED); if (account_control) { uint32 not_settable = ~(ACB_DISABLED|ACB_HOMDIRREQ|ACB_PWNOTREQ| ACB_PWNOEXP|ACB_AUTOLOCK); uint32 newflag = pdb_decode_acct_ctrl(account_control); if (newflag & not_settable) { fprintf(stderr, "Can only set [NDHLX] flags\n"); TALLOC_FREE(sam_pwent); return -1; } pdb_set_acct_ctrl(sam_pwent, (pdb_get_acct_ctrl(sam_pwent) & not_settable) | newflag, PDB_CHANGED); } if (user_sid) { DOM_SID u_sid; if (!string_to_sid(&u_sid, user_sid)) { /* not a complete sid, may be a RID, try building a SID */ int u_rid; if (sscanf(user_sid, "%d", &u_rid) != 1) { fprintf(stderr, "Error passed string is not a complete user SID or RID!\n"); return -1; } sid_copy(&u_sid, get_global_sam_sid()); sid_append_rid(&u_sid, u_rid); } pdb_set_user_sid (sam_pwent, &u_sid, PDB_CHANGED); } if (badpw) { pdb_set_bad_password_count(sam_pwent, 0, PDB_CHANGED); pdb_set_bad_password_time(sam_pwent, 0, PDB_CHANGED); } if (NT_STATUS_IS_OK(in->update_sam_account (in, sam_pwent))) print_user_info (in, username, True, False); else { fprintf (stderr, "Unable to modify entry!\n"); TALLOC_FREE(sam_pwent); return -1; } TALLOC_FREE(sam_pwent); return 0; }
int pam_sm_acct_mgmt( pam_handle_t *pamh, int flags, int argc, const char **argv ) { unsigned int ctrl; int retval; const char *name; struct samu *sampass = NULL; void (*oldsig_handler)(int); /* Samba initialization. */ load_case_tables(); setup_logging( "pam_smbpass", False ); lp_set_in_client(True); ctrl = set_ctrl( flags, argc, argv ); /* get the username */ retval = pam_get_user( pamh, &name, "Username: "******"acct: could not identify user" ); } return retval; } if (on( SMB_DEBUG, ctrl )) { _log_err( LOG_DEBUG, "acct: username [%s] obtained", name ); } if (geteuid() != 0) { _log_err( LOG_DEBUG, "Cannot access samba password database, not running as root."); return PAM_AUTHINFO_UNAVAIL; } /* Getting into places that might use LDAP -- protect the app from a SIGPIPE it's not expecting */ oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN); if (!initialize_password_db(True, NULL)) { _log_err( LOG_ALERT, "Cannot access samba password database" ); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_AUTHINFO_UNAVAIL; } /* Get the user's record. */ if (!(sampass = samu_new( NULL ))) { CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); /* malloc fail. */ return nt_status_to_pam(NT_STATUS_NO_MEMORY); } if (!pdb_getsampwnam(sampass, name )) { _log_err( LOG_DEBUG, "acct: could not identify user" ); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_USER_UNKNOWN; } /* check for lookup failure */ if (!strlen(pdb_get_username(sampass)) ) { CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_USER_UNKNOWN; } if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { if (on( SMB_DEBUG, ctrl )) { _log_err( LOG_DEBUG , "acct: account %s is administratively disabled", name ); } make_remark( pamh, ctrl, PAM_ERROR_MSG , "Your account has been disabled; " "please see your system administrator." ); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_ACCT_EXPIRED; } /* TODO: support for expired passwords. */ CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_SUCCESS; }
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; }
NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *r_u) { NTSTATUS status = NT_STATUS_ACCESS_DENIED; DOM_CRED srv_cred; pstring workstation; SAM_ACCOUNT *sampass=NULL; BOOL ret = False; unsigned char pwd[16]; int i; uint32 acct_ctrl; /* checks and updates credentials. creates reply credentials */ if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->clnt_id.cred, &srv_cred))) return NT_STATUS_INVALID_HANDLE; memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred)); DEBUG(5,("_net_srv_pwset: %d\n", __LINE__)); rpcstr_pull(workstation,q_u->clnt_id.login.uni_comp_name.buffer, sizeof(workstation),q_u->clnt_id.login.uni_comp_name.uni_str_len*2,0); DEBUG(3,("Server Password Set by Wksta:[%s] on account [%s]\n", workstation, p->dc.mach_acct)); pdb_init_sam(&sampass); become_root(); ret=pdb_getsampwnam(sampass, p->dc.mach_acct); unbecome_root(); /* Ensure the account exists and is a machine account. */ acct_ctrl = pdb_get_acct_ctrl(sampass); if (!(ret && (acct_ctrl & ACB_WSTRUST || acct_ctrl & ACB_SVRTRUST || acct_ctrl & ACB_DOMTRUST))) { pdb_free_sam(&sampass); return NT_STATUS_NO_SUCH_USER; } if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { pdb_free_sam(&sampass); return NT_STATUS_ACCOUNT_DISABLED; } DEBUG(100,("Server password set : new given value was :\n")); for(i = 0; i < 16; i++) DEBUG(100,("%02X ", q_u->pwd[i])); DEBUG(100,("\n")); cred_hash3( pwd, q_u->pwd, p->dc.sess_key, 0); /* lies! nt and lm passwords are _not_ the same: don't care */ if (!pdb_set_lanman_passwd (sampass, pwd, PDB_CHANGED)) { pdb_free_sam(&sampass); return NT_STATUS_NO_MEMORY; } if (!pdb_set_nt_passwd (sampass, pwd, PDB_CHANGED)) { pdb_free_sam(&sampass); return NT_STATUS_NO_MEMORY; } if (!pdb_set_pass_changed_now (sampass)) { pdb_free_sam(&sampass); /* Not quite sure what this one qualifies as, but this will do */ return NT_STATUS_UNSUCCESSFUL; } become_root(); ret = pdb_update_sam_account (sampass); unbecome_root(); if (ret) status = NT_STATUS_OK; /* set up the LSA Server Password Set response */ init_net_r_srv_pwset(r_u, &srv_cred, status); pdb_free_sam(&sampass); return r_u->status; }
/** * Check whether the given password is one of the last two * password history entries. If so, the bad pwcount should * not be incremented even thought the actual password check * failed. */ static bool need_to_increment_bad_pw_count( const DATA_BLOB *challenge, struct samu* sampass, const struct auth_usersupplied_info *user_info) { uint8_t i; const uint8_t *pwhistory; uint32_t pwhistory_len; uint32_t policy_pwhistory_len; uint32_t acct_ctrl; const char *username; TALLOC_CTX *mem_ctx = talloc_stackframe(); bool result = true; pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &policy_pwhistory_len); if (policy_pwhistory_len == 0) { goto done; } pwhistory = pdb_get_pw_history(sampass, &pwhistory_len); if (!pwhistory || pwhistory_len == 0) { goto done; } acct_ctrl = pdb_get_acct_ctrl(sampass); username = pdb_get_username(sampass); for (i=1; i < MIN(MIN(3, policy_pwhistory_len), pwhistory_len); i++) { static const uint8_t zero16[SALTED_MD5_HASH_LEN]; const uint8_t *salt; const uint8_t *nt_pw; NTSTATUS status; DATA_BLOB user_sess_key = data_blob_null; DATA_BLOB lm_sess_key = data_blob_null; salt = &pwhistory[i*PW_HISTORY_ENTRY_LEN]; nt_pw = salt + PW_HISTORY_SALT_LEN; if (memcmp(zero16, nt_pw, NT_HASH_LEN) == 0) { /* skip zero password hash */ continue; } if (memcmp(zero16, salt, PW_HISTORY_SALT_LEN) != 0) { /* skip nonzero salt (old format entry) */ continue; } status = sam_password_ok(mem_ctx, username, acct_ctrl, challenge, NULL, nt_pw, user_info, &user_sess_key, &lm_sess_key); if (NT_STATUS_IS_OK(status)) { result = false; break; } } done: TALLOC_FREE(mem_ctx); return result; }
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 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; }
void copy_id21_to_sam_passwd(const char *log_prefix, struct samu *to, struct samr_UserInfo21 *from) { time_t unix_time, stored_time; const char *old_string, *new_string; const char *l; if (from == NULL || to == NULL) { return; } if (log_prefix) { l = log_prefix; } else { l = "INFO_21"; } if (from->fields_present & SAMR_FIELD_LAST_LOGON) { unix_time = nt_time_to_unix(from->last_logon); stored_time = pdb_get_logon_time(to); DEBUG(10,("%s SAMR_FIELD_LAST_LOGON: %lu -> %lu\n", l, (long unsigned int)stored_time, (long unsigned int)unix_time)); if (stored_time != unix_time) { pdb_set_logon_time(to, unix_time, PDB_CHANGED); } } if (from->fields_present & SAMR_FIELD_LAST_LOGOFF) { unix_time = nt_time_to_unix(from->last_logoff); stored_time = pdb_get_logoff_time(to); DEBUG(10,("%s SAMR_FIELD_LAST_LOGOFF: %lu -> %lu\n", l, (long unsigned int)stored_time, (long unsigned int)unix_time)); if (stored_time != unix_time) { pdb_set_logoff_time(to, unix_time, PDB_CHANGED); } } if (from->fields_present & SAMR_FIELD_ACCT_EXPIRY) { unix_time = nt_time_to_unix(from->acct_expiry); stored_time = pdb_get_kickoff_time(to); DEBUG(10,("%s SAMR_FIELD_ACCT_EXPIRY: %lu -> %lu\n", l, (long unsigned int)stored_time, (long unsigned int)unix_time)); if (stored_time != unix_time) { pdb_set_kickoff_time(to, unix_time , PDB_CHANGED); } } if (from->fields_present & SAMR_FIELD_LAST_PWD_CHANGE) { unix_time = nt_time_to_unix(from->last_password_change); stored_time = pdb_get_pass_last_set_time(to); DEBUG(10,("%s SAMR_FIELD_LAST_PWD_CHANGE: %lu -> %lu\n", l, (long unsigned int)stored_time, (long unsigned int)unix_time)); if (stored_time != unix_time) { pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_ACCOUNT_NAME) && (from->account_name.string)) { old_string = pdb_get_username(to); new_string = from->account_name.string; DEBUG(10,("%s SAMR_FIELD_ACCOUNT_NAME: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_username(to, new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_FULL_NAME) && (from->full_name.string)) { old_string = pdb_get_fullname(to); new_string = from->full_name.string; DEBUG(10,("%s SAMR_FIELD_FULL_NAME: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_fullname(to, new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_HOME_DIRECTORY) && (from->home_directory.string)) { old_string = pdb_get_homedir(to); new_string = from->home_directory.string; DEBUG(10,("%s SAMR_FIELD_HOME_DIRECTORY: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_homedir(to, new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_HOME_DRIVE) && (from->home_drive.string)) { old_string = pdb_get_dir_drive(to); new_string = from->home_drive.string; DEBUG(10,("%s SAMR_FIELD_HOME_DRIVE: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_dir_drive(to, new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_LOGON_SCRIPT) && (from->logon_script.string)) { old_string = pdb_get_logon_script(to); new_string = from->logon_script.string; DEBUG(10,("%s SAMR_FIELD_LOGON_SCRIPT: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_logon_script(to , new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_PROFILE_PATH) && (from->profile_path.string)) { old_string = pdb_get_profile_path(to); new_string = from->profile_path.string; DEBUG(10,("%s SAMR_FIELD_PROFILE_PATH: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_profile_path(to , new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_DESCRIPTION) && (from->description.string)) { old_string = pdb_get_acct_desc(to); new_string = from->description.string; DEBUG(10,("%s SAMR_FIELD_DESCRIPTION: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_acct_desc(to, new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_WORKSTATIONS) && (from->workstations.string)) { old_string = pdb_get_workstations(to); new_string = from->workstations.string; DEBUG(10,("%s SAMR_FIELD_WORKSTATIONS: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_workstations(to , new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_COMMENT) && (from->comment.string)) { old_string = pdb_get_comment(to); new_string = from->comment.string; DEBUG(10,("%s SAMR_FIELD_COMMENT: %s -> %s\n", l, old_string, new_string)); if (STRING_CHANGED) { pdb_set_comment(to, new_string, PDB_CHANGED); } } if ((from->fields_present & SAMR_FIELD_PARAMETERS) && (from->parameters.array)) { char *newstr; DATA_BLOB mung; old_string = pdb_get_munged_dial(to); mung = data_blob_const(from->parameters.array, from->parameters.length); newstr = (mung.length == 0) ? NULL : base64_encode_data_blob(talloc_tos(), mung); DEBUG(10,("%s SAMR_FIELD_PARAMETERS: %s -> %s\n", l, old_string, newstr)); if (STRING_CHANGED_NC(old_string,newstr)) { pdb_set_munged_dial(to, newstr, PDB_CHANGED); } TALLOC_FREE(newstr); } if (from->fields_present & SAMR_FIELD_RID) { if (from->rid == 0) { DEBUG(10,("%s: Asked to set User RID to 0 !? Skipping change!\n", l)); } else if (from->rid != pdb_get_user_rid(to)) { DEBUG(10,("%s SAMR_FIELD_RID: %u -> %u NOT UPDATED!\n", l, pdb_get_user_rid(to), from->rid)); } } if (from->fields_present & SAMR_FIELD_PRIMARY_GID) { if (from->primary_gid == 0) { DEBUG(10,("%s: Asked to set Group RID to 0 !? Skipping change!\n", l)); } else if (from->primary_gid != pdb_get_group_rid(to)) { DEBUG(10,("%s SAMR_FIELD_PRIMARY_GID: %u -> %u\n", l, pdb_get_group_rid(to), from->primary_gid)); pdb_set_group_sid_from_rid(to, from->primary_gid, PDB_CHANGED); } } if (from->fields_present & SAMR_FIELD_ACCT_FLAGS) { DEBUG(10,("%s SAMR_FIELD_ACCT_FLAGS: %08X -> %08X\n", l, pdb_get_acct_ctrl(to), from->acct_flags)); if (from->acct_flags != pdb_get_acct_ctrl(to)) { /* You cannot autolock an unlocked account via * setuserinfo calls, so make sure to remove the * ACB_AUTOLOCK bit here - gd */ if ((from->acct_flags & ACB_AUTOLOCK) && !(pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) { from->acct_flags &= ~ACB_AUTOLOCK; } if (!(from->acct_flags & ACB_AUTOLOCK) && (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) { /* We're unlocking a previously locked user. Reset bad password counts. Patch from Jianliang Lu. <*****@*****.**> */ pdb_set_bad_password_count(to, 0, PDB_CHANGED); pdb_set_bad_password_time(to, 0, PDB_CHANGED); } pdb_set_acct_ctrl(to, from->acct_flags, PDB_CHANGED); } } if (from->fields_present & SAMR_FIELD_LOGON_HOURS) { char oldstr[44]; /* hours strings are 42 bytes. */ char newstr[44]; DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week): %08X -> %08X\n", l, pdb_get_logon_divs(to), from->logon_hours.units_per_week)); if (from->logon_hours.units_per_week != pdb_get_logon_divs(to)) { pdb_set_logon_divs(to, from->logon_hours.units_per_week, PDB_CHANGED); } DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week/8): %08X -> %08X\n", l, pdb_get_hours_len(to), from->logon_hours.units_per_week/8)); if (from->logon_hours.units_per_week/8 != pdb_get_hours_len(to)) { pdb_set_hours_len(to, from->logon_hours.units_per_week/8, PDB_CHANGED); } DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (bits): %s -> %s\n", l, pdb_get_hours(to), from->logon_hours.bits)); pdb_sethexhours(oldstr, pdb_get_hours(to)); pdb_sethexhours(newstr, from->logon_hours.bits); if (!strequal(oldstr, newstr)) { pdb_set_hours(to, from->logon_hours.bits, from->logon_hours.units_per_week/8, PDB_CHANGED); } } if (from->fields_present & SAMR_FIELD_BAD_PWD_COUNT) { DEBUG(10,("%s SAMR_FIELD_BAD_PWD_COUNT: %08X -> %08X\n", l, pdb_get_bad_password_count(to), from->bad_password_count)); if (from->bad_password_count != pdb_get_bad_password_count(to)) { pdb_set_bad_password_count(to, from->bad_password_count, PDB_CHANGED); } } if (from->fields_present & SAMR_FIELD_NUM_LOGONS) { DEBUG(10,("%s SAMR_FIELD_NUM_LOGONS: %08X -> %08X\n", l, pdb_get_logon_count(to), from->logon_count)); if (from->logon_count != pdb_get_logon_count(to)) { pdb_set_logon_count(to, from->logon_count, PDB_CHANGED); } } /* If the must change flag is set, the last set time goes to zero. the must change and can change fields also do, but they are calculated from policy, not set from the wire */ if (from->fields_present & SAMR_FIELD_EXPIRED_FLAG) { DEBUG(10,("%s SAMR_FIELD_EXPIRED_FLAG: %02X\n", l, from->password_expired)); if (from->password_expired != 0) { /* Only allow the set_time to zero (which means "User Must Change Password on Next Login" if the user object allows password change. */ if (pdb_get_pass_can_change(to)) { pdb_set_pass_last_set_time(to, 0, PDB_CHANGED); } else { DEBUG(10,("%s Disallowing set of 'User Must " "Change Password on Next Login' as " "user object disallows this.\n", l)); } } else { /* A subtlety here: some windows commands will clear the expired flag even though it's not set, and we don't want to reset the time in these caess. "net user /dom <user> /active:y" for example, to clear an autolocked acct. We must check to see if it's expired first. jmcd */ uint32_t pwd_max_age = 0; time_t now = time(NULL); pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &pwd_max_age); if (pwd_max_age == (uint32_t)-1 || pwd_max_age == 0) { pwd_max_age = get_time_t_max(); } stored_time = pdb_get_pass_last_set_time(to); /* we will only *set* a pwdlastset date when a) the last pwdlastset time was 0 (user was forced to change password). b) the users password has not expired. gd. */ if ((stored_time == 0) || ((now - stored_time) > pwd_max_age)) { pdb_set_pass_last_set_time(to, now, PDB_CHANGED); } } } if (from->fields_present & SAMR_FIELD_COUNTRY_CODE) { DEBUG(10,("%s SAMR_FIELD_COUNTRY_CODE: %08X -> %08X\n", l, pdb_get_country_code(to), from->country_code)); if (from->country_code != pdb_get_country_code(to)) { pdb_set_country_code(to, from->country_code, PDB_CHANGED); } } if (from->fields_present & SAMR_FIELD_CODE_PAGE) { DEBUG(10,("%s SAMR_FIELD_CODE_PAGE: %08X -> %08X\n", l, pdb_get_code_page(to), from->code_page)); if (from->code_page != pdb_get_code_page(to)) { pdb_set_code_page(to, from->code_page, PDB_CHANGED); } } }
static int process_root(int local_flags) { struct passwd *pwd; int result = 0; char *old_passwd = NULL; if (local_flags & LOCAL_SET_LDAP_ADMIN_PW) { char *ldap_admin_dn = lp_ldap_admin_dn(); if ( ! *ldap_admin_dn ) { DEBUG(0,("ERROR: 'ldap admin dn' not defined! Please check your smb.conf\n")); goto done; } printf("Setting stored password for \"%s\" in secrets.tdb\n", ldap_admin_dn); if ( ! *ldap_secret ) { new_passwd = prompt_for_new_password(stdin_passwd_get); fstrcpy(ldap_secret, new_passwd); } if (!store_ldap_admin_pw(ldap_secret)) { DEBUG(0,("ERROR: Failed to store the ldap admin password!\n")); } goto done; } /* Ensure passdb startup(). */ if(!initialize_password_db(False)) { DEBUG(0, ("Failed to open passdb!\n")); exit(1); } /* Ensure we have a SAM sid. */ get_global_sam_sid(); /* * Ensure both add/delete user are not set * Ensure add/delete user and either remote machine or join domain are * not both set. */ if(((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) == (LOCAL_ADD_USER|LOCAL_DELETE_USER)) || ((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) && (remote_machine != NULL))) { usage(); } /* Only load interfaces if we are doing network operations. */ if (remote_machine) { load_interfaces(); } if (!user_name[0] && (pwd = getpwuid_alloc(NULL, geteuid()))) { fstrcpy(user_name, pwd->pw_name); TALLOC_FREE(pwd); } if (!user_name[0]) { fprintf(stderr,"You must specify a username\n"); exit(1); } if (local_flags & LOCAL_TRUST_ACCOUNT) { /* add the $ automatically */ static fstring buf; /* * Remove any trailing '$' before we * generate the initial machine password. */ if (user_name[strlen(user_name)-1] == '$') { user_name[strlen(user_name)-1] = 0; } if (local_flags & LOCAL_ADD_USER) { SAFE_FREE(new_passwd); new_passwd = smb_xstrdup(user_name); strlower_m(new_passwd); } /* * Now ensure the username ends in '$' for * the machine add. */ slprintf(buf, sizeof(buf)-1, "%s$", user_name); fstrcpy(user_name, buf); } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) { static fstring buf; if ((local_flags & LOCAL_ADD_USER) && (new_passwd == NULL)) { /* * Prompt for trusting domain's account password */ new_passwd = prompt_for_new_password(stdin_passwd_get); if(!new_passwd) { fprintf(stderr, "Unable to get newpassword.\n"); exit(1); } } /* prepare uppercased and '$' terminated username */ slprintf(buf, sizeof(buf) - 1, "%s$", user_name); fstrcpy(user_name, buf); } else { if (remote_machine != NULL) { old_passwd = get_pass("Old SMB password:"******"talloc fail for struct samu.\n"); exit(1); } if (!pdb_getsampwnam(sampass, user_name)) { fprintf(stderr, "Failed to find user %s in passdb backend.\n", user_name ); exit(1); } if(pdb_get_nt_passwd(sampass) == NULL) { local_flags |= LOCAL_SET_PASSWORD; } TALLOC_FREE(sampass); } } if((local_flags & LOCAL_SET_PASSWORD) && (new_passwd == NULL)) { new_passwd = prompt_for_new_password(stdin_passwd_get); if(!new_passwd) { fprintf(stderr, "Unable to get new password.\n"); exit(1); } } } if (!NT_STATUS_IS_OK(password_change(remote_machine, user_name, old_passwd, new_passwd, local_flags))) { fprintf(stderr,"Failed to modify password entry for user %s\n", user_name); result = 1; goto done; } if(remote_machine) { printf("Password changed for user %s on %s.\n", user_name, remote_machine ); } else if(!(local_flags & (LOCAL_ADD_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|LOCAL_DELETE_USER|LOCAL_SET_NO_PASSWORD|LOCAL_SET_PASSWORD))) { struct samu *sampass = NULL; sampass = samu_new( NULL ); if (!sampass) { fprintf(stderr, "talloc fail for struct samu.\n"); exit(1); } if (!pdb_getsampwnam(sampass, user_name)) { fprintf(stderr, "Failed to find user %s in passdb backend.\n", user_name ); exit(1); } printf("Password changed for user %s.", user_name ); if(pdb_get_acct_ctrl(sampass)&ACB_DISABLED) { printf(" User has disabled flag set."); } if(pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ) { printf(" User has no password flag set."); } printf("\n"); TALLOC_FREE(sampass); } done: SAFE_FREE(new_passwd); return result; }
/************************************************************************ makes a struct sam_passwd from a NIS+ object. ************************************************************************/ static BOOL make_sam_from_nisp_object(SAM_ACCOUNT *pw_buf, nis_object *obj) { char *ptr; pstring full_name; /* this must be translated to dos code page */ pstring acct_desc; /* this must be translated to dos code page */ pstring home_dir; /* set default value from smb.conf for user */ pstring home_drive; /* set default value from smb.conf for user */ pstring logon_script; /* set default value from smb.conf for user */ pstring profile_path; /* set default value from smb.conf for user */ pstring hours; int hours_len; unsigned char smbpwd[16]; unsigned char smbntpwd[16]; /* * time values. note: this code assumes 32bit time_t! */ pdb_set_logon_time(pw_buf, (time_t)0); ptr = ENTRY_VAL(obj, NPF_LOGON_T); if(ptr && *ptr && (StrnCaseCmp(ptr, "LNT-", 4)==0)) { int i; ptr += 4; for(i = 0; i < 8; i++) { if(ptr[i] == '\0' || !isxdigit(ptr[i])) break; } if(i == 8) { pdb_set_logon_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); } } pdb_set_logoff_time(pw_buf, get_time_t_max()); ptr = ENTRY_VAL(obj, NPF_LOGOFF_T); if(ptr && *ptr && (StrnCaseCmp(ptr, "LOT-", 4)==0)) { int i; ptr += 4; for(i = 0; i < 8; i++) { if(ptr[i] == '\0' || !isxdigit(ptr[i])) break; } if(i == 8) { pdb_set_logoff_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); } } pdb_set_kickoff_time(pw_buf, get_time_t_max()); ptr = ENTRY_VAL(obj, NPF_KICK_T); if(ptr && *ptr && (StrnCaseCmp(ptr, "KOT-", 4)==0)) { int i; ptr += 4; for(i = 0; i < 8; i++) { if(ptr[i] == '\0' || !isxdigit(ptr[i])) break; } if(i == 8) { pdb_set_kickoff_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); } } pdb_set_pass_last_set_time(pw_buf, (time_t)0); ptr = ENTRY_VAL(obj, NPF_PWDLSET_T); if(ptr && *ptr && (StrnCaseCmp(ptr, "LCT-", 4)==0)) { int i; ptr += 4; for(i = 0; i < 8; i++) { if(ptr[i] == '\0' || !isxdigit(ptr[i])) break; } if(i == 8) { pdb_set_pass_last_set_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); } } pdb_set_pass_can_change_time(pw_buf, (time_t)0); ptr = ENTRY_VAL(obj, NPF_PWDCCHG_T); if(ptr && *ptr && (StrnCaseCmp(ptr, "CCT-", 4)==0)) { int i; ptr += 4; for(i = 0; i < 8; i++) { if(ptr[i] == '\0' || !isxdigit(ptr[i])) break; } if(i == 8) { pdb_set_pass_can_change_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); } } pdb_set_pass_must_change_time(pw_buf, get_time_t_max()); /* Password never expires. */ ptr = ENTRY_VAL(obj, NPF_PWDMCHG_T); if(ptr && *ptr && (StrnCaseCmp(ptr, "MCT-", 4)==0)) { int i; ptr += 4; for(i = 0; i < 8; i++) { if(ptr[i] == '\0' || !isxdigit(ptr[i])) break; } if(i == 8) { pdb_set_pass_must_change_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); } } /* string values */ pdb_set_username(pw_buf, ENTRY_VAL(obj, NPF_NAME)); pdb_set_domain(pw_buf, lp_workgroup()); /* pdb_set_nt_username() -- cant set it here... */ get_single_attribute(obj, NPF_FULL_NAME, full_name, sizeof(pstring)); unix_to_dos(full_name); pdb_set_fullname(pw_buf, full_name); pdb_set_acct_ctrl(pw_buf, pdb_decode_acct_ctrl(ENTRY_VAL(obj, NPF_ACB))); get_single_attribute(obj, NPF_ACCT_DESC, acct_desc, sizeof(pstring)); unix_to_dos(acct_desc); pdb_set_acct_desc(pw_buf, acct_desc); pdb_set_workstations(pw_buf, ENTRY_VAL(obj, NPF_WORKSTATIONS)); pdb_set_munged_dial(pw_buf, NULL); /* Might want to consult sys_getpwnam for the following two. for now, use same default as pdb_fill-default_sam */ ptr = ENTRY_VAL(obj, NPF_UID); pdb_set_uid(pw_buf, ptr ? atoi(ptr) : -1); ptr = ENTRY_VAL(obj, NPF_SMB_GRPID); pdb_set_gid(pw_buf, ptr ? atoi(ptr) : -1); ptr = ENTRY_VAL(obj, NPF_USER_RID); pdb_set_user_rid(pw_buf, ptr ? atoi(ptr) : pdb_uid_to_user_rid(pdb_get_uid(pw_buf))); ptr = ENTRY_VAL(obj, NPF_GROUP_RID); pdb_set_group_rid(pw_buf, ptr ? atoi(ptr) : pdb_gid_to_group_rid(pdb_get_gid(pw_buf))); /* values, must exist for user */ if( !(pdb_get_acct_ctrl(pw_buf) & ACB_WSTRUST) ) { /* FIXME!! This doesn't belong here. Should be set in net_sam_logon() --jerry */ pstrcpy(samlogon_user, pdb_get_username(pw_buf)); get_single_attribute(obj, NPF_HOME_DIR, home_dir, sizeof(pstring)); if( !(home_dir && *home_dir) ) { pstrcpy(home_dir, lp_logon_home()); pdb_set_homedir(pw_buf, home_dir, False); } else pdb_set_homedir(pw_buf, home_dir, True); get_single_attribute(obj, NPF_DIR_DRIVE, home_drive, sizeof(pstring)); if( !(home_drive && *home_drive) ) { pstrcpy(home_drive, lp_logon_drive()); pdb_set_dir_drive(pw_buf, home_drive, False); } else pdb_set_dir_drive(pw_buf, home_drive, True); get_single_attribute(obj, NPF_LOGON_SCRIPT, logon_script, sizeof(pstring)); if( !(logon_script && *logon_script) ) { pstrcpy(logon_script, lp_logon_script()); pdb_set_logon_script(pw_buf, logon_script, False); } else pdb_set_logon_script(pw_buf, logon_script, True); get_single_attribute(obj, NPF_PROFILE_PATH, profile_path, sizeof(pstring)); if( !(profile_path && *profile_path) ) { pstrcpy(profile_path, lp_logon_path()); pdb_set_profile_path(pw_buf, profile_path, False); } else pdb_set_profile_path(pw_buf, profile_path, True); } else { /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */ pdb_set_group_rid (pw_buf, DOMAIN_GROUP_RID_USERS); } /* Check the lanman password column. */ ptr = ENTRY_VAL(obj, NPF_LMPWD); if (!pdb_set_lanman_passwd(pw_buf, NULL)) return False; if (!strncasecmp(ptr, "NO PASSWORD", 11)) { pdb_set_acct_ctrl(pw_buf, pdb_get_acct_ctrl(pw_buf) | ACB_PWNOTREQ); } else { if (strlen(ptr) != 32 || !pdb_gethexpwd(ptr, smbpwd)) { DEBUG(0, ("malformed LM pwd entry: %s.\n", pdb_get_username(pw_buf))); return False; } if (!pdb_set_lanman_passwd(pw_buf, smbpwd)) return False; } /* Check the NT password column. */ ptr = ENTRY_VAL(obj, NPF_NTPWD); if (!pdb_set_nt_passwd(pw_buf, NULL)) return False; if (!(pdb_get_acct_ctrl(pw_buf) & ACB_PWNOTREQ) && strncasecmp(ptr, "NO PASSWORD", 11)) { if (strlen(ptr) != 32 || !pdb_gethexpwd(ptr, smbntpwd)) { DEBUG(0, ("malformed NT pwd entry:\ uid = %d.\n", pdb_get_uid(pw_buf))); return False; } if (!pdb_set_nt_passwd(pw_buf, smbntpwd)) return False; }
int pam_sm_acct_mgmt( pam_handle_t *pamh, int flags, int argc, const char **argv ) { unsigned int ctrl; int retval; const char *name; SAM_ACCOUNT *sampass = NULL; void (*oldsig_handler)(int); extern BOOL in_client; /* Samba initialization. */ setup_logging( "pam_smbpass", False ); in_client = True; ctrl = set_ctrl( flags, argc, argv ); /* get the username */ retval = pam_get_user( pamh, &name, "Username: "******"acct: could not identify user" ); } return retval; } if (on( SMB_DEBUG, ctrl )) { _log_err( LOG_DEBUG, "acct: username [%s] obtained", name ); } /* Getting into places that might use LDAP -- protect the app from a SIGPIPE it's not expecting */ oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN); if (!initialize_password_db(True)) { _log_err( LOG_ALERT, "Cannot access samba password database" ); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_AUTHINFO_UNAVAIL; } /* Get the user's record. */ pdb_init_sam(&sampass); pdb_getsampwnam(sampass, name ); if (!sampass) { CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_USER_UNKNOWN; } if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { if (on( SMB_DEBUG, ctrl )) { _log_err( LOG_DEBUG , "acct: account %s is administratively disabled", name ); } make_remark( pamh, ctrl, PAM_ERROR_MSG , "Your account has been disabled; " "please see your system administrator." ); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_ACCT_EXPIRED; } /* TODO: support for expired passwords. */ CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_SUCCESS; }
static int set_user_info(const char *username, const char *fullname, const char *homedir, const char *acct_desc, const char *drive, const char *script, const char *profile, const char *account_control, const char *user_sid, const char *user_domain, const bool badpw, const bool hours, const char *kickoff_time) { bool updated_autolock = False, updated_badpw = False; struct samu *sam_pwent; uint8_t hours_array[MAX_HOURS_LEN]; uint32_t hours_len; uint32_t acb_flags; uint32_t not_settable; uint32_t new_flags; struct dom_sid u_sid; bool ret; sam_pwent = samu_new(NULL); if (!sam_pwent) { return 1; } ret = pdb_getsampwnam(sam_pwent, username); if (!ret) { fprintf (stderr, "Username not found!\n"); TALLOC_FREE(sam_pwent); return -1; } if (hours) { hours_len = pdb_get_hours_len(sam_pwent); memset(hours_array, 0xff, hours_len); pdb_set_hours(sam_pwent, hours_array, hours_len, PDB_CHANGED); } if (!pdb_update_autolock_flag(sam_pwent, &updated_autolock)) { DEBUG(2,("pdb_update_autolock_flag failed.\n")); } if (!pdb_update_bad_password_count(sam_pwent, &updated_badpw)) { DEBUG(2,("pdb_update_bad_password_count failed.\n")); } if (fullname) pdb_set_fullname(sam_pwent, fullname, PDB_CHANGED); if (acct_desc) pdb_set_acct_desc(sam_pwent, acct_desc, PDB_CHANGED); if (homedir) pdb_set_homedir(sam_pwent, homedir, PDB_CHANGED); if (drive) pdb_set_dir_drive(sam_pwent,drive, PDB_CHANGED); if (script) pdb_set_logon_script(sam_pwent, script, PDB_CHANGED); if (profile) pdb_set_profile_path (sam_pwent, profile, PDB_CHANGED); if (user_domain) pdb_set_domain(sam_pwent, user_domain, PDB_CHANGED); if (account_control) { not_settable = ~(ACB_DISABLED | ACB_HOMDIRREQ | ACB_PWNOTREQ | ACB_PWNOEXP | ACB_AUTOLOCK); new_flags = pdb_decode_acct_ctrl(account_control); if (new_flags & not_settable) { fprintf(stderr, "Can only set [NDHLX] flags\n"); TALLOC_FREE(sam_pwent); return -1; } acb_flags = pdb_get_acct_ctrl(sam_pwent); pdb_set_acct_ctrl(sam_pwent, (acb_flags & not_settable) | new_flags, PDB_CHANGED); } if (user_sid) { if (get_sid_from_cli_string(&u_sid, user_sid)) { fprintf(stderr, "Failed to parse SID\n"); return -1; } pdb_set_user_sid(sam_pwent, &u_sid, PDB_CHANGED); } if (badpw) { pdb_set_bad_password_count(sam_pwent, 0, PDB_CHANGED); pdb_set_bad_password_time(sam_pwent, 0, PDB_CHANGED); } if (kickoff_time) { char *endptr; time_t value = get_time_t_max(); if (strcmp(kickoff_time, "never") != 0) { uint32_t num = strtoul(kickoff_time, &endptr, 10); if ((endptr == kickoff_time) || (endptr[0] != '\0')) { fprintf(stderr, "Failed to parse kickoff time\n"); return -1; } value = convert_uint32_t_to_time_t(num); } pdb_set_kickoff_time(sam_pwent, value, PDB_CHANGED); } if (NT_STATUS_IS_OK(pdb_update_sam_account(sam_pwent))) { print_user_info(username, True, False); } else { fprintf (stderr, "Unable to modify entry!\n"); TALLOC_FREE(sam_pwent); return -1; } TALLOC_FREE(sam_pwent); return 0; }
NTSTATUS serverinfo_to_SamInfo3(struct auth_serversupplied_info *server_info, uint8_t pipe_session_key[16], struct netr_SamInfo3 *sam3) { struct samu *sampw; DOM_GID *gids = NULL; const DOM_SID *user_sid = NULL; const DOM_SID *group_sid = NULL; DOM_SID domain_sid; uint32 user_rid, group_rid; NTSTATUS status; int num_gids = 0; const char *my_name; struct netr_UserSessionKey user_session_key; struct netr_LMSessionKey lm_session_key; NTTIME last_logon, last_logoff, acct_expiry, last_password_change; NTTIME allow_password_change, force_password_change; struct samr_RidWithAttributeArray groups; int i; struct dom_sid2 *sid = NULL; ZERO_STRUCT(user_session_key); ZERO_STRUCT(lm_session_key); sampw = server_info->sam_account; user_sid = pdb_get_user_sid(sampw); group_sid = pdb_get_group_sid(sampw); if ((user_sid == NULL) || (group_sid == NULL)) { DEBUG(1, ("_netr_LogonSamLogon: User without group or user SID\n")); return NT_STATUS_UNSUCCESSFUL; } sid_copy(&domain_sid, user_sid); sid_split_rid(&domain_sid, &user_rid); sid = sid_dup_talloc(sam3, &domain_sid); if (!sid) { return NT_STATUS_NO_MEMORY; } if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) { DEBUG(1, ("_netr_LogonSamLogon: user %s\\%s has user sid " "%s\n but group sid %s.\n" "The conflicting domain portions are not " "supported for NETLOGON calls\n", pdb_get_domain(sampw), pdb_get_username(sampw), sid_string_dbg(user_sid), sid_string_dbg(group_sid))); return NT_STATUS_UNSUCCESSFUL; } if(server_info->login_server) { my_name = server_info->login_server; } else { my_name = global_myname(); } status = nt_token_to_group_list(sam3, &domain_sid, server_info->num_sids, server_info->sids, &num_gids, &gids); if (!NT_STATUS_IS_OK(status)) { return status; } if (server_info->user_session_key.length) { memcpy(user_session_key.key, server_info->user_session_key.data, MIN(sizeof(user_session_key.key), server_info->user_session_key.length)); SamOEMhash(user_session_key.key, pipe_session_key, 16); } if (server_info->lm_session_key.length) { memcpy(lm_session_key.key, server_info->lm_session_key.data, MIN(sizeof(lm_session_key.key), server_info->lm_session_key.length)); SamOEMhash(lm_session_key.key, pipe_session_key, 8); } groups.count = num_gids; groups.rids = TALLOC_ARRAY(sam3, struct samr_RidWithAttribute, groups.count); if (!groups.rids) { return NT_STATUS_NO_MEMORY; } for (i=0; i < groups.count; i++) { groups.rids[i].rid = gids[i].g_rid; groups.rids[i].attributes = gids[i].attr; } unix_to_nt_time(&last_logon, pdb_get_logon_time(sampw)); unix_to_nt_time(&last_logoff, get_time_t_max()); unix_to_nt_time(&acct_expiry, get_time_t_max()); unix_to_nt_time(&last_password_change, pdb_get_pass_last_set_time(sampw)); unix_to_nt_time(&allow_password_change, pdb_get_pass_can_change_time(sampw)); unix_to_nt_time(&force_password_change, pdb_get_pass_must_change_time(sampw)); init_netr_SamInfo3(sam3, last_logon, last_logoff, acct_expiry, last_password_change, allow_password_change, force_password_change, talloc_strdup(sam3, pdb_get_username(sampw)), talloc_strdup(sam3, pdb_get_fullname(sampw)), talloc_strdup(sam3, pdb_get_logon_script(sampw)), talloc_strdup(sam3, pdb_get_profile_path(sampw)), talloc_strdup(sam3, pdb_get_homedir(sampw)), talloc_strdup(sam3, pdb_get_dir_drive(sampw)), 0, /* logon_count */ 0, /* bad_password_count */ user_rid, group_rid, groups, NETLOGON_EXTRA_SIDS, user_session_key, my_name, talloc_strdup(sam3, pdb_get_domain(sampw)), sid, lm_session_key, pdb_get_acct_ctrl(sampw), 0, /* sidcount */ NULL); /* struct netr_SidAttr *sids */ ZERO_STRUCT(user_session_key); ZERO_STRUCT(lm_session_key); return NT_STATUS_OK; }
NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx, struct samu *samu, const char *login_server, struct netr_SamInfo3 **_info3, struct extra_auth_info *extra) { struct netr_SamInfo3 *info3; const struct dom_sid *user_sid; const struct dom_sid *group_sid; struct dom_sid domain_sid; struct dom_sid *group_sids; uint32_t num_group_sids = 0; const char *tmp; gid_t *gids; NTSTATUS status; bool ok; user_sid = pdb_get_user_sid(samu); group_sid = pdb_get_group_sid(samu); if (!user_sid || !group_sid) { DEBUG(1, ("Sam account is missing sids!\n")); return NT_STATUS_UNSUCCESSFUL; } info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); if (!info3) { return NT_STATUS_NO_MEMORY; } ZERO_STRUCT(domain_sid); /* check if this is a "Unix Users" domain user, * we need to handle it in a special way if that's the case */ if (sid_check_is_in_unix_users(user_sid)) { /* in info3 you can only set rids for the user and the * primary group, and the domain sid must be that of * the sam domain. * * Store a completely bogus value here. * The real SID is stored in the extra sids. * Other code will know to look there if (-1) is found */ info3->base.rid = (uint32_t)(-1); sid_copy(&extra->user_sid, user_sid); DEBUG(10, ("Unix User found in struct samu. Rid marked as " "special and sid (%s) saved as extra sid\n", sid_string_dbg(user_sid))); } else { sid_copy(&domain_sid, user_sid); sid_split_rid(&domain_sid, &info3->base.rid); } if (is_null_sid(&domain_sid)) { sid_copy(&domain_sid, get_global_sam_sid()); } /* check if this is a "Unix Groups" domain group, * if so we need special handling */ if (sid_check_is_in_unix_groups(group_sid)) { /* in info3 you can only set rids for the user and the * primary group, and the domain sid must be that of * the sam domain. * * Store a completely bogus value here. * The real SID is stored in the extra sids. * Other code will know to look there if (-1) is found */ info3->base.primary_gid = (uint32_t)(-1); sid_copy(&extra->pgid_sid, group_sid); DEBUG(10, ("Unix Group found in struct samu. Rid marked as " "special and sid (%s) saved as extra sid\n", sid_string_dbg(group_sid))); } else { ok = sid_peek_check_rid(&domain_sid, group_sid, &info3->base.primary_gid); if (!ok) { DEBUG(1, ("The primary group domain sid(%s) does not " "match the domain sid(%s) for %s(%s)\n", sid_string_dbg(group_sid), sid_string_dbg(&domain_sid), pdb_get_username(samu), sid_string_dbg(user_sid))); TALLOC_FREE(info3); return NT_STATUS_UNSUCCESSFUL; } } unix_to_nt_time(&info3->base.last_logon, pdb_get_logon_time(samu)); unix_to_nt_time(&info3->base.last_logoff, get_time_t_max()); unix_to_nt_time(&info3->base.acct_expiry, get_time_t_max()); unix_to_nt_time(&info3->base.last_password_change, pdb_get_pass_last_set_time(samu)); unix_to_nt_time(&info3->base.allow_password_change, pdb_get_pass_can_change_time(samu)); unix_to_nt_time(&info3->base.force_password_change, pdb_get_pass_must_change_time(samu)); tmp = pdb_get_username(samu); if (tmp) { info3->base.account_name.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.account_name.string); } tmp = pdb_get_fullname(samu); if (tmp) { info3->base.full_name.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.full_name.string); } tmp = pdb_get_logon_script(samu); if (tmp) { info3->base.logon_script.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.logon_script.string); } tmp = pdb_get_profile_path(samu); if (tmp) { info3->base.profile_path.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.profile_path.string); } tmp = pdb_get_homedir(samu); if (tmp) { info3->base.home_directory.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.home_directory.string); } tmp = pdb_get_dir_drive(samu); if (tmp) { info3->base.home_drive.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.home_drive.string); } info3->base.logon_count = pdb_get_logon_count(samu); info3->base.bad_password_count = pdb_get_bad_password_count(samu); info3->base.domain.string = talloc_strdup(info3, pdb_get_domain(samu)); RET_NOMEM(info3->base.domain.string); info3->base.domain_sid = dom_sid_dup(info3, &domain_sid); RET_NOMEM(info3->base.domain_sid); status = pdb_enum_group_memberships(mem_ctx, samu, &group_sids, &gids, &num_group_sids); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to get groups from sam account.\n")); TALLOC_FREE(info3); return status; } if (num_group_sids) { status = group_sids_to_info3(info3, group_sids, num_group_sids); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); return status; } } /* We don't need sids and gids after the conversion */ TALLOC_FREE(group_sids); TALLOC_FREE(gids); num_group_sids = 0; /* FIXME: should we add other flags ? */ info3->base.user_flags = NETLOGON_EXTRA_SIDS; if (login_server) { info3->base.logon_server.string = talloc_strdup(info3, login_server); RET_NOMEM(info3->base.logon_server.string); } info3->base.acct_flags = pdb_get_acct_ctrl(samu); *_info3 = info3; return NT_STATUS_OK; }
void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from) { time_t unix_time, stored_time; const char *old_string, *new_string; DATA_BLOB mung; if (from == NULL || to == NULL) return; if (from->fields_present & ACCT_LAST_LOGON) { unix_time=nt_time_to_unix(&from->logon_time); stored_time = pdb_get_logon_time(to); DEBUG(10,("INFO_21 LOGON_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time)); if (stored_time != unix_time) pdb_set_logon_time(to, unix_time, PDB_CHANGED); } if (from->fields_present & ACCT_LAST_LOGOFF) { unix_time=nt_time_to_unix(&from->logoff_time); stored_time = pdb_get_logoff_time(to); DEBUG(10,("INFO_21 LOGOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time)); if (stored_time != unix_time) pdb_set_logoff_time(to, unix_time, PDB_CHANGED); } if (from->fields_present & ACCT_EXPIRY) { unix_time=nt_time_to_unix(&from->kickoff_time); stored_time = pdb_get_kickoff_time(to); DEBUG(10,("INFO_21 KICKOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time)); if (stored_time != unix_time) pdb_set_kickoff_time(to, unix_time , PDB_CHANGED); } if (from->fields_present & ACCT_ALLOW_PWD_CHANGE) { unix_time=nt_time_to_unix(&from->pass_can_change_time); stored_time = pdb_get_pass_can_change_time(to); DEBUG(10,("INFO_21 PASS_CAN_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time)); if (stored_time != unix_time) pdb_set_pass_can_change_time(to, unix_time, PDB_CHANGED); } if (from->fields_present & ACCT_LAST_PWD_CHANGE) { unix_time=nt_time_to_unix(&from->pass_last_set_time); stored_time = pdb_get_pass_last_set_time(to); DEBUG(10,("INFO_21 PASS_LAST_SET: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time)); if (stored_time != unix_time) pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED); } if (from->fields_present & ACCT_FORCE_PWD_CHANGE) { unix_time=nt_time_to_unix(&from->pass_must_change_time); stored_time=pdb_get_pass_must_change_time(to); DEBUG(10,("INFO_21 PASS_MUST_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time)); if (stored_time != unix_time) pdb_set_pass_must_change_time(to, unix_time, PDB_CHANGED); } if ((from->fields_present & ACCT_USERNAME) && (from->hdr_user_name.buffer)) { old_string = pdb_get_username(to); new_string = unistr2_static(&from->uni_user_name); DEBUG(10,("INFO_21 UNI_USER_NAME: %s -> %s\n", old_string, new_string)); if (STRING_CHANGED) pdb_set_username(to , new_string, PDB_CHANGED); } if ((from->fields_present & ACCT_FULL_NAME) && (from->hdr_full_name.buffer)) { old_string = pdb_get_fullname(to); new_string = unistr2_static(&from->uni_full_name); DEBUG(10,("INFO_21 UNI_FULL_NAME: %s -> %s\n",old_string, new_string)); if (STRING_CHANGED) pdb_set_fullname(to , new_string, PDB_CHANGED); } if ((from->fields_present & ACCT_HOME_DIR) && (from->hdr_home_dir.buffer)) { old_string = pdb_get_homedir(to); new_string = unistr2_static(&from->uni_home_dir); DEBUG(10,("INFO_21 UNI_HOME_DIR: %s -> %s\n",old_string,new_string)); if (STRING_CHANGED) pdb_set_homedir(to , new_string, PDB_CHANGED); } if ((from->fields_present & ACCT_HOME_DRIVE) && (from->hdr_dir_drive.buffer)) { old_string = pdb_get_dir_drive(to); new_string = unistr2_static(&from->uni_dir_drive); DEBUG(10,("INFO_21 UNI_DIR_DRIVE: %s -> %s\n",old_string,new_string)); if (STRING_CHANGED) pdb_set_dir_drive(to , new_string, PDB_CHANGED); } if ((from->fields_present & ACCT_LOGON_SCRIPT) && (from->hdr_logon_script.buffer)) { old_string = pdb_get_logon_script(to); new_string = unistr2_static(&from->uni_logon_script); DEBUG(10,("INFO_21 UNI_LOGON_SCRIPT: %s -> %s\n",old_string,new_string)); if (STRING_CHANGED) pdb_set_logon_script(to , new_string, PDB_CHANGED); } if ((from->fields_present & ACCT_PROFILE) && (from->hdr_profile_path.buffer)) { old_string = pdb_get_profile_path(to); new_string = unistr2_static(&from->uni_profile_path); DEBUG(10,("INFO_21 UNI_PROFILE_PATH: %s -> %s\n",old_string, new_string)); if (STRING_CHANGED) pdb_set_profile_path(to , new_string, PDB_CHANGED); } if ((from->fields_present & ACCT_DESCRIPTION) && (from->hdr_acct_desc.buffer)) { old_string = pdb_get_acct_desc(to); new_string = unistr2_static(&from->uni_acct_desc); DEBUG(10,("INFO_21 UNI_ACCT_DESC: %s -> %s\n",old_string,new_string)); if (STRING_CHANGED) pdb_set_acct_desc(to , new_string, PDB_CHANGED); } if ((from->fields_present & ACCT_WORKSTATIONS) && (from->hdr_workstations.buffer)) { old_string = pdb_get_workstations(to); new_string = unistr2_static(&from->uni_workstations); DEBUG(10,("INFO_21 UNI_WORKSTATIONS: %s -> %s\n",old_string, new_string)); if (STRING_CHANGED) pdb_set_workstations(to , new_string, PDB_CHANGED); } /* is this right? */ if ((from->fields_present & ACCT_ADMIN_DESC) && (from->hdr_unknown_str.buffer)) { old_string = pdb_get_unknown_str(to); new_string = unistr2_static(&from->uni_unknown_str); DEBUG(10,("INFO_21 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string)); if (STRING_CHANGED) pdb_set_unknown_str(to , new_string, PDB_CHANGED); } if ((from->fields_present & ACCT_CALLBACK) && (from->hdr_munged_dial.buffer)) { char *newstr; old_string = pdb_get_munged_dial(to); mung.length = from->hdr_munged_dial.uni_str_len; mung.data = (uint8 *) from->uni_munged_dial.buffer; newstr = (mung.length == 0) ? NULL : base64_encode_data_blob(mung); DEBUG(10,("INFO_21 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr)); if (STRING_CHANGED_NC(old_string,newstr)) pdb_set_munged_dial(to , newstr, PDB_CHANGED); SAFE_FREE(newstr); } if (from->fields_present & ACCT_RID) { if (from->user_rid == 0) { DEBUG(10, ("INFO_21: Asked to set User RID to 0 !? Skipping change!\n")); } else if (from->user_rid != pdb_get_user_rid(to)) { DEBUG(10,("INFO_21 USER_RID: %u -> %u NOT UPDATED!\n",pdb_get_user_rid(to),from->user_rid)); } } if (from->fields_present & ACCT_PRIMARY_GID) { if (from->group_rid == 0) { DEBUG(10, ("INFO_21: Asked to set Group RID to 0 !? Skipping change!\n")); } else if (from->group_rid != pdb_get_group_rid(to)) { DEBUG(10,("INFO_21 GROUP_RID: %u -> %u\n",pdb_get_group_rid(to),from->group_rid)); pdb_set_group_sid_from_rid(to, from->group_rid, PDB_CHANGED); } } if (from->fields_present & ACCT_FLAGS) { DEBUG(10,("INFO_21 ACCT_CTRL: %08X -> %08X\n",pdb_get_acct_ctrl(to),from->acb_info)); if (from->acb_info != pdb_get_acct_ctrl(to)) { if (!(from->acb_info & ACB_AUTOLOCK) && (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) { /* We're unlocking a previously locked user. Reset bad password counts. Patch from Jianliang Lu. <*****@*****.**> */ pdb_set_bad_password_count(to, 0, PDB_CHANGED); pdb_set_bad_password_time(to, 0, PDB_CHANGED); } pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED); } } if (from->fields_present & ACCT_LOGON_HOURS) { DEBUG(15,("INFO_21 LOGON_DIVS: %08X -> %08X\n",pdb_get_logon_divs(to),from->logon_divs)); if (from->logon_divs != pdb_get_logon_divs(to)) { pdb_set_logon_divs(to, from->logon_divs, PDB_CHANGED); } DEBUG(15,("INFO_21 LOGON_HRS.LEN: %08X -> %08X\n",pdb_get_hours_len(to),from->logon_hrs.len)); if (from->logon_hrs.len != pdb_get_hours_len(to)) { pdb_set_hours_len(to, from->logon_hrs.len, PDB_CHANGED); } DEBUG(15,("INFO_21 LOGON_HRS.HOURS: %s -> %s\n",pdb_get_hours(to),from->logon_hrs.hours)); /* Fix me: only update if it changes --metze */ pdb_set_hours(to, from->logon_hrs.hours, PDB_CHANGED); /* This is max logon hours */ DEBUG(10,("INFO_21 UNKNOWN_6: %08X -> %08X\n",pdb_get_unknown_6(to),from->unknown_6)); if (from->unknown_6 != pdb_get_unknown_6(to)) { pdb_set_unknown_6(to, from->unknown_6, PDB_CHANGED); } } if (from->fields_present & ACCT_BAD_PWD_COUNT) { DEBUG(10,("INFO_21 BAD_PASSWORD_COUNT: %08X -> %08X\n",pdb_get_bad_password_count(to),from->bad_password_count)); if (from->bad_password_count != pdb_get_bad_password_count(to)) { pdb_set_bad_password_count(to, from->bad_password_count, PDB_CHANGED); } } if (from->fields_present & ACCT_NUM_LOGONS) { DEBUG(10,("INFO_21 LOGON_COUNT: %08X -> %08X\n",pdb_get_logon_count(to),from->logon_count)); if (from->logon_count != pdb_get_logon_count(to)) { pdb_set_logon_count(to, from->logon_count, PDB_CHANGED); } } DEBUG(10,("INFO_21 PASS_MUST_CHANGE_AT_NEXT_LOGON: %02X\n",from->passmustchange)); if (from->passmustchange==PASS_MUST_CHANGE_AT_NEXT_LOGON) { pdb_set_pass_must_change_time(to,0, PDB_CHANGED); } DEBUG(10,("INFO_21 PADDING_2: %02X\n",from->padding2)); DEBUG(10,("INFO_21 PADDING_4: %08X\n",from->padding4)); }