27#define SOCKET_CALL "-s"
28#define DOVECOT_SERVICE "-x"
29#define POP_USER "qmail-pop3d"
33static struct passwd *pw;
38static struct spwd *spw;
44static struct userpw *upw;
85int dig_ascii(
char *digascii,
const char *digest,
const int len)
87 static const char hextab[] =
"0123456789abcdef";
90 for (
j = 0;
j < len;
j++) {
91 digascii[2 *
j] = hextab[digest[
j] >> 4];
92 digascii[2 *
j + 1] = hextab[digest[
j] & 0x0f];
94 digascii[2 * len] =
'\0';
101 unsigned char digest[20];
102 unsigned char digascii[41];
104 sha1_hash(digest,response,str_len(response));
107 return str_diffn(digascii,pwdhash,40);
112 unsigned char digest[32];
113 unsigned char digascii[65];
118 return str_diffn(digascii,pwdhash,64);
124 unsigned char digest[16];
125 unsigned char digascii[33];
132 return str_diffn(digascii,pwdhash,32);
137 switch (str_len(password)) {
138 case 32:
return auth_md5(password,response);
139 case 40:
return auth_sha1(password,response);
153 stored = pw->pw_passwd;
157 if (errno == ETXTBSY)
exit(111);
163 upw = getuserpw(
user);
165 stored = upw->upw_passwd;
167 if (errno == ETXTBSY)
exit(111);
169 spw = getspnam(
user);
171 stored = spw->sp_pwdp;
173 if (errno == ETXTBSY)
exit(111);
175 if (!stored || !*stored)
exit(111);
176 encrypted =
crypt(response,stored);
177 if (!encrypted)
exit(111);
178 r = str_diff(encrypted,stored);
181 if (r == 0 || !response) {
184 if (chdir(pw->pw_dir) == -1)
exit(111);
190int auth_apop(
unsigned char *password,
unsigned char *response,
unsigned char *challenge)
193 unsigned char digest[16];
194 unsigned char digascii[33];
197 MD5Update(&context,challenge,str_len(challenge));
198 MD5Update(&context,password,str_len(password));
202 return (str_diff(digascii,response));
205int auth_cram(
unsigned char *password,
unsigned char *response,
unsigned char *challenge)
207 unsigned char digest[16];
208 unsigned char digascii[33];
210 hmac_md5(challenge,str_len(challenge),password,str_len(password),digest);
213 return (str_diff(digascii,response) && str_diff(password,response));
220 char *wrapper[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
225 switch (child = fork()) {
229 wrapper[i] =
"doveadm";
230 wrapper[++i] =
"auth";
231 wrapper[++i] =
"test";
234 wrapper[++i] = socket;
238 wrapper[++i] = service;
241 wrapper[++i] = response;
244 execvp(wrapper[0],wrapper);
248 if (wait_pid(&wstat,child) == -1)
exit(111);
249 if (wait_crashed(wstat))
exit(111);
250 return wait_exitcode(wstat);
258 char *wrapper[4] = {0, 0, 0, 0};
260 if (pipe(pi) == -1)
exit(111);
263 switch (child = fork()) {
275 execvp(wrapper[0],wrapper);
281 if (buffer_put(&
ba,
auth,len) == -1)
exit(111);
282 if (buffer_flush(&
ba) == -1)
exit(111);
285 if (wait_pid(&wstat,child) == -1)
exit(111);
286 if (wait_crashed(wstat))
exit(111);
287 return wait_exitcode(wstat);
297 char *authsocket = 0;
299 char *maildirname = 0;
311 if (!case_diffs(argv[1],
POP_USER)) {
312 if (!argv[3])
exit(2);
313 maildirname = argv[2];
317 if (!argv[3])
exit(2);
318 authsocket = argv[2];
321 if (!argv[5])
exit(2);
325 if (!argv[3])
exit(2);
328 if (!argv[5])
exit(2);
329 authsocket = argv[4];
339 while ((r == -1) && (errno == EINTR));
340 if (r == -1)
exit(111);
348 if (i == buflen)
exit(2);
350 if (i == buflen)
exit(2);
352 if (i == buflen)
exit(2);
354 if (i == buflen)
exit(2);
357 authlen = str_len(authuser);
358 if (!stralloc_copyb(&
user,authuser,authlen))
exit(111);
360 if ((i = byte_rchr(authuser,authlen,
'@')))
361 if (i < authlen && authuser[i] ==
'@') {
364 case_lowerb(
domain,domlen);
366 if (!stralloc_copyb(&
user,authuser,i))
exit(111);
383 if (!stralloc_catb(&
disabled,authuser,authlen))
exit(111);
397 if (!authpass && domlen)
404 if (!authpass)
exit(1);
406 if (str_len(authpass) == 1) {
407 switch (authpass[0]) {
409 case '+':
if (popuser)
413 case '&':
if (popuser)
417 case '=': rc =
auth_dovecot(authuser,response,authsocket,service);
break;
418 default: rc = 2;
break;
421 switch (authpass[0]) {
422 case '%': rc =
auth_hash(authpass + 1,response);
break;
425 if ((rc =
auth_apop(authpass,response,challenge)) == 0) {
428 }
else rc =
auth_cram(authpass,response,challenge);
437 if (authsocket && service) pathexec(argv + 5);
438 if (authsocket || service || popuser) pathexec(argv + 3);
439 else pathexec(argv + 1);
int constmap_init(struct constmap *cm, char *s, int len, int flagcolon)
int control_readfile(stralloc *sa, char *fn, int flagme)
int stralloc_copys(stralloc *, char const *)
void hmac_md5(unsigned char *text, int text_len, unsigned char *key, int key_len, unsigned char *digest)
void MD5Init(MD5_CTX *context)
void MD5Final(digest, MD5_CTX *context)
void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputLen)
void exit(int fail)
Supported storage methods: (1) authuser:[=]plainpasswd, (2) authuser:hashpasswd, (3) authuser:?...
int auth_unix(char *user, char *response)
int auth_md5(char *pwdhash, char *response)
int auth_wrapper(char *pam, char *arg1, char *arg2, char *auth, int len)
struct constmap mapauthuser
int auth_apop(unsigned char *password, unsigned char *response, unsigned char *challenge)
int auth_sha1(char *pwdhash, char *response)
int dig_ascii(char *digascii, const char *digest, const int len)
int auth_hash(char *password, char *response)
int auth_sha256(char *pwdhash, char *response)
int auth_dovecot(char *user, char *response, char *socket, char *service)
void sha1_hash(char *hash, const char *data, uint32_t len)
void sha256_hash(char *hash, const char *data, size_t len)