diff -u -N qmail-1.03-patch20010301-orig/Makefile qmail-1.03-patch20010301/Makefile --- qmail-1.03-patch20010301-orig/Makefile Thu Mar 1 23:33:39 2001 +++ qmail-1.03-patch20010301/Makefile Thu Mar 1 23:52:48 2001 @@ -6,7 +6,7 @@ # -DQLDAP_CLUSTER for enabling cluster support # to use cleartext passwords (a bad idea on production systems) add # -DCLEARTEXTPASSWD to the LDAPFLAGS -LDAPFLAGS=-DQLDAP_CLUSTER +LDAPFLAGS=-DQLDAP_CLUSTER -DMXPS -DSMTP_AFTER_POP -DDASH_EXT # Perhaps you have different ldap libraries, change them here LDAPLIBS=-L/usr/local/lib -lldap -llber diff -u -N qmail-1.03-patch20010301-orig/auth_pop.c qmail-1.03-patch20010301/auth_pop.c --- qmail-1.03-patch20010301-orig/auth_pop.c Thu Mar 1 23:33:39 2001 +++ qmail-1.03-patch20010301/auth_pop.c Thu Mar 1 23:36:07 2001 @@ -15,6 +15,14 @@ #ifdef AUTOHOMEDIRMAKE #include "qldap-mdm.h" #endif +#ifdef SMTP_AFTER_POP +#include +#include + +int child; +int wstat; +char *opensmtp = "/usr/local/bin/pop3-record"; +#endif unsigned int auth_port; @@ -125,8 +133,22 @@ qldap_errno = AUTH_ERROR; auth_error(); } - - /* first set the group id */ + +#ifdef SMTP_AFTER_POP + if (!env_put2("AUTHUSER",login)) { + qldap_errno = ERRNO; + auth_error(); + } + + switch(child = fork()) { + case -1: _exit(111); break; + case 0: execl(opensmtp, opensmtp, 0); _exit(111); break; + } + waitpid(child, &wstat, 0); + if (!WIFEXITED(wstat)) _exit(111); +#endif + + /* first set the group id */ if (prot_gid(gid) == -1) { qldap_errno = AUTH_ERROR; auth_error(); diff -u -N qmail-1.03-patch20010301-orig/qmail-lspawn.c qmail-1.03-patch20010301/qmail-lspawn.c --- qmail-1.03-patch20010301-orig/qmail-lspawn.c Thu Mar 1 23:33:40 2001 +++ qmail-1.03-patch20010301/qmail-lspawn.c Thu Mar 1 23:42:53 2001 @@ -351,6 +351,9 @@ int reply; int at; int i; +#ifdef DASH_EXT + int dash; +#endif int force_forward; char *r; stralloc filter = {0}; @@ -401,37 +404,76 @@ ret = ldap_lookup(&search, attrs, &info, extra); if ( ret != 0 && qldap_errno == LDAP_NOSUCH ) { - /* this handles the "catch all" extension */ + /* extensions: catchall and dash-trick */ at = 0; r = mail->s; i = mail->len; for (at = i - 1; r[at] != '@' && at >= 0 ; at--) ; /* handels also mailwith 2 @ */ - /* build the search string for the email address */ - if (!stralloc_copys(&filter, "")) _exit(QLX_NOMEM); - if (!stralloc_copys(&filter,"(|(" ) ) _exit(QLX_NOMEM); - /* optional objectclass */ - if (qldap_objectclass.len) { - if (!stralloc_cats(&filter,LDAP_OBJECTCLASS)) _exit(QLX_NOMEM); + +#ifdef DASH_EXT + dash=0; + for (dash = at-1; r[dash] != '-' && dash > 0; dash--); + + /* dash trick */ + if ((dash > 0) && (dash < at)) { + if (!stralloc_copys(&filter, "")) _exit(QLX_NOMEM); + if (!stralloc_copys(&filter,"(|(" ) ) _exit(QLX_NOMEM); + /* optional objectclass */ + if (qldap_objectclass.len) { + if (!stralloc_cats(&filter,LDAP_OBJECTCLASS)) _exit(QLX_NOMEM); + if (!stralloc_cats(&filter,"=")) _exit(QLX_NOMEM); + if (!stralloc_cat(&filter,&qldap_objectclass)) _exit(QLX_NOMEM); + if (!stralloc_cats(&filter,")(")) _exit(QLX_NOMEM); + } /* end */ + if (!stralloc_cats(&filter,LDAP_MAIL)) _exit(QLX_NOMEM); if (!stralloc_cats(&filter,"=")) _exit(QLX_NOMEM); - if (!stralloc_cat(&filter,&qldap_objectclass)) _exit(QLX_NOMEM); + if (!stralloc_catb(&filter,r,dash)) _exit(QLX_NOMEM); + if (!stralloc_catb(&filter,r+at, i-at)) _exit(QLX_NOMEM); if (!stralloc_cats(&filter,")(")) _exit(QLX_NOMEM); - } /* end */ - if (!stralloc_cats(&filter,LDAP_MAIL)) _exit(QLX_NOMEM); - if (!stralloc_cats(&filter,"=")) _exit(QLX_NOMEM); - if (!stralloc_cats(&filter,LDAP_CATCH_ALL)) _exit(QLX_NOMEM); - if (!stralloc_catb(&filter,r+at, i-at)) _exit(QLX_NOMEM); - if (!stralloc_cats(&filter,")(")) _exit(QLX_NOMEM); - if (!stralloc_cats(&filter,LDAP_MAILALTERNATE)) _exit(QLX_NOMEM); - if (!stralloc_cats(&filter,"=")) _exit(QLX_NOMEM); - if (!stralloc_cats(&filter,LDAP_CATCH_ALL)) _exit(QLX_NOMEM); - if (!stralloc_catb(&filter,r+at, i-at)) _exit(QLX_NOMEM); - if (!stralloc_cats(&filter,"))")) _exit(QLX_NOMEM); - if (!stralloc_0(&filter)) _exit(QLX_NOMEM); + if (!stralloc_cats(&filter,LDAP_MAILALTERNATE)) _exit(QLX_NOMEM); + if (!stralloc_cats(&filter,"=")) _exit(QLX_NOMEM); + if (!stralloc_catb(&filter,r,dash)) _exit(QLX_NOMEM); + if (!stralloc_catb(&filter,r+at, i-at)) _exit(QLX_NOMEM); + if (!stralloc_cats(&filter,"))")) _exit(QLX_NOMEM); + if (!stralloc_0(&filter)) _exit(QLX_NOMEM); + + debug(16, "retry with filter '%s'\n", filter.s); + /* do the search */ + ret = ldap_lookup(&search, attrs, &info, extra); + } + + if (ret != 0 && qldap_errno == LDAP_NOSUCH) { +#endif + /* catchall */ + /* build the search string for the email address */ + if (!stralloc_copys(&filter, "")) _exit(QLX_NOMEM); + if (!stralloc_copys(&filter,"(|(" ) ) _exit(QLX_NOMEM); + /* optional objectclass */ + if (qldap_objectclass.len) { + if (!stralloc_cats(&filter,LDAP_OBJECTCLASS)) _exit(QLX_NOMEM); + if (!stralloc_cats(&filter,"=")) _exit(QLX_NOMEM); + if (!stralloc_cat(&filter,&qldap_objectclass)) _exit(QLX_NOMEM); + if (!stralloc_cats(&filter,")(")) _exit(QLX_NOMEM); + } /* end */ + if (!stralloc_cats(&filter,LDAP_MAIL)) _exit(QLX_NOMEM); + if (!stralloc_cats(&filter,"=")) _exit(QLX_NOMEM); + if (!stralloc_cats(&filter,LDAP_CATCH_ALL)) _exit(QLX_NOMEM); + if (!stralloc_catb(&filter,r+at, i-at)) _exit(QLX_NOMEM); + if (!stralloc_cats(&filter,")(")) _exit(QLX_NOMEM); + if (!stralloc_cats(&filter,LDAP_MAILALTERNATE)) _exit(QLX_NOMEM); + if (!stralloc_cats(&filter,"=")) _exit(QLX_NOMEM); + if (!stralloc_cats(&filter,LDAP_CATCH_ALL)) _exit(QLX_NOMEM); + if (!stralloc_catb(&filter,r+at, i-at)) _exit(QLX_NOMEM); + if (!stralloc_cats(&filter,"))")) _exit(QLX_NOMEM); + if (!stralloc_0(&filter)) _exit(QLX_NOMEM); - debug(16, "retry with filter '%s'\n", filter.s); - /* do the search for the catchall address */ - ret = ldap_lookup(&search, attrs, &info, extra); + debug(16, "retry with filter '%s'\n", filter.s); + /* do the search for the catchall address */ + ret = ldap_lookup(&search, attrs, &info, extra); +#ifdef DASH_EXT + } +#endif } alloc_free(filter.s); filter.s = 0; @@ -525,11 +567,23 @@ } if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); - /* At the moment we ignore the dash-field and the extension field * - * so we fill up the nughde structure with '\0' */ - - if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); - if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); +#ifdef DASH_EXT + /* Here we fill the nughde structure with the dash-field the extension field */ + if ((dash > 0) && (dash < (at-1))) { + if (!stralloc_cats(&nughde,"-")) _exit(QLX_NOMEM); + if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); + if (!stralloc_catb(&nughde,r+dash+1,at-dash-1)) _exit(QLX_NOMEM); + if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); + + } else { +#endif + + if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); + if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); + +#ifdef DASH_EXT + } +#endif /* get the quota for the user of that maildir mbox */ if ( extra[0].vals != 0 ) { diff -u -N qmail-1.03-patch20010301-orig/qmail-remote.c qmail-1.03-patch20010301/qmail-remote.c --- qmail-1.03-patch20010301-orig/qmail-remote.c Thu Mar 1 23:33:40 2001 +++ qmail-1.03-patch20010301/qmail-remote.c Thu Mar 1 23:36:16 2001 @@ -32,8 +32,15 @@ #include "timeoutwrite.h" #endif +#ifdef MXPS +#include +#include "fmt.h" +#endif + #ifdef TLS +#ifndef MXPS #include +#endif #include SSL *ssl = 0; @@ -42,11 +49,10 @@ #define HUGESMTPTEXT 5000 -#ifndef PORT_SMTP /* this is for testing purposes, so you can overwrite - this port via a simple -D argument */ -#define PORT_SMTP 25 /* silly rabbit, /etc/services is for users */ +unsigned long smtp_port = 25; /* silly rabbit, /etc/services is for users */ +#ifdef MXPS +unsigned long qmtp_port = 209; #endif -unsigned long port = PORT_SMTP; GEN_ALLOC_typedef(saa,stralloc,sa,len,a) GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus) @@ -84,6 +90,10 @@ Unable to switch to home directory. (#4.3.0)\n"); zerodie(); } void temp_control() { out("Z\ Unable to read control files. (#4.3.0)\n"); zerodie(); } +#ifdef MXPS +void temp_proto() { out("Z\ +recipient did not talk proper QMTP (#4.3.0)\n"); zerodie(); } +#endif void perm_partialline() { out("D\ SMTP cannot transfer messages with partial final lines. (#5.6.2)\n"); zerodie(); } void perm_usage() { out("D\ @@ -175,10 +185,14 @@ if (r <= 0) dropped(); return r; } - +#ifdef MXPS +char inbuf[1500]; +char smtptobuf[1500]; +#else char inbuf[1024]; -substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf); char smtptobuf[1024]; +#endif +substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf); substdio smtpto = SUBSTDIO_FDBUF(safewrite,-1,smtptobuf,sizeof smtptobuf); char smtpfrombuf[128]; substdio smtpfrom = SUBSTDIO_FDBUF(saferead,-1,smtpfrombuf,sizeof smtpfrombuf); @@ -486,6 +500,115 @@ quit("K"," accepted message"); } +#ifdef MXPS +int qmtp_priority(int pref) +{ + if (pref < 12800) return 0; + if (pref > 13055) return 0; + if (pref % 16 == 1) return 1; + return 0; +} + +void qmtp() +{ + struct stat st; + unsigned long len; + int len2; + char *x; + int i; + int n; + unsigned char ch; + char num[FMT_ULONG]; + int flagallok; + + if (fstat(0,&st) == -1) quit("Z", " unable to fstat stdin"); + len = st.st_size; + + /* the following code was substantially taken from serialmail'ss serialqmtp.c */ + substdio_put(&smtpto,num,fmt_ulong(num,len+1)); + substdio_put(&smtpto,":\n",2); + while (len > 0) { + n = substdio_feed(&ssin); + if (n <= 0) _exit(32); /* wise guy again */ + x = substdio_PEEK(&ssin); + substdio_put(&smtpto,x,n); + substdio_SEEK(&ssin,n); + len -= n; + } + substdio_put(&smtpto,",",1); + + len = sender.len; + substdio_put(&smtpto,num,fmt_ulong(num,len)); + substdio_put(&smtpto,":",1); + substdio_put(&smtpto,sender.s,sender.len); + substdio_put(&smtpto,",",1); + + len = 0; + for (i = 0;i < reciplist.len;++i) + len += fmt_ulong(num,reciplist.sa[i].len) + 1 + reciplist.sa[i].len + 1; + substdio_put(&smtpto,num,fmt_ulong(num,len)); + substdio_put(&smtpto,":",1); + for (i = 0;i < reciplist.len;++i) { + substdio_put(&smtpto,num,fmt_ulong(num,reciplist.sa[i].len)); + substdio_put(&smtpto,":",1); + substdio_put(&smtpto,reciplist.sa[i].s,reciplist.sa[i].len); + substdio_put(&smtpto,",",1); + } + substdio_put(&smtpto,",",1); + substdio_flush(&smtpto); + + flagallok = 1; + + for (i = 0;i < reciplist.len;++i) { + len = 0; + for (;;) { + get(&ch); + if (ch == ':') break; + if (len > 200000000) temp_proto(); + if (ch - '0' > 9) temp_proto(); + len = 10 * len + (ch - '0'); + } + if (!len) temp_proto(); + get(&ch); --len; + if ((ch != 'Z') && (ch != 'D') && (ch != 'K')) temp_proto(); + + if (!stralloc_copyb(&smtptext,&ch,1)) temp_proto(); + if (!stralloc_cats(&smtptext,"qmtp: ")) temp_nomem(); + + while (len > 0) { + get(&ch); + --len; + } + + for (len = 0;len < smtptext.len;++len) { + ch = smtptext.s[len]; + if ((ch < 32) || (ch > 126)) smtptext.s[len] = '?'; + } + get(&ch); + if (ch != ',') temp_proto(); + smtptext.s[smtptext.len-1] = '\n'; + + if (smtptext.s[0] == 'K') out("r"); + else if (smtptext.s[0] == 'D') { + out("h"); + flagallok = 0; + } + else { /* if (smtptext.s[0] == 'Z') */ + out("s"); + flagallok = 0; + } + if (substdio_put(subfdoutsmall,smtptext.s+1,smtptext.len-1) == -1) temp_noconn(); + zero(); + } + if (!flagallok) { + out("DGiving up on ");outhost();out("\n"); + } else { + out("KAll received okay by ");outhost();out("\n"); + } + zerodie(); +} +#endif + stralloc canonhost = {0}; stralloc canonbox = {0}; @@ -574,7 +697,7 @@ if (relayhost) { i = str_chr(relayhost,':'); if (relayhost[i]) { - scan_ulong(relayhost + i + 1,&port); + scan_ulong(relayhost + i + 1,&smtp_port); relayhost[i] = 0; } if (!stralloc_copys(&host,relayhost)) temp_nomem(); @@ -633,8 +756,21 @@ /* performace hack to send TCP ACK's without delay */ setsockopt(smtpfd, IPPROTO_TCP, TCP_NODELAY, &tcpnodelay, sizeof(tcpnodelay)); - - if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) { + +#ifdef MXPS + if (qmtp_priority(ip.ix[i].pref)) { + if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) qmtp_port,timeoutconnect) == 0) { + tcpto_err(&ip.ix[i].ip,0); + partner = ip.ix[i].ip; + qmtp(); /* does not return */ + } + close(smtpfd); /* in case of failure: it is not allowed to call connect twice on the same socket */ + smtpfd = socket(AF_INET,SOCK_STREAM,0); + if (smtpfd == -1) temp_oserr(); + } +#endif + + if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) smtp_port,timeoutconnect) == 0) { tcpto_err(&ip.ix[i].ip,0); partner = ip.ix[i].ip; #ifdef TLS