Download | Plain Text | No Line Numbers
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <errno.h>
- #include <pwd.h>
- #include <mntent.h>
- #include <time.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/quota.h>
-
- #include <sys/sysmacros.h>
- #define CMP_DEV_T(a, b) (major(a) == major(b) && minor(a) == minor(b))
-
- #define LOGPREFIX "QUOTA: "
-
- int check_parent(const char *username)
- {
- pid_t parent;
- int num;
- char buf[256], buf2[256];
- const char *smtpbin = "/var/qmail/bin/qmail-smtpd";
-
- // check parent
- parent = getppid();
- if (num < 0 || num > sizeof(buf))
- {
- return 0;
- }
-
- num = readlink(buf, buf2, sizeof(buf2));
- if (num < 0)
- {
- return 0;
- }
- buf2[num] = '\0';
-
- {
- fprintf(stderr, LOGPREFIX "Error: Parent \"%s\" doesn't match qmail-smtp for user \"%s\".\n", buf2, username);
- return 0;
- }
-
- return 1;
- }
-
- int main()
- {
- const char *username = NULL, *device_path = NULL;
- struct passwd *pw;
- struct stat st, st2;
- FILE *fp;
- struct mntent *ent;
- struct dqblk dq;
- time_t now;
-
- if (!username)
- return 0;
-
- // lookup user in passwd
- pw = getpwnam(username);
- if (pw == NULL)
- {
- return 0;
- }
-
- // check parent
- if (!check_parent(username))
- return 0;
-
- // seteuid
- if (seteuid(pw->pw_uid))
- {
- return 0;
- }
-
- if (pw->pw_dir == NULL)
- {
- return 0;
- }
-
- // stat homedir to fetch blockdevice id
- if (stat(pw->pw_dir, &st) < 0)
- {
- return 0;
- }
-
- // iterate over mounted devices and check blockdevice id
- fp = setmntent(_PATH_MOUNTED, "r");
- if (fp == NULL)
- {
- return 0;
- }
- while ((ent = getmntent(fp)) != NULL)
- {
- continue;
-
- if (stat(ent->mnt_dir, &st2) == 0 &&
- CMP_DEV_T(st.st_dev, st2.st_dev))
- {
- device_path = ent->mnt_fsname;
- break;
- }
- }
- endmntent(fp);
-
- // nothing found...
- if (device_path == NULL)
- {
- return 0;
- }
-
- // fetch quota
- if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device_path, pw->pw_uid, (caddr_t) &dq))
- {
- return 0;
- }
-
- //TODO +space?
- if ((dq.dqb_bhardlimit && btodb(dq.dqb_curspace) >= dq.dqb_bhardlimit)
- || (dq.dqb_ihardlimit && dq.dqb_curinodes >= dq.dqb_ihardlimit)
- || (dq.dqb_bsoftlimit && btodb(dq.dqb_curspace) >= dq.dqb_bsoftlimit && dq.dqb_btime && now >= dq.dqb_btime)
- || (dq.dqb_isoftlimit && dq.dqb_curinodes >= dq.dqb_isoftlimit && dq.dqb_itime && now >= dq.dqb_itime))
- {
- }
-
- return 0;
- }
-