diff options
Diffstat (limited to 'mail-mta/qmail/files/1.03-r8/qmail-1.03-starttls-smtp-auth.patch')
-rw-r--r-- | mail-mta/qmail/files/1.03-r8/qmail-1.03-starttls-smtp-auth.patch | 1408 |
1 files changed, 0 insertions, 1408 deletions
diff --git a/mail-mta/qmail/files/1.03-r8/qmail-1.03-starttls-smtp-auth.patch b/mail-mta/qmail/files/1.03-r8/qmail-1.03-starttls-smtp-auth.patch deleted file mode 100644 index 1a427fb55b62..000000000000 --- a/mail-mta/qmail/files/1.03-r8/qmail-1.03-starttls-smtp-auth.patch +++ /dev/null @@ -1,1408 +0,0 @@ - -A word of warning: the TLS part of this patch is not type-safe at -at least one point (hey, I didn't write it.) I don't think this -causes problems on i386 architectures, but it made qmail-smtpd -crash frequently on an Alpha. Commenting out the substdio_fdbuf(...); -call in qmail-smtpd appears to fix the issue. - -diff -urP qmail-1.03-vanilla/Makefile qmail-1.03-tls-auth/Makefile ---- qmail-1.03-vanilla/Makefile Mon Jun 15 05:53:16 1998 -+++ qmail-1.03-tls-auth/Makefile Wed Jun 19 16:09:58 2002 -@@ -136,6 +136,10 @@ - compile auto_usera.c - ./compile auto_usera.c - -+base64.o: \ -+compile base64.c base64.h stralloc.h substdio.h str.h -+ ./compile base64.c -+ - binm1: \ - binm1.sh conf-qmail - cat binm1.sh \ -@@ -1446,7 +1450,8 @@ - timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \ - ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \ - lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \ -- str.a fs.a auto_qmail.o `cat dns.lib` `cat socket.lib` -+ str.a fs.a auto_qmail.o `cat dns.lib` `cat socket.lib` \ -+ -lssl -lcrypto - - qmail-remote.0: \ - qmail-remote.8 -@@ -1536,13 +1541,13 @@ - timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \ - date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \ - open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \ --fs.a auto_qmail.o socket.lib -+fs.a auto_qmail.o base64.o socket.lib - ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \ - timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \ - received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \ - datetime.a getln.a open.a sig.a case.a env.a stralloc.a \ -- alloc.a substdio.a error.a str.a fs.a auto_qmail.o `cat \ -- socket.lib` -+ alloc.a substdio.a error.a str.a fs.a auto_qmail.o base64.o `cat \ -+ socket.lib` -lssl -lcrypto - - qmail-smtpd.0: \ - qmail-smtpd.8 -@@ -1553,7 +1558,8 @@ - substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \ - error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \ - substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \ --exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h -+exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h wait.h \ -+fd.h base64.h - ./compile qmail-smtpd.c - - qmail-start: \ -@@ -2139,3 +2145,23 @@ - wait_pid.o: \ - compile wait_pid.c error.h haswaitp.h - ./compile wait_pid.c -+ -+cert: -+ openssl req -new -x509 -nodes \ -+ -out /var/qmail/control/servercert.pem -days 366 \ -+ -keyout /var/qmail/control/servercert.pem -+ chmod 640 /var/qmail/control/servercert.pem -+ chown qmaild:qmail /var/qmail/control/servercert.pem -+ ln -s /var/qmail/control/servercert.pem /var/qmail/control/clientcert.pem -+ -+cert-req: -+ openssl req -new -nodes \ -+ -out req.pem \ -+ -keyout /var/qmail/control/servercert.pem -+ chmod 640 /var/qmail/control/servercert.pem -+ chown qmaild:qmail /var/qmail/control/servercert.pem -+ ln -s /var/qmail/control/servercert.pem /var/qmail/control/clientcert.pem -+ @echo -+ @echo "Send req.pem to your CA to obtain signed_req.pem, and do:" -+ @echo "cat signed_req.pem >> /var/qmail/control/servercert.pem" -+ -diff -urP qmail-1.03-vanilla/README.auth qmail-1.03-tls-auth/README.auth ---- qmail-1.03-vanilla/README.auth Wed Dec 31 18:00:00 1969 -+++ qmail-1.03-tls-auth/README.auth Wed Jun 19 15:31:37 2002 -@@ -0,0 +1,175 @@ -+*** Warning! Cuidado! Vorsicht! *** -+=================================== -+*** Version 0.30 of the patch changes the arguments which must be -+*** passed to qmail-smtpd. If you are upgrading from a previous -+*** version of the patch, take care to ensure your invocation of -+*** qmail-smtpd uses the correct arguments. Otherwise, your server -+*** may run as an open relay! -+=================================== -+*** Warning! Cuidado! Vorsicht! *** -+ -+ -+This patch adds ESMTP AUTH authentication protocol support to -+qmail-1.03. It's originally based on Mrs. Brisby's smtp-auth patch -+with many enhancements from Krzysztof Dabrowski <brush@elysium.pl>. -+ -+Beginning with version 0.30, the patch was completely rewritten to -+use only djb's string functions by Eric M. Johnston <emj@postal.net>. -+ -+You can always get the newest version from: -+http://members.elysium.pl/brush/qmail-smtpd-auth/ -+ -+To use all of it's functionality you will also have to obtain and -+install Krzysztof's cmd5checkpw utility available at: -+http://members.elysium.pl/brush/cmd5checkpw/ -+ -+If you need more information about SMTP-AUTH itself and the -+client/server support and configuration, visit: -+http://members.elysium.pl/brush/smtp-auth/ -+ -+--- -+ -+Detailed patch information: -+ -+This patch adds the ESMTP AUTH option to qmail-1.03, allowing the -+LOGIN, PLAIN, and CRAM-MD5 AUTH types. An appropriate checkpassword -+tool is necessary to support the authentication. See -+http://cr.yp.to/checkpwd.html for more information on the interface. -+Note that the checkpassword tool should support all of the AUTH types -+advertised by qmail-smtpd. -+ -+As reflected in the modified qmail-smtpd(8) man page, qmail-smtpd -+must be invoked with three arguments: hostname, checkprogram, and -+subprogram. If these arguments are missing, qmail-smtpd will still -+advertise availability of AUTH, but will fail with a permanent error -+when AUTH is used. -+ -+hostname is simply used to form the CRAM-MD5 challenge. qmail-smtpd -+invokes checkprogram, feeding it the username and password, in the -+case of LOGIN or PLAIN, or the username, challenge, and response, in -+the case of CRAM-MD5. If the user is permitted, checkprogram invokes -+subprogram, which just has to exit with a status of 0 for the user to -+be authenticated. Otherwise, checkprogram exits with a non-zero -+status. subprogram can usually be /usr/bin/true (or /bin/true, -+depending on your flavor of OS). -+ -+If the user is successfully authenticated, the RELAYCLIENT -+environment variable is effectively set for the SMTP session, and -+the TCPREMOTEINFO environment variable is set to the authenticated -+username, overriding any value that tcpserver may have set. The -+value of TCPREMOTEINFO is reflected in a Received header. -+ -+ -+How to install it: -+ -+Simply patch your qmail-1.03 distribution with the included patch -+file and recompile & install like usual. -+ -+The steps to do this are as follows (assuming your virgin -+qmail-1.03 install is in "../qmail-1.03"): -+ -+ cp README.auth base64.c base64.h ../qmail-1.03 -+ patch -d ../qmail-1.03 < auth.patch -+ -+Install qmail normally, with the exception of the new arguments -+to qmail-smtpd described elsewhere in this file. -+ -+Also obtain, unpack, compile and install the cmd5checkpw utility -+(or some other checkpassword utility) and add a sample account to -+/etc/poppasswd file. This file must be readable by the qmail-smtpd -+user, usually qmaild. -+ -+ -+How to use it: -+ -+*** Warning: In version 0.30 the arguments have changed from -+*** previous versions of qmail-smtpd-auth. Take care to make sure -+*** you update your startup scripts if updating! -+ -+If you're running qmail-smtpd from inetd, you'll want to do the -+following: -+ -+smtp stream tcp nowait qmaild /var/qmail/bin/tcp-env tcp-env \ -+/var/qmail/bin/qmail-smtpd mail.acme.com /bin/cmd5checkpw /bin/true -+ -+Replace mail.acme.com with your hostname. The second argument to -+qmail-smtpd is your checkpassword utility (preferably cmd5checkpw -+or some alternative that can handle CRAM-MD5). The third argument -+is the executable that the checkpassword utility execs when -+authentication is successful. (Note that the location of "true" -+is OS dependent: you may need /usr/bin/true.) -+ -+Invocations using tcpserver will require analagous changes. Give -+your inetd a kill -HUP or restart tcpserver and away you go. -+ -+ -+Caveats: -+ -+Please note that as authentication needs vary wildly across -+installations, no effort has been made to make this patch work ``out -+of the box.'' You'll have to procure or develop your own -+checkpassword program. Also note that CRAM-MD5 will require you to -+keep plaintext passwords. You'll probably want to disable this AUTH -+type if you're just using /etc/passwd (keeping in mind that PLAIN and -+LOGIN aren't quite as safe over the wire) -- just undefine AUTHCRAM -+in qmail-smtpd. -+ -+Krzysztof Dabrowski's cmd5checkpw tool used as an example in this -+document supports the three AUTH types included in this patch. -+It's available at http://www.elysium.pl/members/brush/cmd5checkpw/. -+ -+This patch has been generated against the stock qmail 1.03 -+distribution. The results of combining this patch with others are -+unknown. -+ -+ -+Features: -+ -+This patch supports the following auth methods: LOGIN, PLAIN and -+CRAM-MD5. -+ -+ -+Compatibility: -+ -+The following MUA's are confirmed to work with this patch: -+ -+Eudora 4.2.2 - CRAM-MD5 -+Eudora 5.0.2 - CRAM-MD5 -+The Bat 1.39 - LOGIN & CRAM-MD5 -+Outlook Express 4 - LOGIN -+Outlook Express 5 - LOGIN -+Outlook 2000 - LOGIN -+Netscape 4.x - LOGIN & PLAIN -+Netscape 4.0x - LOGIN -+Pegasus Mail 3.1x - CRAM-MD5 -+ -+ -+Various compatibility issues: -+ -+Testing with Pegasus Mail 3.1 revealed that it requires the new style -+(RFC recommended) greeting message. Both styles are now enabled to -+maintain the highest degree of compatibility with various clients. -+This fix was suggested by David Harris <David.Harris@pmail.gen.nz>, -+the developer of Pegasus Mail. -+ -+ -+Acknowledgments: -+ -+This patch is based on work by Krzysztof Dabrowski at -+http://members.elysium.pl/brush/qmail-smtpd-auth/ and ``Mrs. Brisby'' -+at http://www.nimh.org/hacks/qmail-smtpd.c which has been further -+developed by Eric M. Johnston <emj@postal.net>. -+ -+--- -+ -+THIS SOFTWARE IS IN THE PUBLIC DOMAIN, IS PROVIDED BY THE AUTHOR -+``AS IS,'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE -+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -diff -urP qmail-1.03-vanilla/TARGETS qmail-1.03-tls-auth/TARGETS ---- qmail-1.03-vanilla/TARGETS Mon Jun 15 05:53:16 1998 -+++ qmail-1.03-tls-auth/TARGETS Wed Jun 19 15:30:20 2002 -@@ -250,6 +250,7 @@ - qmail-qmtpd.o - rcpthosts.o - qmail-qmtpd -+base64.o - qmail-smtpd.o - qmail-smtpd - sendmail.o -diff -urP qmail-1.03-vanilla/base64.c qmail-1.03-tls-auth/base64.c ---- qmail-1.03-vanilla/base64.c Wed Dec 31 18:00:00 1969 -+++ qmail-1.03-tls-auth/base64.c Wed Jun 19 15:29:53 2002 -@@ -0,0 +1,90 @@ -+#include "base64.h" -+#include "stralloc.h" -+#include "substdio.h" -+#include "str.h" -+ -+static char *b64alpha = -+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -+#define B64PAD '=' -+ -+/* returns 0 ok, 1 illegal, -1 problem */ -+ -+int b64decode(in,l,out) -+const unsigned char *in; -+int l; -+stralloc *out; /* not null terminated */ -+{ -+ int i, j; -+ unsigned char a[4]; -+ unsigned char b[3]; -+ char *s; -+ -+ if (l == 0) -+ { -+ if (!stralloc_copys(out,"")) return -1; -+ return 0; -+ } -+ -+ if (!stralloc_ready(out,l + 2)) return -1; /* XXX generous */ -+ s = out->s; -+ -+ for (i = 0;i < l;i += 4) { -+ for (j = 0;j < 4;j++) -+ if ((i + j) < l && in[i + j] != B64PAD) -+ { -+ a[j] = str_chr(b64alpha,in[i + j]); -+ if (a[j] > 63) return 1; -+ } -+ else a[j] = 0; -+ -+ b[0] = (a[0] << 2) | (a[1] >> 4); -+ b[1] = (a[1] << 4) | (a[2] >> 2); -+ b[2] = (a[2] << 6) | (a[3]); -+ -+ *s++ = b[0]; -+ -+ if (in[i + 1] == B64PAD) break; -+ *s++ = b[1]; -+ -+ if (in[i + 2] == B64PAD) break; -+ *s++ = b[2]; -+ } -+ out->len = s - out->s; -+ while (out->len && !out->s[out->len - 1]) --out->len; /* XXX avoid? */ -+ return 0; -+} -+ -+int b64encode(in,out) -+stralloc *in; -+stralloc *out; /* not null terminated */ -+{ -+ unsigned char a, b, c; -+ int i; -+ char *s; -+ -+ if (in->len == 0) -+ { -+ if (!stralloc_copys(out,"")) return -1; -+ return 0; -+ } -+ -+ if (!stralloc_ready(out,in->len / 3 * 4 + 4)) return -1; -+ s = out->s; -+ -+ for (i = 0;i < in->len;i += 3) { -+ a = in->s[i]; -+ b = i + 1 < in->len ? in->s[i + 1] : 0; -+ c = i + 2 < in->len ? in->s[i + 2] : 0; -+ -+ *s++ = b64alpha[a >> 2]; -+ *s++ = b64alpha[((a & 3 ) << 4) | (b >> 4)]; -+ -+ if (i + 1 >= in->len) *s++ = B64PAD; -+ else *s++ = b64alpha[((b & 15) << 2) | (c >> 6)]; -+ -+ if (i + 2 >= in->len) *s++ = B64PAD; -+ else *s++ = b64alpha[c & 63]; -+ } -+ out->len = s - out->s; -+ return 0; -+} -diff -urP qmail-1.03-vanilla/base64.h qmail-1.03-tls-auth/base64.h ---- qmail-1.03-vanilla/base64.h Wed Dec 31 18:00:00 1969 -+++ qmail-1.03-tls-auth/base64.h Wed Jun 19 15:29:53 2002 -@@ -0,0 +1,7 @@ -+#ifndef BASE64_H -+#define BASE64_H -+ -+extern int b64decode(); -+extern int b64encode(); -+ -+#endif -diff -urP qmail-1.03-vanilla/conf-cc qmail-1.03-tls-auth/conf-cc ---- qmail-1.03-vanilla/conf-cc Mon Jun 15 05:53:16 1998 -+++ qmail-1.03-tls-auth/conf-cc Wed Jun 19 15:35:59 2002 -@@ -1,3 +1,3 @@ --cc -O2 -+cc -O2 -DTLS -I/usr/local/ssl/include - - This will be used to compile .c files. -diff -urP qmail-1.03-vanilla/dns.c qmail-1.03-tls-auth/dns.c ---- qmail-1.03-vanilla/dns.c Mon Jun 15 05:53:16 1998 -+++ qmail-1.03-tls-auth/dns.c Wed Jun 19 15:36:06 2002 -@@ -270,6 +270,14 @@ - { - int r; - struct ip_mx ix; -+#ifdef TLS -+ stralloc fqdn = {0}; -+ -+ if (!stralloc_copy(&fqdn,sa)) return DNS_MEM; -+ if (!stralloc_0(&fqdn)) return DNS_MEM; -+ ix.fqdn = fqdn.s; -+ alloc_free(fqdn); -+#endif - - if (!stralloc_copy(&glue,sa)) return DNS_MEM; - if (!stralloc_0(&glue)) return DNS_MEM; -@@ -330,6 +338,9 @@ - ix.pref = 0; - if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)]) - { -+#ifdef TLS -+ ix.fqdn = NULL; -+#endif - if (!ipalloc_append(ia,&ix)) return DNS_MEM; - return 0; - } -diff -urP qmail-1.03-vanilla/ipalloc.h qmail-1.03-tls-auth/ipalloc.h ---- qmail-1.03-vanilla/ipalloc.h Mon Jun 15 05:53:16 1998 -+++ qmail-1.03-tls-auth/ipalloc.h Wed Jun 19 15:36:15 2002 -@@ -3,7 +3,12 @@ - - #include "ip.h" - -+#ifdef TLS -+#include "stralloc.h" -+struct ip_mx { struct ip_address ip; int pref; char *fqdn; } ; -+#else - struct ip_mx { struct ip_address ip; int pref; } ; -+#endif - - #include "gen_alloc.h" - -diff -urP qmail-1.03-vanilla/qmail-remote.c qmail-1.03-tls-auth/qmail-remote.c ---- qmail-1.03-vanilla/qmail-remote.c Mon Jun 15 05:53:16 1998 -+++ qmail-1.03-tls-auth/qmail-remote.c Wed Jun 19 15:36:38 2002 -@@ -26,8 +26,18 @@ - #include "tcpto.h" - #include "readwrite.h" - #include "timeoutconn.h" -+#ifndef TLS - #include "timeoutread.h" - #include "timeoutwrite.h" -+#endif -+ -+#ifdef TLS -+#include <sys/stat.h> -+#include <openssl/ssl.h> -+SSL *ssl = NULL; -+ -+stralloc tlsclientciphers = {0}; -+#endif - - #define HUGESMTPTEXT 5000 - -@@ -107,17 +117,94 @@ - int smtpfd; - int timeout = 1200; - -+#ifdef TLS -+int flagtimedout = 0; -+void sigalrm() -+{ -+ flagtimedout = 1; -+} -+ -+int ssl_timeoutread(timeout,fd,buf,n) int timeout; int fd; char *buf; int n; -+{ -+ int r; int saveerrno; -+ if (flagtimedout) { errno = error_timeout; return -1; } -+ alarm(timeout); -+ if (ssl) { -+ while(((r = SSL_read(ssl,buf,n)) <= 0) -+ && (SSL_get_error(ssl, r) == SSL_ERROR_WANT_READ)); -+ if (SSL_get_error(ssl, r) != SSL_ERROR_NONE) -+ {char buf[1024]; -+ -+ out("ZTLS connection to "); outhost(); out(" died: "); -+ SSL_load_error_strings(); -+ out(ERR_error_string(ERR_get_error(), buf)); out("\n"); -+ SSL_shutdown(ssl); -+ zerodie(); -+ } -+ }else r = read(fd,buf,n); -+ saveerrno = errno; -+ alarm(0); -+ if (flagtimedout) { errno = error_timeout; return -1; } -+ errno = saveerrno; -+ return r; -+} -+ -+int ssl_timeoutwrite(timeout,fd,buf,n) int timeout; int fd; char *buf; int n; -+{ -+ int r; int saveerrno; -+ if (flagtimedout) { errno = error_timeout; return -1; } -+ alarm(timeout); -+ if (ssl) { -+ while(((r = SSL_write(ssl,buf,n)) <= 0) -+ && (SSL_get_error(ssl, r) == SSL_ERROR_WANT_WRITE)); -+ if (SSL_get_error(ssl, r) != SSL_ERROR_NONE) -+ {char buf[1024]; -+ -+ out("ZTLS connection to "); outhost(); out(" died: "); -+ SSL_load_error_strings(); -+ out(ERR_error_string(ERR_get_error(), buf)); out("\n"); -+ SSL_shutdown(ssl); -+ zerodie(); -+ } -+ }else r = write(fd,buf,n); -+ saveerrno = errno; -+ alarm(0); -+ if (flagtimedout) { errno = error_timeout; return -1; } -+ errno = saveerrno; -+ return r; -+} -+ -+static int client_cert_cb(SSL *s,X509 **x509, EVP_PKEY **pkey) -+{ -+ out("ZTLS found no client cert in control/clientcert.pem\n"); -+ zerodie(NULL,NULL); -+} -+ -+static int verify_cb(int ok, X509_STORE_CTX * ctx) -+{ -+ return (1); -+} -+#endif -+ - int saferead(fd,buf,len) int fd; char *buf; int len; - { - int r; -+#ifdef TLS -+ r = ssl_timeoutread(timeout,smtpfd,buf,len); -+#else - r = timeoutread(timeout,smtpfd,buf,len); -+#endif - if (r <= 0) dropped(); - return r; - } - int safewrite(fd,buf,len) int fd; char *buf; int len; - { - int r; -+#ifdef TLS -+ r = ssl_timeoutwrite(timeout,smtpfd,buf,len); -+#else - r = timeoutwrite(timeout,smtpfd,buf,len); -+#endif - if (r <= 0) dropped(); - return r; - } -@@ -186,6 +273,34 @@ - out(append); - out(".\n"); - outsmtptext(); -+ -+/* TAG */ -+#if defined(TLS) && defined(DEBUG) -+#define ONELINE_NAME(X) X509_NAME_oneline(X,NULL,0) -+ -+ if(ssl){ -+ X509 *peer; -+ -+ out("STARTTLS proto="); out(SSL_get_version(ssl)); -+ out("; cipher="); out(SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))); -+ -+ /* we want certificate details */ -+ peer=SSL_get_peer_certificate(ssl); -+ if (peer != NULL) { -+ char *str; -+ -+ str=ONELINE_NAME(X509_get_subject_name(peer)); -+ out("; subject="); out(str); -+ OPENSSL_free(str); -+ str=ONELINE_NAME(X509_get_issuer_name(peer)); -+ out("; issuer="); out(str); -+ OPENSSL_free(str); -+ X509_free(peer); -+ } -+ out(";\n"); -+ } -+#endif -+ - zerodie(); - } - -@@ -216,20 +331,158 @@ - - stralloc recip = {0}; - -+#ifdef TLS -+void smtp(fqdn) -+char *fqdn; -+#else - void smtp() -+#endif - { - unsigned long code; - int flagbother; - int i; -- -+#ifdef TLS -+ int needtlsauth = 0; -+ SSL_CTX *ctx; -+ int saveerrno, r; -+ -+ stralloc servercert = {0}; -+ struct stat st; -+ if(fqdn){ -+ if(!stralloc_copys(&servercert, "control/tlshosts/")) temp_nomem(); -+ if(!stralloc_catb(&servercert, fqdn, str_len(fqdn))) temp_nomem(); -+ if(!stralloc_catb(&servercert, ".pem", 4)) temp_nomem(); -+ if(!stralloc_0(&servercert)) temp_nomem(); -+ if (stat(servercert.s,&st) == 0) needtlsauth = 1; -+ } -+#endif -+ - if (smtpcode() != 220) quit("ZConnected to "," but greeting failed"); - -+#ifdef TLS -+ substdio_puts(&smtpto,"EHLO "); -+#else - substdio_puts(&smtpto,"HELO "); -+#endif - substdio_put(&smtpto,helohost.s,helohost.len); - substdio_puts(&smtpto,"\r\n"); - substdio_flush(&smtpto); -+#ifdef TLS -+ if (smtpcode() != 250){ -+ substdio_puts(&smtpto,"HELO "); -+ substdio_put(&smtpto,helohost.s,helohost.len); -+ substdio_puts(&smtpto,"\r\n"); -+ substdio_flush(&smtpto); -+ if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected"); -+ } -+#else - if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected"); -- -+#endif -+ -+#ifdef TLS -+ i = 0; -+ while((i += str_chr(smtptext.s+i,'\n') + 1) && (i+12 < smtptext.len) && -+ str_diffn(smtptext.s+i+4,"STARTTLS\n",9)); -+ if (i+12 < smtptext.len) -+ { -+ substdio_puts(&smtpto,"STARTTLS\r\n"); -+ substdio_flush(&smtpto); -+ if (smtpcode() == 220) -+ { -+ SSL_library_init(); -+ if(!(ctx=SSL_CTX_new(SSLv23_client_method()))) -+ {char buf[1024]; -+ -+ out("ZTLS not available: error initializing ctx: "); -+ SSL_load_error_strings(); -+ out(ERR_error_string(ERR_get_error(), buf)); -+ out("\n"); -+ SSL_shutdown(ssl); -+ zerodie(); -+ } -+ if((stat("control/clientcert.pem", &st) == 0) && -+ ((SSL_CTX_use_RSAPrivateKey_file(ctx, "control/clientcert.pem", SSL_FILETYPE_PEM) <= 0) || -+ (SSL_CTX_use_certificate_chain_file(ctx, "control/clientcert.pem") <= 0) || -+ (SSL_CTX_check_private_key(ctx) <= 0))) -+ /* if there is a cert and it is bad, I fail -+ if there is no cert, I leave it to the other side to complain */ -+ SSL_CTX_set_client_cert_cb(ctx, client_cert_cb); -+ -+ /*SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);*/ -+ SSL_CTX_set_cipher_list(ctx,tlsclientciphers.s); -+ -+ if (needtlsauth){ -+ if (!SSL_CTX_load_verify_locations(ctx, servercert.s, NULL)) -+ {out("ZTLS unable to load "); out(servercert.s); out("\n"); -+ zerodie();} -+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); -+ } -+ -+ if(!(ssl=SSL_new(ctx))) -+ {char buf[1024]; -+ -+ out("ZTLS not available: error initializing ssl: "); -+ SSL_load_error_strings(); -+ out(ERR_error_string(ERR_get_error(), buf)); -+ out("\n"); -+ SSL_shutdown(ssl); -+ zerodie(); -+ } -+ SSL_set_fd(ssl,smtpfd); -+ -+ alarm(timeout); -+ r = SSL_connect(ssl); saveerrno = errno; -+ alarm(0); -+ if (flagtimedout) -+ {out("ZTLS not available: connect timed out\n"); -+ zerodie();} -+ errno = saveerrno; -+ if (r<=0) -+ {char buf[1024]; -+ -+ out("ZTLS not available: connect failed: "); -+ SSL_load_error_strings(); -+ out(ERR_error_string(ERR_get_error(), buf)); -+ out("\n"); -+ SSL_shutdown(ssl); -+ zerodie(); -+ } -+ if (needtlsauth) -+ /* should also check alternate names */ -+ {char commonName[256]; -+ -+ if ((r=SSL_get_verify_result(ssl)) != X509_V_OK) -+ {out("ZTLS unable to verify server with "); -+ out(servercert.s); out(": "); -+ out(X509_verify_cert_error_string(r)); out("\n"); -+ zerodie(); -+ } -+ X509_NAME_get_text_by_NID(X509_get_subject_name( -+ SSL_get_peer_certificate(ssl)), -+ NID_commonName, commonName, 256); -+ if (strcasecmp(fqdn,commonName)){ -+ out("ZTLS connection to "); out(fqdn); -+ out(" wanted, certificate for "); out(commonName); -+ out(" received\n"); -+ zerodie();} -+ } -+ -+ substdio_puts(&smtpto,"EHLO "); -+ substdio_put(&smtpto,helohost.s,helohost.len); -+ substdio_puts(&smtpto,"\r\n"); -+ substdio_flush(&smtpto); -+ -+ if (smtpcode() != 250) -+ { -+ quit("ZTLS connected to "," but my name was rejected"); -+ } -+ } -+ } -+ if ((!ssl) && needtlsauth) -+ {out("ZNo TLS achieved while "); out(servercert.s); out(" exists.\n"); -+ quit();} -+#endif -+ - substdio_puts(&smtpto,"MAIL FROM:<"); - substdio_put(&smtpto,sender.s,sender.len); - substdio_puts(&smtpto,">\r\n"); -@@ -324,6 +577,11 @@ - case 1: - if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break; - } -+#ifdef TLS -+ if (control_rldef(&tlsclientciphers,"control/tlsclientciphers",0,"DEFAULT") != 1) -+ temp_control(); -+ if(!stralloc_0(&tlsclientciphers)) temp_nomem(); -+#endif - } - - void main(argc,argv) -@@ -338,7 +596,10 @@ - int flagallaliases; - int flagalias; - char *relayhost; -- -+ -+#ifdef TLS -+ sig_alarmcatch(sigalrm); -+#endif - sig_pipeignore(); - if (argc < 4) perm_usage(); - if (chdir(auto_qmail) == -1) temp_chdir(); -@@ -417,7 +678,11 @@ - if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) { - tcpto_err(&ip.ix[i].ip,0); - partner = ip.ix[i].ip; -+#ifdef TLS -+ smtp(ip.ix[i].fqdn); /* does not return */ -+#else - smtp(); /* does not return */ -+#endif - } - tcpto_err(&ip.ix[i].ip,errno == error_timeout); - close(smtpfd); -diff -urP qmail-1.03-vanilla/qmail-smtpd.8 qmail-1.03-tls-auth/qmail-smtpd.8 ---- qmail-1.03-vanilla/qmail-smtpd.8 Mon Jun 15 05:53:16 1998 -+++ qmail-1.03-tls-auth/qmail-smtpd.8 Wed Jun 19 15:30:20 2002 -@@ -3,6 +3,11 @@ - qmail-smtpd \- receive mail via SMTP - .SH SYNOPSIS - .B qmail-smtpd -+[ -+.I hostname -+.I checkprogram -+.I subprogram -+] - .SH DESCRIPTION - .B qmail-smtpd - receives mail messages via the Simple Mail Transfer Protocol (SMTP) -@@ -23,7 +28,29 @@ - header fields. - - .B qmail-smtpd --supports ESMTP, including the 8BITMIME and PIPELINING options. -+supports ESMTP, including the 8BITMIME, PIPELINING, and AUTH options. -+ -+.B qmail-smtpd -+can accept LOGIN, PLAIN, and CRAM-MD5 AUTH types. It invokes -+.IR checkprogram , -+which reads on file descriptor 3 the username, a 0 byte, the password -+or challenge derived from -+.IR hostname , -+another 0 byte, a CRAM-MD5 response (if applicable to the AUTH type), -+and a final 0 byte. -+.I checkprogram -+invokes -+.I subprogram -+upon successful authentication, which should in turn return 0 to -+.BR qmail-smtpd , -+effectively setting the environment variables RELAYCLIENT and TCPREMOTEINFO -+(any supplied value replaced with the authenticated username). -+.B qmail-smtpd -+will reject the authentication attempt if it receives a nonzero return -+value from -+.I checkprogram -+or -+.IR subprogram . - .SH TRANSPARENCY - .B qmail-smtpd - converts the SMTP newline convention into the UNIX newline convention -@@ -177,3 +204,6 @@ - qmail-newmrh(8), - qmail-queue(8), - qmail-remote(8) -+.SH "HISTORY" -+The patch enabling the ESMTP AUTH option is not part of the standard -+qmail-1.03 distribution. -diff -urP qmail-1.03-vanilla/qmail-smtpd.c qmail-1.03-tls-auth/qmail-smtpd.c ---- qmail-1.03-vanilla/qmail-smtpd.c Mon Jun 15 05:53:16 1998 -+++ qmail-1.03-tls-auth/qmail-smtpd.c Wed Jun 19 16:05:56 2002 -@@ -20,18 +20,75 @@ - #include "now.h" - #include "exit.h" - #include "rcpthosts.h" -+#ifndef TLS - #include "timeoutread.h" - #include "timeoutwrite.h" -+#endif - #include "commands.h" -+#include "wait.h" -+#include "fd.h" - -+#ifdef TLS -+#include <openssl/ssl.h> -+SSL *ssl = NULL; -+ -+stralloc clientcert = {0}; -+stralloc tlsserverciphers = {0}; -+#endif -+ -+#define AUTHCRAM - #define MAXHOPS 100 - unsigned int databytes = 0; - int timeout = 1200; - -+#ifdef TLS -+int flagtimedout = 0; -+void sigalrm() -+{ -+ flagtimedout = 1; -+} -+int ssl_timeoutread(timeout,fd,buf,n) int timeout; int fd; char *buf; int n; -+{ -+ int r; int saveerrno; -+ if (flagtimedout) { errno = error_timeout; return -1; } -+ alarm(timeout); -+ if (ssl) { -+ while(((r = SSL_read(ssl,buf,n)) <= 0) -+ && (SSL_get_error(ssl, r) == SSL_ERROR_WANT_READ)); -+ }else r = read(fd,buf,n); -+ saveerrno = errno; -+ alarm(0); -+ if (flagtimedout) { errno = error_timeout; return -1; } -+ errno = saveerrno; -+ return r; -+} -+ -+ -+int ssl_timeoutwrite(timeout,fd,buf,n) int timeout; int fd; char *buf; int n; -+{ -+ int r; int saveerrno; -+ if (flagtimedout) { errno = error_timeout; return -1; } -+ alarm(timeout); -+ if (ssl) { -+ while(((r = SSL_write(ssl,buf,n)) <= 0) -+ && (SSL_get_error(ssl, r) == SSL_ERROR_WANT_WRITE)); -+ }else r = write(fd,buf,n); -+ saveerrno = errno; -+ alarm(0); -+ if (flagtimedout) { errno = error_timeout; return -1; } -+ errno = saveerrno; -+ return r; -+} -+#endif -+ - int safewrite(fd,buf,len) int fd; char *buf; int len; - { - int r; -+#ifdef TLS -+ r = ssl_timeoutwrite(timeout,fd,buf,len); -+#else - r = timeoutwrite(timeout,fd,buf,len); -+#endif - if (r <= 0) _exit(1); - return r; - } -@@ -51,6 +108,9 @@ - - void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); } - void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); } -+#ifdef TLS -+void err_nogwcert() { out("553 no valid cert for gatewaying (#5.7.1)\r\n"); } -+#endif - void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); } - void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); } - void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); } -@@ -59,6 +119,15 @@ - void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); } - void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); } - -+int err_child() { out("454 oops, problem with child and I can't auth (#4.3.0)\r\n"); return -1; } -+int err_fork() { out("454 oops, child won't start and I can't auth (#4.3.0)\r\n"); return -1; } -+int err_pipe() { out("454 oops, unable to open pipe and I can't auth (#4.3.0)\r\n"); return -1; } -+int err_write() { out("454 oops, unable to write pipe and I can't auth (#4.3.0)\r\n"); return -1; } -+void err_authd() { out("503 you're already authenticated (#5.5.0)\r\n"); } -+void err_authmail() { out("503 no auth during mail transaction (#5.5.0)\r\n"); } -+int err_noauth() { out("504 auth type unimplemented (#5.5.1)\r\n"); return -1; } -+int err_authabrt() { out("501 auth exchange cancelled (#5.0.0)\r\n"); return -1; } -+int err_input() { out("501 malformed auth input (#5.5.4)\r\n"); return -1; } - - stralloc greeting = {0}; - -@@ -81,6 +150,9 @@ - char *remoteinfo; - char *local; - char *relayclient; -+#ifdef TLS -+char *tlsciphers; -+#endif - - stralloc helohost = {0}; - char *fakehelo; /* pointer into helohost, or 0 */ -@@ -101,6 +173,9 @@ - { - char *x; - unsigned long u; -+#ifdef TLS -+ char *tlsciphers; -+#endif - - if (control_init() == -1) die_control(); - if (control_rldef(&greeting,"control/smtpgreeting",1,(char *) 0) != 1) -@@ -131,6 +206,17 @@ - if (!remotehost) remotehost = "unknown"; - remoteinfo = env_get("TCPREMOTEINFO"); - relayclient = env_get("RELAYCLIENT"); -+#ifdef TLS -+ if (tlsciphers = env_get("TLSCIPHERS")){ -+ if (!stralloc_copys(&tlsserverciphers,tlsciphers)) die_nomem(); -+ } -+ else { -+ if (control_rldef(&tlsserverciphers,"control/tlsserverciphers",0,"DEFAULT") != 1) -+ die_control(); -+ } -+ if (!stralloc_0(&tlsserverciphers)) die_nomem(); -+#endif -+ - dohelo(remotehost); - } - -@@ -229,7 +315,18 @@ - } - void smtp_ehlo(arg) char *arg; - { -- smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n"); -+ smtp_greet("250-"); -+#ifdef AUTHCRAM -+ out("\r\n250-AUTH LOGIN CRAM-MD5 PLAIN"); -+ out("\r\n250-AUTH=LOGIN CRAM-MD5 PLAIN"); -+#else -+ out("\r\n250-AUTH LOGIN PLAIN"); -+ out("\r\n250-AUTH=LOGIN PLAIN"); -+#endif -+#ifdef TLS -+ if (!ssl) out("\r\n250-STARTTLS"); -+#endif -+ out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n"); - seenmail = 0; dohelo(arg); - } - void smtp_rset() -@@ -247,6 +344,12 @@ - if (!stralloc_0(&mailfrom)) die_nomem(); - out("250 ok\r\n"); - } -+#ifdef TLS -+static int verify_cb(int ok, X509_STORE_CTX * ctx) -+{ -+ return (1); -+} -+#endif - void smtp_rcpt(arg) char *arg; { - if (!seenmail) { err_wantmail(); return; } - if (!addrparse(arg)) { err_syntax(); return; } -@@ -257,7 +360,54 @@ - if (!stralloc_0(&addr)) die_nomem(); - } - else -+#ifndef TLS - if (!addrallowed()) { err_nogateway(); return; } -+#else -+ if (!addrallowed()) -+ { -+ if (ssl) -+ { STACK_OF(X509_NAME) *sk; -+ X509 *peercert; -+ stralloc tlsclients = {0}; -+ struct constmap maptlsclients; -+ int r; -+ -+ SSL_set_verify(ssl, -+ SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, -+ verify_cb); -+ if ((sk = SSL_load_client_CA_file("control/clientca.pem")) == NULL) -+ { err_nogateway(); return; } -+ SSL_set_client_CA_list(ssl, sk); -+ if((control_readfile(&tlsclients,"control/tlsclients",0) != 1) || -+ !constmap_init(&maptlsclients,tlsclients.s,tlsclients.len,0)) -+ { err_nogateway(); return; } -+ -+ SSL_renegotiate(ssl); -+ SSL_do_handshake(ssl); -+ ssl->state = SSL_ST_ACCEPT; -+ SSL_do_handshake(ssl); -+ if ((r = SSL_get_verify_result(ssl)) != X509_V_OK) -+ {out("553 no valid cert for gatewaying: "); -+ out(X509_verify_cert_error_string(r)); -+ out(" (#5.7.1)\r\n"); -+ return; -+ } -+ -+ if (peercert = SSL_get_peer_certificate(ssl)) -+ {char emailAddress[256]; -+ -+ X509_NAME_get_text_by_NID(X509_get_subject_name( -+ SSL_get_peer_certificate(ssl)), -+ NID_pkcs9_emailAddress, emailAddress, 256); if (!stralloc_copys(&clientcert, emailAddress)) die_nomem(); -+ if (!constmap(&maptlsclients,clientcert.s,clientcert.len)) -+ { err_nogwcert(); return; } -+ relayclient = ""; -+ } -+ else { err_nogwcert(); return; } -+ } -+ else { err_nogateway(); return; } -+ } -+#endif - if (!stralloc_cats(&rcptto,"T")) die_nomem(); - if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); - if (!stralloc_0(&rcptto)) die_nomem(); -@@ -269,7 +419,11 @@ - { - int r; - flush(); -+#ifdef TLS -+ r = ssl_timeoutread(timeout,fd,buf,len); -+#else - r = timeoutread(timeout,fd,buf,len); -+#endif - if (r == -1) if (errno == error_timeout) die_alarm(); - if (r <= 0) die_read(); - return r; -@@ -369,6 +523,9 @@ - int hops; - unsigned long qp; - char *qqx; -+#ifdef TLS -+ stralloc protocolinfo = {0}; -+#endif - - if (!seenmail) { err_wantmail(); return; } - if (!rcptto.len) { err_wantrcpt(); return; } -@@ -377,8 +534,20 @@ - if (qmail_open(&qqt) == -1) { err_qqt(); return; } - qp = qmail_qp(&qqt); - out("354 go ahead\r\n"); -- -+#ifdef TLS -+ if(ssl){ -+ if (!stralloc_copys(&protocolinfo, SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)))) die_nomem(); -+ if (!stralloc_catb(&protocolinfo, " encrypted SMTP", 15)) die_nomem(); -+ if (clientcert.len){ -+ if (!stralloc_catb(&protocolinfo," cert ", 6)) die_nomem(); -+ if (!stralloc_catb(&protocolinfo,clientcert.s, clientcert.len)) die_nomem(); -+ } -+ if (!stralloc_0(&protocolinfo)) die_nomem(); -+ } else if (!stralloc_copyb(&protocolinfo,"SMTP",5)) die_nomem(); -+ received(&qqt,protocolinfo.s,local,remoteip,remotehost,remoteinfo,case_diffs(remotehost,helohost.s) ? helohost.s : 0); -+#else - received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo); -+#endif - blast(&hops); - hops = (hops >= MAXHOPS); - if (hops) qmail_fail(&qqt); -@@ -393,23 +562,299 @@ - out(qqx + 1); - out("\r\n"); - } -+#ifdef TLS -+static RSA *tmp_rsa_cb(ssl,export,keylength) SSL *ssl; int export; int keylength; -+{ -+ RSA* rsa; -+ BIO* in; -+ -+ if (!export || keylength == 512) -+ if (in=BIO_new(BIO_s_file_internal())) -+ if (BIO_read_filename(in,"control/rsa512.pem") > 0) -+ if (rsa=PEM_read_bio_RSAPrivateKey(in,NULL,NULL,NULL)) -+ return rsa; -+ return (RSA_generate_key(export?keylength:512,RSA_F4,NULL,NULL)); -+} -+ -+void smtp_tls(arg) char *arg; -+{ -+ SSL_CTX *ctx; -+ -+ if (*arg) -+ {out("501 Syntax error (no parameters allowed) (#5.5.4)\r\n"); -+ return;} -+ -+ SSL_library_init(); -+ if(!(ctx=SSL_CTX_new(SSLv23_server_method()))) -+ {out("454 TLS not available: unable to initialize ctx (#4.3.0)\r\n"); -+ return;} -+ if(!SSL_CTX_use_RSAPrivateKey_file(ctx, "control/servercert.pem", SSL_FILETYPE_PEM)) -+ {out("454 TLS not available: missing RSA private key (#4.3.0)\r\n"); -+ return;} -+ if(!SSL_CTX_use_certificate_chain_file(ctx, "control/servercert.pem")) -+ {out("454 TLS not available: missing certificate (#4.3.0)\r\n"); -+ return;} -+ SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_cb); -+ SSL_CTX_set_cipher_list(ctx,tlsserverciphers.s); -+ SSL_CTX_load_verify_locations(ctx, "control/clientca.pem",NULL); -+ SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_cb); -+ -+ out("220 ready for tls\r\n"); flush(); -+ -+ if(!(ssl=SSL_new(ctx))) die_read(); -+ SSL_set_fd(ssl,0); -+ if(SSL_accept(ssl)<=0) die_read(); -+ substdio_fdbuf(&ssout,SSL_write,ssl,ssoutbuf,sizeof(ssoutbuf)); -+ -+ remotehost = env_get("TCPREMOTEHOST"); -+ if (!remotehost) remotehost = "unknown"; -+ dohelo(remotehost); -+} -+#endif -+ -+ -+char unique[FMT_ULONG + FMT_ULONG + 3]; -+static stralloc authin = {0}; -+static stralloc user = {0}; -+static stralloc pass = {0}; -+static stralloc resp = {0}; -+static stralloc slop = {0}; -+char *hostname; -+char **childargs; -+substdio ssup; -+char upbuf[128]; -+int authd = 0; -+ -+int authgetl(void) { -+ int i; -+ -+ if (!stralloc_copys(&authin, "")) die_nomem(); -+ -+ for (;;) { -+ if (!stralloc_readyplus(&authin,1)) die_nomem(); /* XXX */ -+ i = substdio_get(&ssin,authin.s + authin.len,1); -+ if (i != 1) die_read(); -+ if (authin.s[authin.len] == '\n') break; -+ ++authin.len; -+ } -+ -+ if (authin.len > 0) if (authin.s[authin.len - 1] == '\r') --authin.len; -+ authin.s[authin.len] = 0; -+ -+ if (*authin.s == '*' && *(authin.s + 1) == 0) { return err_authabrt(); } -+ if (authin.len == 0) { return err_input(); } -+ return authin.len; -+} -+ -+int authenticate(void) -+{ -+ int child; -+ int wstat; -+ int pi[2]; -+ -+ if (!stralloc_0(&user)) die_nomem(); -+ if (!stralloc_0(&pass)) die_nomem(); -+ if (!stralloc_0(&resp)) die_nomem(); -+ -+ if (fd_copy(2,1) == -1) return err_pipe(); -+ close(3); -+ if (pipe(pi) == -1) return err_pipe(); -+ if (pi[0] != 3) return err_pipe(); -+ switch(child = fork()) { -+ case -1: -+ return err_fork(); -+ case 0: -+ close(pi[1]); -+ sig_pipedefault(); -+ execvp(*childargs, childargs); -+ _exit(1); -+ } -+ close(pi[0]); -+ -+ substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof upbuf); -+ if (substdio_put(&ssup,user.s,user.len) == -1) return err_write(); -+ if (substdio_put(&ssup,pass.s,pass.len) == -1) return err_write(); -+ if (substdio_put(&ssup,resp.s,resp.len) == -1) return err_write(); -+ if (substdio_flush(&ssup) == -1) return err_write(); -+ -+ close(pi[1]); -+ byte_zero(pass.s,pass.len); -+ byte_zero(upbuf,sizeof upbuf); -+ if (wait_pid(&wstat,child) == -1) return err_child(); -+ if (wait_crashed(wstat)) return err_child(); -+ if (wait_exitcode(wstat)) { sleep(5); return 1; } /* no */ -+ return 0; /* yes */ -+} -+ -+int auth_login(arg) char *arg; -+{ -+ int r; -+ -+ if (*arg) { -+ if (r = b64decode(arg,str_len(arg),&user) == 1) return err_input(); -+ } -+ else { -+ out("334 VXNlcm5hbWU6\r\n"); flush(); /* Username: */ -+ if (authgetl() < 0) return -1; -+ if (r = b64decode(authin.s,authin.len,&user) == 1) return err_input(); -+ } -+ if (r == -1) die_nomem(); -+ -+ out("334 UGFzc3dvcmQ6\r\n"); flush(); /* Password: */ -+ -+ if (authgetl() < 0) return -1; -+ if (r = b64decode(authin.s,authin.len,&pass) == 1) return err_input(); -+ if (r == -1) die_nomem(); -+ -+ if (!user.len || !pass.len) return err_input(); -+ return authenticate(); -+} -+ -+int auth_plain(arg) char *arg; -+{ -+ int r, id = 0; -+ -+ if (*arg) { -+ if (r = b64decode(arg,str_len(arg),&slop) == 1) return err_input(); -+ } -+ else { -+ out("334 \r\n"); flush(); -+ if (authgetl() < 0) return -1; -+ if (r = b64decode(authin.s,authin.len,&slop) == 1) return err_input(); -+ } -+ if (r == -1 || !stralloc_0(&slop)) die_nomem(); -+ while (slop.s[id]) id++; /* ignore authorize-id */ -+ -+ if (slop.len > id + 1) -+ if (!stralloc_copys(&user,slop.s + id + 1)) die_nomem(); -+ if (slop.len > id + user.len + 2) -+ if (!stralloc_copys(&pass,slop.s + id + user.len + 2)) die_nomem(); -+ -+ if (!user.len || !pass.len) return err_input(); -+ return authenticate(); -+} -+ -+#ifdef AUTHCRAM -+int auth_cram() -+{ -+ int i, r; -+ char *s; -+ -+ s = unique; -+ s += fmt_uint(s,getpid()); -+ *s++ = '.'; -+ s += fmt_ulong(s,(unsigned long) now()); -+ *s++ = '@'; -+ *s++ = 0; -+ -+ if (!stralloc_copys(&pass,"<")) die_nomem(); -+ if (!stralloc_cats(&pass,unique)) die_nomem(); -+ if (!stralloc_cats(&pass,hostname)) die_nomem(); -+ if (!stralloc_cats(&pass,">")) die_nomem(); -+ if (b64encode(&pass,&slop) < 0) die_nomem(); -+ if (!stralloc_0(&slop)) die_nomem(); -+ -+ out("334 "); -+ out(slop.s); -+ out("\r\n"); -+ flush(); -+ -+ if (authgetl() < 0) return -1; -+ if (r = b64decode(authin.s,authin.len,&slop) == 1) return err_input(); -+ if (r == -1 || !stralloc_0(&slop)) die_nomem(); -+ -+ i = str_chr(slop.s,' '); -+ s = slop.s + i; -+ while (*s == ' ') ++s; -+ slop.s[i] = 0; -+ if (!stralloc_copys(&user,slop.s)) die_nomem(); -+ if (!stralloc_copys(&resp,s)) die_nomem(); -+ -+ if (!user.len || !resp.len) return err_input(); -+ return authenticate(); -+} -+#endif -+ -+struct authcmd { -+ char *text; -+ int (*fun)(); -+} authcmds[] = { -+ { "login", auth_login } -+, { "plain", auth_plain } -+#ifdef AUTHCRAM -+, { "cram-md5", auth_cram } -+#endif -+, { 0, err_noauth } -+}; -+ -+void smtp_auth(arg) -+char *arg; -+{ -+ int i; -+ char *cmd = arg; -+ -+ if (!hostname || !*childargs) -+ { -+ out("503 auth not available (#5.3.3)\r\n"); -+ return; -+ } -+ if (authd) { err_authd(); return; } -+ if (seenmail) { err_authmail(); return; } -+ -+ if (!stralloc_copys(&user,"")) die_nomem(); -+ if (!stralloc_copys(&pass,"")) die_nomem(); -+ if (!stralloc_copys(&resp,"")) die_nomem(); -+ -+ i = str_chr(cmd,' '); -+ arg = cmd + i; -+ while (*arg == ' ') ++arg; -+ cmd[i] = 0; -+ -+ for (i = 0;authcmds[i].text;++i) -+ if (case_equals(authcmds[i].text,cmd)) break; -+ -+ switch (authcmds[i].fun(arg)) { -+ case 0: -+ authd = 1; -+ relayclient = ""; -+ remoteinfo = user.s; -+ if (!env_unset("TCPREMOTEINFO")) die_read(); -+ if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem(); -+ out("235 ok, go ahead (#2.0.0)\r\n"); -+ break; -+ case 1: -+ out("535 authorization failed (#5.7.0)\r\n"); -+ } -+} - - struct commands smtpcommands[] = { - { "rcpt", smtp_rcpt, 0 } - , { "mail", smtp_mail, 0 } - , { "data", smtp_data, flush } -+, { "auth", smtp_auth, flush } - , { "quit", smtp_quit, flush } - , { "helo", smtp_helo, flush } - , { "ehlo", smtp_ehlo, flush } - , { "rset", smtp_rset, 0 } - , { "help", smtp_help, flush } -+#ifdef TLS -+, { "starttls", smtp_tls, flush } -+#endif - , { "noop", err_noop, flush } - , { "vrfy", err_vrfy, flush } - , { 0, err_unimpl, flush } - } ; - --void main() --{ -+void main(argc,argv) -+int argc; -+char **argv; -+{ -+ hostname = argv[1]; -+ childargs = argv + 2; -+ -+#ifdef TLS -+ sig_alarmcatch(sigalrm); -+#endif - sig_pipeignore(); - if (chdir(auto_qmail) == -1) die_control(); - setup(); |