Hi, Here is a patch to pam_mkhomedir.c from PAM 0.72 that adds quota support. Brian --- Linux-PAM-0.72/modules/pam_mkhomedir/pam_mkhomedir.c.old Wed Feb 13 11:39:45 2002 +++ Linux-PAM-0.72/modules/pam_mkhomedir/pam_mkhomedir.c Wed Feb 13 12:55:17 2002 @@ -25,6 +25,18 @@ Originally written by Jason Gunthorpe <jgg@debian.org> Feb 1999 Structure taken from pam_lastlogin by Andrew Morgan <morgan@parc.power.net> 1996 + + 2/13/2002 - Brian Masney <masneyb@seul.org> - added quota support + Extra options are quota_bhardlimit=, quota_bsoftlimit=, + quota_ihardlimit=, quota_isoftlimit=, quota_btime= and + quota_itime=. You must also specify the mount point with + blkdevice=. If any of the options are left out, the value + defaults to 0. Note blkdevice cannot point to a mount point, it + must be the device of the filesystem. Here is an example for + your pam config: + + session required /lib/security/pam_mkhomedir.so skel=/etc/skel umask=022 quota_bsoftlimit=19000 quota_bhardlimit=20000 quota_isoftlimit=3000 quota_ihardlimit=4000 blkdevice=/dev/sda9 + */ /* I want snprintf dammit */ @@ -32,6 +44,7 @@ #include <stdarg.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/quota.h> #include <fcntl.h> #include <unistd.h> #include <pwd.h> @@ -39,6 +52,7 @@ #include <stdio.h> #include <string.h> #include <dirent.h> +#include <errno.h> /* * here, we make a definition for the externally accessible function @@ -57,7 +71,16 @@ #define MKHOMEDIR_QUIET 040 /* keep quiet about things */ static unsigned int UMask = 0022; -static char SkelDir[BUFSIZ] = "/etc/skel"; +static char SkelDir[BUFSIZ] = "/etc/skel", + QuotaDevice[BUFSIZ] = ""; + +/* Several variables for setting up quotas */ +static u_int32_t dqb_bhardlimit = 0, + dqb_bsoftlimit = 0, + dqb_ihardlimit = 0, + dqb_isoftlimit = 0; +static time_t dqb_btime = 0, + dqb_itime = 0; /* some syslogging */ static void _log_err(int err, const char *format, ...) @@ -90,6 +113,20 @@ UMask = strtol(*argv+6,0,0); else if (!strncmp(*argv,"skel=",5)) strcpy(SkelDir,*argv+5); + else if (!strncmp(*argv,"quota_bhardlimit=",17)) + dqb_bhardlimit = strtol(*argv+17,0,0); + else if (!strncmp(*argv,"quota_bsoftlimit=",17)) + dqb_bsoftlimit = strtol(*argv+17,0,0); + else if (!strncmp(*argv,"quota_ihardlimit=",17)) + dqb_ihardlimit = strtol(*argv+17,0,0); + else if (!strncmp(*argv,"quota_isoftlimit=",17)) + dqb_isoftlimit = strtol(*argv+17,0,0); + else if (!strncmp(*argv,"quota_btime=",12)) + dqb_btime = strtol(*argv+12,0,0); + else if (!strncmp(*argv,"quota_itime=",12)) + dqb_itime = strtol(*argv+12,0,0); + else if (!strncmp(*argv,"blkdevice=",10)) + strcpy(QuotaDevice,*argv+10); else { _log_err(LOG_ERR, "unknown option; %s", *argv); @@ -175,6 +212,7 @@ static int create_homedir(pam_handle_t * pamh, int ctrl, const struct passwd *pwd) { + struct dqblk quotablk; char *remark; DIR *D; struct dirent *Dir; @@ -198,14 +236,14 @@ if (mkdir(pwd->pw_dir,0700) != 0) { free(remark); - _log_err(LOG_DEBUG, "unable to create home directory %s",pwd->pw_dir); + _log_err(LOG_ERR, "unable to create home directory %s",pwd->pw_dir); return PAM_PERM_DENIED; } if (chmod(pwd->pw_dir,0777 & (~UMask)) != 0 || chown(pwd->pw_dir,pwd->pw_uid,pwd->pw_gid) != 0) { free(remark); - _log_err(LOG_DEBUG, "unable to chance perms on home directory %s",pwd->pw_dir); + _log_err(LOG_ERR, "unable to chance perms on home directory %s",pwd->pw_dir); return PAM_PERM_DENIED; } @@ -221,7 +259,7 @@ if (D == 0) { free(remark); - _log_err(LOG_DEBUG, "unable to read directory %s",SkelDir); + _log_err(LOG_ERR, "unable to read directory %s",SkelDir); return PAM_PERM_DENIED; } @@ -249,7 +287,7 @@ chown(remark,pwd->pw_uid,pwd->pw_gid) != 0) { free(remark); - _log_err(LOG_DEBUG, "unable to change perms on copy %s",remark); + _log_err(LOG_ERR, "unable to change perms on copy %s",remark); return PAM_PERM_DENIED; } continue; @@ -259,7 +297,7 @@ if ((SrcFd = open(remark,O_RDONLY)) < 0 || fstat(SrcFd,&St) != 0) { free(remark); - _log_err(LOG_DEBUG, "unable to open src file %s",remark); + _log_err(LOG_ERR, "unable to open src file %s",remark); return PAM_PERM_DENIED; } stat(remark,&St); @@ -270,7 +308,7 @@ { close(SrcFd); free(remark); - _log_err(LOG_DEBUG, "unable to open dest file %s",remark); + _log_err(LOG_ERR, "unable to open dest file %s",remark); return PAM_PERM_DENIED; } @@ -281,7 +319,7 @@ fchown(DestFd,pwd->pw_uid,pwd->pw_gid) != 0) { free(remark); - _log_err(LOG_DEBUG, "unable to chang perms on copy %s",remark); + _log_err(LOG_ERR, "unable to chang perms on copy %s",remark); return PAM_PERM_DENIED; } @@ -294,7 +332,7 @@ close(SrcFd); close(DestFd); free(remark); - _log_err(LOG_DEBUG, "unable to perform IO"); + _log_err(LOG_ERR, "unable to perform IO"); return PAM_PERM_DENIED; } } @@ -304,6 +342,27 @@ } free(remark); + + /* Setup user quotas if we were passed any quota arguments */ + if(*QuotaDevice != '\0' && (dqb_bhardlimit > 0 || dqb_bsoftlimit > 0 || + dqb_ihardlimit > 0 || dqb_isoftlimit > 0)) + { + memset("ablk,0,sizeof(quotablk)); + quotablk.dqb_bhardlimit = dqb_bhardlimit; + quotablk.dqb_bsoftlimit = dqb_bsoftlimit; + quotablk.dqb_ihardlimit = dqb_ihardlimit; + quotablk.dqb_isoftlimit = dqb_isoftlimit; + quotablk.dqb_btime = dqb_btime; + quotablk.dqb_itime = dqb_itime; + if(quotactl(QCMD(Q_SETQLIM, USRQUOTA),QuotaDevice,pwd->pw_uid, + (caddr_t) "ablk) != 0) + { + _log_err(LOG_ERR,"unable to setup quota on %s: %s", + QuotaDevice,strerror(errno)); + return PAM_PERM_DENIED; + } + } + return PAM_SUCCESS; }