--- pam_setquota.c 2010-01-26 20:48:30.000000000 -0800 +++ pam_setquota.c.new 2010-01-27 12:18:58.000000000 -0800 @@ -10,7 +10,7 @@ Here are sample PAM config lines: - session required /lib/security/pam_setquota.so bsoftlimit=19000 bhardlimit=20000 isoftlimit=3000 ihardlimit=4000 startuid=1000 enduid=2000 fs=/dev/sda1 + session required /lib/security/pam_setquota.so bsoftlimit=19000 bhardlimit=20000 isoftlimit=3000 ihardlimit=4000 startuid=1000 enduid=2000 fs=/dev/sda1 overwrite=1 session required /lib/security/pam_setquota.so bsoftlimit=1000 bhardlimit=2000 isoftlimit=1000 ihardlimit=2000 startuid=2001 enduid=0 fs=/home Released under the GNU LGPL version 2 or later @@ -18,6 +18,9 @@ Structure taken from pam_mkhomedir by Jason Gunthorpe 1999 + Modified Jan 26, 2010 by Shane Tzen + - added overwrite option to avoid overwriting existing quotas + */ #include @@ -41,8 +44,15 @@ uid_t start_uid; uid_t end_uid; char *fs; + int overwrite; + int debug; }; +static void +debug(struct if_dqblk *p) +{ + syslog(LOG_DEBUG,"bsoftlimit=%llu bhardlimit=%llu isoftlimit=%llu ihardlimit=%llu", p->dqb_bsoftlimit, p->dqb_bhardlimit, p->dqb_isoftlimit, p->dqb_ihardlimit); +} static void _pam_parse_dqblk(int argc, const char **argv, struct if_dqblk *p) @@ -93,6 +103,10 @@ p->end_uid = strtol (*argv + 7, NULL, 10); else if (strncmp (*argv, "fs=",3) == 0) p->fs = (char*) *argv + 3; + else if (strncmp (*argv, "overwrite=",10) == 0) + p->overwrite = strtol (*argv + 10, NULL, 10); + else if (strncmp (*argv, "debug=",6) == 0) + p->debug = strtol (*argv + 6, NULL, 10); } } @@ -123,7 +137,7 @@ service = ""; /* Start logging */ - snprintf (srvstr, sizeof (srvstr), "%s[%d]: (pam_setquota) ", service, getpid ()); + snprintf (srvstr, sizeof (srvstr), "%s[%d]: pam_setquota", service, getpid ()); openlog(srvstr,0,LOG_AUTHPRIV); /* Parse values */ @@ -199,16 +213,23 @@ sysctl(LOG_ERR,"fail to get limits for user %s : %s", pwd->pw_name, strerror(errno)); return PAM_PERM_DENIED; } + if ( param.debug == 1 ) + debug(&ndqblk); /* Parse new limits */ ndqblk.dqb_valid = 0; _pam_parse_dqblk(argc,argv,&ndqblk); - - /* Set limits */ - if (quotactl(QCMD(Q_SETQUOTA,USRQUOTA), mntdevice, pwd->pw_uid, (void*) &ndqblk) == -1) + /* Only overwrite if quotas aren't already set or if overwrite is set */ + if ( (ndqblk.dqb_bsoftlimit == 0 && ndqblk.dqb_bhardlimit == 0 && ndqblk.dqb_isoftlimit == 0 && ndqblk.dqb_ihardlimit == 0) || param.overwrite == 1 ) { - sysctl(LOG_ERR,"fail to set limits for user %s : %s", pwd->pw_name, strerror(errno)); - return PAM_PERM_DENIED; + /* Set limits */ + if (quotactl(QCMD(Q_SETQUOTA,USRQUOTA), mntdevice, pwd->pw_uid, (void*) &ndqblk) == -1) + { + sysctl(LOG_ERR,"fail to set limits for user %s : %s", pwd->pw_name, strerror(errno)); + return PAM_PERM_DENIED; + } + if ( param.debug == 1 ) + debug(&ndqblk); }