diff options
Diffstat (limited to 'src/qmail-vmailuser.c')
-rw-r--r-- | src/qmail-vmailuser.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/src/qmail-vmailuser.c b/src/qmail-vmailuser.c new file mode 100644 index 0000000..a65135f --- /dev/null +++ b/src/qmail-vmailuser.c @@ -0,0 +1,148 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include "global.h" +#include "qmail.h" +#include "auto_qmail.h" +#include "stralloc.h" +#include "case.h" +#include "control.h" +#include "constmap.h" +#include "direntry.h" +#include "error.h" +#include "str.h" +#include "fmt.h" +#include "open.h" +#include "byte.h" +#include "scan.h" +#include "str.h" + +#define FDAUTH 3 +#define RESPECT_CASE "-C" + +/** @file qmail-vmailuser.c + @return 0: virtual user exists + 1: virtual user dir not accessible + 2: qmail-vmailuser is misused + 110: can't read controls + 111: temporary problem +*/ + +char inputbuf[BUFSIZE_AUTH]; +struct constmap mapvdoms; +stralloc vdoms = {0}; +stralloc vdomdir = {0}; +stralloc vuser = {0}; +stralloc vuserdir = {0}; + +void pam_exit(int fail) +{ + int i; + + close(FDAUTH); + for (i = 0; i < sizeof(inputbuf); ++i) inputbuf[i] = 0; + _exit(fail); +} + +int main(int argc,char **argv) +{ + DIR *dir; + char *vdomuser; + char *domain = 0; + int buflen = 0; + int domlen = 0; + int flagrespect = 0; + int i, r; + char ch; + char *homedir = "/home"; + + if (argv[1]) + if (!case_diffs(argv[1],RESPECT_CASE)) { + flagrespect = 1; + } else { + homedir = argv[1]; + dir = opendir(homedir); + if (!dir) pam_exit(2); + } + + if (argv[2]) + if (!case_diffs(argv[2],RESPECT_CASE)) flagrespect = 1; + + if (chdir(auto_qmail) == -1) pam_exit(110); + + switch (control_readfile(&vdoms,"control/virtualdomains",0)) { + case -1: pam_exit(110); + case 0: if (!constmap_init(&mapvdoms,"",0,1)) pam_exit(111); + case 1: if (!constmap_init(&mapvdoms,vdoms.s,vdoms.len,1)) pam_exit(111); + } + + for (;;) { /* read input */ + do + r = read(FDAUTH,inputbuf + buflen,sizeof(inputbuf) - buflen); + while ((r == -1) && (errno == EINTR)); + if (r == -1) pam_exit(111); + if (r == 0) break; + buflen += r; + if (buflen >= sizeof(inputbuf)) pam_exit(2); + } + close(FDAUTH); + + if ((r = byte_rchr(inputbuf,buflen,'@'))) /* @domain */ + if (r < buflen && inputbuf[r] == '@') { + domain = inputbuf + r + 1; + domlen = str_len(domain); + if (!flagrespect) + case_lowerb(inputbuf,buflen); + else + case_lowerb(domain,domlen); + } + vdomuser = constmap(&mapvdoms,domain,domlen); + if (!vdomuser) pam_exit(1); + + if (!stralloc_copys(&vuser,"")) pam_exit(111); /* user */ + for (i = 0; i < r; ++i) { + ch = inputbuf[i]; + if (ch == '.') ch = ':'; + if (!stralloc_append(&vuser,&ch)) pam_exit(111); + } + if (!stralloc_0(&vuser)) pam_exit(111); + + if (!stralloc_copys(&vdomdir,homedir)) pam_exit(111); /* vpopmail */ + if (!stralloc_cats(&vdomdir,"/")) pam_exit(111); + if (!stralloc_cats(&vdomdir,"vpopmail")) pam_exit(111); + if (!stralloc_copy(&vuserdir,&vdomdir)) pam_exit(111); + if (!stralloc_cats(&vuserdir,"/domains/")) pam_exit(111); + if (!stralloc_cats(&vuserdir,vdomuser)) pam_exit(111); + if (!stralloc_copy(&vdomdir,&vuserdir)) pam_exit(111); + if (!stralloc_0(&vdomdir)) pam_exit(111); + + dir = opendir(vdomdir.s); + if (dir) { + if (!stralloc_cats(&vuserdir,"/")) pam_exit(111); + if (!stralloc_cat(&vuserdir,&vuser)) pam_exit(111); + if (!stralloc_0(&vuserdir)) pam_exit(111); + + dir = opendir(vuserdir.s); + if (dir) pam_exit(0); + } + + if (!stralloc_copys(&vdomdir,homedir)) pam_exit(111); /* vmailmgr */ + if (!stralloc_cats(&vdomdir,"/")) pam_exit(111); + if (!stralloc_copy(&vuserdir,&vdomdir)) pam_exit(111); + if (!stralloc_cats(&vuserdir,vdomuser)) pam_exit(111); + if (!stralloc_cats(&vuserdir,"/users")) pam_exit(111); + if (!stralloc_copy(&vdomdir,&vuserdir)) pam_exit(111); + if (!stralloc_0(&vdomdir)) pam_exit(111); + + dir = opendir(vdomdir.s); + if (dir) { + if (!stralloc_cats(&vuserdir,"/")) pam_exit(111); + if (!stralloc_cat(&vuserdir,&vuser)) pam_exit(111); + if (!stralloc_0(&vuserdir)) pam_exit(111); + + dir = opendir(vuserdir.s); + if (dir) pam_exit(0); + } + + pam_exit(1); +} |