summaryrefslogtreecommitdiff
path: root/src/qmail-authuser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmail-authuser.c')
-rw-r--r--src/qmail-authuser.c296
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);
}