int smb_update_db( pam_handle_t *pamh, int ctrl, const char *user, const char *pass_new ) { int retval; pstring err_str; pstring msg_str; err_str[0] = '\0'; msg_str[0] = '\0'; retval = local_password_change( user, LOCAL_SET_PASSWORD, pass_new, err_str, sizeof(err_str), msg_str, sizeof(msg_str) ); if (!retval) { if (*err_str) { err_str[PSTRING_LEN-1] = '\0'; make_remark( pamh, ctrl, PAM_ERROR_MSG, err_str ); } /* FIXME: what value is appropriate here? */ retval = PAM_AUTHTOK_ERR; } else { if (*msg_str) { msg_str[PSTRING_LEN-1] = '\0'; make_remark( pamh, ctrl, PAM_TEXT_INFO, msg_str ); } retval = PAM_SUCCESS; } return retval; }
/* 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; }
/* 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; }
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; }
/* Do the actual work of creating a home dir */ static int create_homedir(pam_handle_t * pamh, int ctrl, const struct passwd *pwd, const char *source, const char *dest) { char remark[BUFSIZ]; DIR *D; struct dirent *Dir; /* Mention what is happening, if the notification fails that is OK */ if (snprintf(remark,sizeof(remark),"Creating directory '%s'.", dest) == -1) return PAM_PERM_DENIED; make_remark(pamh, ctrl, remark); /* Create the new directory */ if (mkdir(dest,0700) != 0) { _log_err(LOG_DEBUG, "unable to create directory %s",dest); return PAM_PERM_DENIED; } if (chmod(dest,0777 & (~UMask)) != 0 || chown(dest,pwd->pw_uid,pwd->pw_gid) != 0) { _log_err(LOG_DEBUG, "unable to change perms on directory %s",dest); return PAM_PERM_DENIED; } /* See if we need to copy the skel dir over. */ if ((source == NULL) || (strlen(source) == 0)) { return PAM_SUCCESS; } /* Scan the directory */ D = opendir(source); if (D == 0) { _log_err(LOG_DEBUG, "unable to read directory %s",source); return PAM_PERM_DENIED; } for (Dir = readdir(D); Dir != 0; Dir = readdir(D)) { int SrcFd; int DestFd; int Res; struct stat St; char newsource[PATH_MAX], newdest[PATH_MAX]; /* Skip some files.. */ if (strcmp(Dir->d_name,".") == 0 || strcmp(Dir->d_name,"..") == 0) continue; /* Determine what kind of file it is. */ snprintf(newsource,sizeof(newsource),"%s/%s",source,Dir->d_name); if (lstat(newsource,&St) != 0) continue; /* We'll need the new file's name. */ snprintf(newdest,sizeof(newdest),"%s/%s",dest,Dir->d_name); /* If it's a directory, recurse. */ if (S_ISDIR(St.st_mode)) { create_homedir(pamh, ctrl, pwd, newsource, newdest); continue; } /* If it's a symlink, create a new link. */ if (S_ISLNK(St.st_mode)) { char pointed[PATH_MAX]; memset(pointed, 0, sizeof(pointed)); if(readlink(newsource, pointed, sizeof(pointed) - 1) != -1) { if(symlink(pointed, newdest) == 0) { if (lchown(newdest,pwd->pw_uid,pwd->pw_gid) != 0) { _log_err(LOG_DEBUG, "unable to chang perms on link %s", newdest); return PAM_PERM_DENIED; } } } continue; } /* If it's not a regular file, it's probably not a good idea to create * the new device node, FIFO, or whatever it is. */ if (!S_ISREG(St.st_mode)) { continue; } /* Open the source file */ if ((SrcFd = open(newsource,O_RDONLY)) < 0 || fstat(SrcFd,&St) != 0) { _log_err(LOG_DEBUG, "unable to open src file %s",newsource); return PAM_PERM_DENIED; } stat(newsource,&St); /* Open the dest file */ if ((DestFd = open(newdest,O_WRONLY | O_TRUNC | O_CREAT,0600)) < 0) { close(SrcFd); _log_err(LOG_DEBUG, "unable to open dest file %s",newdest); return PAM_PERM_DENIED; } /* Set the proper ownership and permissions for the module. We make the file a+w and then mask it with the set mask. This preseves execute bits */ if (fchmod(DestFd,(St.st_mode | 0222) & (~UMask)) != 0 || fchown(DestFd,pwd->pw_uid,pwd->pw_gid) != 0) { close(SrcFd); close(DestFd); _log_err(LOG_DEBUG, "unable to chang perms on copy %s",newdest); return PAM_PERM_DENIED; } /* Copy the file */ do { Res = read(SrcFd,remark,sizeof(remark)); if (Res < 0 || write(DestFd,remark,Res) != Res) { close(SrcFd); close(DestFd); _log_err(LOG_DEBUG, "unable to perform IO"); return PAM_PERM_DENIED; } } while (Res != 0); close(SrcFd); close(DestFd); } return PAM_SUCCESS; }
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; }