static int delete_user_entry(const char *username) { struct samu *samaccount; samaccount = samu_new(NULL); if (!samaccount) { fprintf(stderr, "Out of memory!\n"); return -1; } if (!pdb_getsampwnam(samaccount, username)) { fprintf (stderr, "user %s does not exist in the passdb\n", username); TALLOC_FREE(samaccount); return -1; } if (!NT_STATUS_IS_OK(pdb_delete_sam_account(samaccount))) { fprintf (stderr, "Unable to delete user %s\n", username); TALLOC_FREE(samaccount); return -1; } TALLOC_FREE(samaccount); return 0; }
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; }
/** * 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; }
static int delete_machine_entry(const char *machinename) { struct samu *samaccount = NULL; const char *name; if (strlen(machinename) == 0) { fprintf(stderr, "No machine name given\n"); return -1; } samaccount = samu_new(NULL); if (!samaccount) { fprintf(stderr, "Out of memory!\n"); return -1; } if (machinename[strlen(machinename)-1] != '$') { name = talloc_asprintf(samaccount, "%s$", machinename); } else { name = machinename; } if (!pdb_getsampwnam(samaccount, name)) { fprintf (stderr, "machine %s does not exist in the passdb\n", name); TALLOC_FREE(samaccount); return -1; } if (!NT_STATUS_IS_OK(pdb_delete_sam_account(samaccount))) { fprintf (stderr, "Unable to delete machine %s\n", name); TALLOC_FREE(samaccount); return -1; } TALLOC_FREE(samaccount); return 0; }
/******************************************************************* Look up a local user name and return a rid ********************************************************************/ NTSTATUS local_lookup_user_rid(char *user_name, uint32 *rid) { SAM_ACCOUNT *sampass=NULL; BOOL ret; (*rid) = 0; pdb_init_sam(&sampass); /* find the user account */ become_root(); ret = pdb_getsampwnam(sampass, user_name); unbecome_root(); if (ret == True) { (*rid) = pdb_get_user_rid(sampass); pdb_free_sam(&sampass); return NT_STATUS_OK; } pdb_free_sam(&sampass); return NT_STATUS_NONE_MAPPED; }
static int print_user_info(const char *username, bool verbosity, bool smbpwdstyle) { struct samu *sam_pwent = NULL; bool bret; int ret; sam_pwent = samu_new(NULL); if (!sam_pwent) { return -1; } bret = pdb_getsampwnam(sam_pwent, username); if (!bret) { fprintf (stderr, "Username not found!\n"); TALLOC_FREE(sam_pwent); return -1; } ret = print_sam_info(sam_pwent, verbosity, smbpwdstyle); TALLOC_FREE(sam_pwent); return ret; }
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 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; }
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { unsigned int ctrl; int retval, *ret_data = NULL; struct samu *sampass = NULL; const char *name; void (*oldsig_handler)(int) = NULL; bool found; /* Points to memory managed by the PAM library. Do not free. */ char *p = NULL; /* Samba initialization. */ load_case_tables(); lp_set_in_client(True); ctrl = set_ctrl(pamh, flags, argc, argv); /* Get a few bytes so we can pass our return value to pam_sm_setcred(). */ ret_data = SMB_MALLOC_P(int); /* we need to do this before we call AUTH_RETURN */ /* 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); /* get the username */ retval = pam_get_user( pamh, &name, "Username: "******"auth: could not identify user"); } AUTH_RETURN; } if (on( SMB_DEBUG, ctrl )) { _log_err(pamh, LOG_DEBUG, "username [%s] obtained", name ); } if (geteuid() != 0) { _log_err(pamh, LOG_DEBUG, "Cannot access samba password database, not running as root."); retval = PAM_AUTHINFO_UNAVAIL; AUTH_RETURN; } if (!initialize_password_db(True, NULL)) { _log_err(pamh, LOG_ALERT, "Cannot access samba password database" ); retval = PAM_AUTHINFO_UNAVAIL; AUTH_RETURN; } sampass = samu_new( NULL ); if (!sampass) { _log_err(pamh, LOG_ALERT, "Cannot talloc a samu struct" ); retval = nt_status_to_pam(NT_STATUS_NO_MEMORY); AUTH_RETURN; } found = pdb_getsampwnam( sampass, name ); if (on( SMB_MIGRATE, ctrl )) { retval = _smb_add_user(pamh, ctrl, name, sampass, found); TALLOC_FREE(sampass); AUTH_RETURN; } if (!found) { _log_err(pamh, LOG_ALERT, "Failed to find entry for user %s.", name); retval = PAM_USER_UNKNOWN; TALLOC_FREE(sampass); sampass = NULL; AUTH_RETURN; } /* if this user does not have a password... */ if (_smb_blankpasswd( ctrl, sampass )) { TALLOC_FREE(sampass); retval = PAM_SUCCESS; AUTH_RETURN; } /* get this user's authentication token */ retval = _smb_read_password(pamh, ctrl, NULL, "Password: "******"auth: no password provided for [%s]", name); TALLOC_FREE(sampass); AUTH_RETURN; } /* verify the password of this user */ retval = _smb_verify_password( pamh, sampass, p, ctrl ); TALLOC_FREE(sampass); p = NULL; AUTH_RETURN; }
NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, char *ntuser, char *ntdomain, char *username, struct passwd *pw, struct PAC_LOGON_INFO *logon_info, bool mapped_to_guest, bool username_was_mapped, DATA_BLOB *session_key, struct auth_session_info **session_info) { NTSTATUS status; struct auth_serversupplied_info *server_info; if (mapped_to_guest) { status = make_server_info_guest(mem_ctx, &server_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("make_server_info_guest failed: %s!\n", nt_errstr(status))); return status; } } else if (logon_info) { /* pass the unmapped username here since map_username() will be called again in make_server_info_info3() */ status = make_server_info_info3(mem_ctx, ntuser, ntdomain, &server_info, &logon_info->info3); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("make_server_info_info3 failed: %s!\n", nt_errstr(status))); return status; } } else { /* * We didn't get a PAC, we have to make up the user * ourselves. Try to ask the pdb backend to provide * SID consistency with ntlmssp session setup */ struct samu *sampass; /* The stupid make_server_info_XX functions here don't take a talloc context. */ struct auth_serversupplied_info *tmp = NULL; sampass = samu_new(talloc_tos()); if (sampass == NULL) { return NT_STATUS_NO_MEMORY; } if (pdb_getsampwnam(sampass, username)) { DEBUG(10, ("found user %s in passdb, calling " "make_server_info_sam\n", username)); status = make_server_info_sam(&tmp, sampass); } else { /* * User not in passdb, make it up artificially */ DEBUG(10, ("didn't find user %s in passdb, calling " "make_server_info_pw\n", username)); status = make_server_info_pw(&tmp, username, pw); } TALLOC_FREE(sampass); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("make_server_info_[sam|pw] failed: %s!\n", nt_errstr(status))); return status; } /* make_server_info_pw does not set the domain. Without this * we end up with the local netbios name in substitutions for * %D. */ if (server_info->info3 != NULL) { server_info->info3->base.domain.string = talloc_strdup(server_info->info3, ntdomain); } } server_info->nss_token |= username_was_mapped; status = create_local_token(mem_ctx, server_info, session_key, ntuser, session_info); talloc_free(server_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("failed to create local token: %s\n", nt_errstr(status))); return status; } return NT_STATUS_OK; }
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { unsigned int ctrl; int retval, *ret_data = NULL; SAM_ACCOUNT *sampass = NULL; extern BOOL in_client; const char *name; void (*oldsig_handler)(int); BOOL found; /* Points to memory managed by the PAM library. Do not free. */ char *p = NULL; /* Samba initialization. */ setup_logging("pam_smbpass",False); in_client = True; ctrl = set_ctrl(flags, argc, argv); /* Get a few bytes so we can pass our return value to pam_sm_setcred(). */ ret_data = malloc(sizeof(int)); /* get the username */ retval = pam_get_user( pamh, &name, "Username: "******"auth: could not identify user"); } AUTH_RETURN; } if (on( SMB_DEBUG, ctrl )) { _log_err( LOG_DEBUG, "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" ); retval = PAM_AUTHINFO_UNAVAIL; AUTH_RETURN; } pdb_init_sam(&sampass); found = pdb_getsampwnam( sampass, name ); if (on( SMB_MIGRATE, ctrl )) { retval = _smb_add_user(pamh, ctrl, name, sampass, found); pdb_free_sam(&sampass); AUTH_RETURN; } if (!found) { _log_err(LOG_ALERT, "Failed to find entry for user %s.", name); retval = PAM_USER_UNKNOWN; pdb_free_sam(&sampass); sampass = NULL; AUTH_RETURN; } /* if this user does not have a password... */ if (_smb_blankpasswd( ctrl, sampass )) { pdb_free_sam(&sampass); retval = PAM_SUCCESS; AUTH_RETURN; } /* get this user's authentication token */ retval = _smb_read_password(pamh, ctrl, NULL, "Password: "******"auth: no password provided for [%s]" , name); pdb_free_sam(&sampass); AUTH_RETURN; } /* verify the password of this user */ retval = _smb_verify_password( pamh, sampass, p, ctrl ); pdb_free_sam(&sampass); p = NULL; AUTH_RETURN; }
int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) { unsigned int ctrl; int retval; extern BOOL in_client; SAM_ACCOUNT *sampass = NULL; void (*oldsig_handler)(int); const char *user; char *pass_old; char *pass_new; NTSTATUS nt_status; /* Samba initialization. */ setup_logging( "pam_smbpass", False ); in_client = True; ctrl = set_ctrl(flags, argc, argv); /* * First get the name of a user. No need to do anything if we can't * determine this. */ retval = pam_get_user( pamh, &user, "Username: "******"password: could not identify user" ); } return retval; } if (on( SMB_DEBUG, ctrl )) { _log_err( LOG_DEBUG, "username [%s] obtained", user ); } /* 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; } /* obtain user record */ if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sampass))) { CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return nt_status_to_pam(nt_status); } if (!pdb_getsampwnam(sampass,user)) { _log_err( LOG_ALERT, "Failed to find entry for user %s.", user ); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_USER_UNKNOWN; } if (flags & PAM_PRELIM_CHECK) { /* * obtain and verify the current password (OLDAUTHTOK) for * the user. */ char *Announce; if (_smb_blankpasswd( ctrl, sampass )) { pdb_free_sam(&sampass); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_SUCCESS; } /* Password change by root, or for an expired token, doesn't require authentication. Is this a good choice? */ if (getuid() != 0 && !(flags & PAM_CHANGE_EXPIRED_AUTHTOK)) { /* tell user what is happening */ #define greeting "Changing password for " Announce = (char *) malloc(sizeof(greeting)+strlen(user)); if (Announce == NULL) { _log_err(LOG_CRIT, "password: out of memory"); pdb_free_sam(&sampass); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_BUF_ERR; } strncpy( Announce, greeting, sizeof(greeting) ); strncpy( Announce+sizeof(greeting)-1, user, strlen(user)+1 ); #undef greeting set( SMB__OLD_PASSWD, ctrl ); retval = _smb_read_password( pamh, ctrl, Announce, "Current SMB password: "******"password - (old) token not obtained" ); pdb_free_sam(&sampass); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return retval; } /* verify that this is the password for this user */ retval = _smb_verify_password( pamh, sampass, pass_old, ctrl ); } else { pass_old = NULL; retval = PAM_SUCCESS; /* root doesn't have to */ } pass_old = NULL; pdb_free_sam(&sampass); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return retval; } else if (flags & PAM_UPDATE_AUTHTOK) { /* * obtain the proposed password */ /* * get the old token back. NULL was ok only if root [at this * point we assume that this has already been enforced on a * previous call to this function]. */ if (off( SMB_NOT_SET_PASS, ctrl )) { retval = pam_get_item( pamh, PAM_OLDAUTHTOK, (const void **)&pass_old ); } else { retval = pam_get_data( pamh, _SMB_OLD_AUTHTOK, (const void **)&pass_old ); if (retval == PAM_NO_MODULE_DATA) { pass_old = NULL; retval = PAM_SUCCESS; } } if (retval != PAM_SUCCESS) { _log_err( LOG_NOTICE, "password: user not authenticated" ); pdb_free_sam(&sampass); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return retval; } /* * use_authtok is to force the use of a previously entered * password -- needed for pluggable password strength checking * or other module stacking */ if (on( SMB_USE_AUTHTOK, ctrl )) { set( SMB_USE_FIRST_PASS, ctrl ); } retval = _smb_read_password( pamh, ctrl , NULL , "Enter new SMB password: "******"Retype new SMB password: "******"password: new password not obtained" ); } pass_old = NULL; /* tidy up */ pdb_free_sam(&sampass); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return retval; } /* * At this point we know who the user is and what they * propose as their new password. Verify that the new * password is acceptable. */ if (pass_new[0] == '\0') { /* "\0" password = NULL */ pass_new = NULL; } retval = _pam_smb_approve_pass(pamh, ctrl, pass_old, pass_new); if (retval != PAM_SUCCESS) { _log_err(LOG_NOTICE, "new password not acceptable"); pass_new = pass_old = NULL; /* tidy up */ pdb_free_sam(&sampass); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return retval; } /* * By reaching here we have approved the passwords and must now * rebuild the smb password file. */ /* update the password database */ retval = smb_update_db(pamh, ctrl, user, pass_new); if (retval == PAM_SUCCESS) { uid_t uid; /* password updated */ if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(sampass), &uid))) { _log_err( LOG_NOTICE, "Unable to get uid for user %s", pdb_get_username(sampass)); _log_err( LOG_NOTICE, "password for (%s) changed by (%s/%d)", user, uidtoname(getuid()), getuid()); } else { _log_err( LOG_NOTICE, "password for (%s/%d) changed by (%s/%d)", user, uid, uidtoname(getuid()), getuid()); } } else { _log_err( LOG_ERR, "password change failed for user %s", user); } pass_old = pass_new = NULL; if (sampass) { pdb_free_sam(&sampass); sampass = NULL; } } else { /* something has broken with the library */ _log_err( LOG_ALERT, "password received unknown request" ); retval = PAM_ABORT; } if (sampass) { pdb_free_sam(&sampass); sampass = NULL; } pdb_free_sam(&sampass); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return retval; }
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 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; }
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; }
/********************************************************* Add New User **********************************************************/ static int new_user(const char *username, const char *fullname, const char *homedir, const char *drive, const char *script, const char *profile, char *user_sid, bool stdin_get) { char *pwd1 = NULL, *pwd2 = NULL; char *err = NULL, *msg = NULL; struct samu *sam_pwent = NULL; TALLOC_CTX *tosctx; NTSTATUS status; struct dom_sid u_sid; int flags; int ret; tosctx = talloc_tos(); if (!tosctx) { fprintf(stderr, "Out of memory!\n"); return -1; } if (user_sid) { if (get_sid_from_cli_string(&u_sid, user_sid)) { fprintf(stderr, "Failed to parse SID\n"); return -1; } } pwd1 = get_pass( "new password:"******"retype new password:"******"Failed to read passwords.\n"); return -1; } ret = strcmp(pwd1, pwd2); if (ret != 0) { fprintf (stderr, "Passwords do not match!\n"); goto done; } flags = LOCAL_ADD_USER | LOCAL_SET_PASSWORD; status = local_password_change(username, flags, pwd1, &err, &msg); if (!NT_STATUS_IS_OK(status)) { if (err) fprintf(stderr, "%s", err); ret = -1; goto done; } sam_pwent = samu_new(tosctx); if (!sam_pwent) { fprintf(stderr, "Out of memory!\n"); ret = -1; goto done; } if (!pdb_getsampwnam(sam_pwent, username)) { fprintf(stderr, "User %s not found!\n", username); ret = -1; goto done; } if (fullname) pdb_set_fullname(sam_pwent, fullname, 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_sid) pdb_set_user_sid(sam_pwent, &u_sid, PDB_CHANGED); status = pdb_update_sam_account(sam_pwent); if (!NT_STATUS_IS_OK(status)) { fprintf(stderr, "Failed to modify entry for user %s.!\n", username); ret = -1; goto done; } print_user_info(username, True, False); ret = 0; done: if (pwd1) memset(pwd1, 0, strlen(pwd1)); if (pwd2) memset(pwd2, 0, strlen(pwd2)); SAFE_FREE(pwd1); SAFE_FREE(pwd2); SAFE_FREE(err); SAFE_FREE(msg); TALLOC_FREE(sam_pwent); return ret; }
static int new_machine(const char *machinename, char *machine_sid) { char *err = NULL, *msg = NULL; struct samu *sam_pwent = NULL; TALLOC_CTX *tosctx; NTSTATUS status; struct dom_sid m_sid; char *compatpwd; char *name; int flags; int len; int 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; } if (machine_sid) { if (get_sid_from_cli_string(&m_sid, machine_sid)) { fprintf(stderr, "Failed to parse SID\n"); return -1; } } compatpwd = talloc_strdup(tosctx, machinename); if (!compatpwd) { fprintf(stderr, "Out of memory!\n"); return -1; } if (machinename[len-1] == '$') { name = talloc_strdup(tosctx, machinename); compatpwd[len-1] = '\0'; } else { name = talloc_asprintf(tosctx, "%s$", machinename); } if (!name) { fprintf(stderr, "Out of memory!\n"); return -1; } if (!strlower_m(name)) { fprintf(stderr, "strlower_m %s failed\n", name); return -1; } flags = LOCAL_ADD_USER | LOCAL_TRUST_ACCOUNT | LOCAL_SET_PASSWORD; status = local_password_change(name, flags, compatpwd, &err, &msg); if (!NT_STATUS_IS_OK(status)) { if (err) fprintf(stderr, "%s", err); ret = -1; } sam_pwent = samu_new(tosctx); if (!sam_pwent) { fprintf(stderr, "Out of memory!\n"); ret = -1; goto done; } if (!pdb_getsampwnam(sam_pwent, name)) { fprintf(stderr, "Machine %s not found!\n", name); ret = -1; goto done; } if (machine_sid) pdb_set_user_sid(sam_pwent, &m_sid, PDB_CHANGED); status = pdb_update_sam_account(sam_pwent); if (!NT_STATUS_IS_OK(status)) { fprintf(stderr, "Failed to modify entry for %s.!\n", name); ret = -1; goto done; } print_user_info(name, True, False); ret = 0; done: SAFE_FREE(err); SAFE_FREE(msg); TALLOC_FREE(sam_pwent); 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; }
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; }
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; }