1 diff -u --new-file qmail-1.03-orig/base64.c qmail-1.03/base64.c
2 --- qmail-1.03-orig/base64.c 1969-12-31 21:00:00.000000000 -0300
3 +++ qmail-1.03/base64.c 2006-03-21 18:40:50.000000000 -0300
10 +static char *b64alpha =
11 + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
14 +/* returns 0 ok, 1 illegal, -1 problem */
16 +int b64decode(in,l,out)
17 +const unsigned char *in;
19 +stralloc *out; /* not null terminated */
30 + if (!stralloc_copys(out,"")) return -1;
34 + while(in[l-1] == B64PAD) {
40 + out->len = (n * 3) - p;
41 + if (!stralloc_ready(out,out->len)) return -1;
44 + for(i = 0; i < n - 1 ; i++) {
46 + for(j = 0; j < 4; j++) {
47 + if(in[j] >= 'A' && in[j] <= 'Z')
48 + x = (x << 6) + (unsigned int)(in[j] - 'A' + 0);
49 + else if(in[j] >= 'a' && in[j] <= 'z')
50 + x = (x << 6) + (unsigned int)(in[j] - 'a' + 26);
51 + else if(in[j] >= '0' && in[j] <= '9')
52 + x = (x << 6) + (unsigned int)(in[j] - '0' + 52);
53 + else if(in[j] == '+')
55 + else if(in[j] == '/')
57 + else if(in[j] == '=')
61 + s[2] = (unsigned char)(x & 255); x >>= 8;
62 + s[1] = (unsigned char)(x & 255); x >>= 8;
63 + s[0] = (unsigned char)(x & 255); x >>= 8;
68 + for(j = 0; j < 4; j++) {
69 + if(in[j] >= 'A' && in[j] <= 'Z')
70 + x = (x << 6) + (unsigned int)(in[j] - 'A' + 0);
71 + else if(in[j] >= 'a' && in[j] <= 'z')
72 + x = (x << 6) + (unsigned int)(in[j] - 'a' + 26);
73 + else if(in[j] >= '0' && in[j] <= '9')
74 + x = (x << 6) + (unsigned int)(in[j] - '0' + 52);
75 + else if(in[j] == '+')
77 + else if(in[j] == '/')
79 + else if(in[j] == '=')
83 + b[2] = (unsigned char)(x & 255); x >>= 8;
84 + b[1] = (unsigned char)(x & 255); x >>= 8;
85 + b[0] = (unsigned char)(x & 255); x >>= 8;
87 + for(i = 0; i < 3 - p; i++)
93 +int b64encode(in,out)
95 +stralloc *out; /* not null terminated */
97 + unsigned char a, b, c;
103 + if (!stralloc_copys(out,"")) return -1;
107 + if (!stralloc_ready(out,in->len / 3 * 4 + 4)) return -1;
110 + for (i = 0;i < in->len;i += 3) {
112 + b = i + 1 < in->len ? in->s[i + 1] : 0;
113 + c = i + 2 < in->len ? in->s[i + 2] : 0;
115 + *s++ = b64alpha[a >> 2];
116 + *s++ = b64alpha[((a & 3 ) << 4) | (b >> 4)];
118 + if (i + 1 >= in->len) *s++ = B64PAD;
119 + else *s++ = b64alpha[((b & 15) << 2) | (c >> 6)];
121 + if (i + 2 >= in->len) *s++ = B64PAD;
122 + else *s++ = b64alpha[c & 63];
124 + out->len = s - out->s;
127 diff -u --new-file qmail-1.03-orig/base64.h qmail-1.03/base64.h
128 --- qmail-1.03-orig/base64.h 1969-12-31 21:00:00.000000000 -0300
129 +++ qmail-1.03/base64.h 2006-03-21 18:40:50.000000000 -0300
134 +extern int b64decode();
135 +extern int b64encode();
138 diff -u --new-file qmail-1.03-orig/case_startb.c qmail-1.03/case_startb.c
139 --- qmail-1.03-orig/case_startb.c 1969-12-31 21:00:00.000000000 -0300
140 +++ qmail-1.03/case_startb.c 2006-03-21 18:40:50.000000000 -0300
144 +int case_startb(s,len,t)
149 + register unsigned char x;
150 + register unsigned char y;
154 + if (y <= 'Z' - 'A') y += 'a'; else y += 'A';
156 + if (!len) return 0;
159 + if (x <= 'Z' - 'A') x += 'a'; else x += 'A';
160 + if (x != y) return 0;
163 diff -u --new-file qmail-1.03-orig/FILES.auth qmail-1.03/FILES.auth
164 --- qmail-1.03-orig/FILES.auth 1969-12-31 21:00:00.000000000 -0300
165 +++ qmail-1.03/FILES.auth 2006-03-21 18:40:50.000000000 -0300
167 +The qmail-smtpd Auth patch modifies the following QMAIL 1.03 files:
184 +Informational files:
186 +% install_auth.sh (Installation shell script)
187 +% LICENSE.authentication (some sort of ...)
189 +% README.auth.old (old description of SMTP Auth)
190 +% README.qmail-remote-auth (ASCII version of Bjoern Kalkbrenner index.html)
191 diff -u --new-file qmail-1.03-orig/install_authentication.sh qmail-1.03/install_authentication.sh
192 --- qmail-1.03-orig/install_authentication.sh 1969-12-31 21:00:00.000000000 -0300
193 +++ qmail-1.03/install_authentication.sh 2006-03-21 18:40:50.000000000 -0300
197 +# qmail-smtpd AUTH (UN)INSTALL Script (install_auth.sh)
198 +# -----------------------------------------------------
200 +# Purpose: To install and uninstall the qmail-smtpd Authentication Patch
202 +# Parameters: -u (uninstall)
203 +# VRF (Version to be uninstalled)
205 +# Usage: ./install_auth.sh [-u] [Version]
207 +# Installation: ./install_auth.sh
208 +# Uninstallation: ./install_auth.sh -u 105
210 +# Return Codes: 0 - Patches applied successfully
211 +# 1 - Original QMAIL files not found (Patch not extracted in QMAIL source directory)
212 +# 2 - Patch files not found
214 +# Output: install_auth.log
216 +# History: 1.0.0 - Erwin Hoffmann - Initial release
217 +# 1.0.1 - - grep fix; Gentoo fix
218 +# 1.0.2 - removed '-v' optio for cp
219 +# 1.0.3 - mods for 'qmail authentication'
221 +#---------------------------------------------------------------------------------------
225 +QMAILHOME=$(head -n 1 conf-qmail)
226 +SOLARIS=$(sh ./find-systype.sh | grep -ci "SunOS")
230 +REL=064 # Should be identical to qmail AUTH level
234 +if [ $# -eq 0 ] ; then
236 + echo "Installing qmail-smtpd AUTH $REL (Build $BUILD) at $DATE <<<" | tee -a $LOGFILE 2>&1
238 + for FILE in $(grep "^= " ${TARGETS} | awk '{print $2}'); do
239 + echo "Targeting file $FILE ..." | tee -a $LOGFILE 2>&1
240 + if [ -s ${FILE} ] ; then
241 + cp ${FILE} ${FILE}.$REL | tee -a $LOGFILE 2>&1
242 + echo "--> ${FILE} copied to ${FILE}.$REL" | tee -a $LOGFILE 2>&1
244 + echo "${FILE} not found !"
247 + if [ -s ${FILE}.patch ] ; then
248 + if [ ${SOLARIS} -gt 0 ]; then
249 + echo "--> Patching qmail source file ${FILE} for Solaris ...." | tee -a $LOGFILE 2>&1
250 + patch -i ${FILE}.patch ${FILE} 2>&1 | tee -a $LOGFILE
252 + echo "--> Patching qmail source file ${FILE} ...." | tee -a $LOGFILE 2>&1
253 + patch ${FILE} ${FILE}.patch 2>&1 | tee -a $LOGFILE
256 + echo "!! ${FILE}.patch not found !"
262 + echo "Copying documentation and samples to ${QMAILHOME}/doc/ ..." | tee -a $LOGFILE 2>&1
264 + cp README.auth* ${QMAILHOME}/doc/ | tee -a $LOGFILE 2>&1
266 + echo "If you dont wont CRAM-MD5 suport disable '#define CRAM_MD5' in qmail-smtpd !"
267 + echo "Installation of qmail authentication $REL (Build $BUILD) finished at $DATE <<<" | tee -a $LOGFILE 2>&1
269 +# Now go for the uninstallation....
271 +elif [ "$1" = "-u" ] ; then
273 +# Get the Version Number from INPUT
275 + if [ $# -eq 2 ] ; then
279 + echo "De-installing qmail authentication $REL (Build $BUILD) at $DATE <<<" | tee -a $LOGFILE 2>&1
281 + for FILE in $(grep "^= " ${TARGETS} | awk '{print $2}'); do
282 + echo "Targeting file $FILE ..." | tee -a $LOGFILE 2>&1
283 + if [ -s ${FILE}.$REL ] ; then
284 + mv ${FILE}.$REL ${FILE} | tee -a $LOGFILE 2>&1
286 + echo "--> ${FILE}.$REL moved to ${FILE}" | tee -a $LOGFILE 2>&1
288 + echo "!! ${FILE}.$REL not found !"
291 + echo "De-installation of qmail authentication $REL (Build $BUILD) finished at $DATE <<<" | tee -a $LOGFILE 2>&1
295 diff -u --new-file qmail-1.03-orig/LICENSE.authentication qmail-1.03/LICENSE.authentication
296 --- qmail-1.03-orig/LICENSE.authentication 1969-12-31 21:00:00.000000000 -0300
297 +++ qmail-1.03/LICENSE.authentication 2006-03-21 18:40:50.000000000 -0300
303 + Dr. Erwin Hoffmann - FEHCom Germany
305 + http://www.fehcom.de/qmail.html
313 +qmail AUTHENTICATION is free software.
315 + You can download and use qmail AUTHENTICATION (and parts of it) as you like.
316 + You can modify the source code without notification to or permission by the author.
318 + http://www.cr.yp.to/softwarelaw.html
324 +qmail AUTHENTICATION patches (modifies) parts of the qmail-1.03 source files.
325 +It should only be applied against the source as supplied by D.J. Bernstein.
331 +The Author does not guarantee a specific fitness of qmail AUTHENTICATION.
332 +If you use qmail AUTHENTICATION, it's on your own risk.
338 +qmail AUTHENTICATION may be included in ports and packages under the following conditions:
339 + The port/package has to show the current version number of qmail AUTHENTICATION.
340 + All files (namely this) have to be included.
342 diff -u --new-file qmail-1.03-orig/Makefile qmail-1.03/Makefile
343 --- qmail-1.03-orig/Makefile 2006-03-21 18:39:35.000000000 -0300
344 +++ qmail-1.03/Makefile 2006-03-21 18:44:49.000000000 -0300
347 ./compile auto_usera.c
350 +compile base64.c base64.h stralloc.h substdio.h str.h
356 @@ -1456,12 +1460,12 @@
357 load qmail-remote.o control.o timeoutread.o timeoutwrite.o \
358 timeoutconn.o constmap.o tcpto.o now.o dns.o ip.o ipalloc.o ipme.o quote.o \
359 ndelay.a case.a sig.a open.a lock.a seek.a getln.a stralloc.a alloc.a \
360 -substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib
361 +substdio.a error.a str.a fs.a auto_qmail.o dns.lib base64.o socket.lib
362 ./load qmail-remote control.o timeoutread.o \
363 timeoutwrite.o timeoutconn.o constmap.o tcpto.o now.o dns.o ip.o \
364 ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
365 lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
366 - str.a fs.a auto_qmail.o `cat dns.lib` `cat socket.lib`
367 + str.a fs.a auto_qmail.o base64.o `cat dns.lib` `cat socket.lib`
371 @@ -1551,13 +1555,13 @@
373 date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
374 open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \
375 -fs.a auto_qmail.o socket.lib
376 +fs.a auto_qmail.o base64.o socket.lib
377 ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
378 timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
380 received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
381 datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
382 - alloc.a substdio.a error.a str.a fs.a auto_qmail.o `cat \
383 + alloc.a substdio.a error.a str.a fs.a auto_qmail.o base64.o `cat \
387 @@ -1569,7 +1573,7 @@
388 substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
389 error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \
390 substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
391 -exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h
392 +exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h base64.h
393 ./compile qmail-smtpd.c
396 Subdirectorios comunes: qmail-1.03-orig/qmail-rhinit y qmail-1.03/qmail-rhinit
397 diff -u --new-file qmail-1.03-orig/qmail-smtpd.8 qmail-1.03/qmail-smtpd.8
398 --- qmail-1.03-orig/qmail-smtpd.8 2006-03-21 18:39:35.000000000 -0300
399 +++ qmail-1.03/qmail-smtpd.8 2006-03-21 18:46:16.000000000 -0300
404 -supports ESMTP, including the 8BITMIME and PIPELINING options.
405 +supports ESMTP, including the 8BITMIME, DATA, PIPELINING, SIZE, and AUTH options.
407 +includes a \'MAIL FROM:\' parameter parser and obeys \'Auth\' and \'Size\' advertisements.
409 +can accept LOGIN, PLAIN, and CRAM-MD5 AUTH types. It invokes
411 +which reads on file descriptor 3 the username, a 0 byte, the password
412 +or CRAM-MD5 digest/response derived from the SMTP client,
413 +another 0 byte, a CRAM-MD5 challenge (if applicable to the AUTH type),
418 +upon successful authentication, which should in turn return 0 to
420 +effectively setting the environment variables $RELAYCLIENT and $TCPREMOTEINFO
421 +(any supplied value replaced with the authenticated username).
423 +will reject the authentication attempt if it receives a nonzero return
431 converts the SMTP newline convention into the UNIX newline convention
432 diff -u --new-file qmail-1.03-orig/qmail-smtpd.c qmail-1.03/qmail-smtpd.c
433 --- qmail-1.03-orig/qmail-smtpd.c 2006-03-21 18:39:35.000000000 -0300
434 +++ qmail-1.03/qmail-smtpd.c 2006-03-21 18:53:10.000000000 -0300
436 #include "timeoutwrite.h"
437 #include "commands.h"
438 #include "ucspitls.h"
445 unsigned int databytes = 0;
447 void die_control() { out("421 unable to read controls (#4.3.0)\r\n"); flush(); _exit(1); }
448 void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); }
449 void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); }
450 +void err_size() { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); }
451 void die_syserr() { out("421 system error (#4.3.0)\r\n"); flush(); _exit(1); }
453 void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
455 void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); }
456 void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); }
458 +int err_child() { out("454 oops, problem with child and I can't auth (#4.3.0)\r\n"); return -1; }
459 +int err_fork() { out("454 oops, child won't start and I can't auth (#4.3.0)\r\n"); return -1; }
460 +int err_pipe() { out("454 oops, unable to open pipe and I can't auth (#4.3.0)\r\n"); return -1; }
461 +int err_write() { out("454 oops, unable to write pipe and I can't auth (#4.3.0)\r\n"); return -1; }
462 +void err_authd() { out("503 you're already authenticated (#5.5.0)\r\n"); }
463 +void err_authmail() { out("503 no auth during mail transaction (#5.5.0)\r\n"); }
464 +int err_noauth() { out("504 auth type unimplemented (#5.5.1)\r\n"); return -1; }
465 +int err_authabrt() { out("501 auth exchange canceled (#5.0.0)\r\n"); return -1; }
466 +int err_input() { out("501 malformed auth input (#5.5.4)\r\n"); return -1; }
467 +void err_authfail() { out("535 authentication failed (#5.7.1)\r\n"); }
469 stralloc greeting = {0};
472 smtp_greet("221 "); out("\r\n"); flush(); _exit(0);
480 if (x) { scan_ulong(x,&u); databytes = u; }
481 if (!(databytes + 1)) --databytes;
484 remoteip = env_get("TCPREMOTEIP");
485 if (!remoteip) remoteip = "unknown";
486 local = env_get("TCPLOCALHOST");
490 int flagbarf; /* defined if seenmail */
492 stralloc mailfrom = {0};
493 stralloc rcptto = {0};
494 +stralloc fuser = {0};
495 +stralloc mfparms = {0};
497 +int mailfrom_size(arg) char *arg;
500 + unsigned long sizebytes = 0;
502 + scan_ulong(arg,&r);
504 + if (databytes) if (sizebytes > databytes) return 1;
508 +void mailfrom_auth(arg,len)
514 + if (!stralloc_copys(&fuser,"")) die_nomem();
515 + if (case_starts(arg,"<>")) { if (!stralloc_cats(&fuser,"unknown")) die_nomem(); }
519 + if (case_starts(arg,"+3D")) { arg=arg+2; len=len-2; if (!stralloc_cats(&fuser,"=")) die_nomem(); }
520 + if (case_starts(arg,"+2B")) { arg=arg+2; len=len-2; if (!stralloc_cats(&fuser,"+")) die_nomem(); }
523 + if (!stralloc_catb(&fuser,arg,1)) die_nomem();
526 + if(!stralloc_0(&fuser)) die_nomem();
528 + remoteinfo = fuser.s;
529 + if (!env_unset("TCPREMOTEINFO")) die_read();
530 + if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
534 +void mailfrom_parms(arg) char *arg;
539 + len = str_len(arg);
540 + if (!stralloc_copys(&mfparms,"")) die_nomem;
541 + i = byte_chr(arg,len,'>');
542 + if (i > 4 && i < len) {
545 + if (*arg == ' ' || *arg == '\0' ) {
546 + if (case_starts(mfparms.s,"SIZE=")) if (mailfrom_size(mfparms.s+5)) { flagsize = 1; return; }
547 + if (case_starts(mfparms.s,"AUTH=")) mailfrom_auth(mfparms.s+5,mfparms.len-5);
548 + if (!stralloc_copys(&mfparms,"")) die_nomem;
551 + if (!stralloc_catb(&mfparms,arg,1)) die_nomem;
556 void smtp_helo(arg) char *arg;
558 @@ -233,10 +312,21 @@
560 void smtp_ehlo(arg) char *arg;
562 - smtp_greet("250-");
564 + char size[FMT_ULONG];
565 + size[fmt_ulong(size,(unsigned int) databytes)] = 0;
566 + smtp_greet("250-");
567 if (tls_available && !tls_started)
568 out("\r\n250-STARTTLS");
569 - out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
570 + out("\r\n250-PIPELINING\r\n250-8BITMIME\r\n");
571 + out("250-SIZE "); out(size); out("\r\n");
573 + out("250-AUTH=LOGIN PLAIN CRAM-MD5\r\n");
574 + out("250 AUTH LOGIN PLAIN CRAM-MD5\r\n");
576 + out("250-AUTH=LOGIN PLAIN\r\n");
577 + out("250 AUTH LOGIN PLAIN\r\n");
579 seenmail = 0; dohelo(arg);
583 void smtp_mail(arg) char *arg;
585 if (!addrparse(arg)) { err_syntax(); return; }
587 + mailfrom_parms(arg);
588 + if (flagsize) { err_size(); return; }
589 flagbarf = bmfcheck();
591 if (!stralloc_copys(&rcptto,"")) die_nomem();
594 out("354 go ahead\r\n");
596 - received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo);
597 + received(&qqt,protocol,local,remoteip,remotehost,remoteinfo,fakehelo);
599 hops = (hops >= MAXHOPS);
600 if (hops) qmail_fail(&qqt);
601 @@ -411,16 +502,244 @@
602 qqx = qmail_close(&qqt);
603 if (!*qqx) { acceptmessage(qp); return; }
604 if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; }
605 - if (databytes) if (!bytestooverflow) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return; }
606 + if (databytes) if (!bytestooverflow) { err_size(); return; }
607 if (*qqx == 'D') out("554 "); else out("451 ");
612 +/* this file is too long ----------------------------------------- SMTP AUTH */
614 +char unique[FMT_ULONG + FMT_ULONG + 3];
615 +static stralloc authin = {0}; /* input from SMTP client */
616 +static stralloc user = {0};
617 +static stralloc pass = {0}; /* plain passwd or digest */
618 +static stralloc resp = {0}; /* b64 response */
620 +static stralloc chal = {0}; /* plain challenge */
621 +static stralloc slop = {0}; /* b64 challenge */
626 +char ssauthbuf[512];
627 +substdio ssauth = SUBSTDIO_FDBUF(safewrite,3,ssauthbuf,sizeof(ssauthbuf));
629 +int authgetl(void) {
632 + if (!stralloc_copys(&authin,"")) die_nomem();
634 + if (!stralloc_readyplus(&authin,1)) die_nomem(); /* XXX */
635 + i = substdio_get(&ssin,authin.s + authin.len,1);
636 + if (i != 1) die_read();
637 + if (authin.s[authin.len] == '\n') break;
641 + if (authin.len > 0) if (authin.s[authin.len - 1] == '\r') --authin.len;
642 + authin.s[authin.len] = 0;
643 + if (*authin.s == '*' && *(authin.s + 1) == 0) { return err_authabrt(); }
644 + if (authin.len == 0) { return err_input(); }
648 +int authenticate(void)
654 + if (!stralloc_0(&user)) die_nomem();
655 + if (!stralloc_0(&pass)) die_nomem();
657 + if (!stralloc_0(&chal)) die_nomem();
660 + if (pipe(pi) == -1) return err_pipe();
661 + switch(child = fork()) {
666 + if(fd_copy(3,pi[0]) == -1) return err_pipe();
668 + execvp(*childargs, childargs);
673 + substdio_fdbuf(&ssauth,write,pi[1],ssauthbuf,sizeof ssauthbuf);
674 + if (substdio_put(&ssauth,user.s,user.len) == -1) return err_write();
675 + if (substdio_put(&ssauth,pass.s,pass.len) == -1) return err_write();
677 + if (substdio_put(&ssauth,chal.s,chal.len) == -1) return err_write();
679 + if (substdio_flush(&ssauth) == -1) return err_write();
683 + if (!stralloc_copys(&chal,"")) die_nomem();
684 + if (!stralloc_copys(&slop,"")) die_nomem();
686 + byte_zero(ssauthbuf,sizeof ssauthbuf);
687 + if (wait_pid(&wstat,child) == -1) return err_child();
688 + if (wait_crashed(wstat)) return err_child();
689 + if (wait_exitcode(wstat)) { sleep(AUTHSLEEP); return 1; } /* no */
690 + return 0; /* yes */
693 +int auth_login(arg) char *arg;
698 + if (r = b64decode(arg,str_len(arg),&user) == 1) return err_input();
701 + out("334 VXNlcm5hbWU6\r\n"); flush(); /* Username: */
702 + if (authgetl() < 0) return -1;
703 + if (r = b64decode(authin.s,authin.len,&user) == 1) return err_input();
705 + if (r == -1) die_nomem();
707 + out("334 UGFzc3dvcmQ6\r\n"); flush(); /* Password: */
709 + if (authgetl() < 0) return -1;
710 + if (r = b64decode(authin.s,authin.len,&pass) == 1) return err_input();
711 + if (r == -1) die_nomem();
713 + if (!user.len || !pass.len) return err_input();
714 + return authenticate();
717 +int auth_plain(arg) char *arg;
722 + if (r = b64decode(arg,str_len(arg),&resp) == 1) return err_input();
725 + out("334 \r\n"); flush();
726 + if (authgetl() < 0) return -1;
727 + if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input();
729 + if (r == -1 || !stralloc_0(&resp)) die_nomem();
730 + while (resp.s[id]) id++; /* "authorize-id\0userid\0passwd\0" */
732 + if (resp.len > id + 1)
733 + if (!stralloc_copys(&user,resp.s + id + 1)) die_nomem();
734 + if (resp.len > id + user.len + 2)
735 + if (!stralloc_copys(&pass,resp.s + id + user.len + 2)) die_nomem();
737 + if (!user.len || !pass.len) return err_input();
738 + return authenticate();
747 + s = unique; /* generate challenge */
748 + s += fmt_uint(s,getpid());
750 + s += fmt_ulong(s,(unsigned long) now());
753 + if (!stralloc_copys(&chal,"<")) die_nomem();
754 + if (!stralloc_cats(&chal,unique)) die_nomem();
755 + if (!stralloc_cats(&chal,local)) die_nomem();
756 + if (!stralloc_cats(&chal,">")) die_nomem();
757 + if (b64encode(&chal,&slop) < 0) die_nomem();
758 + if (!stralloc_0(&slop)) die_nomem();
760 + out("334 "); /* "334 base64_challenge \r\n" */
765 + if (authgetl() < 0) return -1; /* got response */
766 + if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input();
767 + if (r == -1 || !stralloc_0(&resp)) die_nomem();
769 + i = str_chr(resp.s,' ');
771 + while (*s == ' ') ++s;
773 + if (!stralloc_copys(&user,resp.s)) die_nomem(); /* userid */
774 + if (!stralloc_copys(&pass,s)) die_nomem(); /* digest */
776 + if (!user.len || !pass.len) return err_input();
777 + return authenticate();
785 + { "login",auth_login }
786 +, { "plain",auth_plain }
788 +, { "cram-md5",auth_cram }
799 + if (!*childargs) { out("503 auth not available (#5.3.3)\r\n"); return; }
800 + if (flagauth) { err_authd(); return; }
801 + if (seenmail) { err_authmail(); return; }
803 + if (!stralloc_copys(&user,"")) die_nomem();
804 + if (!stralloc_copys(&pass,"")) die_nomem();
805 + if (!stralloc_copys(&resp,"")) die_nomem();
807 + if (!stralloc_copys(&chal,"")) die_nomem();
810 + i = str_chr(cmd,' ');
812 + while (*arg == ' ') ++arg;
815 + for (i = 0;authcmds[i].text;++i)
816 + if (case_equals(authcmds[i].text,cmd)) break;
818 + switch (authcmds[i].fun(arg)) {
821 + protocol = "ESMTPA";
823 + remoteinfo = user.s;
824 + if (!env_unset("TCPREMOTEINFO")) die_read();
825 + if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
826 + if (!env_put2("RELAYCLIENT",relayclient)) die_nomem();
827 + out("235 ok, go ahead (#2.0.0)\r\n");
830 + err_authfail(user.s,authcmds[i].text);
835 +/* this file is too long --------------------------------------------- GO ON */
839 struct commands smtpcommands[] = {
840 { "rcpt", smtp_rcpt, 0 }
841 , { "mail", smtp_mail, 0 }
842 , { "data", smtp_data, flush }
843 +, { "auth", smtp_auth, flush }
844 , { "quit", smtp_quit, flush }
845 , { "helo", smtp_helo, flush }
846 , { "ehlo", smtp_ehlo, flush }
848 , { 0, err_unimpl, flush }
852 +void main(argc,argv)
856 + childargs = argv + 1;
858 if (chdir(auto_qmail) == -1) die_control();
860 diff -u --new-file qmail-1.03-orig/README.auth qmail-1.03/README.auth
861 --- qmail-1.03-orig/README.auth 1969-12-31 21:00:00.000000000 -0300
862 +++ qmail-1.03/README.auth 2006-03-21 18:40:50.000000000 -0300
864 +README qmail Authentication
865 +===========================
871 +This patch supports RFC 2554 "SMTP Service Extension for Authentication" for
873 +- qmail-smtpd (AUTH types LOGIN, PLAIN, and CRAM-MD5) and
874 +- qmail-remote (AUTH types LOGIN, PLAIN).
876 +Additionally, RFC 1870 is honoured ("SMTP Service Extension for Message Size Declaration").
877 +For more technical details see: http://www.fehcom.de/qmail/docu/smtpauth.html.
883 +This patch was based on Krzysztof Dabrowski's qmail-smtpd-auth-0.31 patch
884 +which itself uses "Mrs. Brisby's" initial code.
885 +Version 0.41 of this patch fixes the "CAPS-LOCK" typo announcing
886 +'CRAM_MD5' instead of 'CRAM-MD5' (german keyboard) - tx to Mike Garrison.
887 +Version 0.42 fixes the '421 unable to read controls (#4.3.0)' problem
888 +(can't read control/morercpthosts.cdb) because FD 3 was already closed - tx Richard Lyons.
889 +Version 0.43 fixes the ba64decode() failure in case CRAM_MD5 is not enabled - tx Vladimir Zidar.
890 +Version 0.51 includes the evaluation of the 'Auth' and the 'Size' parameter in the 'Mail From:' command.
891 +Version 0.52 uses DJB functions to copy FDs.
892 +Version 0.56 corrects some minor mistakes displaying the 'Auth' userid.
893 +Version 0.57 uses keyword "ESMTPA" in Received header in case of authentication to comply with RFC 3848.
895 +Starting with version 0.60 the patch includes the qmail-smtp-auth-send enhancement
896 +from Bjoern Kalkbrenner to support SMTP autentication for qmail-remote.
902 +* Untar the source in the qmail-1.03 home directory.
903 +* Run ./install_authentication.
904 +* Modify the compile time option "#define CRAM_MD5" to your needs.
908 +Setup for qmail-smtpd:
909 +----------------------
911 +In order to use SMTP Authentication you have to use a 'Pluggable Authentication Module'
912 +PAM to be called by qmail-smtpd; typically
914 + /var/qmail/bin/qmail-smtpd /bin/checkpassword true 2>&1
916 +Since qmail-smtpd does not run as root, checkpassword has to be made sticky.
917 +There is no need to include additionally the hostname in the call.
918 +In order to compute the CRAM-MD5 challenge, qmail-smtpd uses the 'tcplocalhost' information.
921 +Setup for qmail-remote:
922 +-----------------------
924 +See man page qmail-remote.
926 +A control file control/authsenders has to be generated and populated accordingly.
929 +Changes wrt. Krysztof Dabrowski's patch:
930 +----------------------------------------
932 +* Avoid the 'hostname' in the call of the PAM.
933 +* Confirm to Dan Bernstein's checkpassword interface even for CRAM-MD5.
934 +* Doesn't close FD 2; thus not inhibiting logging to STDERR.
935 +* Fixed bugs in base64.c.
936 +* Modified unconditional close of FD 3 in order to sustain reading of 'control/morecpthosts.cdb'.
937 +* Evaluation of the (informational) Mail From: < > Auth=username.
938 +* Additional support for the advertised "Size" via 'Mail From: <return-path> SIZE=123456780' (RFC 1870).
939 +* RFC 3848 conformance for Received header in case of SMTP Auth.
942 +Changes wrt. Bjoern Kalkbrenner's patch:
943 +----------------------------------------
945 +* Included AUTH PLAIN support.
946 +* Fixed wrong use of 'MAIL FROM: <return-path> AUTH=user'.
948 +* Renamed "smtproutes_user" to "authsenders".
949 +* Added man page for qmail-remote including AUTH behaviour.
950 +* Modified qmail-control man page to include "authsenders".
951 +* Modified qmail-showctl to parse "authsenders".
957 +0.6.0 includes SMTP authentication for qmail-remote.
958 +0.6.1 Initial Version: Transmitts 'user' in Mail From: as xtext; flexible AUTH recognition.
959 +0.6.2 Auth plain: mailfrom\0user-id\0password; thus authorization-id is the Return-Path.
960 +0.6.3 Compliance with RFC 3848 (synced with qmail-auth-smtpd.057).
961 +0.6.4 FIXED a bug in PLAIN checking for the wrong SMTP Reply code
962 + FIXED a bug in the evaluation of the SENDER (tx. Benjamin Meyer).
965 +Erwin Hoffmann - Cologne 2005-06-27 (www.fehcom.de)
968 diff -u --new-file qmail-1.03-orig/README.qmail-remote-auth qmail-1.03/README.qmail-remote-auth
969 --- qmail-1.03-orig/README.qmail-remote-auth 1969-12-31 21:00:00.000000000 -0300
970 +++ qmail-1.03/README.qmail-remote-auth 2006-03-21 18:40:50.000000000 -0300
972 ++++++++++++++++++++++++++++
974 ++ THIS FILE IS OBSOLETE +
976 ++++++++++++++++++++++++++++
979 +Qmail 1.03 qmail-remote.c SMTP-AUTH send patch
982 + * Version: 0.0.1 ;)
983 + * Author: Bjoern Kalkbrenner
984 + * Location: Home | Download
988 + 1. Copy the base64.c and base64.h to your qmail source and chdir into it.
989 + 2. Patch the source with patch -p1 <smtp-auth-send.patch
990 + 3. make setup check
991 + 4. ...follow the qmail-installation or copy your new qmail-remote to
993 + 5. create your /var/qmail/control/smtproutes_users
997 +This patch is based on Robert Sander's AUTH LOGIN patch which is based on
998 +the qmail-smtpd-auth patch which itself is based on the patch from Mrs.
1002 +I made this patch because my ISP also switched to AUTH LOGIN on his SMTP
1003 +relay and we are using an internal linux qmail server in our company, but
1004 +the patch Robert wrote was only working for 1 user. . Several users use
1005 +this ISP for outgoing mail, mails are fetched with fetchmail, (scanned for
1006 +viruses) and send to the local mailaccounts which is used as relay. Now it
1007 +is easy for us to internal mailaccounts mapped to the external mailservers.
1008 +You can even select the outgoing mailserver with the smtproutes_users file.
1010 +The username and password for the remote smtp relay are stored in
1011 +/var/qmail/control/smtproutes_users (new controlfile!) separated with pipes
1012 +after the entry for the relay server.
1016 +mail@example.com:smtp.example.com|example.com1|examplePasswd
1017 +info@example.com:smtp.example.com|example.com2|anotherPasswd
1019 +mailuser-examples sending to port 26
1020 +anotherport@example.com:smtp.example.com:26|example.com3|justfoobar
1022 +#default, not sure if this entry is used, untested!!!!!! Maybe i had to
1024 +:relay.provider.com|username|password
1026 +Password has to be stored in cleartext. This is maybe not bug-free, but
1029 +It works for me, no guarantee...
1030 diff -u --new-file qmail-1.03-orig/TARGETS qmail-1.03/TARGETS
1031 --- qmail-1.03-orig/TARGETS 2006-03-21 18:39:35.000000000 -0300
1032 +++ qmail-1.03/TARGETS 2006-03-21 18:53:38.000000000 -0300