diff options
Diffstat (limited to 'src/qmail-authuser.c')
-rw-r--r-- | src/qmail-authuser.c | 296 |
1 files changed, 152 insertions, 144 deletions
diff --git a/src/qmail-authuser.c b/src/qmail-authuser.c index e90468f..2cdb01e 100644 --- a/src/qmail-authuser.c +++ b/src/qmail-authuser.c @@ -1,32 +1,35 @@ -#include <stdio.h> #include <unistd.h> -#include "global.h" -#include "stralloc.h" + +#include <stdio.h> + #include "buffer.h" -#include "auto_qmail.h" +#include "byte.h" #include "case.h" -#include "control.h" #include "constmap.h" -#include "str.h" -#include "fmt.h" +#include "error.h" #include "fd.h" +#include "fmt.h" #include "open.h" -#include "byte.h" +#include "pathexec.h" +#include "prot.h" #include "scan.h" -#include "md5.h" +#include "sig.h" +#include "str.h" +#include "stralloc.h" +#include "wait.h" + +#include "auto_qmail.h" +#include "control.h" +#include "global.h" #include "hmac_md5.h" +#include "md5.h" #include "sha1.h" #include "sha256.h" -#include "pathexec.h" -#include "prot.h" -#include "wait.h" -#include "sig.h" -#include "error.h" -#define FDAUTH 3 -#define FDGOSSIP 1 -#define SOCKET_CALL "-s" +#define FDAUTH 3 +#define FDGOSSIP 1 +#define SOCKET_CALL "-s" #define DOVECOT_SERVICE "-x" -#define POP_USER "qmail-pop3d" +#define POP_USER "qmail-pop3d" extern char *crypt(); #include <pwd.h> @@ -34,13 +37,13 @@ static struct passwd *pw; #include "hasspnam.h" #ifdef HASGETSPNAM -#include <shadow.h> + #include <shadow.h> static struct spwd *spw; #endif #include "hasuserpw.h" #ifdef HASUSERPW -#include <userpw.h> + #include <userpw.h> static struct userpw *upw; #endif @@ -53,12 +56,12 @@ static struct userpw *upw; */ char authbuf[512]; -buffer ba = BUFFER_INIT(write,FDAUTH,authbuf,sizeof(authbuf)); +buffer ba = BUFFER_INIT(write, FDAUTH, authbuf, sizeof(authbuf)); struct constmap mapauthuser; stralloc authfile = {0}; stralloc disabled = {0}; -stralloc user = {0}; // user w/o domain appended +stralloc user = {0}; // user w/o domain appended stralloc homedir = {0}; stralloc shell = {0}; @@ -78,11 +81,11 @@ void exit(int fail) { int i; - for (i = 0; i < sizeof(authbuf); ++i) authbuf[i] = 0; + for (i = 0; i < sizeof(authbuf); ++i) authbuf[i] = 0; _exit(fail); } -int dig_ascii(char *digascii,const char *digest,const int len) +int dig_ascii(char *digascii, const char *digest, const int len) { static const char hextab[] = "0123456789abcdef"; int j; @@ -93,56 +96,56 @@ int dig_ascii(char *digascii,const char *digest,const int len) } digascii[2 * len] = '\0'; - return (2*j); // 2*len + return (2 * j); // 2*len } -int auth_sha1(char *pwdhash,char *response) +int auth_sha1(char *pwdhash, char *response) { unsigned char digest[20]; unsigned char digascii[41]; - sha1_hash(digest,response,str_len(response)); - dig_ascii(digascii,digest,20); + sha1_hash(digest, response, str_len(response)); + dig_ascii(digascii, digest, 20); - return str_diffn(digascii,pwdhash,40); -} + return str_diffn(digascii, pwdhash, 40); +} -int auth_sha256(char *pwdhash,char *response) +int auth_sha256(char *pwdhash, char *response) { unsigned char digest[32]; unsigned char digascii[65]; - sha256_hash(digest,response,str_len(response)); - dig_ascii(digascii,digest,32); + sha256_hash(digest, response, str_len(response)); + dig_ascii(digascii, digest, 32); - return str_diffn(digascii,pwdhash,64); -} + return str_diffn(digascii, pwdhash, 64); +} -int auth_md5(char *pwdhash,char *response) -{ +int auth_md5(char *pwdhash, char *response) +{ MD5_CTX ctx; unsigned char digest[16]; unsigned char digascii[33]; MD5Init(&ctx); - MD5Update(&ctx,response,str_len(response)); - MD5Final(digest,&ctx); - dig_ascii(digascii,digest,16); + MD5Update(&ctx, response, str_len(response)); + MD5Final(digest, &ctx); + dig_ascii(digascii, digest, 16); - return str_diffn(digascii,pwdhash,32); + return str_diffn(digascii, pwdhash, 32); } -int auth_hash(char *password,char *response) +int auth_hash(char *password, char *response) { switch (str_len(password)) { - case 32: return auth_md5(password,response); - case 40: return auth_sha1(password,response); - case 64: return auth_sha256(password,response); - default: return -1; + case 32: return auth_md5(password, response); + case 40: return auth_sha1(password, response); + case 64: return auth_sha256(password, response); + default: return -1; } } -int auth_unix(char *user,char* response) +int auth_unix(char *user, char *response) { char *encrypted = 0; char *stored = 0; @@ -151,8 +154,8 @@ int auth_unix(char *user,char* response) pw = getpwnam(user); if (pw) { stored = pw->pw_passwd; - if (!stralloc_copys(&homedir,pw->pw_dir)) exit(111); - if (!stralloc_copys(&shell,pw->pw_shell)) exit(111); + if (!stralloc_copys(&homedir, pw->pw_dir)) exit(111); + if (!stralloc_copys(&shell, pw->pw_shell)) exit(111); } else { if (errno == ETXTBSY) exit(111); exit(1); @@ -163,68 +166,67 @@ int auth_unix(char *user,char* response) upw = getuserpw(user); if (upw) stored = upw->upw_passwd; - else - if (errno == ETXTBSY) exit(111); + else if (errno == ETXTBSY) + exit(111); #elif HASGETSPNAM spw = getspnam(user); if (spw) stored = spw->sp_pwdp; - else - if (errno == ETXTBSY) exit(111); + else if (errno == ETXTBSY) + exit(111); #endif if (!stored || !*stored) exit(111); - encrypted = crypt(response,stored); + encrypted = crypt(response, stored); if (!encrypted) exit(111); // no password given (tx. M.B.) - r = str_diff(encrypted,stored); + r = str_diff(encrypted, stored); } if (r == 0 || !response) { - if (prot_gid((int) pw->pw_gid) == -1) exit(1); - if (prot_uid((int) pw->pw_uid) == -1) exit(1); + if (prot_gid((int)pw->pw_gid) == -1) exit(1); + if (prot_uid((int)pw->pw_uid) == -1) exit(1); if (chdir(pw->pw_dir) == -1) exit(111); } return r; } -int auth_apop(unsigned char *password,unsigned char *response,unsigned char *challenge) +int auth_apop(unsigned char *password, unsigned char *response, unsigned char *challenge) { MD5_CTX context; unsigned char digest[16]; unsigned char digascii[33]; MD5Init(&context); - MD5Update(&context,challenge,str_len(challenge)); - MD5Update(&context,password,str_len(password)); - MD5Final(digest,&context); - dig_ascii(digascii,digest,16); + MD5Update(&context, challenge, str_len(challenge)); + MD5Update(&context, password, str_len(password)); + MD5Final(digest, &context); + dig_ascii(digascii, digest, 16); - return (str_diff(digascii,response)); + return (str_diff(digascii, response)); } -int auth_cram(unsigned char *password,unsigned char *response,unsigned char *challenge) +int auth_cram(unsigned char *password, unsigned char *response, unsigned char *challenge) { unsigned char digest[16]; unsigned char digascii[33]; - hmac_md5(challenge,str_len(challenge),password,str_len(password),digest); - dig_ascii(digascii,digest,16); + hmac_md5(challenge, str_len(challenge), password, str_len(password), digest); + dig_ascii(digascii, digest, 16); - return (str_diff(digascii,response) && str_diff(password,response)); + return (str_diff(digascii, response) && str_diff(password, response)); } -int auth_dovecot(char *user,char *response,char *socket,char *service) +int auth_dovecot(char *user, char *response, char *socket, char *service) { int wstat; int child; char *wrapper[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int i = 0; - close(FDGOSSIP); /* gossiping doveadm */ + close(FDGOSSIP); /* gossiping doveadm */ switch (child = fork()) { - case -1: - exit(111); + case -1: exit(111); case 0: wrapper[i] = "doveadm"; wrapper[++i] = "auth"; @@ -238,56 +240,55 @@ int auth_dovecot(char *user,char *response,char *socket,char *service) wrapper[++i] = service; } wrapper[++i] = user; - wrapper[++i] = response; + wrapper[++i] = response; wrapper[++i] = 0; - execvp(wrapper[0],wrapper); + execvp(wrapper[0], wrapper); exit(111); } - if (wait_pid(&wstat,child) == -1) exit(111); + if (wait_pid(&wstat, child) == -1) exit(111); if (wait_crashed(wstat)) exit(111); - return wait_exitcode(wstat); + return wait_exitcode(wstat); } -int auth_wrapper(char *pam,char *arg1,char *arg2,char *auth,int len) +int auth_wrapper(char *pam, char *arg1, char *arg2, char *auth, int len) { int wstat; int child; int pi[2]; char *wrapper[4] = {0, 0, 0, 0}; - + if (pipe(pi) == -1) exit(111); if (pi[0] != FDAUTH) exit(111); switch (child = fork()) { - case -1: - exit(111); - case 0: + case -1: exit(111); + case 0: close(pi[1]); - if (fd_copy(FDAUTH,pi[0]) == -1) exit(111); + if (fd_copy(FDAUTH, pi[0]) == -1) exit(111); wrapper[0] = pam; wrapper[1] = arg1; wrapper[2] = arg2; wrapper[3] = 0; sig_pipedefault(); - execvp(wrapper[0],wrapper); + execvp(wrapper[0], wrapper); exit(111); } close(pi[0]); - buffer_init(&ba,write,pi[1],authbuf,sizeof(authbuf)); - if (buffer_put(&ba,auth,len) == -1) exit(111); + buffer_init(&ba, write, pi[1], authbuf, sizeof(authbuf)); + if (buffer_put(&ba, auth, len) == -1) exit(111); if (buffer_flush(&ba) == -1) exit(111); close(pi[1]); - if (wait_pid(&wstat,child) == -1) exit(111); + if (wait_pid(&wstat, child) == -1) exit(111); if (wait_crashed(wstat)) exit(111); return wait_exitcode(wstat); } -int main(int argc,char **argv) +int main(int argc, char **argv) { char *authuser; char *authpass; @@ -300,31 +301,31 @@ int main(int argc,char **argv) int rc = -1; /* initialise: -1; ok: 0; !ok: > 0 */ int authlen = 0; int buflen = 0; - int domlen = 0; + int domlen = 0; int popuser = 0; int i = 0; int r; - if (!argv[1]) + if (!argv[1]) exit(2); else if (argv[2]) { // pop user with homedir - if (!case_diffs(argv[1],POP_USER)) { + if (!case_diffs(argv[1], POP_USER)) { if (!argv[3]) exit(2); maildirname = argv[2]; - popuser = 1; + popuser = 1; } - if (!case_diffs(argv[1],SOCKET_CALL)) { // dovecot socket + if (!case_diffs(argv[1], SOCKET_CALL)) { // dovecot socket if (!argv[3]) exit(2); authsocket = argv[2]; - if (!case_diffs(argv[3],DOVECOT_SERVICE)) { // ++ dovecot service + if (!case_diffs(argv[3], DOVECOT_SERVICE)) { // ++ dovecot service service = argv[4]; if (!argv[5]) exit(2); } } - if (!case_diffs(argv[1],DOVECOT_SERVICE)) { // dovecot service + if (!case_diffs(argv[1], DOVECOT_SERVICE)) { // dovecot service if (!argv[3]) exit(2); service = argv[2]; - if (!case_diffs(argv[3],SOCKET_CALL)) { // ++ dovecot socket + if (!case_diffs(argv[3], SOCKET_CALL)) { // ++ dovecot socket if (!argv[5]) exit(2); authsocket = argv[4]; } @@ -333,9 +334,8 @@ int main(int argc,char **argv) /* Read input on FDAUTH */ - for (;;) { - do - r = read(FDAUTH,authbuf + buflen,sizeof(authbuf) - buflen); + for (;;) { + do r = read(FDAUTH, authbuf + buflen, sizeof(authbuf) - buflen); while ((r == -1) && (errno == EINTR)); if (r == -1) exit(111); if (r == 0) break; @@ -344,98 +344,106 @@ int main(int argc,char **argv) } close(FDAUTH); - authuser = authbuf + i; /* username */ + authuser = authbuf + i; /* username */ if (i == buflen) exit(2); - while (authbuf[i++]) /* response */ + while (authbuf[i++]) /* response */ if (i == buflen) exit(2); response = authbuf + i; if (i == buflen) exit(2); - while (authbuf[i++]) /* challenge */ + while (authbuf[i++]) /* challenge */ if (i == buflen) exit(2); challenge = authbuf + i; - authlen = str_len(authuser); - if (!stralloc_copyb(&user,authuser,authlen)) exit(111); + authlen = str_len(authuser); + if (!stralloc_copyb(&user, authuser, authlen)) exit(111); - if ((i = byte_rchr(authuser,authlen,'@'))) /* @domain */ + if ((i = byte_rchr(authuser, authlen, '@'))) /* @domain */ if (i < authlen && authuser[i] == '@') { domain = authuser + i; domlen = str_len(domain); - case_lowerb(domain,domlen); + case_lowerb(domain, domlen); user.len = 0; - if (!stralloc_copyb(&user,authuser,i)) exit(111); + if (!stralloc_copyb(&user, authuser, i)) exit(111); } if (!stralloc_0(&user)) exit(111); /* Read control file users/authuser and go for checks */ if (chdir(auto_qmail) == -1) exit(110); - - switch (control_readfile(&authfile,"users/authuser",0)) { + + switch (control_readfile(&authfile, "users/authuser", 0)) { case -1: exit(110); - case 0: if (!constmap_init(&mapauthuser,"",0,1)) exit(111); - case 1: if (!constmap_init(&mapauthuser,authfile.s,authfile.len,1)) exit(111); + case 0: + if (!constmap_init(&mapauthuser, "", 0, 1)) exit(111); + case 1: + if (!constmap_init(&mapauthuser, authfile.s, authfile.len, 1)) exit(111); } /* Check for disabled authuser/domains */ - if (!stralloc_copys(&disabled,"!")) exit(111); - if (!stralloc_catb(&disabled,authuser,authlen)) exit(111); - if (constmap(&mapauthuser,disabled.s,disabled.len)) exit(1); + if (!stralloc_copys(&disabled, "!")) exit(111); + if (!stralloc_catb(&disabled, authuser, authlen)) exit(111); + if (constmap(&mapauthuser, disabled.s, disabled.len)) exit(1); if (domlen) { disabled.len = 0; - if (!stralloc_copys(&disabled,"!")) exit(111); - if (!stralloc_catb(&disabled,domain,domlen)) exit(111); - if (constmap(&mapauthuser,disabled.s,disabled.len)) exit(1); + if (!stralloc_copys(&disabled, "!")) exit(111); + if (!stralloc_catb(&disabled, domain, domlen)) exit(111); + if (constmap(&mapauthuser, disabled.s, disabled.len)) exit(1); } /* Virtual and system user accounts */ - authpass = constmap(&mapauthuser,authuser,authlen); + authpass = constmap(&mapauthuser, authuser, authlen); - if (!authpass && domlen) - authpass = constmap(&mapauthuser,domain,domlen); // 1. authuser accounts - if (!authpass) - authpass = constmap(&mapauthuser,"*",1); // 2. system accounts - if (!authpass) - authpass = constmap(&mapauthuser,"@",1); // 3. virtual user accounts + if (!authpass && domlen) authpass = constmap(&mapauthuser, domain, domlen); // 1. authuser accounts + if (!authpass) authpass = constmap(&mapauthuser, "*", 1); // 2. system accounts + if (!authpass) authpass = constmap(&mapauthuser, "@", 1); // 3. virtual user accounts if (!authpass) exit(1); if (str_len(authpass) == 1) { switch (authpass[0]) { - case '?': rc = auth_unix(user.s,response); break; - case '+': if (popuser) - rc = auth_wrapper("checkvpw","qmail-pop3d",maildirname,authbuf,buflen); - else - rc = auth_wrapper("checkvpw","true","Maildir",authbuf,buflen); break; - case '&': if (popuser) - rc = auth_wrapper("vchkpw","qmail-pop3d",maildirname,authbuf,buflen); - else - rc = auth_wrapper("vchkpw","true",0,authbuf,buflen); break; - case '=': rc = auth_dovecot(authuser,response,authsocket,service); break; + case '?': rc = auth_unix(user.s, response); break; + case '+': + if (popuser) + rc = auth_wrapper("checkvpw", "qmail-pop3d", maildirname, authbuf, buflen); + else + rc = auth_wrapper("checkvpw", "true", "Maildir", authbuf, buflen); + break; + case '&': + if (popuser) + rc = auth_wrapper("vchkpw", "qmail-pop3d", maildirname, authbuf, buflen); + else + rc = auth_wrapper("vchkpw", "true", 0, authbuf, buflen); + break; + case '=': rc = auth_dovecot(authuser, response, authsocket, service); break; default: rc = 2; break; } } else { switch (authpass[0]) { - case '%': rc = auth_hash(authpass + 1,response); break; - default: if (rc) { - if (popuser) { - if ((rc = auth_apop(authpass,response,challenge)) == 0) { - auth_unix(user.s,0); // Unix environment only - } - } else rc = auth_cram(authpass,response,challenge); - } break; - } + case '%': rc = auth_hash(authpass + 1, response); break; + default: + if (rc) { + if (popuser) { + if ((rc = auth_apop(authpass, response, challenge)) == 0) { + auth_unix(user.s, 0); // Unix environment only + } + } else + rc = auth_cram(authpass, response, challenge); + } + break; + } } if (rc) exit(rc); - for (i = 0; i < sizeof(authbuf); ++i) authbuf[i] = 0; + for (i = 0; i < sizeof(authbuf); ++i) authbuf[i] = 0; if (authsocket && service) pathexec(argv + 5); - if (authsocket || service || popuser) pathexec(argv + 3); - else pathexec(argv + 1); + if (authsocket || service || popuser) + pathexec(argv + 3); + else + pathexec(argv + 1); exit(111); } |