File qmailtoaster-1.3.1.patch of Package qmail-toaster
qmailtoaster-1.3.1.patch May 10, 2006
Nick Hemmesch <nick@ndhsoft.com>
http://www.qmailtoaster.com
~~~~~~~~~~~~~ Patches Applied ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
qmail-1.03 patched to netqmail-1.05
-----------------------------------
QMAILQUEUE patch
qmail-local patch
local IP 0.0.0.0 patch
sendmail -f patch
Andrew St. Jean - qregex-starttls-2way-auth-20060305
http://www.arda.homeunix.net/store/qmail/
Frederik Vermeulen - qmail-tls 20060104
http://inoa.net/qmail-tls/
Erwin Hoffman - SMTP-AUTH Version 0.57
http://www.fehcom.de/qmail/
Robert Sander - qmail-remote-auth
http://www.ornl.gov/lists/mailing-lists/qmail/2002/03/msg00091.html
Antonio Nati - chkuser-2.0.8b
http://www.interazioni.it/opensource/chkuser/
Chris christophe@saout.de - qmail-spf.rc5
http://www.saout.de/misc/spf/
Russ Nelson - qmail-1.03-dk-0.54 domainkeys patch
http://www.qmail.org/qmail-1.03-dk-0.54.patch
Jeremy Kister - qmail-dk-0.54-auth patch
http://jeremy.kister.net/code/qmail-dk-0.54-auth.patch
Erwin Hoffmann - warlord-1.3.11
http://www.fehcom.de/qmail/
Bill Shupp - netqmail-maildir++.patch
http://shupp.org/patches/netqmail-maildir++.patch
Bill Shupp - custom-smtp-reject
http://www.shupp.org/patches/custom.patch
Johannes Erdfelt - big-concurrency patch
http://qmail.org/big-concurrency.patch
Inter7 - qmailtap-1.1 tap
http://www.inter7.com/qmailtap/qmail-tap-1.1.diff
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff -Naur ./badloadertypes ../qmail-1.03-build-10/badloadertypes
--- ./badloadertypes 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/badloadertypes 2005-01-29 06:08:50.000000000 -0600
@@ -0,0 +1,4 @@
+Mi5kb
+MzIuZ
+MyLmR
+MyLkR
diff -Naur ./badmimetypes ../qmail-1.03-build-10/badmimetypes
--- ./badmimetypes 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/badmimetypes 2005-01-29 06:09:25.000000000 -0600
@@ -0,0 +1,12 @@
+TVqQAAMAA
+TVpQAAIAA
+TVpAALQAc
+TVpyAXkAX
+TVrmAU4AA
+TVrhARwAk
+TVoFAQUAA
+TVoAAAQAA
+TVoIARMAA
+TVouARsAA
+TVrQAT8AA
+TVoAAAEAA
diff -Naur ./base64.c ../qmail-1.03-build-10/base64.c
--- ./base64.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/base64.c 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,122 @@
+#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 p = 0;
+ int n;
+ unsigned int x;
+ int i, j;
+ char *s;
+ unsigned char b[3];
+
+ if (l == 0)
+ {
+ if (!stralloc_copys(out,"")) return -1;
+ return 0;
+ }
+
+ while(in[l-1] == B64PAD) {
+ p ++;
+ l--;
+ }
+
+ n = (l + p) / 4;
+ out->len = (n * 3) - p;
+ if (!stralloc_ready(out,out->len)) return -1;
+ s = out->s;
+
+ for(i = 0; i < n - 1 ; i++) {
+ x = 0;
+ for(j = 0; j < 4; j++) {
+ if(in[j] >= 'A' && in[j] <= 'Z')
+ x = (x << 6) + (unsigned int)(in[j] - 'A' + 0);
+ else if(in[j] >= 'a' && in[j] <= 'z')
+ x = (x << 6) + (unsigned int)(in[j] - 'a' + 26);
+ else if(in[j] >= '0' && in[j] <= '9')
+ x = (x << 6) + (unsigned int)(in[j] - '0' + 52);
+ else if(in[j] == '+')
+ x = (x << 6) + 62;
+ else if(in[j] == '/')
+ x = (x << 6) + 63;
+ else if(in[j] == '=')
+ x = (x << 6);
+ }
+
+ s[2] = (unsigned char)(x & 255); x >>= 8;
+ s[1] = (unsigned char)(x & 255); x >>= 8;
+ s[0] = (unsigned char)(x & 255); x >>= 8;
+ s += 3; in += 4;
+ }
+
+ x = 0;
+ for(j = 0; j < 4; j++) {
+ if(in[j] >= 'A' && in[j] <= 'Z')
+ x = (x << 6) + (unsigned int)(in[j] - 'A' + 0);
+ else if(in[j] >= 'a' && in[j] <= 'z')
+ x = (x << 6) + (unsigned int)(in[j] - 'a' + 26);
+ else if(in[j] >= '0' && in[j] <= '9')
+ x = (x << 6) + (unsigned int)(in[j] - '0' + 52);
+ else if(in[j] == '+')
+ x = (x << 6) + 62;
+ else if(in[j] == '/')
+ x = (x << 6) + 63;
+ else if(in[j] == '=')
+ x = (x << 6);
+ }
+
+ b[2] = (unsigned char)(x & 255); x >>= 8;
+ b[1] = (unsigned char)(x & 255); x >>= 8;
+ b[0] = (unsigned char)(x & 255); x >>= 8;
+
+ for(i = 0; i < 3 - p; i++)
+ s[i] = b[i];
+
+ 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 -Naur ./base64.h ../qmail-1.03-build-10/base64.h
--- ./base64.h 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/base64.h 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,7 @@
+#ifndef BASE64_H
+#define BASE64_H
+
+extern int b64decode();
+extern int b64encode();
+
+#endif
diff -Naur ./byte_cspn.c ../qmail-1.03-build-10/byte_cspn.c
--- ./byte_cspn.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/byte_cspn.c 2006-05-05 21:22:33.000000000 -0500
@@ -0,0 +1,11 @@
+#include "byte.h"
+
+unsigned int byte_cspn(s,n,c)
+register char *s;
+register unsigned int n;
+register char *c;
+{
+ while(*c)
+ n = byte_chr(s,n,*c++);
+ return n;
+}
diff -Naur ./byte.h ../qmail-1.03-build-10/byte.h
--- ./byte.h 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/byte.h 2006-05-07 10:26:22.000000000 -0500
@@ -3,6 +3,8 @@
extern unsigned int byte_chr();
extern unsigned int byte_rchr();
+extern unsigned int byte_cspn();
+extern unsigned int byte_rcspn();
extern void byte_copy();
extern void byte_copyr();
extern int byte_diff();
diff -Naur ./byte_rcspn.c ../qmail-1.03-build-10/byte_rcspn.c
--- ./byte_rcspn.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/byte_rcspn.c 2006-05-05 21:22:37.000000000 -0500
@@ -0,0 +1,17 @@
+#include "byte.h"
+
+unsigned int byte_rcspn(s,n,c)
+register char *s;
+register unsigned int n;
+register char *c;
+{
+ unsigned int ret,pos,i;
+
+ for(ret = n,pos = 0;*c;++c) {
+ i = byte_rchr(s + pos,n - pos,*c) + pos;
+ if (i < n) ret = pos = i;
+ }
+
+ return ret;
+}
+
diff -Naur ./case_startb.c ../qmail-1.03-build-10/case_startb.c
--- ./case_startb.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/case_startb.c 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,21 @@
+#include "case.h"
+
+int case_startb(s,len,t)
+register char *s;
+unsigned int len;
+register char *t;
+{
+ register unsigned char x;
+ register unsigned char y;
+
+ for (;;) {
+ y = *t++ - 'A';
+ if (y <= 'Z' - 'A') y += 'a'; else y += 'A';
+ if (!y) return 1;
+ if (!len) return 0;
+ --len;
+ x = *s++ - 'A';
+ if (x <= 'Z' - 'A') x += 'a'; else x += 'A';
+ if (x != y) return 0;
+ }
+}
diff -Naur ./cdbmake_add.c ../qmail-1.03-build-10/cdbmake_add.c
--- ./cdbmake_add.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/cdbmake_add.c 2006-04-24 21:24:32.000000000 -0500
@@ -1,3 +1,4 @@
+#include "alloc.h"
#include "cdbmake.h"
void cdbmake_init(cdbm)
diff -Naur ./cdb_seek.c ../qmail-1.03-build-10/cdb_seek.c
--- ./cdb_seek.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/cdb_seek.c 2006-04-24 21:24:32.000000000 -0500
@@ -1,6 +1,5 @@
#include <sys/types.h>
#include <errno.h>
-extern int errno;
#include "cdb.h"
#ifndef SEEK_SET
diff -Naur ./CHANGES ../qmail-1.03-build-10/CHANGES
--- ./CHANGES 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/CHANGES 2006-04-24 21:24:32.000000000 -0500
@@ -1,3 +1,24 @@
+20040121 version: netqmail 1.05
+20040121 code: qmail-smtpd is protected from exceedingly long (eg 2GB)
+ header lines
+20040121 code: qmail_lspawn, qmail-newmrh, qmail-newu, and qmail-rspawn
+ are protected from misbehaving on hosts where the size of an
+ integer is not the same as the size of a character pointer
+ (eg 64 bit hosts with 32 bit ints)
+20031027 version: netqmail 1.04.
+20031027 doc: INSTALL points to http://lifewithqmail.org/lwq.html
+20031027 doc: qmail.7 identifies installation as netqmail and points to
+ http://qmail.org/
+20031027 doc: qmail-queue.8 adds explanation of $QMAILQUEUE
+20031027 doc: qmail-log.5 adds reference to errors from $QMAILQUEUE script
+20031027 doc: FAQ also points to http://cr.yp.to/qmail/faq.html and
+ http://qmail.org/
+20031027 code: qmail-smtpd identifies itself as netqmail
+20031027 code: if $QMAILQUEUE is set, it's invoked instead of qmail-queue
+20031024 code: changed errno from int to #include.
+20031024 code: fixed .qmail parsing bug.
+20031024 code: recognize 0.0.0.0 as a local address.
+20031024 code: sendmail's -f flag now overrides environment variables.
19980615 version: qmail 1.03.
19980614 doc: eliminated BIN.setup in favor of a web page.
19980614 code: added other auto* to qmail-showctl output.
diff -Naur ./chkspawn.c ../qmail-1.03-build-10/chkspawn.c
--- ./chkspawn.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/chkspawn.c 2006-05-05 19:36:34.000000000 -0500
@@ -22,8 +22,8 @@
_exit(1);
}
- if (auto_spawn > 255) {
- substdio_puts(subfderr,"Oops. You have set conf-spawn higher than 255.\n");
+ if (auto_spawn > 65000) {
+ substdio_puts(subfderr,"Oops. You have set conf-spawn higher than 65000.\n");
substdio_flush(subfderr);
_exit(1);
}
diff -Naur ./chkuser.c ../qmail-1.03-build-10/chkuser.c
--- ./chkuser.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/chkuser.c 2006-04-25 13:54:57.000000000 -0500
@@ -0,0 +1,1156 @@
+
+/*
+ *
+ * 'chkuser.c' v.2.0.8
+ * for qmail/netqmail > 1.0.3 and vpopmail > 5.3.x
+ *
+ * Author: Antonio Nati tonix@interazioni.it
+ * All rights on this software and
+ * the identifying words chkusr and chkuser kept by the author
+ *
+ * This software may be freely used, modified and distributed,
+ * but this lines must be kept in every original or derived version.
+ * Original author "Antonio Nati" and the web URL
+ * "http://www.interazioni.it/opensource"
+ * must be indicated in every related work or web page
+ *
+ */
+
+#include <pwd.h>
+
+/* required by vpopmail */
+#include <stdio.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dns.h"
+#include "env.h"
+#include "ipme.h"
+#include "now.h"
+#include "open.h"
+#include "subfd.h"
+#include "substdio.h"
+#include "stralloc.h"
+
+#include "/home/vpopmail/include/vpopmail.h"
+#include "/home/vpopmail/include/vauth.h"
+#include "/home/vpopmail/include/vpopmail_config.h"
+
+#include "chkuser.h"
+#include "chkuser_settings.h"
+
+#if defined _exit
+#undef _exit
+#endif
+
+extern void flush();
+extern void out (char *s);
+
+extern char *remotehost;
+extern char *remoteip;
+extern char *remoteinfo;
+extern char *relayclient;
+extern char *fakehelo;
+
+extern void die_nomem();
+
+#define DIE_NOMEM() die_nomem()
+
+#if defined CHKUSER_DEBUG
+
+#if defined CHKUSER_DEBUG_STDERR
+
+#define CHKUSER_DBG(a) write (STDERR_FILENO, a, strlen (a))
+#define CHKUSER_DBG_INT(a) { int x; char str[30]; sprintf (str, "%d", a); write (STDERR_FILENO, str, strlen (str));}
+
+#else
+
+#define CHKUSER_DBG(a) write (STDOUT_FILENO, a, strlen (a))
+#define CHKUSER_DBG_INT(a) { int x; char str[30]; sprintf (str, "%d", a); write (STDOUT_FILENO, str, strlen (str));}
+
+#endif
+#else
+
+#define CHKUSER_DBG(a) /* DBG dummy */
+#define CHKUSER_DBG_INT(a) /* DBG dummy */
+
+#endif
+
+static int INTRUSION_threshold_reached = 0;
+static int first_time_init_flag = 1;
+
+static int recipients = 0;
+static int wrong_recipients = 0;
+
+static stralloc user = {0};
+static stralloc domain = {0};
+static stralloc domain_path = {0};
+static stralloc tmp_path = {0};
+static stralloc alias_path = {0};
+
+#if defined CHKUSER_IDENTIFY_REMOTE_VARIABLE
+ static char *identify_remote;
+#endif
+
+#if defined CHKUSER_ENABLE_EXTENSIONS
+#define CHKUSER_ENABLE_USERS_EXTENSIONS
+#endif
+
+#if defined CHKUSER_ENABLE_LISTS
+#define CHKUSER_ENABLE_EZMLM_LISTS
+#endif
+
+#if defined CHKUSER_EXTENSION_DASH
+#define CHKUSER_USERS_DASH CHKUSER_EXTENSION_DASH
+#endif
+
+
+#if defined CHKUSER_ENABLE_VAUTH_OPEN
+ static int db_already_open = 0;
+#endif
+
+#if !defined CHKUSER_ALWAYS_ON && defined CHKUSER_STARTING_VARIABLE
+ static char *starting_string = 0;
+ static int starting_value = -1;
+#endif
+
+#if defined CHKUSER_RCPT_LIMIT_VARIABLE
+ static char *maxrcpt_string = 0;
+ static int maxrcpt_limit = 0;
+ static int maxrcpt_limit_reached = 0;
+#endif
+
+#if defined CHKUSER_WRONGRCPT_LIMIT_VARIABLE
+ static char *maxwrongrcpt_string = 0;
+ static int maxwrongrcpt_limit = 0;
+ static int maxwrongrcpt_limit_reached = 0;
+#endif
+
+#if defined CHKUSER_MBXQUOTA_VARIABLE
+ static char *maxmbxquota_string = 0;
+ static int maxmbxquota_limit = 0;
+#endif
+
+#if defined CHKUSER_SENDER_NOCHECK_VARIABLE
+
+ static unsigned int sender_nocheck = 0;
+
+#endif
+
+#if defined CHKUSER_SENDER_FORMAT || defined CHKUSER_SENDER_MX
+static stralloc sender_user = {0};
+static stralloc sender_domain = {0};
+#endif
+
+
+#if defined CHKUSER_ERROR_DELAY
+
+ static int chkuser_delay_interval = CHKUSER_ERROR_DELAY * 1000;
+
+#define CHKUSER_DELAY() chkuser_delay()
+
+void chkuser_delay (void) {
+
+ usleep (chkuser_delay_interval);
+
+#if defined CHKUSER_ERROR_DELAY_INCREASE
+ chkuser_delay_interval += CHKUSER_ERROR_DELAY_INCREASE * 1000;
+#endif
+}
+
+#if defined CHKUSER_RCPT_DELAY_ANYERROR
+#define CHKUSER_RCPT_DELAY_ANY() chkuser_delay()
+#else
+#define CHKUSER_RCPT_DELAY_ANY() /* no delay for any error */
+#endif
+
+#if defined CHKUSER_SENDER_DELAY_ANYERROR
+#define CHKUSER_SENDER_DELAY_ANY() chkuser_delay()
+#else
+#define CHKUSER_SENDER_DELAY_ANY() /* no delay for any error */
+#endif
+
+
+#else
+#define CHKUSER_DELAY() /* no delay */
+#define CHKUSER_RCPT_DELAY_ANY() /* no delay */
+#define CHKUSER_SENDER_DELAY_ANY() /* no delay */
+#endif
+
+#if defined CHKUSER_ENABLE_LOGGING
+
+static stralloc logstr = { 0 };
+
+static void chkuser_commonlog (char *sender, char *rcpt, char *title, char *description) {
+
+ substdio_puts (subfderr, "CHKUSER ");
+ substdio_puts (subfderr, title);
+ substdio_puts (subfderr, ": from <");
+ substdio_puts (subfderr, sender);
+ substdio_puts (subfderr, ":" );
+ if (remoteinfo) {
+ substdio_puts (subfderr, remoteinfo);
+ }
+ substdio_puts (subfderr, ":" );
+#if defined CHKUSER_IDENTIFY_REMOTE_VARIABLE
+ if (identify_remote) substdio_puts (subfderr, identify_remote);
+#endif
+ substdio_puts (subfderr, "> remote <");
+ if (fakehelo) substdio_puts (subfderr, fakehelo);
+ substdio_puts (subfderr, ":" );
+ if (remotehost) substdio_puts (subfderr, remotehost);
+ substdio_puts (subfderr, ":" );
+ if (remoteip) substdio_puts (subfderr, remoteip);
+ substdio_puts (subfderr, "> rcpt <");
+ substdio_puts (subfderr, rcpt);
+ substdio_puts (subfderr, "> : ");
+ substdio_puts (subfderr, description);
+ substdio_puts (subfderr, "\n");
+ substdio_flush (subfderr);
+}
+
+#else
+#define chkuser_commonlog(a,b,c,d) /* no log */
+#endif
+
+#if defined CHKUSER_SENDER_FORMAT
+
+static int check_sender_address_format (stralloc *user, stralloc *domain) {
+
+ int x;
+
+ for (x = 0; x < (user->len -1); ++x) {
+ if ((!isalnum (user->s[x]))
+
+#if defined CHKUSER_ALLOW_SENDER_SRS
+ && (user->s[x] != '#')
+ && (user->s[x] != '+')
+#endif
+#if defined CHKUSER_ALLOW_SENDER_CHAR_1
+ && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_1)
+#endif
+#if defined CHKUSER_ALLOW_SENDER_CHAR_2
+ && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_2)
+#endif
+#if defined CHKUSER_ALLOW_SENDER_CHAR_3
+ && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_3)
+#endif
+#if defined CHKUSER_ALLOW_SENDER_CHAR_4
+ && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_4)
+#endif
+#if defined CHKUSER_ALLOW_SENDER_CHAR_5
+ && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_5)
+#endif
+ && (user->s[x] != '_') && (user->s[x] != '-') && (user->s[x] != '.') && (user->s[x] != '=')) {
+ return 0;
+ }
+ }
+
+/*
+ * Be careful, this is a base check
+ * Minimum is x.xx + ending \0
+ * Minimum characters needed are 5
+ */
+#if defined CHKUSER_MIN_DOMAIN_LEN
+ if (domain->len < (CHKUSER_MIN_DOMAIN_LEN +1)) {
+ return 0;
+ }
+#endif
+
+/*
+ * This is a safety check
+ */
+#if defined CHKUSER_MIN_DOMAIN_LEN
+ if (domain->len < 2) {
+ return 0;
+ }
+#endif
+
+ for (x = 0; x < (domain->len -1); ++x) {
+ if ((!isalnum (domain->s[x])) && (domain->s[x] != '-') && (domain->s[x] != '.')) {
+ return 0;
+ }
+ }
+
+ if ((domain->s[0] == '-') || (domain->s[domain->len -2] == '-') || (domain->s[0] == '.') || (domain->s[domain->len -2] == '.')) {
+ return 0;
+ }
+ if (strstr (domain->s, "..") != NULL) {
+ return 0;
+ }
+ if (strncmp (domain->s, "xn--", 4) == 0) {
+ if (strstr (&domain->s[4], "--") != NULL)
+ return 0;
+ } else {
+ if (strstr (domain->s, "--") != NULL)
+ return 0;
+ }
+ if (strstr (domain->s, ".-") != NULL) {
+ return 0;
+ }
+ if (strstr (domain->s, "-.") != NULL) {
+ return 0;
+ }
+ if (strchr (domain->s, '.') == NULL) {
+ return 0;
+ }
+
+ return 1;
+}
+
+#endif
+
+#if defined CHKUSER_RCPT_FORMAT
+
+static int check_rcpt_address_format (stralloc *user, stralloc *domain) {
+
+ int x;
+
+ for (x = 0; x < (user->len -1); ++x) {
+ if ((!isalnum (user->s[x]))
+#if defined CHKUSER_ALLOW_RCPT_SRS
+ && (user->s[x] != '#')
+ && (user->s[x] != '+')
+#endif
+#if defined CHKUSER_ALLOW_RCPT_CHAR_1
+ && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_1)
+#endif
+#if defined CHKUSER_ALLOW_RCPT_CHAR_2
+ && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_2)
+#endif
+#if defined CHKUSER_ALLOW_RCPT_CHAR_3
+ && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_3)
+#endif
+#if defined CHKUSER_ALLOW_RCPT_CHAR_4
+ && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_4)
+#endif
+#if defined CHKUSER_ALLOW_RCPT_CHAR_5
+ && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_5)
+#endif
+
+ && (user->s[x] != '_') && (user->s[x] != '-') && (user->s[x] != '.') && (user->s[x] != '=')) {
+ return 0;
+ }
+ }
+
+/*
+ * Be careful, this is a base check
+ * Minimum is x.xx + ending \0
+ * Minimum characters needed are 5
+ */
+#if defined CHKUSER_MIN_DOMAIN_LEN
+ if (domain->len < (CHKUSER_MIN_DOMAIN_LEN +1)) {
+ return 0;
+ }
+#endif
+
+/*
+ * This is a safety check
+ */
+#if defined CHKUSER_MIN_DOMAIN_LEN
+ if (domain->len < 2) {
+ return 0;
+ }
+#endif
+ for (x = 0; x < (domain->len -1); ++x) {
+ if ((!isalnum (domain->s[x])) && (domain->s[x] != '-') && (domain->s[x] != '.')) {
+ return 0;
+ }
+ }
+
+ if ((domain->s[0] == '-') || (domain->s[domain->len -2] == '-') || (domain->s[0] == '.') || (domain->s[domain->len -2] == '.')) {
+ return 0;
+ }
+ if (strstr (domain->s, "..") != NULL) {
+ return 0;
+ }
+ if (strncmp (domain->s, "xn--", 4) == 0) {
+ if (strstr (&domain->s[4], "--") != NULL)
+ return 0;
+ } else {
+ if (strstr (domain->s, "--") != NULL)
+ return 0;
+ }
+ if (strstr (domain->s, ".-") != NULL) {
+ return 0;
+ }
+ if (strstr (domain->s, "-.") != NULL) {
+ return 0;
+ }
+ if (strchr (domain->s, '.') == NULL) {
+ return 0;
+ }
+
+ return 1;
+}
+
+#endif
+
+#if defined CHKUSER_SENDER_MX || defined CHKUSER_RCPT_MX
+
+static unsigned long mx_random;
+static ipalloc mx_ip = {0};
+
+static int chkuser_mx_lookup (stralloc *domain) {
+
+ int status;
+
+ mx_random = now() + getpid();
+ dns_init(0);
+ status = dns_mxip (&mx_ip, domain, mx_random);
+
+ if (status == DNS_MEM) DIE_NOMEM();
+
+ return status;
+}
+
+#endif
+
+
+void chkuser_cleanup (int exit_value) {
+
+#if defined CHKUSER_DB_CLEANUP
+ vclose ();
+#endif
+ _exit (exit_value);
+}
+
+static void first_time_init (void) {
+
+ char * temp_string;
+
+#if !defined CHKUSER_ALWAYS_ON && defined CHKUSER_STARTING_VARIABLE
+ starting_string = env_get (CHKUSER_STARTING_VARIABLE);
+ if (starting_string) {
+ if (strcasecmp(starting_string, "ALWAYS") == 0) {
+ starting_value = 1;
+ } else if (strcasecmp(starting_string, "DOMAIN") == 0) {
+ starting_value = 0;
+ }
+ } else {
+ starting_string = "";
+ }
+#endif
+
+#if defined CHKUSER_RCPT_LIMIT_VARIABLE
+ maxrcpt_string = env_get (CHKUSER_RCPT_LIMIT_VARIABLE);
+ if (maxrcpt_string) {
+ maxrcpt_limit = atoi (maxrcpt_string);
+ if (maxrcpt_limit < 1) {
+ maxrcpt_limit = 0;
+ }
+ } else {
+ maxrcpt_string = "";;
+ }
+#endif
+
+#if defined CHKUSER_WRONGRCPT_LIMIT_VARIABLE
+ maxwrongrcpt_string = env_get (CHKUSER_WRONGRCPT_LIMIT_VARIABLE);
+ if (maxwrongrcpt_string) {
+ maxwrongrcpt_limit = atoi (maxwrongrcpt_string);
+ if (maxwrongrcpt_limit < 1) {
+ maxwrongrcpt_limit = 0;
+ }
+ } else {
+ maxwrongrcpt_string = "";
+ }
+#endif
+
+#if defined CHKUSER_MBXQUOTA_VARIABLE
+ maxmbxquota_string = env_get (CHKUSER_MBXQUOTA_VARIABLE);
+ if (maxmbxquota_string) {
+ maxmbxquota_limit = atoi (maxmbxquota_string);
+ if (maxmbxquota_limit < 1) {
+ maxmbxquota_limit = 0;
+ }
+ } else {
+ maxmbxquota_string = "";
+ }
+#endif
+
+#if defined CHKUSER_SENDER_NOCHECK_VARIABLE
+
+ temp_string = env_get (CHKUSER_SENDER_NOCHECK_VARIABLE);
+ if (temp_string) {
+ sender_nocheck = 1;
+ } else {
+ sender_nocheck = 0;
+ }
+
+#endif
+
+#if defined CHKUSER_IDENTIFY_REMOTE_VARIABLE
+
+ identify_remote = env_get (CHKUSER_IDENTIFY_REMOTE_VARIABLE);
+ if (identify_remote) {
+ }
+
+#endif
+
+ if (!stralloc_ready (&user, 300)) DIE_NOMEM();
+ if (!stralloc_ready (&domain, 500)) DIE_NOMEM();
+ if (!stralloc_ready (&domain_path, 1000)) DIE_NOMEM();
+ if (!stralloc_ready (&tmp_path, 1000)) DIE_NOMEM();
+ if (!stralloc_ready (&alias_path, 1000)) DIE_NOMEM();
+
+ first_time_init_flag = 0;
+
+}
+
+/*
+ * realrcpt ()
+ *
+ * Returns:
+ *
+ * CHKUSER_OK = 1 = Ok, recipients does exists
+ *
+ * 0 = Not in rcpthosts
+ *
+ * < 0 various errors
+ *
+ *
+ * Parameters:
+ * stralloc *sender = sender address
+ * stralloc *rcpt = rcpt address to check
+ *
+ *
+*/
+
+static int realrcpt (stralloc *sender, stralloc *rcpt)
+{
+ int count;
+ int retstat = CHKUSER_KO;
+ struct vqpasswd *user_passwd = NULL;
+ int fd_file = -1;
+ int read_char;
+ int offset;
+ char read_buf[1024];
+
+#if defined CHKUSER_ENABLE_UIDGID
+ uid_t eff_uid;
+ gid_t eff_gid;
+#endif
+
+#if !defined CHKUSER_ALWAYS_ON && defined CHKUSER_STARTING_VARIABLE
+ if (starting_value == -1) {
+ if (addrallowed()) {
+ return CHKUSER_OK;
+ } else {
+ if (relayclient) {
+ return CHKUSER_RELAYING;
+ }
+
+ return CHKUSER_NORCPTHOSTS;
+ }
+ }
+#endif
+
+ if (INTRUSION_threshold_reached == 1) {
+ return CHKUSER_ERR_INTRUSION_THRESHOLD;
+ }
+
+#if defined CHKUSER_RCPT_LIMIT_VARIABLE
+
+ ++recipients;
+ if ((maxrcpt_limit > 0) && (recipients >= maxrcpt_limit)) {
+ chkuser_commonlog (sender->s, rcpt->s, "intrusion threshold", "max number of allowed rcpt");
+ INTRUSION_threshold_reached = 1;
+ return CHKUSER_ERR_MAXRCPT;
+ }
+#endif
+
+/* Search the '@' character */
+ count = byte_rchr(rcpt->s,rcpt->len,'@');
+
+ if (count < rcpt->len) {
+ if (!stralloc_copyb (&user, rcpt->s, count)) DIE_NOMEM();
+ if (!stralloc_copys (&domain, rcpt->s + count + 1)) DIE_NOMEM();
+ }
+ else {
+ if (!stralloc_copys (&user, rcpt->s)) DIE_NOMEM();
+ domain.len = 0;
+ }
+ if (!stralloc_0 (&user)) DIE_NOMEM();
+ if (!stralloc_0 (&domain)) DIE_NOMEM();
+
+#if defined CHKUSER_ENABLE_UIDGID
+
+/* qmail-smtpd is running now as (effective) qmaild:nofiles */
+/* Save the effective UID & GID (qmaild:nofiles) */
+ eff_uid = geteuid ();
+ eff_gid = getegid ();
+
+/* Now set new effective UID & GID, getting it from real UID & GID (vpopmail:vchkpw) */
+ setegid (getgid());
+ seteuid (getuid());
+
+/* qmail-smtpd is running now as effective vpopmail:vchkpw */
+#endif
+
+
+/*
+ *
+ * Now let's start the test/setting suite
+ *
+ **/
+
+ switch (0) {
+
+ case 0:
+/* These are some preliminary settings */
+ case_lowers (user.s);
+ case_lowers (domain.s);
+
+ case 1:
+
+ if (domain.len == 1) {
+#if defined CHKUSER_DOMAIN_WANTED
+ retstat = CHKUSER_ERR_DOMAIN_MISSING;
+ break;
+#else
+ if (!stralloc_copys (&domain, DEFAULT_DOMAIN)) DIE_NOMEM();
+ if (!stralloc_0 (&domain)) DIE_NOMEM();
+#endif
+ }
+
+ case 2:
+
+#if defined CHKUSER_RCPT_FORMAT
+
+ if (check_rcpt_address_format (&user, &domain) == 0) {
+ retstat = CHKUSER_ERR_RCPT_FORMAT;
+ break;
+ }
+#endif
+
+ case 3:
+
+ if (!addrallowed()) {
+
+#if defined CHKUSER_RCPT_MX
+ switch (chkuser_mx_lookup(&domain)) {
+
+ case DNS_HARD:
+ retstat = CHKUSER_ERR_RCPT_MX;
+ break;
+
+ case DNS_SOFT:
+ retstat = CHKUSER_ERR_RCPT_MX_TMP;
+ break;
+ }
+
+ if (retstat != CHKUSER_KO) {
+ break;
+ }
+#endif
+
+ if (relayclient) {
+ retstat = CHKUSER_RELAYING;
+ break;
+ }
+
+ retstat = CHKUSER_NORCPTHOSTS;
+ break;
+ }
+
+ case 4:
+
+#if defined CHKUSER_ENABLE_VAUTH_OPEN
+ if (db_already_open != 1) {
+ if (vauth_open () == 0) {
+ db_already_open == 1;
+ } else {
+ retstat = CHKUSER_ERR_AUTH_RESOURCE;
+ }
+ };
+#endif
+
+ case 5:
+
+#if defined CHKUSER_ENABLE_VGET_REAL_DOMAIN
+/* Check if domain is a real domain */
+
+ vget_real_domain(domain.s, domain.a);
+
+ domain.len = strlen (domain.s) +1;
+ if (domain.len > (domain.a - 1)) DIE_NOMEM();
+#endif
+
+/* Let's get domain's real path */
+ if (vget_assign(domain.s, domain_path.s, domain_path.a -1, NULL, NULL) == NULL) {
+ retstat = CHKUSER_OK;
+ break;
+ }
+
+ domain_path.len = strlen (domain_path.s);
+
+ case 6:
+
+/* Check if domain has bouncing enabled */
+
+#if !defined CHKUSER_ALWAYS_ON
+
+#if defined CHKUSER_STARTING_VARIABLE
+ if (starting_value == 0) {
+#endif
+
+ if (!stralloc_copy (&tmp_path, &domain_path)) DIE_NOMEM();
+
+#if defined CHKUSER_SPECIFIC_BOUNCING
+ if (!stralloc_cats (&tmp_path, "/")) DIE_NOMEM();
+ if (!stralloc_cats (&tmp_path, CHKUSER_SPECIFIC_BOUNCING)) DIE_NOMEM();
+ if (!stralloc_0 (&tmp_path)) DIE_NOMEM();
+ fd_file = open_read (tmp_path.s);
+ if (fd_file != -1) {
+ close (fd_file);
+ } else {
+ retstat = CHKUSER_OK;
+ break;
+ }
+#else
+ if (!stralloc_cats (&tmp_path, "/.qmail-default")) DIE_NOMEM();
+ if (!stralloc_0 (&tmp_path)) DIE_NOMEM();
+
+ read_char = 0;
+ fd_file = open_read (tmp_path.s);
+ if (fd_file != -1) {
+ read_char = read (fd_file, read_buf, sizeof(read_buf) - 1);
+ close (fd_file);
+ if (read_char < 0) read_char = 0;
+ }
+ read_buf[read_char] = 0;
+
+ if ( strstr(read_buf, CHKUSER_BOUNCE_STRING) == NULL ) {
+ retstat = CHKUSER_OK;
+ break;
+ }
+#endif
+#if defined CHKUSER_STARTING_VARIABLE
+ }
+#endif
+#endif
+
+ case 7:
+#if defined VALIAS
+/* Check for aliases/forwards - valias*/
+
+ if (valias_select (user.s, domain.s) != NULL) {
+ retstat = CHKUSER_OK;
+ break;
+ }
+#endif
+
+ case 8:
+#if defined CHKUSER_ENABLE_ALIAS
+/* Check for aliases/forwards - .qmail.x files */
+
+ if (!stralloc_copy (&tmp_path, &user)) DIE_NOMEM();
+ /* Change all '.' in ':' before continuing on aliases */
+ for (count = 0; count < tmp_path.len; ++count)
+ if (*(tmp_path.s + count) == '.') *(tmp_path.s + count) = ':';
+
+ if (!stralloc_copy (&alias_path, &domain_path)) DIE_NOMEM();
+ if (!stralloc_cats (&alias_path, "/.qmail-")) DIE_NOMEM();
+ if (!stralloc_cats (&alias_path, tmp_path.s)) DIE_NOMEM();
+ if (!stralloc_0 (&alias_path)) DIE_NOMEM();
+
+ fd_file = open_read (alias_path.s);
+ if (fd_file != -1) {
+ close (fd_file);
+ retstat = CHKUSER_OK;
+ break;
+ }
+#endif
+
+ case 9:
+
+#if defined CHKUSER_ENABLE_ALIAS_DEFAULT
+
+ if (!stralloc_copy (&tmp_path, &user)) DIE_NOMEM();
+ /* Change all '.' in ':' before continuing on aliases */
+ for (count = 0; count < tmp_path.len; ++count)
+ if (*(tmp_path.s + count) == '.') *(tmp_path.s + count) = ':';
+
+ /* Search for the outer '-' character */
+ for (offset = user.len - 1; offset > 0; --offset)
+ if (*(user.s + offset) == CHKUSER_USERS_DASH) {
+ if (!stralloc_copy (&alias_path, &domain_path)) die_nomem();
+ if (!stralloc_cats (&alias_path, "/.qmail-")) die_nomem();
+ if (!stralloc_catb (&alias_path, user.s, offset)) die_nomem();
+ if (!stralloc_cats (&alias_path, "-default")) die_nomem();
+ if (!stralloc_0 (&alias_path)) die_nomem();
+
+ fd_file = open_read (alias_path.s);
+ if (fd_file != -1) {
+ close (fd_file);
+ retstat = CHKUSER_OK;
+ break;
+ }
+ }
+
+ if (retstat != CHKUSER_KO) {
+ break;
+ }
+
+#endif
+
+ case 10:
+#if defined CHKUSER_ENABLE_USERS
+/* User control: check the existance of a real user */
+
+ user_passwd = vauth_getpw (user.s, domain.s);
+
+#if defined CHKUSER_ENABLE_USERS_EXTENSIONS
+ if (user_passwd == NULL) {
+ count = 0;
+ while ((count < (user.len -1)) && (user_passwd == NULL)) {
+ count += byte_chr(&user.s[count], user.len - count, CHKUSER_USERS_DASH);
+ if (count < user.len) {
+ if (!stralloc_copyb (&tmp_path, user.s, count)) DIE_NOMEM();
+ if (!stralloc_0 (&tmp_path)) DIE_NOMEM();
+ user_passwd = vauth_getpw (tmp_path.s, domain.s);
+ ++count;
+ }
+ }
+ }
+
+#endif
+ if (user_passwd != NULL) {
+
+ /* If user exists check if he has BOUNCE_MAIL flag set */
+
+ if (user_passwd->pw_gid & BOUNCE_MAIL)
+ retstat = CHKUSER_KO;
+ else {
+ retstat = CHKUSER_OK;
+#if defined CHKUSER_MBXQUOTA_VARIABLE
+ if ((maxmbxquota_limit > 0) && (strcasecmp(user_passwd->pw_shell, "NOQUOTA") != 0)) {
+ if (!stralloc_copys (&tmp_path, user_passwd->pw_dir)) DIE_NOMEM();
+ if (!stralloc_cats (&tmp_path, "/Maildir")) DIE_NOMEM();
+ if (!stralloc_0 (&tmp_path)) DIE_NOMEM();
+
+ if (vmaildir_readquota(tmp_path.s,format_maildirquota(user_passwd->pw_shell))
+ >= maxmbxquota_limit) {
+ retstat = CHKUSER_ERR_MBXFULL;
+ }
+ }
+#endif
+ }
+ break;
+ }
+#endif
+
+ case 11:
+#if defined CHKUSER_ENABLE_EZMLM_LISTS
+/* Let's check for mailing lists */
+
+ /* Search for the outer CHKUSER_EZMLM_DASH character */
+ for (offset = user.len - 2; offset > 0; --offset) {
+ if (*(user.s + offset) == CHKUSER_EZMLM_DASH) {
+ if (!stralloc_copy (&tmp_path, &domain_path)) DIE_NOMEM();
+ if (!stralloc_cats (&tmp_path, "/")) DIE_NOMEM();
+ if (!stralloc_catb (&tmp_path, user.s, offset)) DIE_NOMEM();
+ if (!stralloc_cats (&tmp_path, "/mailinglist")) DIE_NOMEM();
+ if (!stralloc_0 (&tmp_path)) DIE_NOMEM();
+ fd_file = open_read (tmp_path.s);
+ if (fd_file != -1) {
+ close (fd_file);
+ retstat = CHKUSER_OK;
+ break;
+ }
+ }
+ }
+ if (retstat != CHKUSER_KO) {
+ break;
+ }
+#endif
+
+ case 12:
+#if defined CHKUSER_ENABLE_MAILMAN_LISTS
+/* Let's check for mailing lists */
+
+ /* Search for the outer CHKUSER_MAILMAN_DASH character */
+ for (offset = user.len - 2; offset > 0; --offset) {
+ if (*(user.s + offset) == CHKUSER_MAILMAN_DASH) {
+ if (!stralloc_copy (&tmp_path, &domain_path)) DIE_NOMEM();
+ if (!stralloc_cats (&tmp_path, "/")) DIE_NOMEM();
+ if (!stralloc_cats (&alias_path, "/.qmail-")) DIE_NOMEM();
+ if (!stralloc_catb (&tmp_path, user.s, offset)) DIE_NOMEM();
+ if (!stralloc_0 (&tmp_path)) DIE_NOMEM();
+ fd_file = open_read (tmp_path.s);
+ read_char = 0;
+ if (fd_file != -1) {
+ read_char = read (fd_file, read_buf, sizeof(read_buf) - 1);
+ close (fd_file);
+ if (read_char < 0) read_char = 0;
+ }
+ read_buf[read_char] = 0;
+
+ if ( strstr(read_buf, CHKUSER_MAILMAN_STRING) == NULL ) {
+ retstat = CHKUSER_OK;
+ break;
+ }
+
+ }
+ }
+ if (retstat != CHKUSER_KO) {
+ break;
+ }
+#endif
+
+/*
+ * Add this code if another case is following
+ case xx:
+ code ....
+ code ....
+ code ....
+ code ....
+
+ if (xxxxxxxx) {
+ retstat != CHKUSER_KO)
+ break;
+ }
+*/
+
+ default:
+ retstat = CHKUSER_KO;
+
+ } /* end switch */
+
+#if defined CHKUSER_ENABLE_UIDGID
+/* Now switch back effective to saved UID & GID (qmaild:nofiles) */
+
+ setegid (eff_gid);
+ seteuid (eff_uid);
+
+/* qmail-smtpd is running again as (effective) qmaild:nofiles */
+#endif
+
+ return retstat;
+
+}
+
+
+
+/*
+ * chkuser_realrcpt ()
+ *
+ * Returns a simple status:
+ *
+ * CHKUSER_OK = 1 = Ok, recipients does exists
+ *
+ * CHKUSER_NORCPTHOSTS = Not in rcpthosts
+ *
+ * CHKUSER_KO = ERROR
+ *
+ *
+ * Parameters:
+ * stralloc *sender = sender address
+ * stralloc *rcpt = rcpt address to check
+ *
+ *
+*/
+
+int chkuser_realrcpt (stralloc *sender, stralloc *rcpt) {
+
+int retstat;
+
+ if (first_time_init_flag) {
+ first_time_init ();
+ }
+
+ retstat = realrcpt (sender, rcpt);
+
+ switch (retstat) {
+
+ case CHKUSER_OK:
+#if defined CHKUSER_LOG_VALID_RCPT
+ chkuser_commonlog (sender->s, rcpt->s, "accepted rcpt", "found existing recipient");
+#endif
+ return CHKUSER_OK;
+ break;
+
+ case CHKUSER_RELAYING:
+#if defined CHKUSER_LOG_VALID_RCPT
+ chkuser_commonlog (sender->s, rcpt->s, "relaying rcpt", "client allowed to relay");
+#endif
+ return CHKUSER_RELAYING;
+ break;
+
+ case CHKUSER_NORCPTHOSTS:
+ chkuser_commonlog (sender->s, rcpt->s, "rejected relaying", "client not allowed to relay");
+ CHKUSER_RCPT_DELAY_ANY();
+ out(CHKUSER_NORELAY_STRING);
+ break;
+
+ case CHKUSER_KO:
+ chkuser_commonlog (sender->s, rcpt->s, "rejected rcpt", "not existing recipient");
+ CHKUSER_DELAY();
+ out(CHKUSER_NORCPT_STRING);
+ break;
+
+ case CHKUSER_ERR_AUTH_RESOURCE:
+ chkuser_commonlog (sender->s, rcpt->s, "no auth resource", "no auth resource available");
+ CHKUSER_RCPT_DELAY_ANY();
+ out(CHKUSER_RESOURCE_STRING);
+ break;
+
+ case CHKUSER_ERR_MBXFULL:
+ chkuser_commonlog (sender->s, rcpt->s, "mbx overquota", "rcpt mailbox is overquota");
+ CHKUSER_RCPT_DELAY_ANY();
+ out(CHKUSER_MBXFULL_STRING);
+ break;
+
+ case CHKUSER_ERR_MAXRCPT:
+ chkuser_commonlog (sender->s, rcpt->s, "rejected rcpt", "max number of recipients");
+ CHKUSER_DELAY ();
+ out(CHKUSER_MAXRCPT_STRING);
+ break;
+
+ case CHKUSER_ERR_MAXWRONGRCPT:
+ chkuser_commonlog (sender->s, rcpt->s, "rejected rcpt", "max number of invalid recipients");
+ CHKUSER_DELAY ();
+ out(CHKUSER_MAXWRONGRCPT_STRING);
+ break;
+
+ case CHKUSER_ERR_INTRUSION_THRESHOLD:
+ chkuser_commonlog (sender->s, rcpt->s, "rejected intrusion", "rcpt ignored, session over INTRUSION threshold");
+ CHKUSER_DELAY ();
+ out(CHKUSER_INTRUSIONTHRESHOLD_STRING);
+ break;
+
+ case CHKUSER_ERR_DOMAIN_MISSING:
+ CHKUSER_DELAY ();
+ out(CHKUSER_DOMAINMISSING_STRING);
+ break;
+
+ case CHKUSER_ERR_RCPT_FORMAT:
+ chkuser_commonlog (sender->s, rcpt->s, "rejected rcpt", "invalid rcpt address format");
+ CHKUSER_RCPT_DELAY_ANY();
+ out(CHKUSER_RCPTFORMAT_STRING);
+ break;
+
+ case CHKUSER_ERR_RCPT_MX:
+ chkuser_commonlog (sender->s, rcpt->s, "rejected rcpt", "invalid rcpt MX domain");
+ CHKUSER_RCPT_DELAY_ANY();
+ out(CHKUSER_RCPTMX_STRING);
+ break;
+
+ case CHKUSER_ERR_RCPT_MX_TMP:
+ chkuser_commonlog (sender->s, rcpt->s, "rejected rcpt", "temporary DNS problem");
+ CHKUSER_RCPT_DELAY_ANY();
+ out(CHKUSER_RCPTMX_TMP_STRING);
+ break;
+ }
+
+
+
+#if defined CHKUSER_WRONGRCPT_LIMIT_VARIABLE
+ if ((retstat == CHKUSER_KO) || (retstat == CHKUSER_ERR_DOMAIN_MISSING)) {
+ ++wrong_recipients;
+ if ((INTRUSION_threshold_reached == 0) && (maxwrongrcpt_limit > 0) && (wrong_recipients >= maxwrongrcpt_limit)) {
+ chkuser_commonlog (sender->s, rcpt->s, "intrusion threshold", "max number of allowed invalid rcpt");
+ INTRUSION_threshold_reached = 1;
+ }
+ }
+#endif
+
+ return CHKUSER_KO;
+}
+
+
+/*
+ *
+ * This routine checks for sender format and MX
+ *
+ */
+
+
+int chkuser_sender (stralloc *sender) {
+
+int count;
+
+ if (first_time_init_flag) {
+ first_time_init ();
+ }
+
+#if !defined CHKUSER_ALWAYS_ON && defined CHKUSER_STARTING_VARIABLE
+ if (starting_value == -1) {
+ return CHKUSER_OK;
+ }
+#endif
+
+#if defined CHKUSER_SENDER_FORMAT || defined CHKUSER_SENDER_MX
+
+#if defined CHKUSER_SENDER_NOCHECK_VARIABLE
+
+ if (sender_nocheck == 1) {
+ return CHKUSER_OK;
+ }
+#endif
+
+ if (sender->len <= 1) {
+#if defined CHKUSER_LOG_VALID_SENDER
+ chkuser_commonlog (sender->s, "", "accepted null sender", "accepted null sender always");
+#endif
+ return CHKUSER_OK;
+ }
+
+ count = byte_rchr(sender->s,sender->len,'@');
+ if (count < sender->len) {
+ if (!stralloc_copyb (&sender_user, sender->s, count)) DIE_NOMEM();
+ if (!stralloc_copys (&sender_domain, sender->s + count + 1)) DIE_NOMEM();
+ } else {
+ if (!stralloc_copys (&sender_user, sender->s)) DIE_NOMEM();
+ sender_domain.len = 0;
+ }
+ if (!stralloc_0 (&sender_user)) DIE_NOMEM();
+ if (!stralloc_0 (&sender_domain)) DIE_NOMEM();
+
+#if defined CHKUSER_SENDER_FORMAT
+ if (check_sender_address_format (&sender_user, &sender_domain) == 0) {
+ chkuser_commonlog (sender->s, "", "rejected sender", "invalid sender address format");
+ CHKUSER_SENDER_DELAY_ANY();
+ out(CHKUSER_SENDERFORMAT_STRING);
+ return CHKUSER_ERR_SENDER_FORMAT;
+ }
+
+#endif
+
+#if defined CHKUSER_SENDER_MX
+
+ switch (chkuser_mx_lookup(&sender_domain)) {
+
+ case DNS_HARD:
+ CHKUSER_SENDER_DELAY_ANY();
+ out(CHKUSER_SENDERMX_STRING);
+ chkuser_commonlog (sender->s, "", "rejected sender", "invalid sender MX domain");
+ return CHKUSER_ERR_SENDER_MX;
+ break;
+
+ case DNS_SOFT:
+ CHKUSER_SENDER_DELAY_ANY();
+ out(CHKUSER_SENDERMX_TMP_STRING);
+ chkuser_commonlog (sender->s, "", "rejected sender", "temporary DNS problem");
+ return CHKUSER_ERR_SENDER_MX_TMP;
+ break;
+ }
+
+#if defined CHKUSER_LOG_VALID_SENDER
+ chkuser_commonlog (sender->s, "", "accepted sender", "sender accepted");
+#endif
+
+ return CHKUSER_OK;
+#endif
+
+#else
+
+ return CHKUSER_OK;
+
+#endif
+
+}
+
+
diff -Naur ./CHKUSER.changelog ../qmail-1.03-build-10/CHKUSER.changelog
--- ./CHKUSER.changelog 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/CHKUSER.changelog 2004-12-08 19:10:36.000000000 -0600
@@ -0,0 +1,141 @@
+
+CHKUSER 2.0 change log
+
+V 2.0.8 - 7 december 2004
+ Features
+ Freeze of new features of 2.0.7, except null senders behaviour.
+ CHKUSER_ENABLE_NULL_SENDER_WITH_TCPREMOTEHOST is no more available
+ CHKUSER_ENABLE_NULL_SENDER is no more available
+ NULL SENDERS are now always accepted. No option is available to disable
+ this behaviour. Previous chkuser versions broke RFC compatibility on
+ null senders, and complicated real life e-mailing.
+ Logging of null senders <> is now available.
+
+ Bugs corrected
+ Sender controls were not executed if CHKUSER_STARTING_VARIABLE was defined
+ (thanks to Charles Sprickman)
+ Domains not in control/virtualdomains are now explicitely excluded from
+ following cascade checks; in previous versions following cascade
+ checks were done using fake domains paths.
+ vget_assign is now handled correctly (a domain in rcpthosts but not
+ in virtualdomains could have an incorrect path in previous versions
+ (this bug is also in all chkusr versions)
+
+ Defaults changed
+ CHKUSER_RCPT_FORMAT is now undefined as default
+ CHKUSER_RCPT_MX is now undefined as default.
+ CHKUSER_SENDER_FORMAT is now undefined as default
+ CHKUSER_SENDER_MX is now undefined as default.
+ CHKUSER_ERROR_DELAY_INCREASE new default is 300 milliseconds
+
+V 2.0.7 - 25 october 2004
+ Features
+ added vclose() of DB auth connection, overriding
+ qmail-smtpd _exit call
+ improved MX checking; now SOFT failure is handled as
+ temporary error.
+ added #define CHKUSER_RCPTMX_TMP_STRING
+ added #define CHKUSER_SENDERMX_TMP_STRING
+ added handling of mailman mailing lists
+ (and related #define CHKUSER_ENABLE_MAILMAN_LISTS)
+ changed order of checking for recipients:
+ 1 - valias
+ 2 - alias
+ 3 - alias extensions
+ 4 - users
+ 5 - users extensions
+ 6 - lists
+ added #define CHKUSER_ACCEPT_NULL_SENDER (default defined)
+ added #define CHKUSER_ENABLE_ALIAS_DEFAULT (default not defined)
+ enables checking of .qmail-alias-default
+ added #define CHKUSER_IDENTIFY_REMOTE_VARIABLE "CHKUSER_IDENTIFY"
+ in order to allow a easy identification of remote IP
+ (substitutes RELAYCLIENT in chkuser logging)
+ added #define CHKUSER_ALLOW_RCPT_SRS
+ enable usage of "#" and "+" characters within rcpt address
+ added #define CHKUSER_ALLOW_RCPT_CHAR_1 '$'
+ added #define CHKUSER_ALLOW_RCPT_CHAR_2 '%'
+ added #define CHKUSER_ALLOW_RCPT_CHAR_3 ''
+ added #define CHKUSER_ALLOW_RCPT_CHAR_4 '?'
+ added #define CHKUSER_ALLOW_RCPT_CHAR_5 '*'
+ #define CHKUSER_ENABLE_USERS_EXTENSIONS
+ substitutes #define CHKUSER_ENABLE_EXTENSIONS
+ #define CHKUSER_ENABLE_EZMLM_LISTS
+ substitutes #define CHKUSER_ENABLE_LISTS
+ #define CHKUSER_USERS_DASH
+ substitutes #define CHKUSER_EXTENSION_DASH
+
+ Bugs
+ sender address "name@" could cause a crash. Corrected
+ (Thanks to Dmitry Petukhov)
+ Corrected Makefile: now qmail-smtpd.c recompiles if chkuser.h
+ changes
+ Corrected a bug in #endif sequence related to
+ #define CHKUSER_RCPT_FORMAT (thanks to Alex Plainer)
+ Corrected a bug in chkuser_sender; now is not executed when
+ chkuser is disabled
+ Corrected check of format for domains:
+ "xn--" admitted as leading string
+ Deleted correction over usage of RELAYCLIENT variable
+ Previous correction could affect a special
+ feature of RELAYCLIENT (thanks to Alex Pleiner)
+
+ Defaults changed
+ #define CHKUSER_ENABLE_NULL_SENDER_WITH_TCPREMOTEHOST (default undefined)
+
+
+V 2.0.6 - 25 september 2004
+ No bugs, just doc updates and an empty patch file corrected
+
+ #define CHKUSER_ENABLE_VGET_REAL_DOMAIN was existing and working in code,
+ but not reported both in docs and inside chkuser_settings.h
+ (default is commented, but this #define is important)
+ patch for toaster-0.6-1 was empty. Now the correct one is provided
+
+V 2.0.5 - 23 september 2004
+ This is the first public release.
+
+ added #define CHKUSER_ALLOW_SENDER_CHAR_1 (default not defined)
+ added #define CHKUSER_ALLOW_SENDER_CHAR_2 (default not defined)
+ added #define CHKUSER_ALLOW_SENDER_CHAR_3 (default not defined)
+ added #define CHKUSER_ALLOW_SENDER_CHAR_4 (default not defined)
+ added #define CHKUSER_ALLOW_SENDER_CHAR_5 (default not defined)
+ added #define CHKUSER_MIN_DOMAIN_LEN (default defined 4) -
+ Previously it was hard coded as 5. Juergen Kendzorra
+ showed me some existing names long only 4 chars.
+ added #define CHKUSER_LOG_VALID_SENDER (default defined)
+
+V 2.0.4 - 15 september 2004
+
+ added #define CHKUSER_SENDER_NOCHECK_VARIABLE (default not defined)
+ added #define CHKUSER_DEBUG_STDERR (default not defined)
+ added #define CHKUSER_ALLOW_SENDER_SRS (default not defined)
+ cleaned some typos in code and documentation (thanks to Juergen
+ Kendzorra - http://www.kendzorra.de)
+
+
+V 2.0.3 - 8 september 2004
+ This is the first version released outside, for wider testing.
+
+ Tested Makefile for netqmail 1.05
+ Added Makefiles for applying over other patches
+
+V 2.0.0 - july 2004
+ chkuser 2.0.0 starts here, and is a private internal release.
+ Version 2.0 is much more modular than previous one (named chkusr),
+ and has been designed with the goal of enabling more features and
+ semplifying installations and upgrades of the patch himself.
+
+ chkusr changes his name, to reflect a deep change of the patch.
+
+ Chkusr 1.0 received a lot of feedbacks and suggestions.
+ The most of these suggestions are now inside version 2.0.
+
+ - Marcelo Coelho (marcelo at tpn.com.br), segnaled me some
+ unseen minor bugs of chkusr 1.0 (minor but very annoying to
+ my pride) and suggested some very interesting features
+ (some of them are now in chkuser 2.0).
+ - Iulian Margarintescu (http:://www.erata.net) suggested a
+ workable way of introducing quota check on recipients
+ (now in chkuser 2.0).
+
diff -Naur ./CHKUSER.copyright ../qmail-1.03-build-10/CHKUSER.copyright
--- ./CHKUSER.copyright 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/CHKUSER.copyright 2004-12-08 19:10:36.000000000 -0600
@@ -0,0 +1,15 @@
+
+chkuser for qmail/netqmail > 1.0.3 and vpopmail > 5.3.x
+
+Author: Antonio Nati tonix@interazioni.it
+
+All rights on this software and
+the identifying words chkusr and chkuser kept by the author
+
+This software may be freely used, modified and distributed,
+but this lines must be kept in every original or derived version.
+
+Original author "Antonio Nati" and the web URL
+"http://www.interazioni.it/opensource"
+must be indicated in every related work or web page
+
diff -Naur ./chkuser.h ../qmail-1.03-build-10/chkuser.h
--- ./chkuser.h 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/chkuser.h 2006-04-24 21:29:10.000000000 -0500
@@ -0,0 +1,51 @@
+
+/*
+ *
+ * 'chkuser.h' v.2.0.8
+ * for qmail/netqmail > 1.0.3 and vpopmail > 5.3.x
+ *
+ * Author: Antonio Nati tonix@interazioni.it
+ * All rights on this software and
+ * the identifying words chkusr and chkuser kept by the author
+ *
+ * This software may be freely used, modified and distributed,
+ * but this lines must be kept in every original or derived version.
+ * Original author "Antonio Nati" and the web URL
+ * "http://www.interazioni.it/opensource"
+ * must be indicated in every related work or web page
+ *
+ */
+
+#define CHKUSER
+#define CHKUSER_VERSION "2.0.8"
+#define CHKUSER_VERSION_RL 2
+#define CHKUSER_VERSION_MJ 0
+#define CHKUSER_VERSION_MN 8
+
+#define CHKUSER_OK 1
+#define CHKUSER_RELAYING 0
+#define CHKUSER_KO -1
+#define CHKUSER_NORCPTHOSTS -10
+#define CHKUSER_ERR_AUTH_RESOURCE -20
+#define CHKUSER_ERR_MBXFULL -30
+#define CHKUSER_ERR_MAXRCPT -40
+#define CHKUSER_ERR_MAXWRONGRCPT -50
+#define CHKUSER_ERR_DOMAIN_MISSING -60
+#define CHKUSER_ERR_RCPT_FORMAT -70
+#define CHKUSER_ERR_RCPT_MX -75
+#define CHKUSER_ERR_RCPT_MX_TMP -76
+#define CHKUSER_ERR_SENDER_FORMAT -80
+#define CHKUSER_ERR_SENDER_MX -85
+#define CHKUSER_ERR_SENDER_MX_TMP -86
+#define CHKUSER_ERR_INTRUSION_THRESHOLD -90
+
+void chkuser_cleanup (int exit_value);
+int chkuser_realrcpt (stralloc *sender, stralloc *rcpt);
+int chkuser_sender (stralloc *sender);
+
+#ifdef TLS_H
+#undef _exit
+#define _exit(value) { if (ssl) ssl_free(ssl); chkuser_cleanup(value); }
+#else
+#define _exit(value) chkuser_cleanup(value);
+#endif
diff -Naur ./CHKUSER.log_format ../qmail-1.03-build-10/CHKUSER.log_format
--- ./CHKUSER.log_format 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/CHKUSER.log_format 2004-12-08 19:10:36.000000000 -0600
@@ -0,0 +1,58 @@
+
+chkuser 2.0.8 logging format
+
+When #defines for logging are enabled, chkuser patch emits log informations
+on the same qmail-smtpd log destination
+
+This is the log format:
+
+ CHKUSER "brief message": \
+ from <sender:remoteinfo:relayclient> \
+ remote <helo:remotehostname:remotehostip> \
+ rcpt <recipient> : "extended message"
+
+where
+ brief message
+ * accepted rcpt
+ * relaying rcpt
+ * rejected relaying
+ * rejected rcpt
+ * no auth resource
+ * mbx overquota
+ * rejected intrusion
+ * intrusion threshold
+ * rejected sender
+
+ sender sender declared within "mail from"
+
+ remoteinfo the value of "TCPREMOTEINFO" or the autenticated user
+
+ relayclient the value of RELAYCLIENT env variable (be careful to set it,
+ inside your tcp.cdb with a value that let you understand who is sending)
+
+ helo helo declared from remote system
+
+ hostname the value of "TCPREMOTEHOST"
+
+ remotehostip the value of "TCPREMOTEIP"
+
+ recipient recipient address
+
+ extended message this field has more wide description for
+ some generic "brief message":
+ accepted rcpt found existing recipient
+ relaying rcpt client allowed to relay
+ rejected relaying client not allowed to relay
+ rejected rcpt not existing recipient
+ rejected rcpt max number of recipients
+ rejected rcpt max number of invalid recipients
+ rejected rcpt invalid rcpt address format
+ rejected rcpt invalid rcpt MX domain
+ intrusion threshold max number of allowed rcpt
+ intrusion threshold max number of allowed invalid rcpt
+ rejected intrusion rcpt ignored, session over intrusion threshold
+ no auth resource no auth resource available
+ mbx overquota rcpt mailbox is overquota
+ rejected sender invalid sender address format
+ rejected sender invalid sender MX domain
+
diff -Naur ./CHKUSER.readme ../qmail-1.03-build-10/CHKUSER.readme
--- ./CHKUSER.readme 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/CHKUSER.readme 2004-12-08 19:10:36.000000000 -0600
@@ -0,0 +1,54 @@
+chkuser 2.0 -README
+
+Description
+===========
+The original qmail-smtpd accepts by default all messages, checking later for
+the existence of the recipient. So, if the message is delivered to not existing
+recipients a lot of additional system work and network traffic are generated,
+with multiple expensive bouncing if the sender is a fake one.
+
+chkuser has been developed with the goal to improve the acceptance SMTP phase
+of qmail-smtpd. qmail-smtpd patched with chkuser may check the existance of
+e-mail recipients immediately in the SMTP acceptance phase of a message and
+rejects istantly all messages not directed to existing users, avoiding
+additional traffic, work and messages bounced more times.
+
+These goals are achieved enquirying the existing vpopmail archives (each
+format is supported: cdb, MySQL, LDAP, etc.) by using standard vpopmail calls,
+or using customized chkuser routines.
+
+Version 2.0 - From chkusr to chkuser
+====================================
+Version 2.0 is a lot different from previous versions, so it deserves a more
+evident change in the name.
+
+Version 2.0 has been designed with the goal to be modular, and to make more easy
+both adding new features to checkuser code and semplifing code update.
+
+Patching over original qmail files is done over a few points, while the most of
+chkuser code remains ouside, in dedicated chkuser's files.
+
+Same for settings, that are inside a dedicated chkuser_settings.h file.
+
+The intention is to semplify upgrading: for future chkuser releases, upgrading
+will require only to update chkuser specific files, leaving all the rest
+untouched, and changing chkuser_settings.h only if new features must be enabled.
+
+Logging and SPAM
+================
+chkuser 2.0 has detailed logging of accepted and refused recipients and senders,
+allowing a deep analysis of "who's sending to who". This can lead to more
+sophisticated future enhancements of anti-SPAM features.
+
+Intrusion rejection
+===================
+chkuser 2.0 can be tuned to reject sessions exceeding some recipients limits
+(limits can be set for max recipients and max not existing recipients).
+
+URL Location
+============
+For any new release, support, FAQ, mailing lists, or other information, see:
+
+ http://www.interazioni.it/opensource
+
+
diff -Naur ./CHKUSER.running ../qmail-1.03-build-10/CHKUSER.running
--- ./CHKUSER.running 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/CHKUSER.running 2004-12-08 19:10:36.000000000 -0600
@@ -0,0 +1,103 @@
+
+CHKUSER 2.0.8 - Running instructions
+
+Chkuser may run using the most of security, following very strictly the sacurity
+model used By Dan Berstein. To achieve this goal, chkuser may switch between
+differents UID/GID, for differente purposes.
+
+However this is incompatible with TLS patches (like toaster-0.6-1), as these patches
+want to run under a unique UID/GID. Luckily, qmail is enought robust to let us
+run this way.
+
+To achieve both these goals, chkuser uses a #define (CHKUSER_ENABLE_UIDGID)
+that indicates if UID/GID switching is wanted, and running instructions must
+adapt to this way.
+
+Instead, when this define is not used, another way of running must be used.
+(Just for precision, even if the CHKUSER_ENABLE_UIDGID define is used, chkuser
+may be run without switching UID/GID).
+
+Running with UID/GID switch
+===========================
+
+If you want the most security when using chkuser, and you have enabled
+CHKUSER_ENABLE_UIDGID within chkuser_settings.h (it's enabled by default), use
+these instructions.
+
+Description.
+ qmail-smtpd-chkusr must be installed (by default in /var/qmail/bin) with
+ setuid (user qmaild) and setgid (group qnofiles), and executed by tcpserver
+ with -u vpopmail-user and -g vchkpw-group parameters.
+
+ qmail-smtpd-chkusr starts running with the original qmail-smtpd uid and gid,
+ switching to needed uid and gid only for vpopmail checks on user existance,
+ turning back to the starting uid and gid.
+
+Instructions.
+ You have to set SUID (set-user-ID-on-execution) and SGID
+ (set-group-ID-on-execution) bits on qmail-smtpd-chkusr:
+ chown qmaild qmail-smtpd
+ chgrp nofiles qmail-smtpd
+ chmod 6555 qmail-smtpd
+
+ and the result you see should be like (different size and date, of course):
+ -r-sr-sr-x 1 qmaild nofiles 57056 Feb 14 18:18 qmail-smtpd-chkusr
+
+ Integrate qmail-smtpd in your start files:
+
+ As example, a real start command for qmail-smtpd-chkusr may be
+
+ #!/bin/sh -e
+ #
+ # Using splogger to send the log through syslog.
+
+ exec env - PATH="/var/qmail/bin:/usr/local/bin" \
+ tcpserver -t 5 -v -p -x <your.tcp.smtp.cdb> \
+ -u <vpopmail-user> -g <vchkpw-group> -l <your-host.domain> 0 smtp \
+ qmail-smtpd-chkusr splogger smtpd &
+
+ where
+ <vpopmail-user> = vpopmail uid
+ <vchkpw-group> = vchkpw gid
+ <your-host.domain> = your host.domain (!)
+ <your.tcp.smtp.cdb> = your tcp.permission.to.relay cdb
+
+ NOTE: if you are using more system users for your domains, the execution
+ uid (which I indicated as vpopmail) should be set to root.
+
+
+Running with fixed UID/GID
+==========================
+You may use these instructions if you've not defined CHKUSER_ENABLE_UIDGID, or if
+you want to run qmail-smtpd as unique user, despite of CHKUSER_ENABLE_UIDGID define.
+qmail-smtpd is well safe and robust, and there is no risk running it directly as
+vpopmail user, unless you use untrusted software layered down.
+
+Description.
+ qmail-smtpd must be installed normally (-r-xr-xr-x) and executed by tcpserver
+ with -u vpopmail-user and -g vchkpw-group parameters.
+
+Instructions.
+ Integrate qmail-smtpd-chkusr in your start files:
+
+ As example, a real start command for qmail-smtpd-chkusr may be
+
+ #!/bin/sh -e
+ #
+ # Using splogger to send the log through syslog.
+
+ exec env - PATH="/var/qmail/bin:/usr/local/bin" \
+ tcpserver -t 5 -v -p -x <your.tcp.smtp.cdb> \
+ -u <vpopmail-user> -g <vchkpw-group> -l <your-host.domain> 0 smtp \
+ qmail-smtpd-chkusr splogger smtpd &
+
+ where
+ <vpopmail-user> = vpopmail uid
+ <vchkpw-group> = vchkpw gid
+ <your-host.domain> = your host.domain (!)
+ <your.tcp.smtp.cdb> = your tcp.permission.to.relay cdb
+
+ NOTE: if you are using more system users for your domains, the execution user
+ (which I indicated as vpopmail) should be set to root.
+
+
diff -Naur ./chkuser_settings.h ../qmail-1.03-build-10/chkuser_settings.h
--- ./chkuser_settings.h 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/chkuser_settings.h 2006-05-05 19:22:07.000000000 -0500
@@ -0,0 +1,373 @@
+
+/*
+ *
+ * 'chkuser_settings.h' v.2.0.8
+ * for qmail/netqmail > 1.0.3 and vpopmail > 5.3.x
+ *
+ * Author: Antonio Nati tonix@interazioni.it
+ * All rights on this software and
+ * the identifying words chkusr and chkuser kept by the author
+ *
+ * This software may be freely used, modified and distributed,
+ * but this lines must be kept in every original or derived version.
+ * Original author "Antonio Nati" and the web URL
+ * "http://www.interazioni.it/opensource"
+ * must be indicated in every related work or web page
+ *
+ */
+
+/*
+ * the following line enables debugging of chkuser
+ */
+/* #define CHKUSER_DEBUG */
+
+/*
+ * The following line moves DEBUG output from STDOUT (default) to STDERR
+ * Example of usage within sh: ./qmail-smtpd 2> /var/log/smtpd-debug.log
+ */
+/* #define CHKUSER_DEBUG_STDERR */
+
+/*
+ * Uncomment the following define if you want chkuser ALWAYS enabled.
+ * If uncommented, it will check for rcpt existance despite any .qmail-default
+ * setting.
+ * So, unsomments this if you are aware that ALL rcpt in all domains will be
+ * ALWAYS checked.
+ */
+/* #define CHKUSER_ALWAYS_ON */
+
+/*
+ * The following defines which virtual manager is used.
+ * Up to know, only vpopmail, but versions with pure qmail are in the mind.
+ */
+#define CHKUSER_VPOPMAIL
+
+/*
+ * Uncomment the following line if you want chkuser to work depending on a VARIABLE setting
+ * VALUE HERE DEFINED is the name of the variable
+ * Values admitted inside the variable: NONE | ALWAYS | DOMAIN
+ * NONE = chkuser will not work
+ * ALWAYS = chkuser will work always
+ * DOMAIN = chkuser will work depending by single domain settings
+ * if CHKUSER_ALWAYS_ON is defined, this define is useless
+ * if CHKUSER_STARTING_VARIABLE is defined, and no variable or no value is set, then chkuser is disabled
+ */
+/* #define CHKUSER_STARTING_VARIABLE "CHKUSER_START" */
+
+/*
+ * Uncomment this to enable uid/gid changing
+ * (switching UID/GID is NOT compatible with TLS; you may keep this commented if you have TLS)
+ */
+/* #define CHKUSER_ENABLE_UIDGID */
+
+/*
+ * Uncomment this to check if a domain is ALWAYS specified in rcpt addresses
+ */
+#define CHKUSER_DOMAIN_WANTED
+
+/*
+ * Uncomment this to check for vpopmail users
+ */
+#define CHKUSER_ENABLE_USERS
+
+/*
+ * Uncomment this to check for alias
+ */
+#define CHKUSER_ENABLE_ALIAS
+
+/*
+ * The following #define set the character used for lists extensions
+ * be careful: this is a single char '-' definition, not a "string"
+ */
+#define CHKUSER_EZMLM_DASH '-'
+
+/*
+ * Uncomment this to set an alternative way to check for bouncing enabling;
+ * with this option enabled, the file here defined
+ * will be searched, inside the domain dir, in order to check if bouncing is enabled
+ * The content of this file is not important, just it's existence is enough
+ */
+/* #define CHKUSER_SPECIFIC_BOUNCING ".qmailchkuser-bouncing" */
+
+/*
+ * This is the string to look for inside .qmail-default
+ * Be careful, chkuser looks within the first 1023 characters of .qmail-default for
+ * this string (despite the line containing the string is working or commented).
+ */
+#define CHKUSER_BOUNCE_STRING "bounce-no-mailbox"
+
+/*
+ * This is to enable auth open checking
+ * it is useful to avoid bouncing if MySQL/LDAP/PostGRES/etc are down or not reachable
+ */
+/* #define CHKUSER_ENABLE_VAUTH_OPEN */
+
+/*
+ * Uncomment to enable logging of rejected recipients and variuos limits reached
+ */
+#define CHKUSER_ENABLE_LOGGING
+
+/*
+ * Uncomment to enable logging of "good" rcpts
+ * valid only if CHKUSER_ENABLE_LOGGING is defined
+ */
+#define CHKUSER_LOG_VALID_RCPT
+
+/*
+ * Uncomment to enable usage of a variable escluding any check on the sender.
+ * The variable should be set in tcp.smtp for clients, with static IP, whose mailer
+ * is composing bad sender addresses
+ */
+/* #define CHKUSER_SENDER_NOCHECK_VARIABLE "SENDER_NOCHECK" */
+
+/*
+ * Uncomment to enable usage of "#" and "+" characters within sender address
+ * This is used by SRS (Sender Rewriting Scheme) products
+ */
+/* #define CHKUSER_ALLOW_SENDER_SRS */
+
+/*
+ * If you need more additional characters to be accepted within sender address
+ * uncomment one of the following #define and edit the character value.
+ * Be careful to use '*' (single hiphen) and NOT "*" (double hiphen) around the
+ * wanted char.
+ */
+/* #define CHKUSER_ALLOW_SENDER_CHAR_1 '$' */
+/* #define CHKUSER_ALLOW_SENDER_CHAR_2 '%' */
+/* #define CHKUSER_ALLOW_SENDER_CHAR_3 '' */
+/* #define CHKUSER_ALLOW_SENDER_CHAR_4 '?' */
+/* #define CHKUSER_ALLOW_SENDER_CHAR_5 '*' */
+
+/*
+ * The following #define sets the minimum length of a domain:
+ * as far as I know, "k.st" is the shortest domain, so 4 characters is the
+ * minimum length.
+ * This value is used to check formally a domain name validity.
+ * if CHKUSER_SENDER_FORMAT is undefined, no check on length is done.
+ * If you comment this define, no check on length is done.
+ */
+#define CHKUSER_MIN_DOMAIN_LEN 4
+
+/*
+ * Uncomment to enable logging of "good" senders
+ * valid only if CHKUSER_ENABLE_LOGGING is defined
+ */
+#define CHKUSER_LOG_VALID_SENDER
+
+/*
+ * Uncomment to define a variable which contains the max recipients number
+ * this will return always error if total recipients exceed this limit.
+ * The first reached, between CHKUSER_RCPT_LIMIT_VARIABLE and CHKUSER_WRONGRCPT_LIMIT_VARIABLE,
+ * makes chkuser rejecting everything else
+ */
+#define CHKUSER_RCPT_LIMIT_VARIABLE "CHKUSER_RCPTLIMIT"
+
+/*
+ * Uncomment to define a variable which contains the max unknown recipients number
+ * this will return always error if not existing recipients exceed this limit.
+ * The first reached, between CHKUSER_RCPT_LIMIT_VARIABLE and CHKUSER_WRONGRCPT_LIMIT_VARIABLE,
+ * makes chkuser rejecting everything else
+ */
+#define CHKUSER_WRONGRCPT_LIMIT_VARIABLE "CHKUSER_WRONGRCPTLIMIT"
+
+/*
+ * Uncomment to define the variable containing the percent to check for.
+ * Remember to define externally (i.e. in tcp.smtp) the environment variable containing
+ * the limit percent.
+ * If the variable is not defined, or it is <= 0, quota checking is not performed.
+ */
+#define CHKUSER_MBXQUOTA_VARIABLE "CHKUSER_MBXQUOTA"
+
+/*
+ * Delay to wait for each not existing recipient
+ * value is expressed in milliseconds
+ */
+#define CHKUSER_ERROR_DELAY 1000
+
+/*
+ * Uncomment to consider rcpt errors on address format and MX as intrusive
+ *
+ */
+#define CHKUSER_RCPT_DELAY_ANYERROR
+
+/*
+ * Uncomment to consider sender errors on address format and MX as intrusive
+ *
+ */
+#define CHKUSER_SENDER_DELAY_ANYERROR
+
+#define CHKUSER_NORCPT_STRING "511 sorry, no mailbox here by that name (#5.1.1 - chkuser)\r\n"
+#define CHKUSER_RESOURCE_STRING "430 system temporary unavailable, try again later (#4.3.0 - chkuser)\r\n"
+#define CHKUSER_MBXFULL_STRING "522 sorry, recipient mailbox is full (#5.2.2 - chkuser)\r\n"
+#define CHKUSER_MAXRCPT_STRING "571 sorry, reached maximum number of recipients for one session (#5.7.1 - chkuser)\r\n"
+#define CHKUSER_MAXWRONGRCPT_STRING "571 sorry, you are violating our security policies (#5.1.1 - chkuser)\r\n"
+#define CHKUSER_DOMAINMISSING_STRING "511 sorry, you must specify a domain (#5.1.1 - chkuser)\r\n"
+#define CHKUSER_RCPTFORMAT_STRING "511 sorry, recipient address has invalid format (#5.1.1 - chkuser)\r\n"
+#define CHKUSER_RCPTMX_STRING "511 sorry, can't find a valid MX for rcpt domain (#5.1.1 - chkuser)\r\n"
+#define CHKUSER_SENDERFORMAT_STRING "571 sorry, sender address has invalid format (#5.7.1 - chkuser)\r\n"
+#define CHKUSER_SENDERMX_STRING "511 sorry, can't find a valid MX for sender domain (#5.1.1 - chkuser)\r\n"
+#define CHKUSER_INTRUSIONTHRESHOLD_STRING "571 sorry, you are violating our security policies (#5.7.1 - chkuser)\r\n"
+#define CHKUSER_NORELAY_STRING "553 sorry, that domain isn't in my list of allowed rcpthosts (#5.5.3 - chkuser)\r\n"
+
+/***************************************************
+ *
+ * new/modified defines in/from 2.0.6
+ *
+ **************************************************/
+
+/*
+ * Before version 5.3.25, vpopmail used the function vget_real_domain()
+ * to get the real name of a domain (useful if rcpt domain is aliasing
+ * another domain).
+ * From version 5.3.25, this call is not available and has been
+ * substituted by other calls.
+ *
+ * must be enabled if vpopmail version< 5.3.5
+ * must be disabled if vpopmail version => 5.3.5 *
+ */
+/* #define CHKUSER_ENABLE_VGET_REAL_DOMAIN */
+
+/***************************************************
+ *
+ * new/modified defines in/from 2.0.7
+ *
+ **************************************************/
+
+/*
+ * Uncomment next define to accept recipients for
+ * aliases that have a -default extension
+ */
+/* #define CHKUSER_ENABLE_ALIAS_DEFAULT */
+
+
+/*
+ * Uncomment to enable usage of "#" and "+" characters within rcpt address
+ * This is used by SRS (Sender Rewriting Scheme) products
+ */
+/* #define CHKUSER_ALLOW_RCPT_SRS */
+
+/*
+ * If you need more additional characters to be accepted within rcpt address
+ * uncomment one of the following #define and edit the character value.
+ * Be careful to use '*' (single hiphen) and NOT "*" (double hiphen) around the
+ * wanted char.
+ */
+/* #define CHKUSER_ALLOW_RCPT_CHAR_1 '$' */
+/* #define CHKUSER_ALLOW_RCPT_CHAR_2 '%' */
+/* #define CHKUSER_ALLOW_RCPT_CHAR_3 '' */
+/* #define CHKUSER_ALLOW_RCPT_CHAR_4 '?' */
+/* #define CHKUSER_ALLOW_RCPT_CHAR_5 '*' */
+
+/*
+ * This define has been eliminated.
+ * Turning it ON or OFF has no effect, as we consider the existence
+ * of #define VALIAS inside ~vpopmail/include/vpopmail_config.h
+ */
+/* #define CHKUSER_ENABLE_VALIAS */
+
+/*
+ * Uncomment this to enable user extension on names (i.e. TMDA)
+ * (for mailing lists this is done without checking this define)
+ * This define substitutes #define CHKUSER_ENABLE_EXTENSIONS
+ */
+#define CHKUSER_ENABLE_USERS_EXTENSIONS
+
+/*
+ * Enables checking for EZMLM lists
+ * this define substitutes #define CHKUSER_ENABLE_LISTS
+ *
+ */
+#define CHKUSER_ENABLE_EZMLM_LISTS
+
+/*
+ * Help identifying remote authorized IPs giving them a descriptive name
+ * Can be put in tcp.smtp, and will be displayed inside chkuser log
+ * Substitutes RELAYCLIENT in chkuser logging
+ */
+#define CHKUSER_IDENTIFY_REMOTE_VARIABLE "CHKUSER_IDENTIFY"
+
+/*
+ * The following #define set the character used for users extensions
+ * be careful: this is a single char '-' definition, not a "string"
+ * this define substitutes #define CHKUSER_EXTENSION_DASH
+ * MUST be defined if CHKUSER_ENABLE_USERS_EXTENSIONS is defined
+ */
+#define CHKUSER_USERS_DASH '-'
+
+/*
+ * New error strings for SOFT DNS problems
+ */
+#define CHKUSER_RCPTMX_TMP_STRING "451 DNS temporary failure (#4.5.1 - chkuser)\r\n"
+#define CHKUSER_SENDERMX_TMP_STRING "451 DNS temporary failure (#4.5.1 - chkuser)\r\n"
+
+/*
+ * Enables checking for mailman lists
+ *
+ */
+/* #define CHKUSER_ENABLE_MAILMAN_LISTS */
+
+/*
+ * Identifies the pattern string to be searched within mailman aliases
+ *
+ */
+#define CHKUSER_MAILMAN_STRING "mailman"
+
+/*
+ * The following #define set the character used for mailman lists extensions
+ * be careful: this is a single char '-' definition, not a "string"
+ */
+#define CHKUSER_MAILMAN_DASH '-'
+
+
+/*
+ * Enables final clean-up routine of chkuser
+ * This routine cleans open DB connections used for checking users and valiases
+ */
+#define CHKUSER_DB_CLEANUP
+
+/***************************************************
+ *
+ * new/modified defines in/from 2.0.8
+ *
+ **************************************************/
+
+/*
+ * The following defines are NO MORE used. NULL SENDER rejecting breaks RFC
+ * compatibility, and makes harder to handle e-mail receipts.
+ * Please comment or delete them from your chkuser_settings.h.
+ */
+/* #define CHKUSER_ACCEPT_NULL_SENDER */
+/* #define CHKUSER_ENABLE_NULL_SENDER_WITH_TCPREMOTEHOST */
+
+/*
+ * Uncomment to enable checking of user and domain format for rcpt addresses
+ * user = [a-z0-9_-]
+ * domain = [a-z0-9-.] with not consecutive "-.", not leading or ending "-."
+ */
+#define CHKUSER_RCPT_FORMAT
+
+/*
+ * Uncomment to enable checking of domain MX for rcpt addresses
+ * It works on any rcpt address domain that is not inside rcpthosts
+ */
+#define CHKUSER_RCPT_MX
+
+/*
+ * Uncomment to enable checking of user and domain format for sender address
+ * user = [a-z0-9_-]
+ * domain = [a-z0-9-.] with not consecutive "-.", not leading or ending "-."
+ */
+#define CHKUSER_SENDER_FORMAT
+
+/*
+ * Uncomment to enable checking of domain MX for sender address
+ * it works on the first rcpt address, despite of any domain setting on chkuser
+ */
+#define CHKUSER_SENDER_MX
+
+/*
+ * Delay to add, for each not existing recipient, to the initial CHKUSER_ERROR_DELAY value
+ * value is expressed in milliseconds
+ */
+#define CHKUSER_ERROR_DELAY_INCREASE 300
+
diff -Naur ./conf-cc ../qmail-1.03-build-10/conf-cc
--- ./conf-cc 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/conf-cc 2006-04-27 13:03:27.000000000 -0500
@@ -1,3 +1,3 @@
-cc -O2
+cc -O2 -DTLS=20060104 -I/usr/include/openssl -I/home/vpopmail/include
This will be used to compile .c files.
diff -Naur ./conf-spawn ../qmail-1.03-build-10/conf-spawn
--- ./conf-spawn 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/conf-spawn 2006-05-05 19:36:49.000000000 -0500
@@ -1,4 +1,4 @@
-120
+509
This is a silent concurrency limit. You can't set it above 255. On some
systems you can't set it above 125. qmail will refuse to compile if the
diff -Naur ./dns.c ../qmail-1.03-build-10/dns.c
--- ./dns.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/dns.c 2006-05-07 10:46:37.000000000 -0500
@@ -7,10 +7,9 @@
#include <errno.h>
extern int res_query();
extern int res_search();
-extern int errno;
-extern int h_errno;
#include "ip.h"
#include "ipalloc.h"
+#include "strsalloc.h"
#include "fmt.h"
#include "alloc.h"
#include "str.h"
@@ -29,6 +28,7 @@
static int numanswers;
static char name[MAXDNAME];
static struct ip_address ip;
+static stralloc txt = {0};
unsigned short pref;
static stralloc glue = {0};
@@ -179,6 +179,49 @@
return 0;
}
+static int findtxt(wanttype)
+int wanttype;
+{
+ unsigned short rrtype;
+ unsigned short rrdlen;
+ int i;
+
+ if (numanswers <= 0) return 2;
+ --numanswers;
+ if (responsepos == responseend) return DNS_SOFT;
+
+ i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
+ if (i < 0) return DNS_SOFT;
+ responsepos += i;
+
+ i = responseend - responsepos;
+ if (i < 4 + 3 * 2) return DNS_SOFT;
+
+ rrtype = getshort(responsepos);
+ rrdlen = getshort(responsepos + 8);
+ responsepos += 10;
+
+ if (rrtype == wanttype)
+ {
+ unsigned short txtpos;
+ unsigned char txtlen;
+
+ txt.len = 0;
+ for (txtpos = 0;txtpos < rrdlen;txtpos += txtlen)
+ {
+ txtlen = responsepos[txtpos++];
+ if (txtlen > rrdlen-txtpos) txtlen = rrdlen-txtpos;
+ if (!stralloc_catb(&txt,&responsepos[txtpos],txtlen)) return DNS_MEM;
+ }
+
+ responsepos += rrdlen;
+ return 1;
+ }
+
+ responsepos += rrdlen;
+ return 0;
+}
+
void dns_init(flagsearch)
int flagsearch;
{
@@ -237,15 +280,18 @@
return len;
}
-int dns_ptr(sa,ip)
-stralloc *sa;
+static int dns_ptrplus(ssa,ip)
+strsalloc *ssa;
struct ip_address *ip;
{
+ stralloc sa = {0};
int r;
- if (!stralloc_ready(sa,iaafmt((char *) 0,ip))) return DNS_MEM;
- sa->len = iaafmt(sa->s,ip);
- switch(resolve(sa,T_PTR))
+ if (!stralloc_ready(&sa,iaafmt((char *) 0,ip))) return DNS_MEM;
+ sa.len = iaafmt(sa.s,ip);
+ r = resolve(&sa,T_PTR);
+ alloc_free(sa.s);
+ switch(r)
{
case DNS_MEM: return DNS_MEM;
case DNS_SOFT: return DNS_SOFT;
@@ -256,25 +302,46 @@
if (r == DNS_SOFT) return DNS_SOFT;
if (r == 1)
{
- if (!stralloc_copys(sa,name)) return DNS_MEM;
- return 0;
+ stralloc sa2 = {0};
+ if (!stralloc_copys(&sa2,name)) return DNS_MEM;
+ if (!strsalloc_append(ssa,&sa2)) return DNS_MEM;
}
}
+ if (ssa->len) return 0;
return DNS_HARD;
}
+int dns_ptr(ssa,ip)
+strsalloc *ssa;
+struct ip_address *ip;
+{
+ int r;
+ int j;
+
+ if (!strsalloc_readyplus(ssa,0)) return DNS_MEM;
+ ssa->len = 0;
+ r = dns_ptrplus(ssa,ip);
+ if (r < 0)
+ {
+ for (j = 0;j < ssa->len;++j)
+ alloc_free(ssa->sa[j].s);
+ ssa->len = 0;
+ }
+ return r;
+}
+
+
static int dns_ipplus(ia,sa,pref)
ipalloc *ia;
stralloc *sa;
int pref;
{
int r;
- struct ip_mx ix;
+ struct ip_mx ix = {0};
if (!stralloc_copy(&glue,sa)) return DNS_MEM;
if (!stralloc_0(&glue)) return DNS_MEM;
if (glue.s[0]) {
- ix.pref = 0;
if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
{
if (!ipalloc_append(ia,&ix)) return DNS_MEM;
@@ -293,9 +360,16 @@
ix.ip = ip;
ix.pref = pref;
if (r == DNS_SOFT) return DNS_SOFT;
- if (r == 1)
+ if (r == 1) {
+#ifdef IX_FQDN
+ ix.fqdn = glue.s;
+#endif
if (!ipalloc_append(ia,&ix)) return DNS_MEM;
}
+ }
+#ifdef IX_FQDN
+ glue.s = 0;
+#endif
return 0;
}
@@ -315,7 +389,7 @@
{
int r;
struct mx { stralloc sa; unsigned short p; } *mx;
- struct ip_mx ix;
+ struct ip_mx ix = {0};
int nummx;
int i;
int j;
@@ -327,7 +401,6 @@
if (!stralloc_copy(&glue,sa)) return DNS_MEM;
if (!stralloc_0(&glue)) return DNS_MEM;
if (glue.s[0]) {
- ix.pref = 0;
if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
{
if (!ipalloc_append(ia,&ix)) return DNS_MEM;
@@ -398,3 +471,49 @@
alloc_free(mx);
return flagsoft;
}
+
+
+static int dns_txtplus(ssa,sa)
+strsalloc *ssa;
+stralloc *sa;
+{
+ int r;
+
+ switch(resolve(sa,T_TXT))
+ {
+ case DNS_MEM: return DNS_MEM;
+ case DNS_SOFT: return DNS_SOFT;
+ case DNS_HARD: return DNS_HARD;
+ }
+ while ((r = findtxt(T_TXT)) != 2)
+ {
+ if (r == DNS_SOFT) return DNS_SOFT;
+ if (r == 1)
+ {
+ stralloc sa = {0};
+ if (!stralloc_copy(&sa,&txt)) return DNS_MEM;
+ if (!strsalloc_append(ssa,&sa)) return DNS_MEM;
+ }
+ }
+ if (ssa->len) return 0;
+ return DNS_HARD;
+}
+
+int dns_txt(ssa,sa)
+strsalloc *ssa;
+stralloc *sa;
+{
+ int r;
+ int j;
+
+ if (!strsalloc_readyplus(ssa,0)) return DNS_MEM;
+ ssa->len = 0;
+ r = dns_txtplus(ssa,sa);
+ if (r < 0)
+ {
+ for (j = 0;j < ssa->len;++j)
+ alloc_free(ssa->sa[j].s);
+ ssa->len = 0;
+ }
+ return r;
+}
diff -Naur ./dnsfq.c ../qmail-1.03-build-10/dnsfq.c
--- ./dnsfq.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/dnsfq.c 2006-05-07 10:48:57.000000000 -0500
@@ -5,15 +5,19 @@
#include "dnsdoe.h"
#include "ip.h"
#include "ipalloc.h"
+#include "strsalloc.h"
#include "exit.h"
stralloc sa = {0};
+strsalloc ssa = {0};
ipalloc ia = {0};
void main(argc,argv)
int argc;
char **argv;
{
+ int j;
+
if (!argv[1]) _exit(100);
if (!stralloc_copys(&sa,argv[1]))
@@ -25,8 +29,11 @@
{
substdio_putsflush(subfderr,"no IP addresses\n"); _exit(100);
}
- dnsdoe(dns_ptr(&sa,&ia.ix[0].ip));
- substdio_putflush(subfdout,sa.s,sa.len);
- substdio_putsflush(subfdout,"\n");
+ dnsdoe(dns_ptr(&ssa,&ia.ix[0].ip));
+ for(j = 0;j < ssa.len;++j)
+ {
+ substdio_putflush(subfdout,ssa.sa[j].s,ssa.sa[j].len);
+ substdio_putsflush(subfdout,"\n");
+ }
_exit(0);
}
diff -Naur ./dns.h ../qmail-1.03-build-10/dns.h
--- ./dns.h 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/dns.h 2006-04-27 13:08:51.000000000 -0500
@@ -10,5 +10,6 @@
int dns_mxip();
int dns_ip();
int dns_ptr();
+int dns_txt();
#endif
diff -Naur ./dnsptr.c ../qmail-1.03-build-10/dnsptr.c
--- ./dnsptr.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/dnsptr.c 2006-05-07 10:52:39.000000000 -0500
@@ -6,22 +6,28 @@
#include "dns.h"
#include "dnsdoe.h"
#include "ip.h"
+#include "strsalloc.h"
#include "exit.h"
-stralloc sa = {0};
+strsalloc ssa = {0};
struct ip_address ip;
void main(argc,argv)
int argc;
char **argv;
{
+ int j;
+
if (!argv[1]) _exit(100);
ip_scan(argv[1],&ip);
dns_init(0);
- dnsdoe(dns_ptr(&sa,&ip));
- substdio_putflush(subfdout,sa.s,sa.len);
- substdio_putsflush(subfdout,"\n");
+ dnsdoe(dns_ptr(&ssa,&ip));
+ for(j = 0;j < ssa.len;++j)
+ {
+ substdio_putflush(subfdout,ssa.sa[j].s,ssa.sa[j].len);
+ substdio_putsflush(subfdout,"\n");
+ }
_exit(0);
}
diff -Naur ./dnstxt.c ../qmail-1.03-build-10/dnstxt.c
--- ./dnstxt.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/dnstxt.c 2006-05-05 21:22:43.000000000 -0500
@@ -0,0 +1,32 @@
+#include "substdio.h"
+#include "subfd.h"
+#include "stralloc.h"
+#include "str.h"
+#include "scan.h"
+#include "dns.h"
+#include "dnsdoe.h"
+#include "strsalloc.h"
+#include "exit.h"
+
+strsalloc ssa = {0};
+stralloc sa = {0};
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+ int j;
+
+ if (!argv[1]) _exit(100);
+
+ if (!stralloc_copys(&sa, argv[1]))
+ { substdio_putsflush(subfderr,"out of memory\n"); _exit(111); }
+ dns_init(0);
+ dnsdoe(dns_txt(&ssa,&sa));
+ for (j = 0;j < ssa.len;++j)
+ {
+ substdio_put(subfdout,ssa.sa[j].s,ssa.sa[j].len);
+ substdio_putsflush(subfdout,"\n");
+ }
+ _exit(0);
+}
diff -Naur ./error.3 ../qmail-1.03-build-10/error.3
--- ./error.3 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/error.3 2006-04-24 21:24:32.000000000 -0500
@@ -3,8 +3,8 @@
error \- syscall error codes
.SH SYNTAX
.B #include <error.h>
-
-extern int \fBerrno\fP;
+.br
+.B #include <errno.h>
extern int \fBerror_intr\fP;
.br
diff -Naur ./error.h ../qmail-1.03-build-10/error.h
--- ./error.h 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/error.h 2006-04-24 21:24:32.000000000 -0500
@@ -1,7 +1,7 @@
#ifndef ERROR_H
#define ERROR_H
-extern int errno;
+#include <errno.h>
extern int error_intr;
extern int error_nomem;
diff -Naur ./FAQ ../qmail-1.03-build-10/FAQ
--- ./FAQ 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/FAQ 2006-04-24 21:24:32.000000000 -0500
@@ -1,3 +1,6 @@
+See http://cr.yp.to/qmail/faq.html for newer FAQs not included in this
+document, and http://qmail.org/ for qmail community contributions.
+
1. Controlling the appearance of outgoing messages
1.1. How do I set up host masquerading?
1.2. How do I set up user masquerading?
diff -Naur ./FILES ../qmail-1.03-build-10/FILES
--- ./FILES 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/FILES 2006-05-07 10:55:27.000000000 -0500
@@ -10,6 +10,7 @@
INSTALL.ids
INSTALL.maildir
INSTALL.mbox
+INSTALL-1.03
INSTALL.vsm
REMOVE.sendmail
REMOVE.binmail
@@ -135,6 +136,8 @@
dnsip.c
dnsmxip.c
dnsptr.c
+dnstxt.c
+spfquery.c
hostname.c
ipmeprint.c
tcp-env.c
@@ -335,13 +338,16 @@
byte.h
byte_chr.c
byte_copy.c
+byte_cspn.c
byte_cr.c
byte_diff.c
byte_rchr.c
+byte_rcspn.c
byte_zero.c
str.h
str_chr.c
str_cpy.c
+str_cpyb.c
str_diff.c
str_diffn.c
str_len.c
@@ -401,6 +407,8 @@
date822fmt.c
dns.h
dns.c
+spf.h
+spf.c
trylsock.c
tryrsolv.c
ip.h
diff -Naur ./FILES.warlord ../qmail-1.03-build-10/FILES.warlord
--- ./FILES.warlord 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/FILES.warlord 2005-01-29 06:08:25.000000000 -0600
@@ -0,0 +1,28 @@
+The WARLORD patch modifies the following QMAIL 1.03 files:
+
+Patched files:
+
+= Makefile
+= qmail-smtpd.c
+= qmail-smtpd.8
+= qmail-showctl.c
+= qmail-control.9
+= hier.c
+= install-big.c
+= cdb_seek.c
+= TARGETS
+
+Added files:
+
++ qmail-badloadertypes.c
++ qmail-badloadertypes.9
++ qmail-badmimetypes.c
++ qmail-badmimetypes.9
++ case_startb.c
+
+Informational files:
+
+% badloadertypes
+% badmimetypes
+% README.warlord
+% HISTORY.warlord
diff -Naur ./hier.c ../qmail-1.03-build-10/hier.c
--- ./hier.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/hier.c 2006-05-05 20:28:07.000000000 -0500
@@ -76,6 +76,10 @@
c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755);
c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"doc","README.qregex",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"doc","README.auth",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"doc","README.remote-auth",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"doc","README.starttls",auto_uido,auto_gidq,0644);
c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644);
c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644);
c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644);
@@ -109,6 +113,8 @@
c(auto_qmail,"bin","qmail-clean",auto_uido,auto_gidq,0711);
c(auto_qmail,"bin","qmail-send",auto_uido,auto_gidq,0711);
c(auto_qmail,"bin","splogger",auto_uido,auto_gidq,0711);
+ c(auto_qmail,"bin","qmail-badmimetypes",auto_uido,auto_gidq,0700);
+ c(auto_qmail,"bin","qmail-badloadertypes",auto_uido,auto_gidq,0700);
c(auto_qmail,"bin","qmail-newu",auto_uido,auto_gidq,0700);
c(auto_qmail,"bin","qmail-newmrh",auto_uido,auto_gidq,0700);
c(auto_qmail,"bin","qmail-pw2u",auto_uido,auto_gidq,0711);
@@ -143,6 +149,9 @@
c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0755);
c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0755);
c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0755);
+#ifdef TLS
+ c(auto_qmail,"bin","update_tmprsadh",auto_uido,auto_gidq,0755);
+#endif
c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644);
c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644);
@@ -221,6 +230,10 @@
c(auto_qmail,"man/cat8","qmail-inject.0",auto_uido,auto_gidq,0644);
c(auto_qmail,"man/man8","qmail-showctl.8",auto_uido,auto_gidq,0644);
c(auto_qmail,"man/cat8","qmail-showctl.0",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"man/man8","qmail-badmimetypes.8",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"man/cat8","qmail-badmimetypes.0",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"man/man8","qmail-badloadertypes.8",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"man/cat8","qmail-badloadertypes.0",auto_uido,auto_gidq,0644);
c(auto_qmail,"man/man8","qmail-newmrh.8",auto_uido,auto_gidq,0644);
c(auto_qmail,"man/cat8","qmail-newmrh.0",auto_uido,auto_gidq,0644);
c(auto_qmail,"man/man8","qmail-newu.8",auto_uido,auto_gidq,0644);
diff -Naur ./HISTORY.warlord ../qmail-1.03-build-10/HISTORY.warlord
--- ./HISTORY.warlord 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/HISTORY.warlord 2005-03-12 11:01:24.000000000 -0600
@@ -0,0 +1,22 @@
+HISTORY
+-------
+
+Convention: Version.Release.Fixlevel
+
+V.R.F Description Date
+--------------------------------------------------------------------
+1.2.1 Initial Release 2003-09-09
+1.3.0 Smarter base64 detection 2004-06-17
+1.3.1 Added badloadertype detection 2004-06-28
+1.3.4 Sync'ed with SPAMCONTROL 2.3 2004-09-14
+1.3.5 Sync'ed with SPAMCONTROL 2.3 2004-09-15
+1.3.6 Removed obsolete qhpsi defs. 2004-09-16
+1.3.7 Wrong length of MIME_LEN fixed. 2004-09-20
+1.3.8 Removed dependency on MIME_LEN. 2004-11-19
+1.3.9 Fixed 'status 11' aborts. 2004-12-09
+1.3.10 Removed function checkline in favour of a more
+ generic multiple occurancee check
+ badmimetype/badloadertyp stralloc now. 2005-01-29
+1.3.11 FIXed false positive badladertype recognition
+ due to smarter base64 block identification. 2005-02-12
+
diff -Naur ./INSTALL ../qmail-1.03-build-10/INSTALL
--- ./INSTALL 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/INSTALL 2006-04-24 21:24:32.000000000 -0500
@@ -1,84 +1 @@
-SAVE COPIES OF YOUR OUTGOING MAIL! Like any other piece of software (and
-information generally), the qmail system comes with NO WARRANTY. It's
-much more secure and reliable than sendmail, but that's not saying much.
-
-
-Things you have to decide before starting:
-
-* The qmail home directory, normally /var/qmail. To change this
-directory, edit conf-qmail now.
-
-* The names of the qmail users and the qmail groups. To change these
-names, edit conf-users and conf-groups now.
-
-
-To create /var/qmail and configure qmail (won't interfere with sendmail):
-
- 1. Create the qmail home directory:
- # mkdir /var/qmail
-
- 2. Read INSTALL.ids. You must set up the qmail group and the qmail
- users before compiling the programs.
-
- 3. Compile the programs and create the qmail directory tree:
- # make setup check
-
- 4. Read INSTALL.ctl and FAQ. Minimal survival command:
- # ./config
-
- 5. Read INSTALL.alias. Minimal survival command:
- # (cd ~alias; touch .qmail-postmaster .qmail-mailer-daemon .qmail-root)
- # chmod 644 ~alias/.qmail*
-
- 6. Read INSTALL.mbox and INSTALL.vsm.
-
- 7. Read INSTALL.maildir.
-
- 8. Copy /var/qmail/boot/home (or proc) to /var/qmail/rc.
-
-
-To test qmail deliveries (won't interfere with sendmail):
-
- 9. Enable deliveries of messages injected into qmail:
- # csh -cf '/var/qmail/rc &'
-
-10. Read TEST.deliver.
-
-
-To upgrade from sendmail to qmail:
-
-11. Read SENDMAIL. This is what your users will want to know about the
- switch from sendmail to qmail.
-
-12. Read REMOVE.sendmail. You must remove sendmail before installing
- qmail.
-
-13. Read REMOVE.binmail.
-
-14. Add
- csh -cf '/var/qmail/rc &'
- to your boot scripts, so that the qmail daemons are restarted
- whenever your system reboots. Make sure you include the &.
-
-15. Make qmail's ``sendmail'' wrapper available to MUAs:
- # ln -s /var/qmail/bin/sendmail /usr/lib/sendmail
- # ln -s /var/qmail/bin/sendmail /usr/sbin/sendmail
- /usr/sbin might not exist on your system.
-
-16. Set up qmail-smtpd in /etc/inetd.conf (all on one line):
- smtp stream tcp nowait qmaild /var/qmail/bin/tcp-env
- tcp-env /var/qmail/bin/qmail-smtpd
-
-17. Reboot. (Or kill -HUP your inetd and make sure the qmail daemons
- are running.)
-
-18. Read TEST.receive.
-
-
-
-That's it! To report success:
- % ( echo 'First M. Last'; cat `cat SYSDEPS` ) | mail djb-qst@cr.yp.to
-Replace First M. Last with your name.
-
-If you have questions about qmail, join the qmail mailing list; see
-http://pobox.com/~djb/qmail.html.
+See http://lifewithqmail.org/lwq.html
diff -Naur ./install-big.c ../qmail-1.03-build-10/install-big.c
--- ./install-big.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/install-big.c 2006-05-05 20:29:22.000000000 -0500
@@ -76,6 +76,10 @@
c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755);
c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"doc","README.qregex",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"doc","README.auth",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"doc","README.remote-auth",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"doc","README.starttls",auto_uido,auto_gidq,0644);
c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644);
c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644);
c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644);
@@ -110,6 +114,8 @@
c(auto_qmail,"bin","qmail-send",auto_uido,auto_gidq,0711);
c(auto_qmail,"bin","splogger",auto_uido,auto_gidq,0711);
c(auto_qmail,"bin","qmail-newu",auto_uido,auto_gidq,0700);
+ c(auto_qmail,"bin","qmail-badloadertypes",auto_uido,auto_gidq,0700);
+ c(auto_qmail,"bin","qmail-badmimetypes",auto_uido,auto_gidq,0700);
c(auto_qmail,"bin","qmail-newmrh",auto_uido,auto_gidq,0700);
c(auto_qmail,"bin","qmail-pw2u",auto_uido,auto_gidq,0711);
c(auto_qmail,"bin","qmail-inject",auto_uido,auto_gidq,0755);
@@ -221,6 +227,10 @@
c(auto_qmail,"man/cat8","qmail-inject.0",auto_uido,auto_gidq,0644);
c(auto_qmail,"man/man8","qmail-showctl.8",auto_uido,auto_gidq,0644);
c(auto_qmail,"man/cat8","qmail-showctl.0",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"man/man8","qmail-badloadertypes.8",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"man/cat8","qmail-badloadertypes.0",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"man/man8","qmail-badmimetypes.8",auto_uido,auto_gidq,0644);
+ c(auto_qmail,"man/cat8","qmail-badmimetypes.0",auto_uido,auto_gidq,0644);
c(auto_qmail,"man/man8","qmail-newmrh.8",auto_uido,auto_gidq,0644);
c(auto_qmail,"man/cat8","qmail-newmrh.0",auto_uido,auto_gidq,0644);
c(auto_qmail,"man/man8","qmail-newu.8",auto_uido,auto_gidq,0644);
diff -Naur ./INSTALL.warlord ../qmail-1.03-build-10/INSTALL.warlord
--- ./INSTALL.warlord 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/INSTALL.warlord 2003-09-09 01:35:32.000000000 -0500
@@ -0,0 +1,26 @@
+Installation
+============
+
+1. Unpack/tar the Warlord archive in Qmail's source directory.
+2. Call ./warlord.sh.
+3. Verify the installation process; look into warlord.log.
+4. Re-make Qmail.
+
+Customization
+=============
+
+1. Copy the file badmimetypes from Qmail ./doc directory to ./control.
+2. Modifiy it to your needs.
+3. Execute qmail-newbmt.
+4. You need to define the environment variable $BADMIMETYPES in order
+ to let qmail-smtpd proceed with the badmime check.
+ You could do this globally in the qmail-smtpd start up script,
+ or for individual senders/nets using tcpserver.
+
+Uninstallation
+==============
+
+1. Cd to the directory from where you installed Qmail/Warlord.
+2. Identify the current installed release of Warlord.
+3. Call ./warlord.sh -u Release.
+4. Re-make Qmail.
diff -Naur ./ipalloc.h ../qmail-1.03-build-10/ipalloc.h
--- ./ipalloc.h 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/ipalloc.h 2006-04-27 11:10:31.000000000 -0500
@@ -3,7 +3,15 @@
#include "ip.h"
+#ifdef TLS
+# define IX_FQDN 1
+#endif
+
+#ifdef IX_FQDN
+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 -Naur ./ipme.c ../qmail-1.03-build-10/ipme.c
--- ./ipme.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/ipme.c 2006-04-24 21:24:32.000000000 -0500
@@ -46,6 +46,11 @@
ipme.len = 0;
ix.pref = 0;
+ /* 0.0.0.0 is a special address which always refers to
+ * "this host, this network", according to RFC 1122, Sec. 3.2.1.3a.
+ */
+ byte_copy(&ix.ip,4,"\0\0\0\0");
+ if (!ipalloc_append(&ipme,&ix)) { return 0; }
if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1;
len = 256;
diff -Naur ./maildirflags.c ../qmail-1.03-build-10/maildirflags.c
--- ./maildirflags.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/maildirflags.c 2006-05-03 17:44:55.000000000 -0500
@@ -0,0 +1,23 @@
+/*
+** Copyright 2000 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#include <sys/types.h>
+#include <string.h>
+
+static const char rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+int maildir_hasflag(const char *filename, char flag)
+{
+ const char *p=strrchr(filename, '/');
+
+ if (p)
+ filename=p+1;
+
+ p=strrchr(p, ':');
+ if (p && strncmp(p, ":2,", 3) == 0 &&
+ strchr(p+3, flag))
+ return (1);
+ return (0);
+}
diff -Naur ./maildirgetquota.c ../qmail-1.03-build-10/maildirgetquota.c
--- ./maildirgetquota.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/maildirgetquota.c 2006-05-03 17:44:55.000000000 -0500
@@ -0,0 +1,50 @@
+/*
+** Copyright 1998 - 2000 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#include "maildirgetquota.h"
+#include "maildirmisc.h"
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+int maildir_getquota(const char *dir, char buf[QUOTABUFSIZE])
+{
+char *p;
+struct stat stat_buf;
+int n;
+int l;
+
+ p=(char *)malloc(strlen(dir)+sizeof("/maildirfolder"));
+ if (!p) return (-1);
+
+ strcat(strcpy(p, dir), "/maildirfolder");
+ if (stat(p, &stat_buf) == 0)
+ {
+ strcat(strcpy(p, dir), "/..");
+ n=maildir_getquota(p, buf);
+ free(p);
+ return (n);
+ }
+
+ strcat(strcpy(p, dir), "/maildirsize");
+ n=maildir_safeopen(p, O_RDONLY, 0);
+ free(p);
+ if (n < 0) return (n);
+ if ((l=read(n, buf, QUOTABUFSIZE-1)) < 0)
+ {
+ close(n);
+ return (-1);
+ }
+ close(n);
+ for (n=0; n<l; n++)
+ if (buf[n] == '\n') break;
+ buf[n]=0;
+ return (0);
+}
diff -Naur ./maildirgetquota.h ../qmail-1.03-build-10/maildirgetquota.h
--- ./maildirgetquota.h 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/maildirgetquota.h 2006-05-03 17:44:55.000000000 -0500
@@ -0,0 +1,30 @@
+#ifndef maildirgetquota_h
+#define maildirgetquota_h
+
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static const char maildirgetquota_h_rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+#define QUOTABUFSIZE 256
+
+int maildir_getquota(const char *, char [QUOTABUFSIZE]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Naur ./maildirmisc.h ../qmail-1.03-build-10/maildirmisc.h
--- ./maildirmisc.h 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/maildirmisc.h 2006-05-03 17:44:55.000000000 -0500
@@ -0,0 +1,145 @@
+#ifndef maildirmisc_h
+#define maildirmisc_h
+
+/*
+** Copyright 2000 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static const char maildirmisc_h_rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+/*
+**
+** Miscellaneous maildir-related code
+**
+*/
+
+/* Some special folders */
+
+#define INBOX "INBOX"
+#define DRAFTS "Drafts"
+#define SENT "Sent"
+#define TRASH "Trash"
+
+#define SHAREDSUBDIR "shared-folders"
+
+char *maildir_folderdir(const char *, /* maildir */
+ const char *); /* folder name */
+ /* Returns the directory corresponding to foldername (foldername is
+ ** checked to make sure that it's a valid name, else we set errno
+ ** to EINVAL, and return (0).
+ */
+
+char *maildir_filename(const char *, /* maildir */
+ const char *, /* folder */
+ const char *); /* filename */
+ /*
+ ** Builds the filename to this message, suitable for opening.
+ ** If the file doesn't appear to be there, search the maildir to
+ ** see if someone changed the flags, and return the current filename.
+ */
+
+int maildir_safeopen(const char *, /* filename */
+ int, /* mode */
+ int); /* perm */
+
+/*
+** Same arguments as open(). When we're accessing a shared maildir,
+** prevent someone from playing cute and dumping a bunch of symlinks
+** in there. This function will open the indicate file only if the
+** last component is not a symlink.
+** This is implemented by opening the file with O_NONBLOCK (to prevent
+** a DOS attack of someone pointing the symlink to a pipe, causing
+** the open to hang), clearing O_NONBLOCK, then stat-int the file
+** descriptor, lstating the filename, and making sure that dev/ino
+** match.
+*/
+
+int maildir_semisafeopen(const char *, /* filename */
+ int, /* mode */
+ int); /* perm */
+
+/*
+** Same thing, except that we allow ONE level of soft link indirection,
+** because we're reading from our own maildir, which points to the
+** message in the sharable maildir.
+*/
+
+int maildir_mkdir(const char *); /* directory */
+/*
+** Create maildir including all subdirectories in the path (like mkdir -p)
+*/
+
+void maildir_purgetmp(const char *); /* maildir */
+ /* purges old stuff out of tmp */
+
+void maildir_purge(const char *, /* directory */
+ unsigned); /* time_t to purge */
+
+void maildir_getnew(const char *, /* maildir */
+ const char *); /* folder */
+ /* move messages from new to cur */
+
+int maildir_deletefolder(const char *, /* maildir */
+ const char *); /* folder */
+ /* deletes a folder */
+
+int maildir_mddelete(const char *); /* delete a maildir folder by path */
+
+void maildir_list_sharable(const char *, /* maildir */
+ void (*)(const char *, void *), /* callback function */
+ void *); /* 2nd arg to callback func */
+ /* list sharable folders */
+
+int maildir_shared_subscribe(const char *, /* maildir */
+ const char *); /* folder */
+ /* subscribe to a shared folder */
+
+void maildir_list_shared(const char *, /* maildir */
+ void (*)(const char *, void *), /* callback function */
+ void *); /* 2nd arg to the callback func */
+ /* list subscribed folders */
+
+int maildir_shared_unsubscribe(const char *, /* maildir */
+ const char *); /* folder */
+ /* unsubscribe from a shared folder */
+
+char *maildir_shareddir(const char *, /* maildir */
+ const char *); /* folder */
+ /*
+ ** Validate and return a path to a shared folder. folderdir must be
+ ** a name of a valid shared folder.
+ */
+
+void maildir_shared_sync(const char *); /* maildir */
+ /* "sync" the shared folder */
+
+int maildir_sharedisro(const char *); /* maildir */
+ /* maildir is a shared read-only folder */
+
+int maildir_unlinksharedmsg(const char *); /* filename */
+ /* Remove a message from a shared folder */
+
+/* Internal function that reads a symlink */
+
+char *maildir_getlink(const char *);
+
+ /* Determine whether the maildir filename has a certain flag */
+
+int maildir_hasflag(const char *filename, char);
+
+#define MAILDIR_DELETED(f) maildir_hasflag((f), 'T')
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Naur ./maildiropen.c ../qmail-1.03-build-10/maildiropen.c
--- ./maildiropen.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/maildiropen.c 2006-05-03 17:44:55.000000000 -0500
@@ -0,0 +1,133 @@
+/*
+** Copyright 2000 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "maildirmisc.h"
+
+static const char rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+char *maildir_getlink(const char *filename)
+{
+#if HAVE_READLINK
+size_t bufsiz;
+char *buf;
+
+ bufsiz=0;
+ buf=0;
+
+ for (;;)
+ {
+ int n;
+
+ if (buf) free(buf);
+ bufsiz += 256;
+ if ((buf=malloc(bufsiz)) == 0)
+ {
+ perror("malloc");
+ return (0);
+ }
+ if ((n=readlink(filename, buf, bufsiz)) < 0)
+ {
+ free(buf);
+ return (0);
+ }
+ if (n < bufsiz)
+ {
+ buf[n]=0;
+ break;
+ }
+ }
+ return (buf);
+#else
+ return (0);
+#endif
+}
+
+int maildir_semisafeopen(const char *path, int mode, int perm)
+{
+
+#if HAVE_READLINK
+
+char *l=maildir_getlink(path);
+
+ if (l)
+ {
+ int f;
+
+ if (*l != '/')
+ {
+ char *q=malloc(strlen(path)+strlen(l)+2);
+ char *s;
+
+ if (!q)
+ {
+ free(l);
+ return (-1);
+ }
+
+ strcpy(q, path);
+ if ((s=strchr(q, '/')) != 0)
+ s[1]=0;
+ else *q=0;
+ strcat(q, l);
+ free(l);
+ l=q;
+ }
+
+ f=maildir_safeopen(l, mode, perm);
+
+ free(l);
+ return (f);
+ }
+#endif
+
+ return (maildir_safeopen(path, mode, perm));
+}
+
+int maildir_safeopen(const char *path, int mode, int perm)
+{
+struct stat stat1, stat2;
+
+int fd=open(path, mode
+#ifdef O_NONBLOCK
+ | O_NONBLOCK
+#else
+ | O_NDELAY
+#endif
+ , perm);
+
+ if (fd < 0) return (fd);
+ if (fcntl(fd, F_SETFL, (mode & O_APPEND)) || fstat(fd, &stat1)
+ || lstat(path, &stat2))
+ {
+ close(fd);
+ return (-1);
+ }
+
+ if (stat1.st_dev != stat2.st_dev || stat1.st_ino != stat2.st_ino)
+ {
+ close(fd);
+ errno=ENOENT;
+ return (-1);
+ }
+
+ return (fd);
+}
diff -Naur ./maildirparsequota.c ../qmail-1.03-build-10/maildirparsequota.c
--- ./maildirparsequota.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/maildirparsequota.c 2006-05-03 17:44:55.000000000 -0500
@@ -0,0 +1,44 @@
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "maildirquota.h"
+#include <stdlib.h>
+#include <string.h>
+
+static const char rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+int maildir_parsequota(const char *n, unsigned long *s)
+{
+const char *o;
+int yes;
+
+ if ((o=strrchr(n, '/')) == 0) o=n;
+
+ for (; *o; o++)
+ if (*o == ':') break;
+ yes=0;
+ for ( ; o >= n; --o)
+ {
+ if (*o == '/') break;
+
+ if (*o == ',' && o[1] == 'S' && o[2] == '=')
+ {
+ yes=1;
+ o += 3;
+ break;
+ }
+ }
+ if (yes)
+ {
+ *s=0;
+ while (*o >= '0' && *o <= '9')
+ *s= *s*10 + (*o++ - '0');
+ return (0);
+ }
+ return (-1);
+}
diff -Naur ./maildirquota.c ../qmail-1.03-build-10/maildirquota.c
--- ./maildirquota.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/maildirquota.c 2006-05-03 17:44:55.000000000 -0500
@@ -0,0 +1,685 @@
+/*
+** Copyright 1998 - 2002 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+/* #if HAVE_DIRENT_H */
+#include <dirent.h>
+#define NAMLEN(dirent) strlen((dirent)->d_name)
+/* #else
+#define dirent direct
+#define NAMLEN(dirent) (dirent)->d_namlen
+#if HAVE_SYS_NDIR_H
+#include <sys/ndir.h>
+#endif
+#if HAVE_SYS_DIR_H
+#include <sys/dir.h>
+#endif
+#if HAVE_NDIR_H
+#include <ndir.h>
+#endif
+#endif */
+#include <sys/types.h>
+/* #if HAVE_SYS_STAT_H */
+#include <sys/stat.h>
+/* #endif */
+#include <sys/uio.h>
+
+#include "maildirquota.h"
+#include "maildirmisc.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+/* #if HAVE_FCNTL_H */
+#include <fcntl.h>
+/* #endif */
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <time.h>
+#include "numlib.h"
+
+static const char rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+/* Read the maildirsize file */
+
+int maildirsize_read(const char *filename, /* The filename */
+ int *fdptr, /* Keep the file descriptor open */
+ off_t *sizeptr, /* Grand total of maildir size */
+ unsigned *cntptr, /* Grand total of message count */
+ unsigned *nlines, /* # of lines in maildirsize */
+ struct stat *statptr) /* The stats on maildirsize */
+{
+char buf[5120];
+int f;
+char *p;
+unsigned l;
+int n;
+int first;
+
+ if ((f=maildir_safeopen(filename, O_RDWR|O_APPEND, 0)) < 0)
+ return (-1);
+ p=buf;
+ l=sizeof(buf);
+
+ while (l)
+ {
+ n=read(f, p, l);
+ if (n < 0)
+ {
+ close(f);
+ return (-1);
+ }
+ if (n == 0) break;
+ p += n;
+ l -= n;
+ }
+ if (l == 0 || fstat(f, statptr)) /* maildir too big */
+ {
+ close(f);
+ return (-1);
+ }
+
+ *sizeptr=0;
+ *cntptr=0;
+ *nlines=0;
+ *p=0;
+ p=buf;
+ first=1;
+ while (*p)
+ {
+ long n=0;
+ int c=0;
+ char *q=p;
+
+ while (*p)
+ if (*p++ == '\n')
+ {
+ p[-1]=0;
+ break;
+ }
+
+ if (first)
+ {
+ first=0;
+ continue;
+ }
+ sscanf(q, "%ld %d", &n, &c);
+ *sizeptr += n;
+ *cntptr += c;
+ ++ *nlines;
+ }
+ *fdptr=f;
+ return (0);
+}
+
+static char *makenewmaildirsizename(const char *, int *);
+static int countcurnew(const char *, time_t *, off_t *, unsigned *);
+static int countsubdir(const char *, const char *,
+ time_t *, off_t *, unsigned *);
+static int statcurnew(const char *, time_t *);
+static int statsubdir(const char *, const char *, time_t *);
+
+#define MDQUOTA_SIZE 'S' /* Total size of all messages in maildir */
+#define MDQUOTA_BLOCKS 'B' /* Total # of blocks for all messages in
+ maildir -- NOT IMPLEMENTED */
+#define MDQUOTA_COUNT 'C' /* Total number of messages in maildir */
+
+static int qcalc(off_t s, unsigned n, const char *quota, int *percentage)
+{
+off_t i;
+int spercentage=0;
+int npercentage=0;
+
+ errno=ENOSPC;
+ while (quota && *quota)
+ {
+ int x=1;
+
+ if (*quota < '0' || *quota > '9')
+ {
+ ++quota;
+ continue;
+ }
+ i=0;
+ while (*quota >= '0' && *quota <= '9')
+ i=i*10 + (*quota++ - '0');
+ switch (*quota) {
+ default:
+ if (i < s)
+ {
+ *percentage=100;
+ return (-1);
+ }
+
+ /*
+ ** For huge quotas, over 20mb,
+ ** divide numerator & denominator by 1024 to prevent
+ ** an overflow when multiplying by 100
+ */
+
+ x=1;
+ if (i > 20000000) x=1024;
+
+ spercentage = i ? (s/x) * 100 / (i/x):100;
+ break;
+ case 'C':
+
+ if (i < n)
+ {
+ *percentage=100;
+ return (-1);
+ }
+
+ /* Ditto */
+
+ x=1;
+ if (i > 20000000) x=1024;
+
+ npercentage = i ? ((off_t)n/x) * 100 / (i/x):100;
+ break;
+ }
+ }
+ *percentage = spercentage > npercentage ? spercentage:npercentage;
+ return (0);
+}
+
+static int doaddquota(const char *, int, const char *, long, int, int);
+
+static int docheckquota(const char *dir,
+ int *maildirsize_fdptr,
+ const char *quota_type,
+ long xtra_size,
+ int xtra_cnt, int *percentage);
+
+
+int maildir_checkquota(const char *dir,
+ int *maildirsize_fdptr,
+ const char *quota_type,
+ long xtra_size,
+ int xtra_cnt)
+{
+int dummy;
+
+ return (docheckquota(dir, maildirsize_fdptr, quota_type,
+ xtra_size, xtra_cnt, &dummy));
+}
+
+int maildir_readquota(const char *dir, const char *quota_type)
+{
+int percentage=0;
+int fd=-1;
+
+ (void)docheckquota(dir, &fd, quota_type, 0, 0, &percentage);
+ if (fd >= 0)
+ close(fd);
+ return (percentage);
+}
+
+static int docheckquota(const char *dir,
+ int *maildirsize_fdptr,
+ const char *quota_type,
+ long xtra_size,
+ int xtra_cnt,
+ int *percentage)
+{
+char *checkfolder=(char *)malloc(strlen(dir)+sizeof("/maildirfolder"));
+char *newmaildirsizename;
+struct stat stat_buf;
+int maildirsize_fd;
+off_t maildirsize_size;
+unsigned maildirsize_cnt;
+unsigned maildirsize_nlines;
+int n;
+time_t tm;
+time_t maxtime;
+DIR *dirp;
+struct dirent *de;
+
+ if (checkfolder == 0) return (-1);
+ *maildirsize_fdptr= -1;
+ strcat(strcpy(checkfolder, dir), "/maildirfolder");
+ if (stat(checkfolder, &stat_buf) == 0) /* Go to parent */
+ {
+ strcat(strcpy(checkfolder, dir), "/..");
+ n=docheckquota(checkfolder, maildirsize_fdptr,
+ quota_type, xtra_size, xtra_cnt, percentage);
+ free(checkfolder);
+ return (n);
+ }
+ if (!quota_type || !*quota_type) return (0);
+
+ strcat(strcpy(checkfolder, dir), "/maildirsize");
+ time(&tm);
+ if (maildirsize_read(checkfolder, &maildirsize_fd,
+ &maildirsize_size, &maildirsize_cnt,
+ &maildirsize_nlines, &stat_buf) == 0)
+ {
+ n=qcalc(maildirsize_size+xtra_size, maildirsize_cnt+xtra_cnt,
+ quota_type, percentage);
+
+ if (n == 0)
+ {
+ free(checkfolder);
+ *maildirsize_fdptr=maildirsize_fd;
+ return (0);
+ }
+ close(maildirsize_fd);
+
+ if (maildirsize_nlines == 1 && tm < stat_buf.st_mtime + 15*60)
+ return (n);
+ }
+
+ maxtime=0;
+ maildirsize_size=0;
+ maildirsize_cnt=0;
+
+ if (countcurnew(dir, &maxtime, &maildirsize_size, &maildirsize_cnt))
+ {
+ free(checkfolder);
+ return (-1);
+ }
+
+ dirp=opendir(dir);
+ while (dirp && (de=readdir(dirp)) != 0)
+ {
+ if (countsubdir(dir, de->d_name, &maxtime, &maildirsize_size,
+ &maildirsize_cnt))
+ {
+ free(checkfolder);
+ closedir(dirp);
+ return (-1);
+ }
+ }
+ if (dirp)
+ {
+#if CLOSEDIR_VOID
+ closedir(dirp);
+#else
+ if (closedir(dirp))
+ {
+ free(checkfolder);
+ return (-1);
+ }
+#endif
+ }
+
+ newmaildirsizename=makenewmaildirsizename(dir, &maildirsize_fd);
+ if (!newmaildirsizename)
+ {
+ free(checkfolder);
+ return (-1);
+ }
+
+ *maildirsize_fdptr=maildirsize_fd;
+
+ if (doaddquota(dir, maildirsize_fd, quota_type, maildirsize_size,
+ maildirsize_cnt, 1))
+ {
+ unlink(newmaildirsizename);
+ free(newmaildirsizename);
+ close(maildirsize_fd);
+ *maildirsize_fdptr= -1;
+ free(checkfolder);
+ return (-1);
+ }
+
+ strcat(strcpy(checkfolder, dir), "/maildirsize");
+
+ if (rename(newmaildirsizename, checkfolder))
+ {
+ /* free(checkfolder); */
+ unlink(newmaildirsizename);
+ close(maildirsize_fd);
+ *maildirsize_fdptr= -1;
+ }
+ free(checkfolder);
+ free(newmaildirsizename);
+
+ tm=0;
+
+ if (statcurnew(dir, &tm))
+ {
+ close(maildirsize_fd);
+ *maildirsize_fdptr= -1;
+ return (-1);
+ }
+
+ dirp=opendir(dir);
+ while (dirp && (de=readdir(dirp)) != 0)
+ {
+ if (statsubdir(dir, de->d_name, &tm))
+ {
+ close(maildirsize_fd);
+ *maildirsize_fdptr= -1;
+ closedir(dirp);
+ return (-1);
+ }
+ }
+ if (dirp)
+ {
+#if CLOSEDIR_VOID
+ closedir(dirp);
+#else
+ if (closedir(dirp))
+ {
+ close(maildirsize_fd);
+ *maildirsize_fdptr= -1;
+ return (-1);
+ }
+#endif
+ }
+
+ if (tm != maxtime) /* Race condition, someone changed something */
+ {
+ errno=EAGAIN;
+ return (-1);
+ }
+
+ return (qcalc(maildirsize_size+xtra_size, maildirsize_cnt+xtra_cnt,
+ quota_type, percentage));
+}
+
+int maildir_addquota(const char *dir, int maildirsize_fd,
+ const char *quota_type, long maildirsize_size, int maildirsize_cnt)
+{
+ if (!quota_type || !*quota_type) return (0);
+ return (doaddquota(dir, maildirsize_fd, quota_type, maildirsize_size,
+ maildirsize_cnt, 0));
+}
+
+static int doaddquota(const char *dir, int maildirsize_fd,
+ const char *quota_type, long maildirsize_size, int maildirsize_cnt,
+ int isnew)
+{
+union {
+ char buf[100];
+ struct stat stat_buf;
+ } u; /* Scrooge */
+char *newname2=0;
+char *newmaildirsizename=0;
+struct iovec iov[3];
+int niov;
+struct iovec *p;
+int n;
+
+ niov=0;
+ if ( maildirsize_fd < 0)
+ {
+ newname2=(char *)malloc(strlen(dir)+sizeof("/maildirfolder"));
+ if (!newname2) return (-1);
+ strcat(strcpy(newname2, dir), "/maildirfolder");
+ if (stat(newname2, &u.stat_buf) == 0)
+ {
+ strcat(strcpy(newname2, dir), "/..");
+ n=doaddquota(newname2, maildirsize_fd, quota_type,
+ maildirsize_size, maildirsize_cnt,
+ isnew);
+ free(newname2);
+ return (n);
+ }
+
+ strcat(strcpy(newname2, dir), "/maildirsize");
+
+ if ((maildirsize_fd=maildir_safeopen(newname2,
+ O_RDWR|O_APPEND, 0644)) < 0)
+ {
+ newmaildirsizename=makenewmaildirsizename(dir, &maildirsize_fd);
+ if (!newmaildirsizename)
+ {
+ free(newname2);
+ return (-1);
+ }
+
+ maildirsize_fd=maildir_safeopen(newmaildirsizename,
+ O_CREAT|O_RDWR|O_APPEND, 0644);
+
+ if (maildirsize_fd < 0)
+ {
+ free(newname2);
+ return (-1);
+ }
+ isnew=1;
+ }
+ }
+
+ if (isnew)
+ {
+ iov[0].iov_base=(caddr_t)quota_type;
+ iov[0].iov_len=strlen(quota_type);
+ iov[1].iov_base=(caddr_t)"\n";
+ iov[1].iov_len=1;
+ niov=2;
+ }
+
+
+ sprintf(u.buf, "%ld %d\n", maildirsize_size, maildirsize_cnt);
+ iov[niov].iov_base=(caddr_t)u.buf;
+ iov[niov].iov_len=strlen(u.buf);
+
+ p=iov;
+ ++niov;
+ n=0;
+ while (niov)
+ {
+ if (n)
+ {
+ if (n < p->iov_len)
+ {
+ p->iov_base=
+ (caddr_t)((char *)p->iov_base + n);
+ p->iov_len -= n;
+ }
+ else
+ {
+ n -= p->iov_len;
+ ++p;
+ --niov;
+ continue;
+ }
+ }
+
+ n=writev( maildirsize_fd, p, niov);
+
+ if (n <= 0)
+ {
+ if (newname2)
+ {
+ close(maildirsize_fd);
+ free(newname2);
+ }
+ return (-1);
+ }
+ }
+ if (newname2)
+ {
+ close(maildirsize_fd);
+
+ if (newmaildirsizename)
+ {
+ rename(newmaildirsizename, newname2);
+ free(newmaildirsizename);
+ }
+ free(newname2);
+ }
+ return (0);
+}
+
+/* New maildirsize is built in the tmp subdirectory */
+
+static char *makenewmaildirsizename(const char *dir, int *fd)
+{
+char hostname[256];
+struct stat stat_buf;
+time_t t;
+char *p;
+
+ hostname[0]=0;
+ hostname[sizeof(hostname)-1]=0;
+ gethostname(hostname, sizeof(hostname)-1);
+ p=(char *)malloc(strlen(dir)+strlen(hostname)+130);
+ if (!p) return (0);
+
+ for (;;)
+ {
+ char tbuf[NUMBUFSIZE];
+ char pbuf[NUMBUFSIZE];
+
+ time(&t);
+ strcat(strcpy(p, dir), "/tmp/");
+ sprintf(p+strlen(p), "%s.%s_NeWmAiLdIrSiZe.%s",
+ str_time_t(t, tbuf),
+ str_pid_t(getpid(), pbuf), hostname);
+
+ if (stat( (const char *)p, &stat_buf) < 0 &&
+ (*fd=maildir_safeopen(p,
+ O_CREAT|O_RDWR|O_APPEND, 0644)) >= 0)
+ break;
+ sleep(3);
+ }
+ return (p);
+}
+
+static int statcurnew(const char *dir, time_t *maxtimestamp)
+{
+char *p=(char *)malloc(strlen(dir)+5);
+struct stat stat_buf;
+
+ if (!p) return (-1);
+ strcat(strcpy(p, dir), "/cur");
+ if ( stat(p, &stat_buf) == 0 && stat_buf.st_mtime > *maxtimestamp)
+ *maxtimestamp=stat_buf.st_mtime;
+ strcat(strcpy(p, dir), "/new");
+ if ( stat(p, &stat_buf) == 0 && stat_buf.st_mtime > *maxtimestamp)
+ *maxtimestamp=stat_buf.st_mtime;
+ free(p);
+ return (0);
+}
+
+static int statsubdir(const char *dir, const char *subdir, time_t *maxtime)
+{
+char *p;
+int n;
+
+ if ( *subdir != '.' || strcmp(subdir, ".") == 0 ||
+ strcmp(subdir, "..") == 0 || strcmp(subdir, "." TRASH) == 0)
+ return (0);
+
+ p=(char *)malloc(strlen(dir)+strlen(subdir)+2);
+ if (!p) return (-1);
+ strcat(strcat(strcpy(p, dir), "/"), subdir);
+ n=statcurnew(p, maxtime);
+ free(p);
+ return (n);
+}
+
+static int docount(const char *, time_t *, off_t *, unsigned *);
+
+static int countcurnew(const char *dir, time_t *maxtime,
+ off_t *sizep, unsigned *cntp)
+{
+char *p=(char *)malloc(strlen(dir)+5);
+int n;
+
+ if (!p) return (-1);
+ strcat(strcpy(p, dir), "/new");
+ n=docount(p, maxtime, sizep, cntp);
+ if (n == 0)
+ {
+ strcat(strcpy(p, dir), "/cur");
+ n=docount(p, maxtime, sizep, cntp);
+ }
+ free(p);
+ return (n);
+}
+
+static int countsubdir(const char *dir, const char *subdir, time_t *maxtime,
+ off_t *sizep, unsigned *cntp)
+{
+char *p;
+int n;
+
+ if ( *subdir != '.' || strcmp(subdir, ".") == 0 ||
+ strcmp(subdir, "..") == 0 || strcmp(subdir, "." TRASH) == 0)
+ return (0);
+
+ p=(char *)malloc(strlen(dir)+strlen(subdir)+2);
+ if (!p) return (2);
+ strcat(strcat(strcpy(p, dir), "/"), subdir);
+ n=countcurnew(p, maxtime, sizep, cntp);
+ free(p);
+ return (n);
+}
+
+static int docount(const char *dir, time_t *dirstamp,
+ off_t *sizep, unsigned *cntp)
+{
+struct stat stat_buf;
+char *p;
+DIR *dirp;
+struct dirent *de;
+unsigned long s;
+
+ if (stat(dir, &stat_buf)) return (0); /* Ignore */
+ if (stat_buf.st_mtime > *dirstamp) *dirstamp=stat_buf.st_mtime;
+ if ((dirp=opendir(dir)) == 0) return (0);
+ while ((de=readdir(dirp)) != 0)
+ {
+ const char *n=de->d_name;
+
+ if (*n == '.') continue;
+
+ /* PATCH - do not count msgs marked as deleted */
+
+ for ( ; *n; n++)
+ {
+ if (n[0] != ':' || n[1] != '2' ||
+ n[2] != ',') continue;
+ n += 3;
+ while (*n >= 'A' && *n <= 'Z')
+ {
+ if (*n == 'T') break;
+ ++n;
+ }
+ break;
+ }
+ if (*n == 'T') continue;
+ n=de->d_name;
+
+
+ if (maildir_parsequota(n, &s) == 0)
+ stat_buf.st_size=s;
+ else
+ {
+ p=(char *)malloc(strlen(dir)+strlen(n)+2);
+ if (!p)
+ {
+ closedir(dirp);
+ return (-1);
+ }
+ strcat(strcat(strcpy(p, dir), "/"), n);
+ if (stat(p, &stat_buf))
+ {
+ free(p);
+ continue;
+ }
+ free(p);
+ }
+ *sizep += stat_buf.st_size;
+ ++*cntp;
+ }
+
+#if CLOSEDIR_VOID
+ closedir(dirp);
+#else
+ if (closedir(dirp))
+ return (-1);
+#endif
+ return (0);
+}
diff -Naur ./maildirquota.h ../qmail-1.03-build-10/maildirquota.h
--- ./maildirquota.h 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/maildirquota.h 2006-05-03 17:44:55.000000000 -0500
@@ -0,0 +1,45 @@
+#ifndef maildirquota_h
+#define maildirquota_h
+
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static const char maildirquota_h_rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+int maildir_checkquota(const char *, /* Pointer to directory */
+ int *, /* Initialized to -1, or opened descriptor for maildirsize */
+ const char *, /* The quota */
+ long, /* Extra bytes planning to add/remove from maildir */
+ int); /* Extra messages planning to add/remove from maildir */
+
+int maildir_addquota(const char *, /* Pointer to the maildir */
+ int, /* Must be the int pointed to by 2nd arg to checkquota */
+ const char *, /* The quota */
+ long, /* +/- bytes */
+ int); /* +/- files */
+
+int maildir_readquota(const char *, /* Directory */
+ const char *); /* Quota, from getquota */
+
+int maildir_parsequota(const char *, unsigned long *);
+ /* Attempt to parse file size encoded in filename. Returns 0 if
+ ** parsed, non-zero if we didn't parse. */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Naur ./Makefile ../qmail-1.03-build-10/Makefile
--- ./Makefile 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/Makefile 2006-05-09 23:55:55.000000000 -0500
@@ -1,5 +1,10 @@
# Don't edit Makefile! Use conf-* for configuration.
+VPOPMAIL_HOME=/home/vpopmail
+SMTPD_CHKUSER_OBJ=chkuser.o
+VPOPMAIL_LIBS=`head -1 $(VPOPMAIL_HOME)/etc/lib_deps` `cat dns.lib`
+LIB_DK=LDK_PATH
+
SHELL=/bin/sh
default: it
@@ -136,6 +141,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 \
@@ -203,6 +212,10 @@
compile byte_cr.c byte.h
./compile byte_cr.c
+byte_cspn.o: \
+compile byte_cspn.c byte.h
+ ./compile byte_cspn.c
+
byte_diff.o: \
compile byte_diff.c byte.h
./compile byte_diff.c
@@ -211,15 +224,19 @@
compile byte_rchr.c byte.h
./compile byte_rchr.c
+byte_rcspn.o: \
+compile byte_rcspn.c byte.h
+ ./compile byte_rcspn.c
+
byte_zero.o: \
compile byte_zero.c byte.h
./compile byte_zero.c
case.a: \
makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \
-case_starts.o
+case_starts.o case_startb.o
./makelib case.a case_diffb.o case_diffs.o case_lowerb.o \
- case_lowers.o case_starts.o
+ case_lowers.o case_starts.o case_startb.o
case_diffb.o: \
compile case_diffb.c case.h
@@ -237,6 +254,10 @@
compile case_lowers.c case.h
./compile case_lowers.c
+case_startb.o: \
+compile case_startb.c case.h
+ ./compile case_startb.c
+
case_starts.o: \
compile case_starts.c case.h
./compile case_starts.c
@@ -263,7 +284,7 @@
cdbmake_add.o
cdbmake_add.o: \
-compile cdbmake_add.c cdbmake.h uint32.h
+compile cdbmake_add.c cdbmake.h alloc.h uint32.h
./compile cdbmake_add.c
cdbmake_hash.o: \
@@ -300,6 +321,10 @@
exit.h auto_spawn.h
./compile chkspawn.c
+chkuser.o: \
+compile chkuser.c chkuser.h chkuser_settings.h
+ ./compile chkuser.c
+
clean: \
TARGETS
rm -f `cat TARGETS`
@@ -393,84 +418,96 @@
rm -f trydrent.o
dns.lib: \
-tryrsolv.c compile load socket.lib dns.o ipalloc.o ip.o stralloc.a \
+tryrsolv.c compile load socket.lib dns.o ipalloc.o strsalloc.o ip.o stralloc.a \
alloc.a error.a fs.a str.a
( ( ./compile tryrsolv.c && ./load tryrsolv dns.o \
- ipalloc.o ip.o stralloc.a alloc.a error.a fs.a str.a \
+ ipalloc.o strsalloc.o ip.o stralloc.a alloc.a error.a fs.a str.a \
-lresolv `cat socket.lib` ) >/dev/null 2>&1 \
&& echo -lresolv || exit 0 ) > dns.lib
rm -f tryrsolv.o tryrsolv
dns.o: \
-compile dns.c ip.h ipalloc.h ip.h gen_alloc.h fmt.h alloc.h str.h \
+compile dns.c ip.h ipalloc.h ip.h strsalloc.h gen_alloc.h fmt.h alloc.h str.h \
stralloc.h gen_alloc.h dns.h case.h
./compile dns.c
dnscname: \
-load dnscname.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+load dnscname.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
substdio.a error.a str.a fs.a dns.lib socket.lib
- ./load dnscname dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+ ./load dnscname dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a \
alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \
socket.lib`
dnscname.o: \
-compile dnscname.c substdio.h subfd.h substdio.h stralloc.h \
+compile dnscname.c substdio.h subfd.h stralloc.h \
gen_alloc.h dns.h dnsdoe.h readwrite.h exit.h
./compile dnscname.c
dnsdoe.o: \
-compile dnsdoe.c substdio.h subfd.h substdio.h exit.h dns.h dnsdoe.h
+compile dnsdoe.c substdio.h subfd.h exit.h dns.h dnsdoe.h
./compile dnsdoe.c
dnsfq: \
-load dnsfq.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+load dnsfq.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
substdio.a error.a str.a fs.a dns.lib socket.lib
- ./load dnsfq dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+ ./load dnsfq dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a \
alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \
socket.lib`
dnsfq.o: \
-compile dnsfq.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
-dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h exit.h
+compile dnsfq.c substdio.h subfd.h stralloc.h gen_alloc.h \
+dns.h dnsdoe.h ip.h ipalloc.h strsalloc.h exit.h
./compile dnsfq.c
dnsip: \
-load dnsip.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+load dnsip.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
substdio.a error.a str.a fs.a dns.lib socket.lib
- ./load dnsip dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+ ./load dnsip dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a \
alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \
socket.lib`
dnsip.o: \
-compile dnsip.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
-dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h exit.h
+compile dnsip.c substdio.h subfd.h stralloc.h gen_alloc.h \
+dns.h dnsdoe.h ip.h ipalloc.h strsalloc.h exit.h
./compile dnsip.c
dnsmxip: \
-load dnsmxip.o dns.o dnsdoe.o ip.o ipalloc.o now.o stralloc.a alloc.a \
+load dnsmxip.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o now.o stralloc.a alloc.a \
substdio.a error.a str.a fs.a dns.lib socket.lib
- ./load dnsmxip dns.o dnsdoe.o ip.o ipalloc.o now.o \
+ ./load dnsmxip dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o now.o \
stralloc.a alloc.a substdio.a error.a str.a fs.a `cat \
dns.lib` `cat socket.lib`
dnsmxip.o: \
-compile dnsmxip.c substdio.h subfd.h substdio.h stralloc.h \
-gen_alloc.h fmt.h dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h \
+compile dnsmxip.c substdio.h subfd.h stralloc.h \
+gen_alloc.h fmt.h dns.h dnsdoe.h ip.h ipalloc.h strsalloc.h \
now.h datetime.h exit.h
./compile dnsmxip.c
dnsptr: \
-load dnsptr.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+load dnsptr.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
substdio.a error.a str.a fs.a dns.lib socket.lib
- ./load dnsptr dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+ ./load dnsptr dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a \
alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \
socket.lib`
dnsptr.o: \
-compile dnsptr.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
+compile dnsptr.c substdio.h subfd.h stralloc.h gen_alloc.h \
str.h scan.h dns.h dnsdoe.h ip.h exit.h
./compile dnsptr.c
+dnstxt: \
+load dnstxt.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+ ./load dnstxt dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a \
+ alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \
+ socket.lib`
+
+dnstxt.o: \
+compile dnstxt.c substdio.h subfd.h stralloc.h gen_alloc.h \
+str.h scan.h dns.h dnsdoe.h ip.h exit.h
+ ./compile dnstxt.c
+
dot-qmail.0: \
dot-qmail.5
nroff -man dot-qmail.5 > dot-qmail.0
@@ -777,24 +814,24 @@
./compile ip.c
ipalloc.o: \
-compile ipalloc.c alloc.h gen_allocdefs.h ip.h ipalloc.h ip.h \
+compile ipalloc.c alloc.h gen_allocdefs.h ip.h ipalloc.h \
gen_alloc.h
./compile ipalloc.c
ipme.o: \
-compile ipme.c hassalen.h byte.h ip.h ipalloc.h ip.h gen_alloc.h \
-stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h
+compile ipme.c hassalen.h byte.h ip.h ipalloc.h strsalloc.h ip.h gen_alloc.h \
+stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h strsalloc.h
./compile ipme.c
ipmeprint: \
-load ipmeprint.o ipme.o ip.o ipalloc.o stralloc.a alloc.a substdio.a \
+load ipmeprint.o ipme.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a substdio.a \
error.a str.a fs.a socket.lib
- ./load ipmeprint ipme.o ip.o ipalloc.o stralloc.a alloc.a \
+ ./load ipmeprint ipme.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
substdio.a error.a str.a fs.a `cat socket.lib`
ipmeprint.o: \
compile ipmeprint.c subfd.h substdio.h substdio.h ip.h ipme.h ip.h \
-ipalloc.h ip.h gen_alloc.h exit.h
+ipalloc.h strsalloc.h ip.h gen_alloc.h exit.h
./compile ipmeprint.c
it: \
@@ -803,12 +840,13 @@
predate datemail mailsubj qmail-upq qmail-showctl qmail-newu \
qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \
qmail-pop3d qmail-popup qmail-qmqpc qmail-qmqpd qmail-qmtpd \
+qmail-badmimetypes qmail-badloadertypes \
qmail-smtpd sendmail tcp-env qmail-newmrh config config-fast dnscname \
-dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \
+dnsptr dnsip dnsmxip dnsfq dnstxt hostname ipmeprint qreceipt qsmhook qbiff \
forward preline condredirect bouncesaying except maildirmake \
maildir2mbox maildirwatch qail elq pinq idedit install-big install \
instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \
-binm3 binm3+df
+binm3 binm3+df spfquery qmail-dk update_tmprsadh
load: \
make-load warn-auto.sh systype
@@ -890,6 +928,38 @@
readwrite.h open.h headerbody.h maildir.h strerr.h
./compile maildirwatch.c
+maildirgetquota.o: \
+compile maildirgetquota.c maildirgetquota.h maildirmisc.h
+ ./compile maildirgetquota.c
+
+maildirflags.o: \
+compile maildirflags.c
+ ./compile maildirflags.c
+
+maildiropen.o: \
+compile maildiropen.c maildirmisc.h
+ ./compile maildiropen.c
+
+maildirparsequota.o: \
+compile maildirparsequota.c
+ ./compile maildirparsequota.c
+
+maildirquota.o: \
+compile maildirquota.c maildirquota.h maildirmisc.h numlib.h
+ ./compile maildirquota.c
+
+overmaildirquota.o: \
+compile overmaildirquota.c
+ ./compile overmaildirquota.c
+
+strtimet.o: \
+compile strtimet.c
+ ./compile strtimet.c
+
+strpidt.o: \
+compile strpidt.c
+ ./compile strpidt.c
+
mailsubj: \
warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split
cat warn-auto.sh mailsubj.sh \
@@ -927,6 +997,7 @@
man: \
qmail-local.0 qmail-lspawn.0 qmail-getpw.0 qmail-remote.0 \
qmail-rspawn.0 qmail-clean.0 qmail-send.0 qmail-start.0 splogger.0 \
+qmail-badmimetypes.0 qmail-badloadertypes.0 \
qmail-queue.0 qmail-inject.0 mailsubj.0 qmail-showctl.0 qmail-newu.0 \
qmail-pw2u.0 qmail-qread.0 qmail-qstat.0 qmail-tcpto.0 qmail-tcpok.0 \
qmail-pop3d.0 qmail-popup.0 qmail-qmqpc.0 qmail-qmqpd.0 qmail-qmtpd.0 \
@@ -1107,6 +1178,29 @@
| sed s}SPAWN}"`head -1 conf-spawn`"}g \
> qmail-control.5
+qmail-dk: \
+load qmail-dk.o triggerpull.o fmtqfn.o now.o date822fmt.o \
+datetime.a seek.a ndelay.a open.a sig.a alloc.a substdio.a error.a \
+str.a fs.a auto_qmail.o auto_split.o auto_uids.o fd.a wait.a \
+$(LIB_DK) env.a getln.a control.o stralloc.a dns.lib
+ ./load qmail-dk triggerpull.o fmtqfn.o now.o \
+ date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \
+ substdio.a error.a fs.a auto_qmail.o \
+ auto_split.o auto_uids.o fd.a wait.a \
+ $(LIB_DK) -lcrypto env.a control.o open.a getln.a \
+ stralloc.a alloc.a scan_ulong.o str.a `cat dns.lib`
+
+qmail-dk.0: \
+qmail-dk.8
+ nroff -man qmail-dk.8 > qmail-dk.0
+
+qmail-dk.o: \
+compile qmail-dk.c readwrite.h sig.h exit.h open.h seek.h fmt.h \
+alloc.h substdio.h datetime.h now.h datetime.h triggerpull.h extra.h \
+env.h wait.h fd.h fork.h str.h \
+auto_qmail.h auto_uids.h date822fmt.h fmtqfn.h
+ ./compile qmail-dk.c
+
qmail-getpw: \
load qmail-getpw.o case.a substdio.a error.a str.a fs.a auto_break.o \
auto_usera.o
@@ -1174,12 +1268,15 @@
load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \
slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \
wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
-fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib
+fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib maildirquota.o \
+maildirgetquota.o maildiropen.o maildirparsequota.o overmaildirquota.o \
+strtimet.o strpidt.o
./load qmail-local qmail.o quote.o now.o gfrom.o myctime.o \
slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a \
lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \
substdio.a error.a str.a fs.a datetime.a auto_qmail.o \
- auto_patrn.o `cat socket.lib`
+ auto_patrn.o `cat socket.lib` maildirquota.o maildirgetquota.o \
+ maildiropen.o maildirparsequota.o overmaildirquota.o strtimet.o strpidt.o
qmail-local.0: \
qmail-local.8
@@ -1216,6 +1313,56 @@
slurpclose.h auto_qmail.h auto_uids.h qlx.h
./compile qmail-lspawn.c
+qmail-badmimetypes: \
+load qmail-badmimetypes.o cdbmss.o getln.a open.a cdbmake.a seek.a case.a \
+stralloc.a alloc.a strerr.a substdio.a error.a str.a auto_qmail.o
+ ./load qmail-badmimetypes cdbmss.o getln.a open.a cdbmake.a \
+ seek.a case.a stralloc.a alloc.a strerr.a substdio.a \
+ error.a str.a auto_qmail.o
+
+qmail-badmimetypes.0: \
+qmail-badmimetypes.8
+ nroff -man qmail-badmimetypes.8 > qmail-badmimetypes.0
+
+qmail-badmimetypes.8: \
+qmail-badmimetypes.9 conf-break conf-spawn
+ cat qmail-badmimetypes.9 \
+ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPAWN}"`head -1 conf-spawn`"}g \
+ > qmail-badmimetypes.8
+
+qmail-badmimetypes.o: \
+compile qmail-badmimetypes.c strerr.h stralloc.h gen_alloc.h substdio.h \
+getln.h exit.h readwrite.h open.h auto_qmail.h cdbmss.h cdbmake.h \
+uint32.h substdio.h
+ ./compile qmail-badmimetypes.c
+
+qmail-badloadertypes: \
+load qmail-badloadertypes.o cdbmss.o getln.a open.a cdbmake.a seek.a case.a \
+stralloc.a alloc.a strerr.a substdio.a error.a str.a auto_qmail.o
+ ./load qmail-badloadertypes cdbmss.o getln.a open.a cdbmake.a \
+ seek.a case.a stralloc.a alloc.a strerr.a substdio.a \
+ error.a str.a auto_qmail.o
+
+qmail-badloadertypes.0: \
+qmail-badloadertypes.8
+ nroff -man qmail-badloadertypes.8 > qmail-badloadertypes.0
+
+qmail-badloadertypes.8: \
+qmail-badloadertypes.9 conf-break conf-spawn
+ cat qmail-badloadertypes.9 \
+ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPAWN}"`head -1 conf-spawn`"}g \
+ > qmail-badloadertypes.8
+
+qmail-badloadertypes.o: \
+compile qmail-badloadertypes.c strerr.h stralloc.h gen_alloc.h substdio.h \
+getln.h exit.h readwrite.h open.h auto_qmail.h cdbmss.h cdbmake.h \
+uint32.h substdio.h
+ ./compile qmail-badloadertypes.c
+
qmail-newmrh: \
load qmail-newmrh.o cdbmss.o getln.a open.a cdbmake.a seek.a case.a \
stralloc.a alloc.a strerr.a substdio.a error.a str.a auto_qmail.o
@@ -1269,11 +1416,13 @@
qmail-pop3d: \
load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \
maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \
-stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib
+stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib maildirquota.o \
+maildirparsequota.o maildirflags.o maildiropen.o strtimet.o strpidt.o
./load qmail-pop3d commands.o case.a timeoutread.o \
timeoutwrite.o maildir.o prioq.o now.o env.a strerr.a sig.a \
open.a getln.a stralloc.a alloc.a substdio.a error.a str.a \
- fs.a `cat socket.lib`
+ fs.a `cat socket.lib` maildirquota.o maildirgetquota.o \
+ maildirparsequota.o maildirflags.o maildiropen.o strtimet.o strpidt.o
qmail-pop3d.0: \
qmail-pop3d.8
@@ -1419,13 +1568,14 @@
nroff -man qmail-qstat.8 > qmail-qstat.0
qmail-queue: \
-load qmail-queue.o triggerpull.o fmtqfn.o now.o date822fmt.o \
-datetime.a seek.a ndelay.a open.a sig.a alloc.a substdio.a error.a \
-str.a fs.a auto_qmail.o auto_split.o auto_uids.o
+load qmail-queue.o triggerpull.o fmtqfn.o now.o date822fmt.o qregex.o \
+datetime.a seek.a case.a ndelay.a open.a sig.a getln.a stralloc.a alloc.a \
+substdio.a error.a control.o constmap.o str.a fs.a auto_qmail.o \
+auto_split.o auto_uids.o
./load qmail-queue triggerpull.o fmtqfn.o now.o \
- date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \
- alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
- auto_split.o auto_uids.o
+ date822fmt.o qregex.o control.o constmap.o datetime.a case.a seek.a \
+ ndelay.a open.a sig.a getln.a stralloc.a alloc.a substdio.a error.a \
+ str.a fs.a auto_qmail.o auto_split.o auto_uids.o
qmail-queue.0: \
qmail-queue.8
@@ -1439,14 +1589,15 @@
qmail-remote: \
load qmail-remote.o control.o constmap.o timeoutread.o timeoutwrite.o \
-timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o ipme.o quote.o \
+timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o strsalloc.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 dns.lib socket.lib
+substdio.a error.a str.a fs.a auto_qmail.o base64.o dns.lib socket.lib
./load qmail-remote control.o constmap.o timeoutread.o \
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 \
+ tls.o ssl_timeoutio.o -L/usr/local/ssl/lib -lssl -lcrypto \
+ ipalloc.o strsalloc.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 base64.o `cat dns.lib` `cat socket.lib`
qmail-remote.0: \
qmail-remote.8
@@ -1455,7 +1606,7 @@
qmail-remote.o: \
compile qmail-remote.c sig.h stralloc.h gen_alloc.h substdio.h \
subfd.h substdio.h scan.h case.h error.h auto_qmail.h control.h dns.h \
-alloc.h quote.h ip.h ipalloc.h ip.h gen_alloc.h ipme.h ip.h ipalloc.h \
+alloc.h quote.h ip.h ipalloc.h strsalloc.h ip.h gen_alloc.h ipme.h ip.h ipalloc.h strsalloc.h \
gen_alloc.h gen_allocdefs.h str.h now.h datetime.h exit.h constmap.h \
tcpto.h readwrite.h timeoutconn.h timeoutread.h timeoutwrite.h
./compile qmail-remote.c
@@ -1483,12 +1634,12 @@
trigger.o fmtqfn.o quote.o now.o readsubdir.o qmail.o date822fmt.o \
datetime.a case.a ndelay.a getln.a wait.a seek.a fd.a sig.a open.a \
lock.a stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
-auto_split.o
+auto_split.o env.a
./load qmail-send qsutil.o control.o constmap.o newfield.o \
prioq.o trigger.o fmtqfn.o quote.o now.o readsubdir.o \
qmail.o date822fmt.o datetime.a case.a ndelay.a getln.a \
wait.a seek.a fd.a sig.a open.a lock.a stralloc.a alloc.a \
- substdio.a error.a str.a fs.a auto_qmail.o auto_split.o
+ substdio.a error.a str.a fs.a auto_qmail.o auto_split.o env.a
qmail-send.0: \
qmail-send.8
@@ -1528,32 +1679,33 @@
compile qmail-showctl.c substdio.h subfd.h substdio.h exit.h fmt.h \
str.h control.h constmap.h stralloc.h gen_alloc.h direntry.h \
auto_uids.h auto_qmail.h auto_break.h auto_patrn.h auto_spawn.h \
-auto_split.h
+auto_split.h spf.h
./compile qmail-showctl.c
qmail-smtpd: \
-load qmail-smtpd.o 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 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 \
+load qmail-smtpd.o rcpthosts.o qregex.o commands.o timeoutread.o \
+timeoutwrite.o ip.o ipme.o ipalloc.o strsalloc.o control.o constmap.o received.o \
+date822fmt.o now.o qmail.o spf.o dns.o cdb.a fd.a wait.a datetime.a getln.a \
+open.a sig.a case.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
+fs.a lock.a auto_qmail.o base64.o socket.lib $(SMTPD_CHKUSER_OBJ) dns.lib
+ ./load qmail-smtpd $(SMTPD_CHKUSER_OBJ) qregex.o rcpthosts.o commands.o timeoutread.o \
+ timeoutwrite.o ip.o ipme.o ipalloc.o strsalloc.o control.o constmap.o \
+ tls.o ssl_timeoutio.o ndelay.a -L/usr/local/ssl/lib -lssl -lcrypto \
+ received.o date822fmt.o now.o qmail.o spf.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 strerr.a substdio.a error.a fs.a auto_qmail.o str.a base64.o \
+ `cat socket.lib dns.lib` dns.o lock.a $(VPOPMAIL_LIBS)
qmail-smtpd.0: \
qmail-smtpd.8
nroff -man qmail-smtpd.8 > qmail-smtpd.0
qmail-smtpd.o: \
-compile qmail-smtpd.c sig.h readwrite.h stralloc.h gen_alloc.h \
+compile qmail-smtpd.c chkuser.h sig.h readwrite.h stralloc.h gen_alloc.h \
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 \
+error.h ipme.h ip.h ipalloc.h strsalloc.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 spf.h base64.h
./compile qmail-smtpd.c
qmail-start: \
@@ -1681,6 +1833,10 @@
constmap.h stralloc.h gen_alloc.h rcpthosts.h
./compile rcpthosts.c
+qregex.o: \
+compile qregex.c qregex.h
+ ./compile qregex.c
+
readsubdir.o: \
compile readsubdir.c readsubdir.h direntry.h fmt.h scan.h str.h \
auto_split.h
@@ -1767,6 +1923,7 @@
maildirwatch.1 mailsubj.1 mbox.5 preline.1 qbiff.1 qmail-clean.8 \
qmail-command.8 qmail-control.9 qmail-getpw.9 qmail-header.5 \
qmail-inject.8 qmail-limits.9 qmail-local.8 qmail-log.5 \
+qmail-badmimetypes.9 qmail-badloadertypes.9 \
qmail-lspawn.8 qmail-newmrh.9 qmail-newu.9 qmail-pop3d.8 \
qmail-popup.8 qmail-pw2u.9 qmail-qmqpc.8 qmail-qmqpd.8 qmail-qmtpd.8 \
qmail-qread.8 qmail-qstat.8 qmail-queue.8 qmail-remote.8 \
@@ -1774,12 +1931,13 @@
qmail-start.9 qmail-tcpok.8 qmail-tcpto.8 qmail-users.9 qmail.7 \
qreceipt.1 splogger.8 tcp-env.1 config.sh config-fast.sh \
qmail-clean.c qmail-getpw.c qmail-inject.c qmail-local.c \
+qmail-badmimetypes.c qmail-badloadertypes.c \
qmail-lspawn.c qmail-newmrh.c qmail-newu.c qmail-pop3d.c \
qmail-popup.c qmail-pw2u.c qmail-qmqpc.c qmail-qmqpd.c qmail-qmtpd.c \
qmail-qread.c qmail-qstat.sh qmail-queue.c qmail-remote.c \
qmail-rspawn.c qmail-send.c qmail-showctl.c qmail-smtpd.c \
qmail-start.c qmail-tcpok.c qmail-tcpto.c spawn.c dnscname.c dnsfq.c \
-dnsip.c dnsmxip.c dnsptr.c hostname.c ipmeprint.c tcp-env.c \
+dnsip.c dnsmxip.c dnsptr.c dnstxt.c hostname.c ipmeprint.c tcp-env.c \
sendmail.c qreceipt.c qsmhook.c qbiff.c forward.c preline.c predate.c \
except.c bouncesaying.c condredirect.c maildirmake.c maildir2mbox.c \
maildirwatch.c splogger.c qail.sh elq.sh pinq.sh qmail-upq.sh \
@@ -1813,8 +1971,9 @@
trywaitp.c sig.h sig_alarm.c sig_block.c sig_catch.c sig_pause.c \
sig_pipe.c sig_child.c sig_term.c sig_hup.c sig_misc.c sig_bug.c \
trysgact.c trysgprm.c env.3 env.h env.c envread.c byte.h byte_chr.c \
-byte_copy.c byte_cr.c byte_diff.c byte_rchr.c byte_zero.c str.h \
-str_chr.c str_cpy.c str_diff.c str_diffn.c str_len.c str_rchr.c \
+byte_copy.c byte_cr.c byte_cspn.c byte_diff.c byte_rchr.c byte_rcspn.c \
+byte_zero.c str.h spf.c spf.h spfquery.c \
+str_chr.c str_cpy.c str_cpyb.c str_diff.c str_diffn.c str_len.c str_rchr.c \
str_start.c lock.h lock_ex.c lock_exnb.c lock_un.c tryflock.c getln.3 \
getln.h getln.c getln2.3 getln2.c sgetopt.3 sgetopt.h sgetopt.c \
subgetopt.3 subgetopt.h subgetopt.c error.3 error_str.3 error_temp.3 \
@@ -1824,10 +1983,11 @@
headerbody.h headerbody.c token822.h token822.c control.h control.c \
datetime.3 datetime.h datetime.c datetime_un.c prioq.h prioq.c \
date822fmt.h date822fmt.c dns.h dns.c trylsock.c tryrsolv.c ip.h ip.c \
-ipalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h ndelay.c \
+ipalloc.h strsalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h ndelay.c \
ndelay_off.c direntry.3 direntry.h1 direntry.h2 trydrent.c prot.h \
prot.c chkshsgr.c warn-shsgr tryshsgr.c ipme.h ipme.c trysalen.c \
-maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c
+maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c \
+update_tmprsadh
shar -m `cat FILES` > shar
chmod 400 shar
@@ -1892,11 +2052,28 @@
spawn.o: \
compile chkspawn spawn.c sig.h wait.h substdio.h byte.h str.h \
-stralloc.h gen_alloc.h select.h exit.h coe.h open.h error.h \
+stralloc.h gen_alloc.h select.h exit.h alloc.h coe.h open.h error.h \
auto_qmail.h auto_uids.h auto_spawn.h
./chkspawn
./compile spawn.c
+spf.o: \
+compile spf.c stralloc.h gen_alloc.h alloc.h ipme.h ip.h ipalloc.h \
+strsalloc.h str.h fmt.h scan.h byte.h now.h case.h
+ ./compile spf.c
+
+spfquery: \
+load spfquery.o spf.o ip.o ipme.o ipalloc.o strsalloc.o now.o dns.o \
+datetime.a stralloc.a alloc.a str.a substdio.a error.a fs.a case.a dns.lib
+ ./load spfquery spf.o ip.o ipme.o ipalloc.o strsalloc.o \
+ now.o dns.o datetime.a stralloc.a alloc.a str.a substdio.a \
+ case.a error.a fs.a `cat dns.lib` `cat socket.lib`
+
+spfquery.o: \
+compile spfquery.c substdio.h subfd.h stralloc.h gen_alloc.h alloc.h \
+spf.h exit.h
+ ./compile spfquery.c
+
splogger: \
load splogger.o substdio.a error.a str.a fs.a syslog.lib socket.lib
./load splogger substdio.a error.a str.a fs.a `cat \
@@ -1912,12 +2089,12 @@
./compile splogger.c
str.a: \
-makelib str_len.o str_diff.o str_diffn.o str_cpy.o str_chr.o \
-str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_diff.o byte_copy.o \
+makelib str_len.o str_diff.o str_diffn.o str_cpy.o str_cpyb.o str_chr.o \
+str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_diff.o byte_copy.o byte_cspn.o byte_rcspn.o \
byte_cr.o byte_zero.o
- ./makelib str.a str_len.o str_diff.o str_diffn.o str_cpy.o \
- str_chr.o str_rchr.o str_start.o byte_chr.o byte_rchr.o \
- byte_diff.o byte_copy.o byte_cr.o byte_zero.o
+ ./makelib str.a str_len.o str_diff.o str_diffn.o str_cpy.o str_cpyb.o \
+ str_chr.o str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_cspn.o \
+ byte_rcspn.o byte_diff.o byte_copy.o byte_cr.o byte_zero.o
str_chr.o: \
compile str_chr.c str.h
@@ -1927,6 +2104,10 @@
compile str_cpy.c str.h
./compile str_cpy.c
+str_cpyb.o: \
+compile str_cpyb.c str.h
+ ./compile str_cpyb.c
+
str_diff.o: \
compile str_diff.c str.h
./compile str_diff.c
@@ -2006,6 +2187,11 @@
compile strerr_sys.c error.h strerr.h
./compile strerr_sys.c
+strsalloc.o: \
+compile strsalloc.c alloc.h gen_allocdefs.h stralloc.h strsalloc.h \
+gen_alloc.h
+ ./compile strsalloc.c
+
subfderr.o: \
compile subfderr.c readwrite.h substdio.h subfd.h substdio.h
./compile subfderr.c
@@ -2066,10 +2252,10 @@
tcp-env: \
load tcp-env.o dns.o remoteinfo.o timeoutread.o timeoutwrite.o \
-timeoutconn.o ip.o ipalloc.o case.a ndelay.a sig.a env.a getopt.a \
+timeoutconn.o ip.o ipalloc.o strsalloc.o case.a ndelay.a sig.a env.a getopt.a \
stralloc.a alloc.a substdio.a error.a str.a fs.a dns.lib socket.lib
./load tcp-env dns.o remoteinfo.o timeoutread.o \
- timeoutwrite.o timeoutconn.o ip.o ipalloc.o case.a ndelay.a \
+ timeoutwrite.o timeoutconn.o ip.o ipalloc.o strsalloc.o case.a ndelay.a \
sig.a env.a getopt.a stralloc.a alloc.a substdio.a error.a \
str.a fs.a `cat dns.lib` `cat socket.lib`
@@ -2108,6 +2294,19 @@
compile timeoutwrite.c timeoutwrite.h select.h error.h readwrite.h
./compile timeoutwrite.c
+qmail-smtpd: tls.o ssl_timeoutio.o ndelay.a
+qmail-remote: tls.o ssl_timeoutio.o
+qmail-smtpd.o: tls.h ssl_timeoutio.h
+qmail-remote.o: tls.h ssl_timeoutio.h
+
+tls.o: \
+compile tls.c exit.h error.h
+ ./compile tls.c
+
+ssl_timeoutio.o: \
+compile ssl_timeoutio.c ssl_timeoutio.h select.h error.h ndelay.h
+ ./compile ssl_timeoutio.c
+
token822.o: \
compile token822.c stralloc.h gen_alloc.h alloc.h str.h token822.h \
gen_alloc.h gen_allocdefs.h
@@ -2139,3 +2338,26 @@
wait_pid.o: \
compile wait_pid.c error.h haswaitp.h
./compile wait_pid.c
+
+cert cert-req: \
+Makefile-cert
+ @$(MAKE) -sf $< $@
+
+Makefile-cert: \
+conf-qmail conf-users conf-groups Makefile-cert.mk
+ @cat Makefile-cert.mk \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ > $@
+
+update_tmprsadh: \
+conf-qmail conf-users conf-groups update_tmprsadh.sh
+ @cat update_tmprsadh.sh\
+ | sed s}UGQMAILD}"`head -2 conf-users|tail -1`:`head -1 conf-groups`"}g \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ > $@
+ chmod 755 update_tmprsadh
+
+tmprsadh: \
+update_tmprsadh
+ echo "Creating new temporary RSA and DH parameters"
+ ./update_tmprsadh
diff -Naur ./Makefile-cert.mk ../qmail-1.03-build-10/Makefile-cert.mk
--- ./Makefile-cert.mk 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/Makefile-cert.mk 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,21 @@
+cert-req: req.pem
+cert cert-req: QMAIL/control/clientcert.pem
+ @:
+
+QMAIL/control/clientcert.pem: QMAIL/control/servercert.pem
+ ln -s $< $@
+
+QMAIL/control/servercert.pem:
+ PATH=$$PATH:/usr/local/ssl/bin \
+ openssl req -new -x509 -nodes -days 366 -out $@ -keyout $@
+ chmod 640 $@
+ chown `head -2 conf-users | tail -1`:`head -1 conf-groups` $@
+
+req.pem:
+ PATH=$$PATH:/usr/local/ssl/bin openssl req \
+ -new -nodes -out $@ -keyout QMAIL/control/servercert.pem
+ chmod 640 QMAIL/control/servercert.pem
+ chown `head -2 conf-users | tail -1`:`head -1 conf-groups` QMAIL/control/servercert.pem
+ @echo
+ @echo "Send req.pem to your CA to obtain signed_req.pem, and do:"
+ @echo "cat signed_req.pem >> QMAIL/control/servercert.pem"
diff -Naur ./Makefile.orig ../qmail-1.03-build-10/Makefile.orig
--- ./Makefile.orig 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/Makefile.orig 2006-04-27 13:19:48.000000000 -0500
@@ -0,0 +1,2197 @@
+# Don't edit Makefile! Use conf-* for configuration.
+
+VPOPMAIL_HOME=/home/vpopmail
+SMTPD_CHKUSER_OBJ=chkuser.o dns.o
+VPOPMAIL_LIBS=`head -1 $(VPOPMAIL_HOME)/etc/lib_deps` `cat dns.lib`
+
+SHELL=/bin/sh
+
+default: it
+
+addresses.0: \
+addresses.5
+ nroff -man addresses.5 > addresses.0
+
+alloc.a: \
+makelib alloc.o alloc_re.o
+ ./makelib alloc.a alloc.o alloc_re.o
+
+alloc.o: \
+compile alloc.c alloc.h error.h
+ ./compile alloc.c
+
+alloc_re.o: \
+compile alloc_re.c alloc.h byte.h
+ ./compile alloc_re.c
+
+auto-ccld.sh: \
+conf-cc conf-ld warn-auto.sh
+ ( cat warn-auto.sh; \
+ echo CC=\'`head -1 conf-cc`\'; \
+ echo LD=\'`head -1 conf-ld`\' \
+ ) > auto-ccld.sh
+
+auto-gid: \
+load auto-gid.o substdio.a error.a str.a fs.a
+ ./load auto-gid substdio.a error.a str.a fs.a
+
+auto-gid.o: \
+compile auto-gid.c subfd.h substdio.h substdio.h readwrite.h exit.h \
+scan.h fmt.h
+ ./compile auto-gid.c
+
+auto-int: \
+load auto-int.o substdio.a error.a str.a fs.a
+ ./load auto-int substdio.a error.a str.a fs.a
+
+auto-int.o: \
+compile auto-int.c substdio.h readwrite.h exit.h scan.h fmt.h
+ ./compile auto-int.c
+
+auto-int8: \
+load auto-int8.o substdio.a error.a str.a fs.a
+ ./load auto-int8 substdio.a error.a str.a fs.a
+
+auto-int8.o: \
+compile auto-int8.c substdio.h readwrite.h exit.h scan.h fmt.h
+ ./compile auto-int8.c
+
+auto-str: \
+load auto-str.o substdio.a error.a str.a
+ ./load auto-str substdio.a error.a str.a
+
+auto-str.o: \
+compile auto-str.c substdio.h readwrite.h exit.h
+ ./compile auto-str.c
+
+auto-uid: \
+load auto-uid.o substdio.a error.a str.a fs.a
+ ./load auto-uid substdio.a error.a str.a fs.a
+
+auto-uid.o: \
+compile auto-uid.c subfd.h substdio.h substdio.h readwrite.h exit.h \
+scan.h fmt.h
+ ./compile auto-uid.c
+
+auto_break.c: \
+auto-str conf-break
+ ./auto-str auto_break \
+ "`head -1 conf-break`" > auto_break.c
+
+auto_break.o: \
+compile auto_break.c
+ ./compile auto_break.c
+
+auto_patrn.c: \
+auto-int8 conf-patrn
+ ./auto-int8 auto_patrn `head -1 conf-patrn` > auto_patrn.c
+
+auto_patrn.o: \
+compile auto_patrn.c
+ ./compile auto_patrn.c
+
+auto_qmail.c: \
+auto-str conf-qmail
+ ./auto-str auto_qmail `head -1 conf-qmail` > auto_qmail.c
+
+auto_qmail.o: \
+compile auto_qmail.c
+ ./compile auto_qmail.c
+
+auto_spawn.c: \
+auto-int conf-spawn
+ ./auto-int auto_spawn `head -1 conf-spawn` > auto_spawn.c
+
+auto_spawn.o: \
+compile auto_spawn.c
+ ./compile auto_spawn.c
+
+auto_split.c: \
+auto-int conf-split
+ ./auto-int auto_split `head -1 conf-split` > auto_split.c
+
+auto_split.o: \
+compile auto_split.c
+ ./compile auto_split.c
+
+auto_uids.c: \
+auto-uid auto-gid conf-users conf-groups
+ ( ./auto-uid auto_uida `head -1 conf-users` \
+ &&./auto-uid auto_uidd `head -2 conf-users | tail -1` \
+ &&./auto-uid auto_uidl `head -3 conf-users | tail -1` \
+ &&./auto-uid auto_uido `head -4 conf-users | tail -1` \
+ &&./auto-uid auto_uidp `head -5 conf-users | tail -1` \
+ &&./auto-uid auto_uidq `head -6 conf-users | tail -1` \
+ &&./auto-uid auto_uidr `head -7 conf-users | tail -1` \
+ &&./auto-uid auto_uids `head -8 conf-users | tail -1` \
+ &&./auto-gid auto_gidq `head -1 conf-groups` \
+ &&./auto-gid auto_gidn `head -2 conf-groups | tail -1` \
+ ) > auto_uids.c.tmp && mv auto_uids.c.tmp auto_uids.c
+
+auto_uids.o: \
+compile auto_uids.c
+ ./compile auto_uids.c
+
+auto_usera.c: \
+auto-str conf-users
+ ./auto-str auto_usera `head -1 conf-users` > auto_usera.c
+
+auto_usera.o: \
+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 \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ > binm1
+ chmod 755 binm1
+
+binm1+df: \
+binm1+df.sh conf-qmail
+ cat binm1+df.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ > binm1+df
+ chmod 755 binm1+df
+
+binm2: \
+binm2.sh conf-qmail
+ cat binm2.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ > binm2
+ chmod 755 binm2
+
+binm2+df: \
+binm2+df.sh conf-qmail
+ cat binm2+df.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ > binm2+df
+ chmod 755 binm2+df
+
+binm3: \
+binm3.sh conf-qmail
+ cat binm3.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ > binm3
+ chmod 755 binm3
+
+binm3+df: \
+binm3+df.sh conf-qmail
+ cat binm3+df.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ > binm3+df
+ chmod 755 binm3+df
+
+bouncesaying: \
+load bouncesaying.o strerr.a error.a substdio.a str.a wait.a
+ ./load bouncesaying strerr.a error.a substdio.a str.a \
+ wait.a
+
+bouncesaying.0: \
+bouncesaying.1
+ nroff -man bouncesaying.1 > bouncesaying.0
+
+bouncesaying.o: \
+compile bouncesaying.c fork.h strerr.h error.h wait.h sig.h exit.h
+ ./compile bouncesaying.c
+
+byte_chr.o: \
+compile byte_chr.c byte.h
+ ./compile byte_chr.c
+
+byte_copy.o: \
+compile byte_copy.c byte.h
+ ./compile byte_copy.c
+
+byte_cr.o: \
+compile byte_cr.c byte.h
+ ./compile byte_cr.c
+
+byte_diff.o: \
+compile byte_diff.c byte.h
+ ./compile byte_diff.c
+
+byte_rchr.o: \
+compile byte_rchr.c byte.h
+ ./compile byte_rchr.c
+
+byte_zero.o: \
+compile byte_zero.c byte.h
+ ./compile byte_zero.c
+
+case.a: \
+makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \
+case_starts.o
+ ./makelib case.a case_diffb.o case_diffs.o case_lowerb.o \
+ case_lowers.o case_starts.o
+
+case_diffb.o: \
+compile case_diffb.c case.h
+ ./compile case_diffb.c
+
+case_diffs.o: \
+compile case_diffs.c case.h
+ ./compile case_diffs.c
+
+case_lowerb.o: \
+compile case_lowerb.c case.h
+ ./compile case_lowerb.c
+
+case_lowers.o: \
+compile case_lowers.c case.h
+ ./compile case_lowers.c
+
+case_starts.o: \
+compile case_starts.c case.h
+ ./compile case_starts.c
+
+cdb.a: \
+makelib cdb_hash.o cdb_unpack.o cdb_seek.o
+ ./makelib cdb.a cdb_hash.o cdb_unpack.o cdb_seek.o
+
+cdb_hash.o: \
+compile cdb_hash.c cdb.h uint32.h
+ ./compile cdb_hash.c
+
+cdb_seek.o: \
+compile cdb_seek.c cdb.h uint32.h
+ ./compile cdb_seek.c
+
+cdb_unpack.o: \
+compile cdb_unpack.c cdb.h uint32.h
+ ./compile cdb_unpack.c
+
+cdbmake.a: \
+makelib cdbmake_pack.o cdbmake_hash.o cdbmake_add.o
+ ./makelib cdbmake.a cdbmake_pack.o cdbmake_hash.o \
+ cdbmake_add.o
+
+cdbmake_add.o: \
+compile cdbmake_add.c cdbmake.h alloc.h uint32.h
+ ./compile cdbmake_add.c
+
+cdbmake_hash.o: \
+compile cdbmake_hash.c cdbmake.h uint32.h
+ ./compile cdbmake_hash.c
+
+cdbmake_pack.o: \
+compile cdbmake_pack.c cdbmake.h uint32.h
+ ./compile cdbmake_pack.c
+
+cdbmss.o: \
+compile cdbmss.c readwrite.h seek.h alloc.h cdbmss.h cdbmake.h \
+uint32.h substdio.h
+ ./compile cdbmss.c
+
+check: \
+it man
+ ./instcheck
+
+chkshsgr: \
+load chkshsgr.o
+ ./load chkshsgr
+
+chkshsgr.o: \
+compile chkshsgr.c exit.h
+ ./compile chkshsgr.c
+
+chkspawn: \
+load chkspawn.o substdio.a error.a str.a fs.a auto_spawn.o
+ ./load chkspawn substdio.a error.a str.a fs.a auto_spawn.o
+
+chkspawn.o: \
+compile chkspawn.c substdio.h subfd.h substdio.h fmt.h select.h \
+exit.h auto_spawn.h
+ ./compile chkspawn.c
+
+chkuser.o: \
+compile chkuser.c chkuser.h chkuser_settings.h
+ ./compile chkuser.c
+
+clean: \
+TARGETS
+ rm -f `cat TARGETS`
+
+coe.o: \
+compile coe.c coe.h
+ ./compile coe.c
+
+commands.o: \
+compile commands.c commands.h substdio.h stralloc.h gen_alloc.h str.h \
+case.h
+ ./compile commands.c
+
+compile: \
+make-compile warn-auto.sh systype
+ ( cat warn-auto.sh; ./make-compile "`cat systype`" ) > \
+ compile
+ chmod 755 compile
+
+condredirect: \
+load condredirect.o qmail.o strerr.a fd.a sig.a wait.a seek.a env.a \
+substdio.a error.a str.a fs.a auto_qmail.o
+ ./load condredirect qmail.o strerr.a fd.a sig.a wait.a \
+ seek.a env.a substdio.a error.a str.a fs.a auto_qmail.o
+
+condredirect.0: \
+condredirect.1
+ nroff -man condredirect.1 > condredirect.0
+
+condredirect.o: \
+compile condredirect.c sig.h readwrite.h exit.h env.h error.h fork.h \
+wait.h seek.h qmail.h substdio.h strerr.h substdio.h fmt.h
+ ./compile condredirect.c
+
+config: \
+warn-auto.sh config.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh config.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPLIT}"`head -1 conf-split`"}g \
+ > config
+ chmod 755 config
+
+config-fast: \
+warn-auto.sh config-fast.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh config-fast.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPLIT}"`head -1 conf-split`"}g \
+ > config-fast
+ chmod 755 config-fast
+
+constmap.o: \
+compile constmap.c constmap.h alloc.h case.h
+ ./compile constmap.c
+
+control.o: \
+compile control.c readwrite.h open.h getln.h stralloc.h gen_alloc.h \
+substdio.h error.h control.h alloc.h scan.h
+ ./compile control.c
+
+date822fmt.o: \
+compile date822fmt.c datetime.h fmt.h date822fmt.h
+ ./compile date822fmt.c
+
+datemail: \
+warn-auto.sh datemail.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh datemail.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPLIT}"`head -1 conf-split`"}g \
+ > datemail
+ chmod 755 datemail
+
+datetime.a: \
+makelib datetime.o datetime_un.o
+ ./makelib datetime.a datetime.o datetime_un.o
+
+datetime.o: \
+compile datetime.c datetime.h
+ ./compile datetime.c
+
+datetime_un.o: \
+compile datetime_un.c datetime.h
+ ./compile datetime_un.c
+
+direntry.h: \
+compile trydrent.c direntry.h1 direntry.h2
+ ( ./compile trydrent.c >/dev/null 2>&1 \
+ && cat direntry.h2 || cat direntry.h1 ) > direntry.h
+ rm -f trydrent.o
+
+dns.lib: \
+tryrsolv.c compile load socket.lib dns.o ipalloc.o ip.o stralloc.a \
+alloc.a error.a fs.a str.a
+ ( ( ./compile tryrsolv.c && ./load tryrsolv dns.o \
+ ipalloc.o ip.o stralloc.a alloc.a error.a fs.a str.a \
+ -lresolv `cat socket.lib` ) >/dev/null 2>&1 \
+ && echo -lresolv || exit 0 ) > dns.lib
+ rm -f tryrsolv.o tryrsolv
+
+dns.o: \
+compile dns.c ip.h ipalloc.h ip.h gen_alloc.h fmt.h alloc.h str.h \
+stralloc.h gen_alloc.h dns.h case.h
+ ./compile dns.c
+
+dnscname: \
+load dnscname.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+ ./load dnscname dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+ alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \
+ socket.lib`
+
+dnscname.o: \
+compile dnscname.c substdio.h subfd.h substdio.h stralloc.h \
+gen_alloc.h dns.h dnsdoe.h readwrite.h exit.h
+ ./compile dnscname.c
+
+dnsdoe.o: \
+compile dnsdoe.c substdio.h subfd.h substdio.h exit.h dns.h dnsdoe.h
+ ./compile dnsdoe.c
+
+dnsfq: \
+load dnsfq.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+ ./load dnsfq dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+ alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \
+ socket.lib`
+
+dnsfq.o: \
+compile dnsfq.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
+dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h exit.h
+ ./compile dnsfq.c
+
+dnsip: \
+load dnsip.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+ ./load dnsip dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+ alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \
+ socket.lib`
+
+dnsip.o: \
+compile dnsip.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
+dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h exit.h
+ ./compile dnsip.c
+
+dnsmxip: \
+load dnsmxip.o dns.o dnsdoe.o ip.o ipalloc.o now.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+ ./load dnsmxip dns.o dnsdoe.o ip.o ipalloc.o now.o \
+ stralloc.a alloc.a substdio.a error.a str.a fs.a `cat \
+ dns.lib` `cat socket.lib`
+
+dnsmxip.o: \
+compile dnsmxip.c substdio.h subfd.h substdio.h stralloc.h \
+gen_alloc.h fmt.h dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h \
+now.h datetime.h exit.h
+ ./compile dnsmxip.c
+
+dnsptr: \
+load dnsptr.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+ ./load dnsptr dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+ alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \
+ socket.lib`
+
+dnsptr.o: \
+compile dnsptr.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
+str.h scan.h dns.h dnsdoe.h ip.h exit.h
+ ./compile dnsptr.c
+
+dot-qmail.0: \
+dot-qmail.5
+ nroff -man dot-qmail.5 > dot-qmail.0
+
+dot-qmail.5: \
+dot-qmail.9 conf-break conf-spawn
+ cat dot-qmail.9 \
+ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPAWN}"`head -1 conf-spawn`"}g \
+ > dot-qmail.5
+
+elq: \
+warn-auto.sh elq.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh elq.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPLIT}"`head -1 conf-split`"}g \
+ > elq
+ chmod 755 elq
+
+env.a: \
+makelib env.o envread.o
+ ./makelib env.a env.o envread.o
+
+env.o: \
+compile env.c str.h alloc.h env.h
+ ./compile env.c
+
+envelopes.0: \
+envelopes.5
+ nroff -man envelopes.5 > envelopes.0
+
+envread.o: \
+compile envread.c env.h str.h
+ ./compile envread.c
+
+error.a: \
+makelib error.o error_str.o error_temp.o
+ ./makelib error.a error.o error_str.o error_temp.o
+
+error.o: \
+compile error.c error.h
+ ./compile error.c
+
+error_str.o: \
+compile error_str.c error.h
+ ./compile error_str.c
+
+error_temp.o: \
+compile error_temp.c error.h
+ ./compile error_temp.c
+
+except: \
+load except.o strerr.a error.a substdio.a str.a wait.a
+ ./load except strerr.a error.a substdio.a str.a wait.a
+
+except.0: \
+except.1
+ nroff -man except.1 > except.0
+
+except.o: \
+compile except.c fork.h strerr.h wait.h error.h exit.h
+ ./compile except.c
+
+fd.a: \
+makelib fd_copy.o fd_move.o
+ ./makelib fd.a fd_copy.o fd_move.o
+
+fd_copy.o: \
+compile fd_copy.c fd.h
+ ./compile fd_copy.c
+
+fd_move.o: \
+compile fd_move.c fd.h
+ ./compile fd_move.c
+
+fifo.o: \
+compile fifo.c hasmkffo.h fifo.h
+ ./compile fifo.c
+
+find-systype: \
+find-systype.sh auto-ccld.sh
+ cat auto-ccld.sh find-systype.sh > find-systype
+ chmod 755 find-systype
+
+fmt_str.o: \
+compile fmt_str.c fmt.h
+ ./compile fmt_str.c
+
+fmt_strn.o: \
+compile fmt_strn.c fmt.h
+ ./compile fmt_strn.c
+
+fmt_uint.o: \
+compile fmt_uint.c fmt.h
+ ./compile fmt_uint.c
+
+fmt_uint0.o: \
+compile fmt_uint0.c fmt.h
+ ./compile fmt_uint0.c
+
+fmt_ulong.o: \
+compile fmt_ulong.c fmt.h
+ ./compile fmt_ulong.c
+
+fmtqfn.o: \
+compile fmtqfn.c fmtqfn.h fmt.h auto_split.h
+ ./compile fmtqfn.c
+
+forgeries.0: \
+forgeries.7
+ nroff -man forgeries.7 > forgeries.0
+
+fork.h: \
+compile load tryvfork.c fork.h1 fork.h2
+ ( ( ./compile tryvfork.c && ./load tryvfork ) >/dev/null \
+ 2>&1 \
+ && cat fork.h2 || cat fork.h1 ) > fork.h
+ rm -f tryvfork.o tryvfork
+
+forward: \
+load forward.o qmail.o strerr.a alloc.a fd.a wait.a sig.a env.a \
+substdio.a error.a str.a fs.a auto_qmail.o
+ ./load forward qmail.o strerr.a alloc.a fd.a wait.a sig.a \
+ env.a substdio.a error.a str.a fs.a auto_qmail.o
+
+forward.0: \
+forward.1
+ nroff -man forward.1 > forward.0
+
+forward.o: \
+compile forward.c sig.h readwrite.h exit.h env.h qmail.h substdio.h \
+strerr.h substdio.h fmt.h
+ ./compile forward.c
+
+fs.a: \
+makelib fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o fmt_ulong.o \
+scan_ulong.o scan_8long.o
+ ./makelib fs.a fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o \
+ fmt_ulong.o scan_ulong.o scan_8long.o
+
+getln.a: \
+makelib getln.o getln2.o
+ ./makelib getln.a getln.o getln2.o
+
+getln.o: \
+compile getln.c substdio.h byte.h stralloc.h gen_alloc.h getln.h
+ ./compile getln.c
+
+getln2.o: \
+compile getln2.c substdio.h stralloc.h gen_alloc.h byte.h getln.h
+ ./compile getln2.c
+
+getopt.a: \
+makelib subgetopt.o sgetopt.o
+ ./makelib getopt.a subgetopt.o sgetopt.o
+
+gfrom.o: \
+compile gfrom.c str.h gfrom.h
+ ./compile gfrom.c
+
+hasflock.h: \
+tryflock.c compile load
+ ( ( ./compile tryflock.c && ./load tryflock ) >/dev/null \
+ 2>&1 \
+ && echo \#define HASFLOCK 1 || exit 0 ) > hasflock.h
+ rm -f tryflock.o tryflock
+
+hasmkffo.h: \
+trymkffo.c compile load
+ ( ( ./compile trymkffo.c && ./load trymkffo ) >/dev/null \
+ 2>&1 \
+ && echo \#define HASMKFIFO 1 || exit 0 ) > hasmkffo.h
+ rm -f trymkffo.o trymkffo
+
+hasnpbg1.h: \
+trynpbg1.c compile load open.h open.a fifo.h fifo.o select.h
+ ( ( ./compile trynpbg1.c \
+ && ./load trynpbg1 fifo.o open.a && ./trynpbg1 ) \
+ >/dev/null 2>&1 \
+ && echo \#define HASNAMEDPIPEBUG1 1 || exit 0 ) > \
+ hasnpbg1.h
+ rm -f trynpbg1.o trynpbg1
+
+hassalen.h: \
+trysalen.c compile
+ ( ./compile trysalen.c >/dev/null 2>&1 \
+ && echo \#define HASSALEN 1 || exit 0 ) > hassalen.h
+ rm -f trysalen.o
+
+hassgact.h: \
+trysgact.c compile load
+ ( ( ./compile trysgact.c && ./load trysgact ) >/dev/null \
+ 2>&1 \
+ && echo \#define HASSIGACTION 1 || exit 0 ) > hassgact.h
+ rm -f trysgact.o trysgact
+
+hassgprm.h: \
+trysgprm.c compile load
+ ( ( ./compile trysgprm.c && ./load trysgprm ) >/dev/null \
+ 2>&1 \
+ && echo \#define HASSIGPROCMASK 1 || exit 0 ) > hassgprm.h
+ rm -f trysgprm.o trysgprm
+
+hasshsgr.h: \
+chkshsgr warn-shsgr tryshsgr.c compile load
+ ./chkshsgr || ( cat warn-shsgr; exit 1 )
+ ( ( ./compile tryshsgr.c \
+ && ./load tryshsgr && ./tryshsgr ) >/dev/null 2>&1 \
+ && echo \#define HASSHORTSETGROUPS 1 || exit 0 ) > \
+ hasshsgr.h
+ rm -f tryshsgr.o tryshsgr
+
+haswaitp.h: \
+trywaitp.c compile load
+ ( ( ./compile trywaitp.c && ./load trywaitp ) >/dev/null \
+ 2>&1 \
+ && echo \#define HASWAITPID 1 || exit 0 ) > haswaitp.h
+ rm -f trywaitp.o trywaitp
+
+headerbody.o: \
+compile headerbody.c stralloc.h gen_alloc.h substdio.h getln.h \
+hfield.h headerbody.h
+ ./compile headerbody.c
+
+hfield.o: \
+compile hfield.c hfield.h
+ ./compile hfield.c
+
+hier.o: \
+compile hier.c auto_qmail.h auto_split.h auto_uids.h fmt.h fifo.h
+ ./compile hier.c
+
+home: \
+home.sh conf-qmail
+ cat home.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ > home
+ chmod 755 home
+
+home+df: \
+home+df.sh conf-qmail
+ cat home+df.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ > home+df
+ chmod 755 home+df
+
+hostname: \
+load hostname.o substdio.a error.a str.a dns.lib socket.lib
+ ./load hostname substdio.a error.a str.a `cat dns.lib` \
+ `cat socket.lib`
+
+hostname.o: \
+compile hostname.c substdio.h subfd.h substdio.h readwrite.h exit.h
+ ./compile hostname.c
+
+idedit: \
+load idedit.o strerr.a substdio.a error.a str.a fs.a wait.a open.a \
+seek.a
+ ./load idedit strerr.a substdio.a error.a str.a fs.a \
+ wait.a open.a seek.a
+
+idedit.o: \
+compile idedit.c readwrite.h exit.h scan.h fmt.h strerr.h open.h \
+seek.h fork.h
+ ./compile idedit.c
+
+install: \
+load install.o fifo.o hier.o auto_qmail.o auto_split.o auto_uids.o \
+strerr.a substdio.a open.a error.a str.a fs.a
+ ./load install fifo.o hier.o auto_qmail.o auto_split.o \
+ auto_uids.o strerr.a substdio.a open.a error.a str.a fs.a
+
+install-big: \
+load install-big.o fifo.o install.o auto_qmail.o auto_split.o \
+auto_uids.o strerr.a substdio.a open.a error.a str.a fs.a
+ ./load install-big fifo.o install.o auto_qmail.o \
+ auto_split.o auto_uids.o strerr.a substdio.a open.a error.a \
+ str.a fs.a
+
+install-big.o: \
+compile install-big.c auto_qmail.h auto_split.h auto_uids.h fmt.h \
+fifo.h
+ ./compile install-big.c
+
+install.o: \
+compile install.c substdio.h strerr.h error.h open.h readwrite.h \
+exit.h
+ ./compile install.c
+
+instcheck: \
+load instcheck.o fifo.o hier.o auto_qmail.o auto_split.o auto_uids.o \
+strerr.a substdio.a error.a str.a fs.a
+ ./load instcheck fifo.o hier.o auto_qmail.o auto_split.o \
+ auto_uids.o strerr.a substdio.a error.a str.a fs.a
+
+instcheck.o: \
+compile instcheck.c strerr.h error.h readwrite.h exit.h
+ ./compile instcheck.c
+
+ip.o: \
+compile ip.c fmt.h scan.h ip.h
+ ./compile ip.c
+
+ipalloc.o: \
+compile ipalloc.c alloc.h gen_allocdefs.h ip.h ipalloc.h ip.h \
+gen_alloc.h
+ ./compile ipalloc.c
+
+ipme.o: \
+compile ipme.c hassalen.h byte.h ip.h ipalloc.h ip.h gen_alloc.h \
+stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h
+ ./compile ipme.c
+
+ipmeprint: \
+load ipmeprint.o ipme.o ip.o ipalloc.o stralloc.a alloc.a substdio.a \
+error.a str.a fs.a socket.lib
+ ./load ipmeprint ipme.o ip.o ipalloc.o stralloc.a alloc.a \
+ substdio.a error.a str.a fs.a `cat socket.lib`
+
+ipmeprint.o: \
+compile ipmeprint.c subfd.h substdio.h substdio.h ip.h ipme.h ip.h \
+ipalloc.h ip.h gen_alloc.h exit.h
+ ./compile ipmeprint.c
+
+it: \
+qmail-local qmail-lspawn qmail-getpw qmail-remote qmail-rspawn \
+qmail-clean qmail-send qmail-start splogger qmail-queue qmail-inject \
+predate datemail mailsubj qmail-upq qmail-showctl qmail-newu \
+qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \
+qmail-pop3d qmail-popup qmail-qmqpc qmail-qmqpd qmail-qmtpd \
+qmail-smtpd sendmail tcp-env qmail-newmrh config config-fast dnscname \
+dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \
+forward preline condredirect bouncesaying except maildirmake \
+maildir2mbox maildirwatch qail elq pinq idedit install-big install \
+instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \
+binm3 binm3+df update_tmprsadh
+
+load: \
+make-load warn-auto.sh systype
+ ( cat warn-auto.sh; ./make-load "`cat systype`" ) > load
+ chmod 755 load
+
+lock.a: \
+makelib lock_ex.o lock_exnb.o lock_un.o
+ ./makelib lock.a lock_ex.o lock_exnb.o lock_un.o
+
+lock_ex.o: \
+compile lock_ex.c hasflock.h lock.h
+ ./compile lock_ex.c
+
+lock_exnb.o: \
+compile lock_exnb.c hasflock.h lock.h
+ ./compile lock_exnb.c
+
+lock_un.o: \
+compile lock_un.c hasflock.h lock.h
+ ./compile lock_un.c
+
+maildir.0: \
+maildir.5
+ nroff -man maildir.5 > maildir.0
+
+maildir.o: \
+compile maildir.c prioq.h datetime.h gen_alloc.h env.h stralloc.h \
+gen_alloc.h direntry.h datetime.h now.h datetime.h str.h maildir.h \
+strerr.h
+ ./compile maildir.c
+
+maildir2mbox: \
+load maildir2mbox.o maildir.o prioq.o now.o myctime.o gfrom.o lock.a \
+getln.a env.a open.a strerr.a stralloc.a alloc.a substdio.a error.a \
+str.a fs.a datetime.a
+ ./load maildir2mbox maildir.o prioq.o now.o myctime.o \
+ gfrom.o lock.a getln.a env.a open.a strerr.a stralloc.a \
+ alloc.a substdio.a error.a str.a fs.a datetime.a
+
+maildir2mbox.0: \
+maildir2mbox.1
+ nroff -man maildir2mbox.1 > maildir2mbox.0
+
+maildir2mbox.o: \
+compile maildir2mbox.c readwrite.h prioq.h datetime.h gen_alloc.h \
+env.h stralloc.h gen_alloc.h subfd.h substdio.h substdio.h getln.h \
+error.h open.h lock.h gfrom.h str.h exit.h myctime.h maildir.h \
+strerr.h
+ ./compile maildir2mbox.c
+
+maildirmake: \
+load maildirmake.o strerr.a substdio.a error.a str.a
+ ./load maildirmake strerr.a substdio.a error.a str.a
+
+maildirmake.0: \
+maildirmake.1
+ nroff -man maildirmake.1 > maildirmake.0
+
+maildirmake.o: \
+compile maildirmake.c strerr.h exit.h
+ ./compile maildirmake.c
+
+maildirwatch: \
+load maildirwatch.o hfield.o headerbody.o maildir.o prioq.o now.o \
+getln.a env.a open.a strerr.a stralloc.a alloc.a substdio.a error.a \
+str.a
+ ./load maildirwatch hfield.o headerbody.o maildir.o \
+ prioq.o now.o getln.a env.a open.a strerr.a stralloc.a \
+ alloc.a substdio.a error.a str.a
+
+maildirwatch.0: \
+maildirwatch.1
+ nroff -man maildirwatch.1 > maildirwatch.0
+
+maildirwatch.o: \
+compile maildirwatch.c getln.h substdio.h subfd.h substdio.h prioq.h \
+datetime.h gen_alloc.h stralloc.h gen_alloc.h str.h exit.h hfield.h \
+readwrite.h open.h headerbody.h maildir.h strerr.h
+ ./compile maildirwatch.c
+
+mailsubj: \
+warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh mailsubj.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPLIT}"`head -1 conf-split`"}g \
+ > mailsubj
+ chmod 755 mailsubj
+
+mailsubj.0: \
+mailsubj.1
+ nroff -man mailsubj.1 > mailsubj.0
+
+make-compile: \
+make-compile.sh auto-ccld.sh
+ cat auto-ccld.sh make-compile.sh > make-compile
+ chmod 755 make-compile
+
+make-load: \
+make-load.sh auto-ccld.sh
+ cat auto-ccld.sh make-load.sh > make-load
+ chmod 755 make-load
+
+make-makelib: \
+make-makelib.sh auto-ccld.sh
+ cat auto-ccld.sh make-makelib.sh > make-makelib
+ chmod 755 make-makelib
+
+makelib: \
+make-makelib warn-auto.sh systype
+ ( cat warn-auto.sh; ./make-makelib "`cat systype`" ) > \
+ makelib
+ chmod 755 makelib
+
+man: \
+qmail-local.0 qmail-lspawn.0 qmail-getpw.0 qmail-remote.0 \
+qmail-rspawn.0 qmail-clean.0 qmail-send.0 qmail-start.0 splogger.0 \
+qmail-queue.0 qmail-inject.0 mailsubj.0 qmail-showctl.0 qmail-newu.0 \
+qmail-pw2u.0 qmail-qread.0 qmail-qstat.0 qmail-tcpto.0 qmail-tcpok.0 \
+qmail-pop3d.0 qmail-popup.0 qmail-qmqpc.0 qmail-qmqpd.0 qmail-qmtpd.0 \
+qmail-smtpd.0 tcp-env.0 qmail-newmrh.0 qreceipt.0 qbiff.0 forward.0 \
+preline.0 condredirect.0 bouncesaying.0 except.0 maildirmake.0 \
+maildir2mbox.0 maildirwatch.0 qmail.0 qmail-limits.0 qmail-log.0 \
+qmail-control.0 qmail-header.0 qmail-users.0 dot-qmail.0 \
+qmail-command.0 tcp-environ.0 maildir.0 mbox.0 addresses.0 \
+envelopes.0 forgeries.0
+
+mbox.0: \
+mbox.5
+ nroff -man mbox.5 > mbox.0
+
+myctime.o: \
+compile myctime.c datetime.h fmt.h myctime.h
+ ./compile myctime.c
+
+ndelay.a: \
+makelib ndelay.o ndelay_off.o
+ ./makelib ndelay.a ndelay.o ndelay_off.o
+
+ndelay.o: \
+compile ndelay.c ndelay.h
+ ./compile ndelay.c
+
+ndelay_off.o: \
+compile ndelay_off.c ndelay.h
+ ./compile ndelay_off.c
+
+newfield.o: \
+compile newfield.c fmt.h datetime.h stralloc.h gen_alloc.h \
+date822fmt.h newfield.h stralloc.h
+ ./compile newfield.c
+
+now.o: \
+compile now.c datetime.h now.h datetime.h
+ ./compile now.c
+
+open.a: \
+makelib open_append.o open_excl.o open_read.o open_trunc.o \
+open_write.o
+ ./makelib open.a open_append.o open_excl.o open_read.o \
+ open_trunc.o open_write.o
+
+open_append.o: \
+compile open_append.c open.h
+ ./compile open_append.c
+
+open_excl.o: \
+compile open_excl.c open.h
+ ./compile open_excl.c
+
+open_read.o: \
+compile open_read.c open.h
+ ./compile open_read.c
+
+open_trunc.o: \
+compile open_trunc.c open.h
+ ./compile open_trunc.c
+
+open_write.o: \
+compile open_write.c open.h
+ ./compile open_write.c
+
+pinq: \
+warn-auto.sh pinq.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh pinq.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPLIT}"`head -1 conf-split`"}g \
+ > pinq
+ chmod 755 pinq
+
+predate: \
+load predate.o datetime.a strerr.a sig.a fd.a wait.a substdio.a \
+error.a str.a fs.a
+ ./load predate datetime.a strerr.a sig.a fd.a wait.a \
+ substdio.a error.a str.a fs.a
+
+predate.o: \
+compile predate.c datetime.h fork.h wait.h fd.h fmt.h strerr.h \
+substdio.h subfd.h substdio.h readwrite.h exit.h
+ ./compile predate.c
+
+preline: \
+load preline.o strerr.a fd.a wait.a sig.a env.a getopt.a substdio.a \
+error.a str.a
+ ./load preline strerr.a fd.a wait.a sig.a env.a getopt.a \
+ substdio.a error.a str.a
+
+preline.0: \
+preline.1
+ nroff -man preline.1 > preline.0
+
+preline.o: \
+compile preline.c fd.h sgetopt.h subgetopt.h readwrite.h strerr.h \
+substdio.h exit.h fork.h wait.h env.h sig.h error.h
+ ./compile preline.c
+
+prioq.o: \
+compile prioq.c alloc.h gen_allocdefs.h prioq.h datetime.h \
+gen_alloc.h
+ ./compile prioq.c
+
+proc: \
+proc.sh conf-qmail
+ cat proc.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ > proc
+ chmod 755 proc
+
+proc+df: \
+proc+df.sh conf-qmail
+ cat proc+df.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ > proc+df
+ chmod 755 proc+df
+
+prot.o: \
+compile prot.c hasshsgr.h prot.h
+ ./compile prot.c
+
+qail: \
+warn-auto.sh qail.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh qail.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPLIT}"`head -1 conf-split`"}g \
+ > qail
+ chmod 755 qail
+
+qbiff: \
+load qbiff.o headerbody.o hfield.o getln.a env.a open.a stralloc.a \
+alloc.a substdio.a error.a str.a
+ ./load qbiff headerbody.o hfield.o getln.a env.a open.a \
+ stralloc.a alloc.a substdio.a error.a str.a
+
+qbiff.0: \
+qbiff.1
+ nroff -man qbiff.1 > qbiff.0
+
+qbiff.o: \
+compile qbiff.c readwrite.h stralloc.h gen_alloc.h substdio.h subfd.h \
+substdio.h open.h byte.h str.h headerbody.h hfield.h env.h exit.h
+ ./compile qbiff.c
+
+qmail-clean: \
+load qmail-clean.o fmtqfn.o now.o getln.a sig.a stralloc.a alloc.a \
+substdio.a error.a str.a fs.a auto_qmail.o auto_split.o
+ ./load qmail-clean fmtqfn.o now.o getln.a sig.a stralloc.a \
+ alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
+ auto_split.o
+
+qmail-clean.0: \
+qmail-clean.8
+ nroff -man qmail-clean.8 > qmail-clean.0
+
+qmail-clean.o: \
+compile qmail-clean.c readwrite.h sig.h now.h datetime.h str.h \
+direntry.h getln.h stralloc.h gen_alloc.h substdio.h subfd.h \
+substdio.h byte.h scan.h fmt.h error.h exit.h fmtqfn.h auto_qmail.h
+ ./compile qmail-clean.c
+
+qmail-command.0: \
+qmail-command.8
+ nroff -man qmail-command.8 > qmail-command.0
+
+qmail-control.0: \
+qmail-control.5
+ nroff -man qmail-control.5 > qmail-control.0
+
+qmail-control.5: \
+qmail-control.9 conf-break conf-spawn
+ cat qmail-control.9 \
+ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPAWN}"`head -1 conf-spawn`"}g \
+ > qmail-control.5
+
+qmail-getpw: \
+load qmail-getpw.o case.a substdio.a error.a str.a fs.a auto_break.o \
+auto_usera.o
+ ./load qmail-getpw case.a substdio.a error.a str.a fs.a \
+ auto_break.o auto_usera.o
+
+qmail-getpw.0: \
+qmail-getpw.8
+ nroff -man qmail-getpw.8 > qmail-getpw.0
+
+qmail-getpw.8: \
+qmail-getpw.9 conf-break conf-spawn
+ cat qmail-getpw.9 \
+ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPAWN}"`head -1 conf-spawn`"}g \
+ > qmail-getpw.8
+
+qmail-getpw.o: \
+compile qmail-getpw.c readwrite.h substdio.h subfd.h substdio.h \
+error.h exit.h byte.h str.h case.h fmt.h auto_usera.h auto_break.h \
+qlx.h
+ ./compile qmail-getpw.c
+
+qmail-header.0: \
+qmail-header.5
+ nroff -man qmail-header.5 > qmail-header.0
+
+qmail-inject: \
+load qmail-inject.o headerbody.o hfield.o newfield.o quote.o now.o \
+control.o date822fmt.o constmap.o qmail.o case.a fd.a wait.a open.a \
+getln.a sig.a getopt.a datetime.a token822.o env.a stralloc.a alloc.a \
+substdio.a error.a str.a fs.a auto_qmail.o
+ ./load qmail-inject headerbody.o hfield.o newfield.o \
+ quote.o now.o control.o date822fmt.o constmap.o qmail.o \
+ case.a fd.a wait.a open.a getln.a sig.a getopt.a datetime.a \
+ token822.o env.a stralloc.a alloc.a substdio.a error.a \
+ str.a fs.a auto_qmail.o
+
+qmail-inject.0: \
+qmail-inject.8
+ nroff -man qmail-inject.8 > qmail-inject.0
+
+qmail-inject.o: \
+compile qmail-inject.c sig.h substdio.h stralloc.h gen_alloc.h \
+subfd.h substdio.h sgetopt.h subgetopt.h getln.h alloc.h str.h fmt.h \
+hfield.h token822.h gen_alloc.h control.h env.h gen_alloc.h \
+gen_allocdefs.h error.h qmail.h substdio.h now.h datetime.h exit.h \
+quote.h headerbody.h auto_qmail.h newfield.h stralloc.h constmap.h
+ ./compile qmail-inject.c
+
+qmail-limits.0: \
+qmail-limits.7
+ nroff -man qmail-limits.7 > qmail-limits.0
+
+qmail-limits.7: \
+qmail-limits.9 conf-break conf-spawn
+ cat qmail-limits.9 \
+ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPAWN}"`head -1 conf-spawn`"}g \
+ > qmail-limits.7
+
+qmail-local: \
+load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \
+slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \
+wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
+fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib
+ ./load qmail-local qmail.o quote.o now.o gfrom.o myctime.o \
+ slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a \
+ lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \
+ substdio.a error.a str.a fs.a datetime.a auto_qmail.o \
+ auto_patrn.o `cat socket.lib`
+
+qmail-local.0: \
+qmail-local.8
+ nroff -man qmail-local.8 > qmail-local.0
+
+qmail-local.o: \
+compile qmail-local.c readwrite.h sig.h env.h byte.h exit.h fork.h \
+open.h wait.h lock.h seek.h substdio.h getln.h strerr.h subfd.h \
+substdio.h sgetopt.h subgetopt.h alloc.h error.h stralloc.h \
+gen_alloc.h fmt.h str.h now.h datetime.h case.h quote.h qmail.h \
+substdio.h slurpclose.h myctime.h gfrom.h auto_patrn.h
+ ./compile qmail-local.c
+
+qmail-log.0: \
+qmail-log.5
+ nroff -man qmail-log.5 > qmail-log.0
+
+qmail-lspawn: \
+load qmail-lspawn.o spawn.o prot.o slurpclose.o coe.o sig.a wait.a \
+case.a cdb.a fd.a open.a stralloc.a alloc.a substdio.a error.a str.a \
+fs.a auto_qmail.o auto_uids.o auto_spawn.o
+ ./load qmail-lspawn spawn.o prot.o slurpclose.o coe.o \
+ sig.a wait.a case.a cdb.a fd.a open.a stralloc.a alloc.a \
+ substdio.a error.a str.a fs.a auto_qmail.o auto_uids.o \
+ auto_spawn.o
+
+qmail-lspawn.0: \
+qmail-lspawn.8
+ nroff -man qmail-lspawn.8 > qmail-lspawn.0
+
+qmail-lspawn.o: \
+compile qmail-lspawn.c fd.h wait.h prot.h substdio.h stralloc.h \
+gen_alloc.h scan.h exit.h fork.h error.h cdb.h uint32.h case.h \
+slurpclose.h auto_qmail.h auto_uids.h qlx.h
+ ./compile qmail-lspawn.c
+
+qmail-newmrh: \
+load qmail-newmrh.o cdbmss.o getln.a open.a cdbmake.a seek.a case.a \
+stralloc.a alloc.a strerr.a substdio.a error.a str.a auto_qmail.o
+ ./load qmail-newmrh cdbmss.o getln.a open.a cdbmake.a \
+ seek.a case.a stralloc.a alloc.a strerr.a substdio.a \
+ error.a str.a auto_qmail.o
+
+qmail-newmrh.0: \
+qmail-newmrh.8
+ nroff -man qmail-newmrh.8 > qmail-newmrh.0
+
+qmail-newmrh.8: \
+qmail-newmrh.9 conf-break conf-spawn
+ cat qmail-newmrh.9 \
+ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPAWN}"`head -1 conf-spawn`"}g \
+ > qmail-newmrh.8
+
+qmail-newmrh.o: \
+compile qmail-newmrh.c strerr.h stralloc.h gen_alloc.h substdio.h \
+getln.h exit.h readwrite.h open.h auto_qmail.h cdbmss.h cdbmake.h \
+uint32.h substdio.h
+ ./compile qmail-newmrh.c
+
+qmail-newu: \
+load qmail-newu.o cdbmss.o getln.a open.a seek.a cdbmake.a case.a \
+stralloc.a alloc.a substdio.a error.a str.a auto_qmail.o
+ ./load qmail-newu cdbmss.o getln.a open.a seek.a cdbmake.a \
+ case.a stralloc.a alloc.a substdio.a error.a str.a \
+ auto_qmail.o
+
+qmail-newu.0: \
+qmail-newu.8
+ nroff -man qmail-newu.8 > qmail-newu.0
+
+qmail-newu.8: \
+qmail-newu.9 conf-break conf-spawn
+ cat qmail-newu.9 \
+ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPAWN}"`head -1 conf-spawn`"}g \
+ > qmail-newu.8
+
+qmail-newu.o: \
+compile qmail-newu.c stralloc.h gen_alloc.h subfd.h substdio.h \
+getln.h substdio.h cdbmss.h cdbmake.h uint32.h substdio.h exit.h \
+readwrite.h open.h error.h case.h auto_qmail.h
+ ./compile qmail-newu.c
+
+qmail-pop3d: \
+load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \
+maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \
+stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib
+ ./load qmail-pop3d commands.o case.a timeoutread.o \
+ timeoutwrite.o maildir.o prioq.o now.o env.a strerr.a sig.a \
+ open.a getln.a stralloc.a alloc.a substdio.a error.a str.a \
+ fs.a `cat socket.lib`
+
+qmail-pop3d.0: \
+qmail-pop3d.8
+ nroff -man qmail-pop3d.8 > qmail-pop3d.0
+
+qmail-pop3d.o: \
+compile qmail-pop3d.c commands.h sig.h getln.h stralloc.h gen_alloc.h \
+substdio.h alloc.h open.h prioq.h datetime.h gen_alloc.h scan.h fmt.h \
+str.h exit.h maildir.h strerr.h readwrite.h timeoutread.h \
+timeoutwrite.h
+ ./compile qmail-pop3d.c
+
+qmail-popup: \
+load qmail-popup.o commands.o timeoutread.o timeoutwrite.o now.o \
+case.a fd.a sig.a wait.a stralloc.a alloc.a substdio.a error.a str.a \
+fs.a socket.lib
+ ./load qmail-popup commands.o timeoutread.o timeoutwrite.o \
+ now.o case.a fd.a sig.a wait.a stralloc.a alloc.a \
+ substdio.a error.a str.a fs.a `cat socket.lib`
+
+qmail-popup.0: \
+qmail-popup.8
+ nroff -man qmail-popup.8 > qmail-popup.0
+
+qmail-popup.o: \
+compile qmail-popup.c commands.h fd.h sig.h stralloc.h gen_alloc.h \
+substdio.h alloc.h wait.h str.h byte.h now.h datetime.h fmt.h exit.h \
+readwrite.h timeoutread.h timeoutwrite.h
+ ./compile qmail-popup.c
+
+qmail-pw2u: \
+load qmail-pw2u.o constmap.o control.o open.a getln.a case.a getopt.a \
+stralloc.a alloc.a substdio.a error.a str.a fs.a auto_usera.o \
+auto_break.o auto_qmail.o
+ ./load qmail-pw2u constmap.o control.o open.a getln.a \
+ case.a getopt.a stralloc.a alloc.a substdio.a error.a str.a \
+ fs.a auto_usera.o auto_break.o auto_qmail.o
+
+qmail-pw2u.0: \
+qmail-pw2u.8
+ nroff -man qmail-pw2u.8 > qmail-pw2u.0
+
+qmail-pw2u.8: \
+qmail-pw2u.9 conf-break conf-spawn
+ cat qmail-pw2u.9 \
+ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPAWN}"`head -1 conf-spawn`"}g \
+ > qmail-pw2u.8
+
+qmail-pw2u.o: \
+compile qmail-pw2u.c substdio.h readwrite.h subfd.h substdio.h \
+sgetopt.h subgetopt.h control.h constmap.h stralloc.h gen_alloc.h \
+fmt.h str.h scan.h open.h error.h getln.h auto_break.h auto_qmail.h \
+auto_usera.h
+ ./compile qmail-pw2u.c
+
+qmail-qmqpc: \
+load qmail-qmqpc.o slurpclose.o timeoutread.o timeoutwrite.o \
+timeoutconn.o ip.o control.o auto_qmail.o sig.a ndelay.a open.a \
+getln.a substdio.a stralloc.a alloc.a error.a str.a fs.a socket.lib
+ ./load qmail-qmqpc slurpclose.o timeoutread.o \
+ timeoutwrite.o timeoutconn.o ip.o control.o auto_qmail.o \
+ sig.a ndelay.a open.a getln.a substdio.a stralloc.a alloc.a \
+ error.a str.a fs.a `cat socket.lib`
+
+qmail-qmqpc.0: \
+qmail-qmqpc.8
+ nroff -man qmail-qmqpc.8 > qmail-qmqpc.0
+
+qmail-qmqpc.o: \
+compile qmail-qmqpc.c substdio.h getln.h readwrite.h exit.h \
+stralloc.h gen_alloc.h slurpclose.h error.h sig.h ip.h timeoutconn.h \
+timeoutread.h timeoutwrite.h auto_qmail.h control.h fmt.h
+ ./compile qmail-qmqpc.c
+
+qmail-qmqpd: \
+load qmail-qmqpd.o received.o now.o date822fmt.o qmail.o auto_qmail.o \
+env.a substdio.a sig.a error.a wait.a fd.a str.a datetime.a fs.a
+ ./load qmail-qmqpd received.o now.o date822fmt.o qmail.o \
+ auto_qmail.o env.a substdio.a sig.a error.a wait.a fd.a \
+ str.a datetime.a fs.a
+
+qmail-qmqpd.0: \
+qmail-qmqpd.8
+ nroff -man qmail-qmqpd.8 > qmail-qmqpd.0
+
+qmail-qmqpd.o: \
+compile qmail-qmqpd.c auto_qmail.h qmail.h substdio.h received.h \
+sig.h substdio.h readwrite.h exit.h now.h datetime.h fmt.h env.h
+ ./compile qmail-qmqpd.c
+
+qmail-qmtpd: \
+load qmail-qmtpd.o rcpthosts.o control.o constmap.o received.o \
+date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a open.a \
+getln.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a \
+str.a fs.a auto_qmail.o
+ ./load qmail-qmtpd rcpthosts.o control.o constmap.o \
+ received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
+ datetime.a open.a getln.a sig.a case.a env.a stralloc.a \
+ alloc.a substdio.a error.a str.a fs.a auto_qmail.o
+
+qmail-qmtpd.0: \
+qmail-qmtpd.8
+ nroff -man qmail-qmtpd.8 > qmail-qmtpd.0
+
+qmail-qmtpd.o: \
+compile qmail-qmtpd.c stralloc.h gen_alloc.h substdio.h qmail.h \
+substdio.h now.h datetime.h str.h fmt.h env.h sig.h rcpthosts.h \
+auto_qmail.h readwrite.h control.h received.h
+ ./compile qmail-qmtpd.c
+
+qmail-qread: \
+load qmail-qread.o fmtqfn.o readsubdir.o date822fmt.o datetime.a \
+open.a getln.a stralloc.a alloc.a substdio.a error.a str.a fs.a \
+auto_qmail.o auto_split.o
+ ./load qmail-qread fmtqfn.o readsubdir.o date822fmt.o \
+ datetime.a open.a getln.a stralloc.a alloc.a substdio.a \
+ error.a str.a fs.a auto_qmail.o auto_split.o
+
+qmail-qread.0: \
+qmail-qread.8
+ nroff -man qmail-qread.8 > qmail-qread.0
+
+qmail-qread.o: \
+compile qmail-qread.c stralloc.h gen_alloc.h substdio.h subfd.h \
+substdio.h fmt.h str.h getln.h fmtqfn.h readsubdir.h direntry.h \
+auto_qmail.h open.h datetime.h date822fmt.h readwrite.h error.h \
+exit.h
+ ./compile qmail-qread.c
+
+qmail-qstat: \
+warn-auto.sh qmail-qstat.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh qmail-qstat.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPLIT}"`head -1 conf-split`"}g \
+ > qmail-qstat
+ chmod 755 qmail-qstat
+
+qmail-qstat.0: \
+qmail-qstat.8
+ nroff -man qmail-qstat.8 > qmail-qstat.0
+
+qmail-queue: \
+load qmail-queue.o triggerpull.o fmtqfn.o now.o date822fmt.o \
+datetime.a seek.a ndelay.a open.a sig.a alloc.a substdio.a error.a \
+str.a fs.a auto_qmail.o auto_split.o auto_uids.o
+ ./load qmail-queue triggerpull.o fmtqfn.o now.o \
+ date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \
+ alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
+ auto_split.o auto_uids.o
+
+qmail-queue.0: \
+qmail-queue.8
+ nroff -man qmail-queue.8 > qmail-queue.0
+
+qmail-queue.o: \
+compile qmail-queue.c readwrite.h sig.h exit.h open.h seek.h fmt.h \
+alloc.h substdio.h datetime.h now.h datetime.h triggerpull.h extra.h \
+auto_qmail.h auto_uids.h date822fmt.h fmtqfn.h
+ ./compile qmail-queue.c
+
+qmail-remote: \
+load qmail-remote.o control.o constmap.o timeoutread.o 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 base64.o dns.lib socket.lib
+ ./load qmail-remote control.o constmap.o timeoutread.o \
+ timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \
+ tls.o ssl_timeoutio.o -L/usr/local/ssl/lib -lssl -lcrypto \
+ 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 base64.o `cat dns.lib` `cat socket.lib`
+
+qmail-remote.0: \
+qmail-remote.8
+ nroff -man qmail-remote.8 > qmail-remote.0
+
+qmail-remote.o: \
+compile qmail-remote.c sig.h stralloc.h gen_alloc.h substdio.h \
+subfd.h substdio.h scan.h case.h error.h auto_qmail.h control.h dns.h \
+alloc.h quote.h ip.h ipalloc.h ip.h gen_alloc.h ipme.h ip.h ipalloc.h \
+gen_alloc.h gen_allocdefs.h str.h now.h datetime.h exit.h constmap.h \
+tcpto.h readwrite.h timeoutconn.h timeoutread.h timeoutwrite.h
+ ./compile qmail-remote.c
+
+qmail-rspawn: \
+load qmail-rspawn.o spawn.o tcpto_clean.o now.o coe.o sig.a open.a \
+seek.a lock.a wait.a fd.a stralloc.a alloc.a substdio.a error.a str.a \
+auto_qmail.o auto_uids.o auto_spawn.o
+ ./load qmail-rspawn spawn.o tcpto_clean.o now.o coe.o \
+ sig.a open.a seek.a lock.a wait.a fd.a stralloc.a alloc.a \
+ substdio.a error.a str.a auto_qmail.o auto_uids.o \
+ auto_spawn.o
+
+qmail-rspawn.0: \
+qmail-rspawn.8
+ nroff -man qmail-rspawn.8 > qmail-rspawn.0
+
+qmail-rspawn.o: \
+compile qmail-rspawn.c fd.h wait.h substdio.h exit.h fork.h error.h \
+tcpto.h
+ ./compile qmail-rspawn.c
+
+qmail-send: \
+load qmail-send.o qsutil.o control.o constmap.o newfield.o prioq.o \
+trigger.o fmtqfn.o quote.o now.o readsubdir.o qmail.o date822fmt.o \
+datetime.a case.a ndelay.a getln.a wait.a seek.a fd.a sig.a open.a \
+lock.a stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
+auto_split.o env.a
+ ./load qmail-send qsutil.o control.o constmap.o newfield.o \
+ prioq.o trigger.o fmtqfn.o quote.o now.o readsubdir.o \
+ qmail.o date822fmt.o datetime.a case.a ndelay.a getln.a \
+ wait.a seek.a fd.a sig.a open.a lock.a stralloc.a alloc.a \
+ substdio.a error.a str.a fs.a auto_qmail.o auto_split.o env.a
+
+qmail-send.0: \
+qmail-send.8
+ nroff -man qmail-send.8 > qmail-send.0
+
+qmail-send.8: \
+qmail-send.9 conf-break conf-spawn
+ cat qmail-send.9 \
+ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPAWN}"`head -1 conf-spawn`"}g \
+ > qmail-send.8
+
+qmail-send.o: \
+compile qmail-send.c readwrite.h sig.h direntry.h control.h select.h \
+open.h seek.h exit.h lock.h ndelay.h now.h datetime.h getln.h \
+substdio.h alloc.h error.h stralloc.h gen_alloc.h str.h byte.h fmt.h \
+scan.h case.h auto_qmail.h trigger.h newfield.h stralloc.h quote.h \
+qmail.h substdio.h qsutil.h prioq.h datetime.h gen_alloc.h constmap.h \
+fmtqfn.h readsubdir.h direntry.h
+ ./compile qmail-send.c
+
+qmail-showctl: \
+load qmail-showctl.o auto_uids.o control.o open.a getln.a stralloc.a \
+alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_break.o \
+auto_patrn.o auto_spawn.o auto_split.o
+ ./load qmail-showctl auto_uids.o control.o open.a getln.a \
+ stralloc.a alloc.a substdio.a error.a str.a fs.a \
+ auto_qmail.o auto_break.o auto_patrn.o auto_spawn.o \
+ auto_split.o
+
+qmail-showctl.0: \
+qmail-showctl.8
+ nroff -man qmail-showctl.8 > qmail-showctl.0
+
+qmail-showctl.o: \
+compile qmail-showctl.c substdio.h subfd.h substdio.h exit.h fmt.h \
+str.h control.h constmap.h stralloc.h gen_alloc.h direntry.h \
+auto_uids.h auto_qmail.h auto_break.h auto_patrn.h auto_spawn.h \
+auto_split.h
+ ./compile qmail-showctl.c
+
+qmail-smtpd: \
+load qmail-smtpd.o rcpthosts.o qregex.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 strerr.a substdio.a error.a str.a \
+fs.a auto_qmail.o base64.o socket.lib $(SMTPD_CHKUSER_OBJ) dns.lib
+ ./load qmail-smtpd $(SMTPD_CHKUSER_OBJ) qregex.o rcpthosts.o commands.o timeoutread.o \
+ timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
+ tls.o ssl_timeoutio.o ndelay.a -L/usr/local/ssl/lib -lssl -lcrypto \
+ 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 strerr.a substdio.a error.a str.a fs.a auto_qmail.o base64.o \
+ $(VPOPMAIL_LIBS) \
+ `cat socket.lib`
+
+qmail-smtpd.0: \
+qmail-smtpd.8
+ nroff -man qmail-smtpd.8 > qmail-smtpd.0
+
+qmail-smtpd.o: \
+compile qmail-smtpd.c chkuser.h sig.h readwrite.h stralloc.h gen_alloc.h \
+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 base64.h
+ ./compile qmail-smtpd.c
+
+qmail-start: \
+load qmail-start.o prot.o fd.a auto_uids.o
+ ./load qmail-start prot.o fd.a auto_uids.o
+
+qmail-start.0: \
+qmail-start.8
+ nroff -man qmail-start.8 > qmail-start.0
+
+qmail-start.8: \
+qmail-start.9 conf-break conf-spawn
+ cat qmail-start.9 \
+ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPAWN}"`head -1 conf-spawn`"}g \
+ > qmail-start.8
+
+qmail-start.o: \
+compile qmail-start.c fd.h prot.h exit.h fork.h auto_uids.h
+ ./compile qmail-start.c
+
+qmail-tcpok: \
+load qmail-tcpok.o open.a lock.a strerr.a substdio.a error.a str.a \
+auto_qmail.o
+ ./load qmail-tcpok open.a lock.a strerr.a substdio.a \
+ error.a str.a auto_qmail.o
+
+qmail-tcpok.0: \
+qmail-tcpok.8
+ nroff -man qmail-tcpok.8 > qmail-tcpok.0
+
+qmail-tcpok.o: \
+compile qmail-tcpok.c strerr.h substdio.h lock.h open.h readwrite.h \
+auto_qmail.h exit.h
+ ./compile qmail-tcpok.c
+
+qmail-tcpto: \
+load qmail-tcpto.o ip.o now.o open.a lock.a substdio.a error.a str.a \
+fs.a auto_qmail.o
+ ./load qmail-tcpto ip.o now.o open.a lock.a substdio.a \
+ error.a str.a fs.a auto_qmail.o
+
+qmail-tcpto.0: \
+qmail-tcpto.8
+ nroff -man qmail-tcpto.8 > qmail-tcpto.0
+
+qmail-tcpto.o: \
+compile qmail-tcpto.c substdio.h subfd.h substdio.h auto_qmail.h \
+fmt.h ip.h lock.h error.h exit.h datetime.h now.h datetime.h
+ ./compile qmail-tcpto.c
+
+qmail-upq: \
+warn-auto.sh qmail-upq.sh conf-qmail conf-break conf-split
+ cat warn-auto.sh qmail-upq.sh \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPLIT}"`head -1 conf-split`"}g \
+ > qmail-upq
+ chmod 755 qmail-upq
+
+qmail-users.0: \
+qmail-users.5
+ nroff -man qmail-users.5 > qmail-users.0
+
+qmail-users.5: \
+qmail-users.9 conf-break conf-spawn
+ cat qmail-users.9 \
+ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+ | sed s}BREAK}"`head -1 conf-break`"}g \
+ | sed s}SPAWN}"`head -1 conf-spawn`"}g \
+ > qmail-users.5
+
+qmail.0: \
+qmail.7
+ nroff -man qmail.7 > qmail.0
+
+qmail.o: \
+compile qmail.c substdio.h readwrite.h wait.h exit.h fork.h fd.h \
+qmail.h substdio.h auto_qmail.h
+ ./compile qmail.c
+
+qreceipt: \
+load qreceipt.o headerbody.o hfield.o quote.o token822.o qmail.o \
+getln.a fd.a wait.a sig.a env.a stralloc.a alloc.a substdio.a error.a \
+str.a auto_qmail.o
+ ./load qreceipt headerbody.o hfield.o quote.o token822.o \
+ qmail.o getln.a fd.a wait.a sig.a env.a stralloc.a alloc.a \
+ substdio.a error.a str.a auto_qmail.o
+
+qreceipt.0: \
+qreceipt.1
+ nroff -man qreceipt.1 > qreceipt.0
+
+qreceipt.o: \
+compile qreceipt.c sig.h env.h substdio.h stralloc.h gen_alloc.h \
+subfd.h substdio.h getln.h alloc.h str.h hfield.h token822.h \
+gen_alloc.h error.h gen_alloc.h gen_allocdefs.h headerbody.h exit.h \
+open.h quote.h qmail.h substdio.h
+ ./compile qreceipt.c
+
+qsmhook: \
+load qsmhook.o sig.a case.a fd.a wait.a getopt.a env.a stralloc.a \
+alloc.a substdio.a error.a str.a
+ ./load qsmhook sig.a case.a fd.a wait.a getopt.a env.a \
+ stralloc.a alloc.a substdio.a error.a str.a
+
+qsmhook.o: \
+compile qsmhook.c fd.h stralloc.h gen_alloc.h readwrite.h sgetopt.h \
+subgetopt.h wait.h env.h byte.h str.h alloc.h exit.h fork.h case.h \
+subfd.h substdio.h error.h substdio.h sig.h
+ ./compile qsmhook.c
+
+qsutil.o: \
+compile qsutil.c stralloc.h gen_alloc.h readwrite.h substdio.h \
+qsutil.h
+ ./compile qsutil.c
+
+quote.o: \
+compile quote.c stralloc.h gen_alloc.h str.h quote.h
+ ./compile quote.c
+
+rcpthosts.o: \
+compile rcpthosts.c cdb.h uint32.h byte.h open.h error.h control.h \
+constmap.h stralloc.h gen_alloc.h rcpthosts.h
+ ./compile rcpthosts.c
+
+qregex.o: \
+compile qregex.c qregex.h
+ ./compile qregex.c
+
+readsubdir.o: \
+compile readsubdir.c readsubdir.h direntry.h fmt.h scan.h str.h \
+auto_split.h
+ ./compile readsubdir.c
+
+received.o: \
+compile received.c fmt.h qmail.h substdio.h now.h datetime.h \
+datetime.h date822fmt.h received.h
+ ./compile received.c
+
+remoteinfo.o: \
+compile remoteinfo.c byte.h substdio.h ip.h fmt.h timeoutconn.h \
+timeoutread.h timeoutwrite.h remoteinfo.h
+ ./compile remoteinfo.c
+
+scan_8long.o: \
+compile scan_8long.c scan.h
+ ./compile scan_8long.c
+
+scan_ulong.o: \
+compile scan_ulong.c scan.h
+ ./compile scan_ulong.c
+
+seek.a: \
+makelib seek_cur.o seek_end.o seek_set.o seek_trunc.o
+ ./makelib seek.a seek_cur.o seek_end.o seek_set.o \
+ seek_trunc.o
+
+seek_cur.o: \
+compile seek_cur.c seek.h
+ ./compile seek_cur.c
+
+seek_end.o: \
+compile seek_end.c seek.h
+ ./compile seek_end.c
+
+seek_set.o: \
+compile seek_set.c seek.h
+ ./compile seek_set.c
+
+seek_trunc.o: \
+compile seek_trunc.c seek.h
+ ./compile seek_trunc.c
+
+select.h: \
+compile trysysel.c select.h1 select.h2
+ ( ./compile trysysel.c >/dev/null 2>&1 \
+ && cat select.h2 || cat select.h1 ) > select.h
+ rm -f trysysel.o trysysel
+
+sendmail: \
+load sendmail.o env.a getopt.a alloc.a substdio.a error.a str.a \
+auto_qmail.o
+ ./load sendmail env.a getopt.a alloc.a substdio.a error.a \
+ str.a auto_qmail.o
+
+sendmail.o: \
+compile sendmail.c sgetopt.h subgetopt.h substdio.h subfd.h \
+substdio.h alloc.h auto_qmail.h exit.h env.h str.h
+ ./compile sendmail.c
+
+setup: \
+it man
+ ./install
+
+sgetopt.o: \
+compile sgetopt.c substdio.h subfd.h substdio.h sgetopt.h subgetopt.h \
+subgetopt.h
+ ./compile sgetopt.c
+
+shar: \
+FILES BLURB BLURB2 BLURB3 BLURB4 README FAQ INSTALL INSTALL.alias \
+INSTALL.ctl INSTALL.ids INSTALL.maildir INSTALL.mbox INSTALL.vsm \
+REMOVE.sendmail REMOVE.binmail TEST.deliver TEST.receive UPGRADE \
+THOUGHTS TODO THANKS CHANGES SECURITY INTERNALS SENDMAIL \
+PIC.local2alias PIC.local2ext PIC.local2local PIC.local2rem \
+PIC.local2virt PIC.nullclient PIC.relaybad PIC.relaygood \
+PIC.rem2local FILES VERSION SYSDEPS TARGETS Makefile BIN.README \
+BIN.Makefile BIN.setup idedit.c conf-break auto_break.h conf-spawn \
+auto_spawn.h chkspawn.c conf-split auto_split.h conf-patrn \
+auto_patrn.h conf-users conf-groups auto_uids.h auto_usera.h extra.h \
+addresses.5 except.1 bouncesaying.1 condredirect.1 dot-qmail.9 \
+envelopes.5 forgeries.7 forward.1 maildir2mbox.1 maildirmake.1 \
+maildirwatch.1 mailsubj.1 mbox.5 preline.1 qbiff.1 qmail-clean.8 \
+qmail-command.8 qmail-control.9 qmail-getpw.9 qmail-header.5 \
+qmail-inject.8 qmail-limits.9 qmail-local.8 qmail-log.5 \
+qmail-lspawn.8 qmail-newmrh.9 qmail-newu.9 qmail-pop3d.8 \
+qmail-popup.8 qmail-pw2u.9 qmail-qmqpc.8 qmail-qmqpd.8 qmail-qmtpd.8 \
+qmail-qread.8 qmail-qstat.8 qmail-queue.8 qmail-remote.8 \
+qmail-rspawn.8 qmail-send.9 qmail-showctl.8 qmail-smtpd.8 \
+qmail-start.9 qmail-tcpok.8 qmail-tcpto.8 qmail-users.9 qmail.7 \
+qreceipt.1 splogger.8 tcp-env.1 config.sh config-fast.sh \
+qmail-clean.c qmail-getpw.c qmail-inject.c qmail-local.c \
+qmail-lspawn.c qmail-newmrh.c qmail-newu.c qmail-pop3d.c \
+qmail-popup.c qmail-pw2u.c qmail-qmqpc.c qmail-qmqpd.c qmail-qmtpd.c \
+qmail-qread.c qmail-qstat.sh qmail-queue.c qmail-remote.c \
+qmail-rspawn.c qmail-send.c qmail-showctl.c qmail-smtpd.c \
+qmail-start.c qmail-tcpok.c qmail-tcpto.c spawn.c dnscname.c dnsfq.c \
+dnsip.c dnsmxip.c dnsptr.c hostname.c ipmeprint.c tcp-env.c \
+sendmail.c qreceipt.c qsmhook.c qbiff.c forward.c preline.c predate.c \
+except.c bouncesaying.c condredirect.c maildirmake.c maildir2mbox.c \
+maildirwatch.c splogger.c qail.sh elq.sh pinq.sh qmail-upq.sh \
+datemail.sh mailsubj.sh qlx.h rcpthosts.h rcpthosts.c commands.h \
+commands.c dnsdoe.h dnsdoe.c fmtqfn.h fmtqfn.c gfrom.h gfrom.c \
+myctime.h myctime.c newfield.h newfield.c qsutil.h qsutil.c \
+readsubdir.h readsubdir.c received.h received.c tcpto.h tcpto.c \
+tcpto_clean.c trigger.h trigger.c triggerpull.h triggerpull.c \
+trynpbg1.c trysyslog.c conf-cc conf-ld home.sh home+df.sh proc.sh \
+proc+df.sh binm1.sh binm2.sh binm3.sh binm1+df.sh binm2+df.sh \
+binm3+df.sh find-systype.sh make-compile.sh make-load.sh \
+make-makelib.sh trycpp.c warn-auto.sh auto-str.c auto-int.c \
+auto-int8.c auto-gid.c auto-uid.c hier.c install.c instcheck.c \
+install-big.c alloc.3 alloc.h alloc.c alloc_re.c case.3 case.h \
+case_diffb.c case_diffs.c case_lowerb.c case_lowers.c case_starts.c \
+cdb.3 cdb.h cdb_hash.c cdb_seek.c cdb_unpack.c cdbmake.h \
+cdbmake_add.c cdbmake_hash.c cdbmake_pack.c cdbmss.h cdbmss.c coe.3 \
+coe.h coe.c fd.h fd_copy.3 fd_copy.c fd_move.3 fd_move.c fifo_make.3 \
+fifo.h fifo.c trymkffo.c fork.h1 fork.h2 tryvfork.c now.3 now.h now.c \
+open.h open_append.c open_excl.c open_read.c open_trunc.c \
+open_write.c seek.h seek_cur.c seek_end.c seek_set.c seek_trunc.c \
+conf-qmail auto_qmail.h qmail.h qmail.c gen_alloc.h gen_allocdefs.h \
+stralloc.3 stralloc.h stralloc_eady.c stralloc_pend.c stralloc_copy.c \
+stralloc_opyb.c stralloc_opys.c stralloc_cat.c stralloc_catb.c \
+stralloc_cats.c stralloc_arts.c strerr.h strerr_sys.c strerr_die.c \
+substdio.h substdio.c substdi.c substdo.c substdio_copy.c subfd.h \
+subfderr.c subfdouts.c subfdout.c subfdins.c subfdin.c readwrite.h \
+exit.h timeoutconn.h timeoutconn.c timeoutread.h timeoutread.c \
+timeoutwrite.h timeoutwrite.c remoteinfo.h remoteinfo.c uint32.h1 \
+uint32.h2 tryulong32.c wait.3 wait.h wait_pid.c wait_nohang.c \
+trywaitp.c sig.h sig_alarm.c sig_block.c sig_catch.c sig_pause.c \
+sig_pipe.c sig_child.c sig_term.c sig_hup.c sig_misc.c sig_bug.c \
+trysgact.c trysgprm.c env.3 env.h env.c envread.c byte.h byte_chr.c \
+byte_copy.c byte_cr.c byte_diff.c byte_rchr.c byte_zero.c str.h \
+str_chr.c str_cpy.c str_diff.c str_diffn.c str_len.c str_rchr.c \
+str_start.c lock.h lock_ex.c lock_exnb.c lock_un.c tryflock.c getln.3 \
+getln.h getln.c getln2.3 getln2.c sgetopt.3 sgetopt.h sgetopt.c \
+subgetopt.3 subgetopt.h subgetopt.c error.3 error_str.3 error_temp.3 \
+error.h error.c error_str.c error_temp.c fmt.h fmt_str.c fmt_strn.c \
+fmt_uint.c fmt_uint0.c fmt_ulong.c scan.h scan_ulong.c scan_8long.c \
+slurpclose.h slurpclose.c quote.h quote.c hfield.h hfield.c \
+headerbody.h headerbody.c token822.h token822.c control.h control.c \
+datetime.3 datetime.h datetime.c datetime_un.c prioq.h prioq.c \
+date822fmt.h date822fmt.c dns.h dns.c trylsock.c tryrsolv.c ip.h ip.c \
+ipalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h ndelay.c \
+ndelay_off.c direntry.3 direntry.h1 direntry.h2 trydrent.c prot.h \
+prot.c chkshsgr.c warn-shsgr tryshsgr.c ipme.h ipme.c trysalen.c \
+maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c \
+update_tmprsadh
+ shar -m `cat FILES` > shar
+ chmod 400 shar
+
+sig.a: \
+makelib sig_alarm.o sig_block.o sig_catch.o sig_pause.o sig_pipe.o \
+sig_child.o sig_hup.o sig_term.o sig_bug.o sig_misc.o
+ ./makelib sig.a sig_alarm.o sig_block.o sig_catch.o \
+ sig_pause.o sig_pipe.o sig_child.o sig_hup.o sig_term.o \
+ sig_bug.o sig_misc.o
+
+sig_alarm.o: \
+compile sig_alarm.c sig.h
+ ./compile sig_alarm.c
+
+sig_block.o: \
+compile sig_block.c sig.h hassgprm.h
+ ./compile sig_block.c
+
+sig_bug.o: \
+compile sig_bug.c sig.h
+ ./compile sig_bug.c
+
+sig_catch.o: \
+compile sig_catch.c sig.h hassgact.h
+ ./compile sig_catch.c
+
+sig_child.o: \
+compile sig_child.c sig.h
+ ./compile sig_child.c
+
+sig_hup.o: \
+compile sig_hup.c sig.h
+ ./compile sig_hup.c
+
+sig_misc.o: \
+compile sig_misc.c sig.h
+ ./compile sig_misc.c
+
+sig_pause.o: \
+compile sig_pause.c sig.h hassgprm.h
+ ./compile sig_pause.c
+
+sig_pipe.o: \
+compile sig_pipe.c sig.h
+ ./compile sig_pipe.c
+
+sig_term.o: \
+compile sig_term.c sig.h
+ ./compile sig_term.c
+
+slurpclose.o: \
+compile slurpclose.c stralloc.h gen_alloc.h readwrite.h slurpclose.h \
+error.h
+ ./compile slurpclose.c
+
+socket.lib: \
+trylsock.c compile load
+ ( ( ./compile trylsock.c && \
+ ./load trylsock -lsocket -lnsl ) >/dev/null 2>&1 \
+ && echo -lsocket -lnsl || exit 0 ) > socket.lib
+ rm -f trylsock.o trylsock
+
+spawn.o: \
+compile chkspawn spawn.c sig.h wait.h substdio.h byte.h str.h \
+stralloc.h gen_alloc.h select.h exit.h alloc.h coe.h open.h error.h \
+auto_qmail.h auto_uids.h auto_spawn.h
+ ./chkspawn
+ ./compile spawn.c
+
+splogger: \
+load splogger.o substdio.a error.a str.a fs.a syslog.lib socket.lib
+ ./load splogger substdio.a error.a str.a fs.a `cat \
+ syslog.lib` `cat socket.lib`
+
+splogger.0: \
+splogger.8
+ nroff -man splogger.8 > splogger.0
+
+splogger.o: \
+compile splogger.c error.h substdio.h subfd.h substdio.h exit.h str.h \
+scan.h fmt.h
+ ./compile splogger.c
+
+str.a: \
+makelib str_len.o str_diff.o str_diffn.o str_cpy.o str_chr.o \
+str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_diff.o byte_copy.o \
+byte_cr.o byte_zero.o
+ ./makelib str.a str_len.o str_diff.o str_diffn.o str_cpy.o \
+ str_chr.o str_rchr.o str_start.o byte_chr.o byte_rchr.o \
+ byte_diff.o byte_copy.o byte_cr.o byte_zero.o
+
+str_chr.o: \
+compile str_chr.c str.h
+ ./compile str_chr.c
+
+str_cpy.o: \
+compile str_cpy.c str.h
+ ./compile str_cpy.c
+
+str_diff.o: \
+compile str_diff.c str.h
+ ./compile str_diff.c
+
+str_diffn.o: \
+compile str_diffn.c str.h
+ ./compile str_diffn.c
+
+str_len.o: \
+compile str_len.c str.h
+ ./compile str_len.c
+
+str_rchr.o: \
+compile str_rchr.c str.h
+ ./compile str_rchr.c
+
+str_start.o: \
+compile str_start.c str.h
+ ./compile str_start.c
+
+stralloc.a: \
+makelib stralloc_eady.o stralloc_pend.o stralloc_copy.o \
+stralloc_opys.o stralloc_opyb.o stralloc_cat.o stralloc_cats.o \
+stralloc_catb.o stralloc_arts.o
+ ./makelib stralloc.a stralloc_eady.o stralloc_pend.o \
+ stralloc_copy.o stralloc_opys.o stralloc_opyb.o \
+ stralloc_cat.o stralloc_cats.o stralloc_catb.o \
+ stralloc_arts.o
+
+stralloc_arts.o: \
+compile stralloc_arts.c byte.h str.h stralloc.h gen_alloc.h
+ ./compile stralloc_arts.c
+
+stralloc_cat.o: \
+compile stralloc_cat.c byte.h stralloc.h gen_alloc.h
+ ./compile stralloc_cat.c
+
+stralloc_catb.o: \
+compile stralloc_catb.c stralloc.h gen_alloc.h byte.h
+ ./compile stralloc_catb.c
+
+stralloc_cats.o: \
+compile stralloc_cats.c byte.h str.h stralloc.h gen_alloc.h
+ ./compile stralloc_cats.c
+
+stralloc_copy.o: \
+compile stralloc_copy.c byte.h stralloc.h gen_alloc.h
+ ./compile stralloc_copy.c
+
+stralloc_eady.o: \
+compile stralloc_eady.c alloc.h stralloc.h gen_alloc.h \
+gen_allocdefs.h
+ ./compile stralloc_eady.c
+
+stralloc_opyb.o: \
+compile stralloc_opyb.c stralloc.h gen_alloc.h byte.h
+ ./compile stralloc_opyb.c
+
+stralloc_opys.o: \
+compile stralloc_opys.c byte.h str.h stralloc.h gen_alloc.h
+ ./compile stralloc_opys.c
+
+stralloc_pend.o: \
+compile stralloc_pend.c alloc.h stralloc.h gen_alloc.h \
+gen_allocdefs.h
+ ./compile stralloc_pend.c
+
+strerr.a: \
+makelib strerr_sys.o strerr_die.o
+ ./makelib strerr.a strerr_sys.o strerr_die.o
+
+strerr_die.o: \
+compile strerr_die.c substdio.h subfd.h substdio.h exit.h strerr.h
+ ./compile strerr_die.c
+
+strerr_sys.o: \
+compile strerr_sys.c error.h strerr.h
+ ./compile strerr_sys.c
+
+subfderr.o: \
+compile subfderr.c readwrite.h substdio.h subfd.h substdio.h
+ ./compile subfderr.c
+
+subfdin.o: \
+compile subfdin.c readwrite.h substdio.h subfd.h substdio.h
+ ./compile subfdin.c
+
+subfdins.o: \
+compile subfdins.c readwrite.h substdio.h subfd.h substdio.h
+ ./compile subfdins.c
+
+subfdout.o: \
+compile subfdout.c readwrite.h substdio.h subfd.h substdio.h
+ ./compile subfdout.c
+
+subfdouts.o: \
+compile subfdouts.c readwrite.h substdio.h subfd.h substdio.h
+ ./compile subfdouts.c
+
+subgetopt.o: \
+compile subgetopt.c subgetopt.h
+ ./compile subgetopt.c
+
+substdi.o: \
+compile substdi.c substdio.h byte.h error.h
+ ./compile substdi.c
+
+substdio.a: \
+makelib substdio.o substdi.o substdo.o subfderr.o subfdout.o \
+subfdouts.o subfdin.o subfdins.o substdio_copy.o
+ ./makelib substdio.a substdio.o substdi.o substdo.o \
+ subfderr.o subfdout.o subfdouts.o subfdin.o subfdins.o \
+ substdio_copy.o
+
+substdio.o: \
+compile substdio.c substdio.h
+ ./compile substdio.c
+
+substdio_copy.o: \
+compile substdio_copy.c substdio.h
+ ./compile substdio_copy.c
+
+substdo.o: \
+compile substdo.c substdio.h str.h byte.h error.h
+ ./compile substdo.c
+
+syslog.lib: \
+trysyslog.c compile load
+ ( ( ./compile trysyslog.c && \
+ ./load trysyslog -lgen ) >/dev/null 2>&1 \
+ && echo -lgen || exit 0 ) > syslog.lib
+ rm -f trysyslog.o trysyslog
+
+systype: \
+find-systype trycpp.c
+ ./find-systype > systype
+
+tcp-env: \
+load tcp-env.o dns.o remoteinfo.o timeoutread.o timeoutwrite.o \
+timeoutconn.o ip.o ipalloc.o case.a ndelay.a sig.a env.a getopt.a \
+stralloc.a alloc.a substdio.a error.a str.a fs.a dns.lib socket.lib
+ ./load tcp-env dns.o remoteinfo.o timeoutread.o \
+ timeoutwrite.o timeoutconn.o ip.o ipalloc.o case.a ndelay.a \
+ sig.a env.a getopt.a stralloc.a alloc.a substdio.a error.a \
+ str.a fs.a `cat dns.lib` `cat socket.lib`
+
+tcp-env.0: \
+tcp-env.1
+ nroff -man tcp-env.1 > tcp-env.0
+
+tcp-env.o: \
+compile tcp-env.c sig.h stralloc.h gen_alloc.h str.h env.h fmt.h \
+scan.h subgetopt.h ip.h dns.h byte.h remoteinfo.h exit.h case.h
+ ./compile tcp-env.c
+
+tcp-environ.0: \
+tcp-environ.5
+ nroff -man tcp-environ.5 > tcp-environ.0
+
+tcpto.o: \
+compile tcpto.c tcpto.h open.h lock.h seek.h now.h datetime.h ip.h \
+byte.h datetime.h readwrite.h
+ ./compile tcpto.c
+
+tcpto_clean.o: \
+compile tcpto_clean.c tcpto.h open.h substdio.h readwrite.h
+ ./compile tcpto_clean.c
+
+timeoutconn.o: \
+compile timeoutconn.c ndelay.h select.h error.h readwrite.h ip.h \
+byte.h timeoutconn.h
+ ./compile timeoutconn.c
+
+timeoutread.o: \
+compile timeoutread.c timeoutread.h select.h error.h readwrite.h
+ ./compile timeoutread.c
+
+timeoutwrite.o: \
+compile timeoutwrite.c timeoutwrite.h select.h error.h readwrite.h
+ ./compile timeoutwrite.c
+
+qmail-smtpd: tls.o ssl_timeoutio.o ndelay.a
+qmail-remote: tls.o ssl_timeoutio.o
+qmail-smtpd.o: tls.h ssl_timeoutio.h
+qmail-remote.o: tls.h ssl_timeoutio.h
+
+tls.o: \
+compile tls.c exit.h error.h
+ ./compile tls.c
+
+ssl_timeoutio.o: \
+compile ssl_timeoutio.c ssl_timeoutio.h select.h error.h ndelay.h
+ ./compile ssl_timeoutio.c
+
+token822.o: \
+compile token822.c stralloc.h gen_alloc.h alloc.h str.h token822.h \
+gen_alloc.h gen_allocdefs.h
+ ./compile token822.c
+
+trigger.o: \
+compile trigger.c select.h open.h trigger.h hasnpbg1.h
+ ./compile trigger.c
+
+triggerpull.o: \
+compile triggerpull.c ndelay.h open.h triggerpull.h
+ ./compile triggerpull.c
+
+uint32.h: \
+tryulong32.c compile load uint32.h1 uint32.h2
+ ( ( ./compile tryulong32.c && ./load tryulong32 && \
+ ./tryulong32 ) >/dev/null 2>&1 \
+ && cat uint32.h2 || cat uint32.h1 ) > uint32.h
+ rm -f tryulong32.o tryulong32
+
+wait.a: \
+makelib wait_pid.o wait_nohang.o
+ ./makelib wait.a wait_pid.o wait_nohang.o
+
+wait_nohang.o: \
+compile wait_nohang.c haswaitp.h
+ ./compile wait_nohang.c
+
+wait_pid.o: \
+compile wait_pid.c error.h haswaitp.h
+ ./compile wait_pid.c
+
+cert cert-req: \
+Makefile-cert
+ @$(MAKE) -sf $< $@
+
+Makefile-cert: \
+conf-qmail conf-users conf-groups Makefile-cert.mk
+ @cat Makefile-cert.mk \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ > $@
+
+update_tmprsadh: \
+conf-qmail conf-users conf-groups update_tmprsadh.sh
+ @cat update_tmprsadh.sh\
+ | sed s}UGQMAILD}"`head -2 conf-users|tail -1`:`head -1 conf-groups`"}g \
+ | sed s}QMAIL}"`head -1 conf-qmail`"}g \
+ > $@
+ chmod 755 update_tmprsadh
+
+tmprsadh: \
+update_tmprsadh
+ echo "Creating new temporary RSA and DH parameters"
+ ./update_tmprsadh
diff -Naur ./numlib.h ../qmail-1.03-build-10/numlib.h
--- ./numlib.h 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/numlib.h 2006-05-03 17:44:55.000000000 -0500
@@ -0,0 +1,45 @@
+#ifndef numlib_h
+#define numlib_h
+
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static const char numlib_h_rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <time.h>
+
+#define NUMBUFSIZE 60
+
+/* Convert various system types to decimal */
+
+char *str_time_t(time_t, char *);
+char *str_off_t(off_t, char *);
+char *str_pid_t(pid_t, char *);
+char *str_ino_t(ino_t, char *);
+char *str_uid_t(uid_t, char *);
+char *str_gid_t(gid_t, char *);
+char *str_size_t(size_t, char *);
+
+char *str_sizekb(unsigned long, char *); /* X Kb or X Mb */
+
+/* Convert selected system types to hex */
+
+char *strh_time_t(time_t, char *);
+char *strh_pid_t(pid_t, char *);
+char *strh_ino_t(ino_t, char *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff -Naur ./overmaildirquota.c ../qmail-1.03-build-10/overmaildirquota.c
--- ./overmaildirquota.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/overmaildirquota.c 2006-05-03 17:44:55.000000000 -0500
@@ -0,0 +1,41 @@
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "maildirquota.h"
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+static const char rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+int user_over_maildirquota( const char *dir, const char *q)
+{
+struct stat stat_buf;
+int quotafd;
+int ret_value;
+
+ if (fstat(0, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode) &&
+ stat_buf.st_size > 0 && *q)
+ {
+ if (maildir_checkquota(dir, "afd, q, stat_buf.st_size, 1)
+ && errno != EAGAIN)
+ {
+ if (quotafd >= 0) close(quotafd);
+ ret_value = 1;
+ } else {
+ maildir_addquota(dir, quotafd, q, stat_buf.st_size, 1);
+ if (quotafd >= 0) close(quotafd);
+ ret_value = 0;
+ }
+ } else {
+ ret_value = 0;
+ }
+
+ return(ret_value);
+}
diff -Naur ./qmail.7 ../qmail-1.03-build-10/qmail.7
--- ./qmail.7 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail.7 2006-04-24 21:24:32.000000000 -0500
@@ -55,12 +55,14 @@
and
.BR qmail-pop3d (8).
-This documentation describes version
-1.03
+This documentation describes netqmail version
+1.05
of
.BR qmail .
See
.B http://pobox.com/~djb/qmail.html
for other
.BR qmail -related
-software.
+software, and
+.B http://qmail.org/
+for other qmail community contributions.
diff -Naur ./qmail-badloadertypes.9 ../qmail-1.03-build-10/qmail-badloadertypes.9
--- ./qmail-badloadertypes.9 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/qmail-badloadertypes.9 2005-03-12 11:01:36.000000000 -0600
@@ -0,0 +1,46 @@
+.TH qmail-badloadertype 8
+.SH NAME
+qmail-badloadertype \- prepare badloadertypes for qmail-smtpd
+.SH SYNOPSIS
+.B qmail-badloadertype
+.SH DESCRIPTION
+.B qmail-badloadertype
+reads the instructions in
+.B QMAILHOME/control/badloadertypes
+and writes them into
+.B QMAILHOME/control/badloadertypes.cdb
+in a binary format suited
+for quick access by
+.BR qmail-smtpd .
+
+If there is a problem with
+.BR control/badloadertypes ,
+.B qmail-badloadertype
+complains and leaves
+.B control/badloadertypes.cdb
+alone.
+
+.B qmail-badloadertype
+ensures that
+.B control/badloadertypes.cdb
+is updated atomically,
+so
+.B qmail-smtpd
+never has to wait for
+.B qmail-badloadertype
+to finish.
+However,
+.B qmail-badloadertype
+makes no attempt to protect against two simultaneous updates of
+.BR control/badloadertypes.cdb .
+For convenience,
+.B qmail-badloadertype
+allows comments (lines starting with '#') and
+copies only the significant leading characters to
+.BR control/badloadertypes.cdb .
+
+The binary
+.B control/badloadertypes.cdb
+format is portable across machines.
+.SH "SEE ALSO"
+qmail-smtpd(8)
diff -Naur ./qmail-badloadertypes.c ../qmail-1.03-build-10/qmail-badloadertypes.c
--- ./qmail-badloadertypes.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/qmail-badloadertypes.c 2005-03-12 11:01:36.000000000 -0600
@@ -0,0 +1,64 @@
+#include "strerr.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "getln.h"
+#include "exit.h"
+#include "readwrite.h"
+#include "open.h"
+#include "auto_qmail.h"
+#include "cdbmss.h"
+
+#define FATAL "qmail-badloadertypes: fatal: "
+#define LOADER_LEN 5
+
+void die_read()
+{
+ strerr_die2sys(111,FATAL,"unable to read control/badloadertypes: ");
+}
+void die_write()
+{
+ strerr_die2sys(111,FATAL,"unable to write to control/badloadertypes.tmp: ");
+}
+
+char inbuf[1024];
+substdio ssin;
+
+int fd;
+int fdtemp;
+
+struct cdbmss cdbmss;
+stralloc line = {0};
+int match;
+
+void main()
+{
+ umask(033);
+ if (chdir(auto_qmail) == -1)
+ strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": ");
+
+ fd = open_read("control/badloadertypes");
+ if (fd == -1) die_read();
+
+ substdio_fdbuf(&ssin,read,fd,inbuf,sizeof inbuf);
+
+ fdtemp = open_trunc("control/badloadertypes.tmp");
+ if (fdtemp == -1) die_write();
+
+ if (cdbmss_start(&cdbmss,fdtemp) == -1) die_write();
+
+ for (;;) {
+ if (getln(&ssin,&line,&match,'\n') != 0) die_read();
+ if (line.s[0] != '#' && line.len > LOADER_LEN)
+ if (cdbmss_add(&cdbmss,line.s,LOADER_LEN,"",0) == -1)
+ die_write();
+ if (!match) break;
+ }
+
+ if (cdbmss_finish(&cdbmss) == -1) die_write();
+ if (fsync(fdtemp) == -1) die_write();
+ if (close(fdtemp) == -1) die_write(); /* NFS stupidity */
+ if (rename("control/badloadertypes.tmp","control/badloadertypes.cdb") == -1)
+ strerr_die2sys(111,FATAL,"unable to move control/badloadertypes.tmp to control/badloadertypes.cdb");
+
+ _exit(0);
+}
diff -Naur ./qmail-badmimetypes.9 ../qmail-1.03-build-10/qmail-badmimetypes.9
--- ./qmail-badmimetypes.9 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/qmail-badmimetypes.9 2005-03-12 11:01:36.000000000 -0600
@@ -0,0 +1,46 @@
+.TH qmail-badmimetype 8
+.SH NAME
+qmail-badmimetype \- prepare badmimetypes for qmail-smtpd
+.SH SYNOPSIS
+.B qmail-badmimetype
+.SH DESCRIPTION
+.B qmail-badmimetype
+reads the instructions in
+.B QMAILHOME/control/badmimetypes
+and writes them into
+.B QMAILHOME/control/badmimetypes.cdb
+in a binary format suited
+for quick access by
+.BR qmail-smtpd .
+
+If there is a problem with
+.BR control/badmimetypes ,
+.B qmail-badmimetype
+complains and leaves
+.B control/badmimetypes.cdb
+alone.
+
+.B qmail-badmimetype
+ensures that
+.B control/badmimetypes.cdb
+is updated atomically,
+so
+.B qmail-smtpd
+never has to wait for
+.B qmail-badmimetype
+to finish.
+However,
+.B qmail-badmimetype
+makes no attempt to protect against two simultaneous updates of
+.BR control/badmimetypes.cdb .
+For convenience,
+.B qmail-badmimetype
+allows comments (lines starting with '#') and
+copies only the significant leading characters to
+.BR control/badmimetypes.cdb .
+
+The binary
+.B control/badmimetypes.cdb
+format is portable across machines.
+.SH "SEE ALSO"
+qmail-smtpd(8)
diff -Naur ./qmail-badmimetypes.c ../qmail-1.03-build-10/qmail-badmimetypes.c
--- ./qmail-badmimetypes.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/qmail-badmimetypes.c 2005-03-12 11:01:36.000000000 -0600
@@ -0,0 +1,64 @@
+#include "strerr.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "getln.h"
+#include "exit.h"
+#include "readwrite.h"
+#include "open.h"
+#include "auto_qmail.h"
+#include "cdbmss.h"
+
+#define FATAL "qmail-badmimetypes: fatal: "
+#define MIMETYPE_LEN 9
+
+void die_read()
+{
+ strerr_die2sys(111,FATAL,"unable to read control/badmimetypes: ");
+}
+void die_write()
+{
+ strerr_die2sys(111,FATAL,"unable to write to control/badmimetypes.tmp: ");
+}
+
+char inbuf[1024];
+substdio ssin;
+
+int fd;
+int fdtemp;
+
+struct cdbmss cdbmss;
+stralloc line = {0};
+int match;
+
+void main()
+{
+ umask(033);
+ if (chdir(auto_qmail) == -1)
+ strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": ");
+
+ fd = open_read("control/badmimetypes");
+ if (fd == -1) die_read();
+
+ substdio_fdbuf(&ssin,read,fd,inbuf,sizeof inbuf);
+
+ fdtemp = open_trunc("control/badmimetypes.tmp");
+ if (fdtemp == -1) die_write();
+
+ if (cdbmss_start(&cdbmss,fdtemp) == -1) die_write();
+
+ for (;;) {
+ if (getln(&ssin,&line,&match,'\n') != 0) die_read();
+ if (line.s[0] != '#' && line.len > MIMETYPE_LEN)
+ if (cdbmss_add(&cdbmss,line.s,MIMETYPE_LEN,"",0) == -1)
+ die_write();
+ if (!match) break;
+ }
+
+ if (cdbmss_finish(&cdbmss) == -1) die_write();
+ if (fsync(fdtemp) == -1) die_write();
+ if (close(fdtemp) == -1) die_write(); /* NFS stupidity */
+ if (rename("control/badmimetypes.tmp","control/badmimetypes.cdb") == -1)
+ strerr_die2sys(111,FATAL,"unable to move control/badmimetypes.tmp to control/badmimetypes.cdb");
+
+ _exit(0);
+}
diff -Naur ./qmail.c ../qmail-1.03-build-10/qmail.c
--- ./qmail.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail.c 2006-05-05 19:25:27.000000000 -0500
@@ -6,28 +6,49 @@
#include "fd.h"
#include "qmail.h"
#include "auto_qmail.h"
+#include "env.h"
-static char *binqqargs[2] = { "bin/qmail-queue", 0 } ;
+static char *binqqargs[2] = { 0, 0 } ;
+
+static void setup_qqargs()
+{
+ if(!binqqargs[0])
+ binqqargs[0] = env_get("QMAILQUEUE");
+ if(!binqqargs[0])
+ binqqargs[0] = "bin/qmail-queue";
+}
int qmail_open(qq)
struct qmail *qq;
{
int pim[2];
int pie[2];
+ int pierr[2];
+
+ setup_qqargs();
if (pipe(pim) == -1) return -1;
if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; }
+ if (pipe(pierr) == -1) {
+ close(pim[0]); close(pim[1]);
+ close(pie[0]); close(pie[1]);
+ close(pierr[0]); close(pierr[1]);
+ return -1;
+ }
switch(qq->pid = vfork()) {
case -1:
+ close(pierr[0]); close(pierr[1]);
close(pim[0]); close(pim[1]);
close(pie[0]); close(pie[1]);
return -1;
case 0:
close(pim[1]);
close(pie[1]);
+ close(pierr[0]); /* we want to receive data */
if (fd_move(0,pim[0]) == -1) _exit(120);
if (fd_move(1,pie[0]) == -1) _exit(120);
+ if (fd_move(4,pierr[1]) == -1) _exit(120);
if (chdir(auto_qmail) == -1) _exit(61);
execv(*binqqargs,binqqargs);
_exit(120);
@@ -35,6 +56,7 @@
qq->fdm = pim[1]; close(pim[0]);
qq->fde = pie[1]; close(pie[0]);
+ qq->fderr = pierr[0]; close(pierr[1]);
substdio_fdbuf(&qq->ss,write,qq->fdm,qq->buf,sizeof(qq->buf));
qq->flagerr = 0;
return 0;
@@ -82,10 +104,22 @@
{
int wstat;
int exitcode;
+ int match;
+ char ch;
+ static char errstr[256];
+ int len = 0;
qmail_put(qq,"",1);
if (!qq->flagerr) if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1;
close(qq->fde);
+ substdio_fdbuf(&qq->ss,read,qq->fderr,qq->buf,sizeof(qq->buf));
+ while( substdio_bget(&qq->ss,&ch,1) && len < 255){
+ errstr[len]=ch;
+ len++;
+ }
+ if (len > 0) errstr[len]='\0'; /* add str-term */
+
+ close(qq->fderr);
if (wait_pid(&wstat,qq->pid) != qq->pid)
return "Zqq waitpid surprise (#4.3.0)";
@@ -118,8 +152,11 @@
case 81: return "Zqq internal bug (#4.3.0)";
case 120: return "Zunable to exec qq (#4.3.0)";
default:
+ if (exitcode == 82 && len > 2){
+ return errstr;
+ }
if ((exitcode >= 11) && (exitcode <= 40))
- return "Dqq permanent problem (#5.3.0)";
+ return "Dqq permanent problem (#5.3.0)";
return "Zqq temporary problem (#4.3.0)";
}
}
diff -Naur ./qmail-control.9 ../qmail-1.03-build-10/qmail-control.9
--- ./qmail-control.9 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail-control.9 2006-05-09 23:44:10.000000000 -0500
@@ -20,7 +20,11 @@
Comments are allowed
in
+.IR badhelo ,
.IR badmailfrom ,
+.IR badmailfromnorelay ,
+.IR badmailto ,
+.IR badmailtonorelay ,
.IR locals ,
.IR percenthack ,
.IR qmqpservers ,
@@ -40,14 +44,24 @@
.ta 5c 10c
control default used by
+.I badhelo \fR(none) \fRqmail-smtpd
+.I badloadertypes.cdb \fR(none) \fRqmail-smtpd
.I badmailfrom \fR(none) \fRqmail-smtpd
+.I badmailfromnorelay \fR(none) \fRqmail-smtpd
+.I badmailto \fR(none) \fRqmail-smtpd
+.I badmailtonorelay \fR(none) \fRqmail-smtpd
+.I badmimetypes.cdb \fR(none) \fRqmail-smtpd
.I bouncefrom \fRMAILER-DAEMON \fRqmail-send
.I bouncehost \fIme \fRqmail-send
+.I clientca.pem \fR(none) \fRqmail-smtpd
+.I clientcert.pem \fR(none) \fRqmail-remote
.I concurrencylocal \fR10 \fRqmail-send
.I concurrencyremote \fR20 \fRqmail-send
.I defaultdomain \fIme \fRqmail-inject
.I defaulthost \fIme \fRqmail-inject
.I databytes \fR0 \fRqmail-smtpd
+.I dh1024.pem \fR(none) \fRqmail-smtpd
+.I dh512.pem \fR(none) \fRqmail-smtpd
.I doublebouncehost \fIme \fRqmail-send
.I doublebounceto \fRpostmaster \fRqmail-send
.I envnoathost \fIme \fRqmail-send
@@ -61,18 +75,33 @@
.I qmqpservers \fR(none) \fRqmail-qmqpc
.I queuelifetime \fR604800 \fRqmail-send
.I rcpthosts \fR(none) \fRqmail-smtpd
+.I rsa512.pem \fR(none) \fRqmail-smtpd
+.I servercert.pem \fR(none) \fRqmail-smtpd
.I smtpgreeting \fIme \fRqmail-smtpd
.I smtproutes \fR(none) \fRqmail-remote
+.I spfbehavior \fR0 \fRqmail-smtpd
+.I spfexp \fR(default) \fRqmail-smtpd
+.I spfguess \fR(none) \fRqmail-smtpd
+.I spfrules \fR(none) \fRqmail-smtpd
+.I taps \fR(none) \fRqmail-queue
.I timeoutconnect \fR60 \fRqmail-remote
.I timeoutremote \fR1200 \fRqmail-remote
.I timeoutsmtpd \fR1200 \fRqmail-smtpd
+.I tlsclients \fR(none) \fRqmail-smtpd
+.I tlsclientciphers \fR(none) \fRqmail-remote
+.I tlshosts/FQDN.pem \fR(none) \fRqmail-remote
+.I tlsserverciphers \fR(none) \fRqmail-smtpd
.I virtualdomains \fR(none) \fRqmail-send
.fi
.RE
.SH "SEE ALSO"
qmail-inject(8),
qmail-qmqpc(8),
+qmail-queue(8),
qmail-remote(8),
qmail-send(8),
qmail-showctl(8),
-qmail-smtpd(8)
+qmail-smtpd(8),
+qmail-badloadertype(8),
+qmail-badmimetype(8),
+qmail-newmrh(8)
diff -Naur ./qmail-dk.8 ../qmail-1.03-build-10/qmail-dk.8
--- ./qmail-dk.8 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/qmail-dk.8 2006-05-12 19:23:30.000000000 -0500
@@ -0,0 +1,125 @@
+.TH qmail-dk 8
+.SH NAME
+qmail-dk \- sign/verify and queue a mail message for delivery
+.SH SYNOPSIS
+.B qmail-dk
+.SH DESCRIPTION
+.B qmail-dk
+has the same interface as
+.B qmail-queue
+except that it inserts an appropriate DomainKeys header before it
+queues the message. There are two separate ways to invoke
+.BR qmail-dk .
+For one way, you can patch qmail with the http://qmail.org/qmailqueue
+patch and set QMAILQUEUE to point to qmail-dk in the environment when
+you send or receive email.
+For another way, you can rename qmail-queue to qmail-queue.orig, and
+set DKQUEUE=bin/qmail-queue.orig.
+
+.B qmail-dk
+has been patched with
+.BR qmail-dk-0.54-auth.patch ,
+which sets up a bit of automatic behavior. If RELAYCLIENT is found in
+the environment, qmail-dk imports the DKSIGN environment variable and
+tries to sign the mail. If RELAYCLIENT is not found in the environment,
+DKVERIFY is imported, and we attempt to verify the mail.
+
+.B qmail-dk
+supports DomainKey signing and verification. It uses the libdomainkey
+and OpenSSL libraries. To sign a message, set the
+.B DKSIGN
+environment variable to the pathname to the private key that will be
+used to sign the message. If there is a % character in the environment
+variable, it is removed and replaced by the domain name in the From: header.
+If, after substituting the %, that file does not exist, the message will not be signed.
+If there is no % and the file does not exist, the message will be rejected with error 32.
+The selector will be taken from the
+basename of the file. The private key should be created by
+.BR dknewkey ,
+which comes with libdomainkey.
+
+To verify a message, set the
+.B DKVERIFY
+environment variable to a desired set of letters. Precisely, if you
+want a libdomainkey return status to generate an error, include that
+letter, where A is the first return status (DK_STAT_OK), B is the
+second (DK_STAT_BADSIG), etc. The letter should be uppercase if you
+want a permanent error to be returned (exit code 13), and lowercase if
+you want a temporary error to be returned (exit code 82).
+
+For example, if you want to permanently reject messages that have a
+signature that has been revoked, include the letter 'K' in the
+.B DKVERIFY
+environment variable. A conservative set of letters is
+.BR DEGIJKfh .
+Reject permanently BADSIG, NOKEY, BADKEY, SYNTAX, ARGS, REVOKED, and
+INTERNAL errors, and temporarily CANTVRFY and NORESOURCE. Add in
+.B B
+if you want to reject messages that have a signature that doesn't
+verify (presumably because the message is a forgery or has been
+damaged in transit. Note that
+.B qmail-dk
+always inserts the
+.B DomainKey-Status
+header, so that messages can be
+rejected at delivery time, or in the mail reader.
+
+Typically, you would sign messages generated on-host by setting
+.B DKSIGN
+in the environment before running an email program. DKSIGN will be carried
+through qmail's sendmail emulation through
+.B qmail-inject
+to
+.BR qmail-dk .
+You would also set it for
+.B qmail-smtpd
+at the same time
+.B RELAYCLIENT
+is set, most often in the tcpserver cdb file. If a host is authorized
+to relay, you probably want to sign messages sent by that host.
+.B DKVERIFY
+should be set for all other hosts.
+
+If neither
+.B DKSIGN
+nor
+.B DKVERIFY
+are set, then
+.B DKSIGN
+will be set to /var/qmail/control/domainkeys/%/default. If such a private
+key exists, it will be used to sign the domain.
+
+.B qmail-dk
+will ordinarily spawn qmail-queue, but if DKQUEUE is set in the environment,
+the program that it points to will be executed instead. If DKQUEUE is not set, and
+.B qmail-dk
+has been invoked as
+.B qmail-queue
+then
+.B qmail-queue.orig
+is spawned instead.
+
+.SH "EXIT CODES"
+.B qmail-dk
+returns the same exit codes as qmail-queue with these additions:
+.TP 5
+.B 32
+The private key file does not exist.
+.TP 5
+.B 57
+Trouble waiting for qmail-queue to exit.
+.TP 5
+.B 58
+Unable to vfork.
+.TP 5
+.B 59
+Unable to create a pipe to qmail-queue.
+.SH "SEE ALSO"
+addresses(5),
+envelopes(5),
+qmail-header(5),
+qmail-inject(8),
+qmail-qmqpc(8),
+qmail-queue(8),
+qmail-send(8),
+qmail-smtpd(8)
diff -Naur ./qmail-dk.c ../qmail-1.03-build-10/qmail-dk.c
--- ./qmail-dk.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/qmail-dk.c 2006-05-12 19:26:10.000000000 -0500
@@ -0,0 +1,303 @@
+#include <sys/types.h>
+#include "readwrite.h"
+#include "sig.h"
+#include "exit.h"
+#include "open.h"
+#include "seek.h"
+#include "fmt.h"
+#include "alloc.h"
+#include "str.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "datetime.h"
+#include "now.h"
+#include "fork.h"
+#include "wait.h"
+#include "extra.h"
+#include "auto_qmail.h"
+#include "auto_uids.h"
+#include "date822fmt.h"
+#include "fmtqfn.h"
+#include "env.h"
+#include "control.h"
+#include <domainkeys.h>
+
+#define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */
+#define ADDR 1003
+
+char inbuf[2048];
+struct substdio ssin;
+char outbuf[256];
+struct substdio ssout;
+
+datetime_sec starttime;
+struct datetime dt;
+unsigned long mypid;
+unsigned long uid;
+char *pidfn;
+int messfd;
+int readfd;
+
+void die(e) int e; { _exit(e); }
+void die_write() { die(53); }
+void die_read() { die(54); }
+void sigalrm() { /* thou shalt not clean up here */ die(52); }
+void sigbug() { die(81); }
+void maybe_die_dk(e) DK_STAT e; {
+ switch(e) {
+ case DK_STAT_BADKEY: _exit(55);
+ case DK_STAT_CANTVRFY: _exit(74);
+ case DK_STAT_NORESOURCE: _exit(51);
+ case DK_STAT_ARGS: _exit(12);
+ case DK_STAT_SYNTAX: _exit(31);
+ case DK_STAT_INTERNAL: _exit(81);
+ }
+}
+
+unsigned int pidfmt(s,seq)
+char *s;
+unsigned long seq;
+{
+ unsigned int i;
+ unsigned int len;
+
+ len = 0;
+ i = fmt_str(s,"/tmp/qmail-dk."); len += i; if (s) s += i;
+ i = fmt_ulong(s,mypid); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,starttime); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,seq); len += i; if (s) s += i;
+ ++len; if (s) *s++ = 0;
+
+ return len;
+}
+
+void pidopen()
+{
+ unsigned int len;
+ unsigned long seq;
+
+ seq = 1;
+ len = pidfmt((char *) 0,seq);
+ pidfn = alloc(len);
+ if (!pidfn) die(51);
+
+ for (seq = 1;seq < 10;++seq)
+ {
+ if (pidfmt((char *) 0,seq) > len) die(81); /* paranoia */
+ pidfmt(pidfn,seq);
+ messfd = open_excl(pidfn);
+ if (messfd != -1) return;
+ }
+
+ die(63);
+}
+
+char tmp[FMT_ULONG];
+
+char *relayclient;
+char *dksign = 0;
+stralloc dksignature = {0};
+stralloc dkoutput = {0};
+char *dkverify = 0;
+char *dkqueue = 0;
+DK_LIB *dklib;
+DK *dk;
+DK_STAT st;
+
+static void write_signature(DK *dk, char *keyfn)
+{
+ char advice[2048];
+ char *selector;
+ char *from;
+ static stralloc keyfnfrom = {0};
+ int i;
+
+ from = dk_from(dk);
+ i = str_chr(keyfn, '%');
+ if (keyfn[i]) {
+ if (!stralloc_copyb(&keyfnfrom,keyfn,i)) die(51);
+ if (!stralloc_cats(&keyfnfrom,from)) die(51);
+ if (!stralloc_cats(&keyfnfrom,keyfn + i + 1)) die(51);
+ } else {
+ if (!stralloc_copys(&keyfnfrom,keyfn)) die(51);
+ }
+ if (!stralloc_0(&keyfnfrom)) die(51);
+
+ switch(control_readfile(&dksignature,keyfnfrom.s,0)) {
+ case 0:
+ if (keyfn[i]) return;
+ die(32);
+ case 1: break;
+ default: die(31);
+ }
+ for(i=0; i < dksignature.len; i++)
+ if (dksignature.s[i] == '\0') dksignature.s[i] = '\n';
+ if (!stralloc_0(&dksignature)) die(51);
+
+ st = dk_getsig(dk, dksignature.s, advice, sizeof(advice));
+ maybe_die_dk(st);
+
+ if (!stralloc_cats(&dkoutput,
+ "Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys\n"
+ "DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;\n"
+ " s=")) die(51);
+ selector = keyfn;
+ while (*keyfn) {
+ if (*keyfn == '/') selector = keyfn+1;
+ keyfn++;
+ }
+ if (!stralloc_cats(&dkoutput,selector)) die(51);
+ if (!stralloc_cats(&dkoutput,"; d=")) die(51);
+ if (from) {
+ if (!stralloc_cats(&dkoutput,from)) die(51);
+ } else if (!stralloc_cats(&dkoutput,"unknown")) die(51);
+ if (!stralloc_cats(&dkoutput,";\n b=")) die(51);
+ if (!stralloc_cats(&dkoutput,advice)) die(51);
+ if (!stralloc_cats(&dkoutput," ;\n")) die(51);
+}
+
+static char *binqqargs[2] = { "bin/qmail-queue", 0 } ;
+
+void main(int argc, char *argv[])
+{
+ unsigned int len;
+ char ch;
+ int pim[2];
+ int wstat;
+ unsigned long pid;
+
+ sig_blocknone();
+ umask(033);
+
+ relayclient = env_get("RELAYCLIENT");
+ if(relayclient){
+ dksign = env_get("DKSIGN");
+ if(! dksign)
+ dksign = "/var/qmail/control/domainkeys/%/default";
+ }else{
+ dkverify = env_get("DKVERIFY");
+ }
+
+ dkqueue = env_get("DKQUEUE");
+ if (dkqueue && *dkqueue) binqqargs[0] = dkqueue;
+ else if (str_equal(argv[0]+str_rchr(argv[0], '/'), "/qmail-queue"))
+ binqqargs[0] = "bin/qmail-queue.orig";
+
+ if (dksign || dkverify) {
+ dklib = dk_init(0);
+ if (!dklib) die(51);
+ }
+ if (dksign) {
+ dk = dk_sign(dklib, &st, DK_CANON_NOFWS);
+ if (!dk) die(31);
+ } else if (dkverify) {
+ dk = dk_verify(dklib, &st);
+ if (!dk) die(31);
+ }
+
+ mypid = getpid();
+ uid = getuid();
+ starttime = now();
+ datetime_tai(&dt,starttime);
+
+ sig_pipeignore();
+ sig_miscignore();
+ sig_alarmcatch(sigalrm);
+ sig_bugcatch(sigbug);
+
+ alarm(DEATH);
+
+ pidopen();
+ readfd = open_read(pidfn);
+ if (unlink(pidfn) == -1) die(63);
+
+ substdio_fdbuf(&ssout,write,messfd,outbuf,sizeof(outbuf));
+ substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
+
+ for (;;) {
+ register int n;
+ register char *x;
+ int i;
+
+ n = substdio_feed(&ssin);
+ if (n < 0) die_read();
+ if (!n) break;
+ x = substdio_PEEK(&ssin);
+ if (dksign || dkverify)
+ for(i=0; i < n; i++) {
+ if (x[i] == '\n') st = dk_message(dk, "\r\n", 2);
+ else st = dk_message(dk, x+i, 1);
+ maybe_die_dk(st);
+ }
+ if (substdio_put(&ssout,x,n) == -1) die_write();
+ substdio_SEEK(&ssin,n);
+ }
+
+ if (substdio_flush(&ssout) == -1) die_write();
+
+ if (dksign || dkverify) {
+ st = dk_eom(dk, (void *)0);
+ maybe_die_dk(st);
+ if (dksign) {
+ write_signature(dk, dksign);
+ } else if (dkverify) {
+ char *status;
+ if (!stralloc_copys(&dkoutput,"DomainKey-Status: ")) die(51);
+ switch(st) {
+ case DK_STAT_OK: status = "good "; break;
+ case DK_STAT_BADSIG: status = "bad "; break;
+ case DK_STAT_NOSIG: status = "no signature"; break;
+ case DK_STAT_NOKEY:
+ case DK_STAT_CANTVRFY: status = "no key "; break;
+ case DK_STAT_BADKEY: status = "bad key "; break;
+ case DK_STAT_INTERNAL:
+ case DK_STAT_ARGS:
+ case DK_STAT_SYNTAX: status = "bad format "; break;
+ case DK_STAT_NORESOURCE: status = "no resources"; break;
+ case DK_STAT_REVOKED: status = "revoked "; break;
+ }
+ if (!stralloc_cats(&dkoutput,status)) die(51);
+ if (!stralloc_cats(&dkoutput,"\n")) die(51);
+ if (dkverify[str_chr(dkverify, 'A'+st)]) die(13);
+ if (dkverify[str_chr(dkverify, 'a'+st)]) die(82);
+ }
+ }
+
+ if (pipe(pim) == -1) die(59);
+
+ switch(pid = vfork()) {
+ case -1:
+ close(pim[0]); close(pim[1]);
+ die(58);
+ case 0:
+ close(pim[1]);
+ if (fd_move(0,pim[0]) == -1) die(120);
+ if (chdir(auto_qmail) == -1) die(61);
+ execv(*binqqargs,binqqargs);
+ die(120);
+ }
+
+ close(pim[0]);
+
+ substdio_fdbuf(&ssin,read,readfd,inbuf,sizeof(inbuf));
+ substdio_fdbuf(&ssout,write,pim[1],outbuf,sizeof(outbuf));
+
+ if (substdio_bput(&ssout,dkoutput.s,dkoutput.len) == -1) die_write();
+ switch(substdio_copy(&ssout,&ssin))
+ {
+ case -2: die_read();
+ case -3: die_write();
+ }
+
+ if (substdio_flush(&ssout) == -1) die_write();
+ close(pim[1]);
+
+ if (wait_pid(&wstat,pid) != pid)
+ die(57);
+ if (wait_crashed(wstat))
+ die(57);
+ die(wait_exitcode(wstat));
+
+}
diff -Naur ./qmail.h ../qmail-1.03-build-10/qmail.h
--- ./qmail.h 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail.h 2006-05-05 19:25:27.000000000 -0500
@@ -8,6 +8,7 @@
unsigned long pid;
int fdm;
int fde;
+ int fderr;
substdio ss;
char buf[1024];
} ;
diff -Naur ./qmail-local.c ../qmail-1.03-build-10/qmail-local.c
--- ./qmail-local.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail-local.c 2006-05-03 17:44:55.000000000 -0500
@@ -66,6 +66,7 @@
char buf[1024];
char outbuf[1024];
+#define QUOTABUFSIZE 256
/* child process */
@@ -86,9 +87,15 @@
int fd;
substdio ss;
substdio ssout;
+ char quotabuf[QUOTABUFSIZE];
sig_alarmcatch(sigalrm);
if (chdir(dir) == -1) { if (error_temp(errno)) _exit(1); _exit(2); }
+ if (maildir_getquota(dir, quotabuf) == 0) {
+ if (user_over_maildirquota(dir,quotabuf)==1) {
+ _exit(1);
+ }
+ }
pid = getpid();
host[0] = 0;
gethostname(host,sizeof(host));
@@ -99,7 +106,10 @@
s += fmt_str(s,"tmp/");
s += fmt_ulong(s,time); *s++ = '.';
s += fmt_ulong(s,pid); *s++ = '.';
- s += fmt_strn(s,host,sizeof(host)); *s++ = 0;
+ s += fmt_strn(s,host,sizeof(host));
+ s += fmt_strn(s,",S=",sizeof(",S="));
+ if (fstat(0,&st) == -1) if (errno == error_noent) break;
+ s += fmt_ulong(s,st.st_size); *s++ = 0;
if (stat(fntmptph,&st) == -1) if (errno == error_noent) break;
/* really should never get to this point */
if (loop == 2) _exit(1);
@@ -159,6 +169,7 @@
switch(wait_exitcode(wstat))
{
case 0: break;
+ case 1: strerr_die1x(1, "User over quota. (#5.1.1)");
case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)");
case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)");
case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)");
@@ -645,7 +656,7 @@
{
cmds.s[j] = 0;
k = j;
- while ((k > i) && (cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t'))
+ while ((k > i) && ((cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t')))
cmds.s[--k] = 0;
switch(cmds.s[i])
{
diff -Naur ./qmail-log.5 ../qmail-1.03-build-10/qmail-log.5
--- ./qmail-log.5 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail-log.5 2006-04-24 21:24:32.000000000 -0500
@@ -232,6 +232,11 @@
is unable to queue a bounce message,
usually because the machine is almost out of memory.
It will try again later.
+This can also be caused by incorrect settings of
+.B $QMAILQUEUE
+or errors in a program or script which
+.B $QMAILQUEUE
+points to.
.TP
.B unable to stat ...
.B qmail-send
diff -Naur ./qmail-pop3d.c ../qmail-1.03-build-10/qmail-pop3d.c
--- ./qmail-pop3d.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail-pop3d.c 2006-05-03 17:44:55.000000000 -0500
@@ -16,6 +16,11 @@
#include "readwrite.h"
#include "timeoutread.h"
#include "timeoutwrite.h"
+#include <errno.h>
+#include "maildirquota.h"
+#include "maildirmisc.h"
+
+#define QUOTABUFSIZE 256
void die() { _exit(0); }
@@ -45,19 +50,15 @@
{
substdio_put(&ssout,buf,len);
}
-void puts(s) char *s;
-{
- substdio_puts(&ssout,s);
-}
void flush()
{
substdio_flush(&ssout);
}
void err(s) char *s;
{
- puts("-ERR ");
- puts(s);
- puts("\r\n");
+ substdio_puts(&ssout,"-ERR ");
+ substdio_puts(&ssout,s);
+ substdio_puts(&ssout,"\r\n");
flush();
}
@@ -66,14 +67,14 @@
void die_scan() { err("unable to scan $HOME/Maildir"); die(); }
void err_syntax() { err("syntax error"); }
-void err_unimpl() { err("unimplemented"); }
+void err_unimpl(arg) char *arg; { err("unimplemented"); }
void err_deleted() { err("already deleted"); }
void err_nozero() { err("messages are counted from 1"); }
void err_toobig() { err("not that many messages"); }
void err_nosuch() { err("unable to open that message"); }
void err_nounlink() { err("unable to unlink all deleted messages"); }
-void okay() { puts("+OK \r\n"); flush(); }
+void okay() { substdio_puts(&ssout,"+OK \r\n"); flush(); }
void printfn(fn) char *fn;
{
@@ -146,43 +147,66 @@
}
}
-void pop3_stat()
+void pop3_stat(arg) char *arg;
{
int i;
unsigned long total;
total = 0;
for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size;
- puts("+OK ");
+ substdio_puts(&ssout,"+OK ");
put(strnum,fmt_uint(strnum,numm));
- puts(" ");
+ substdio_puts(&ssout," ");
put(strnum,fmt_ulong(strnum,total));
- puts("\r\n");
+ substdio_puts(&ssout,"\r\n");
flush();
}
-void pop3_rset()
+void pop3_rset(arg) char *arg;
{
int i;
for (i = 0;i < numm;++i) m[i].flagdeleted = 0;
last = 0;
- okay();
+ okay(0);
}
-void pop3_last()
+void pop3_last(arg) char *arg;
{
- puts("+OK ");
+ substdio_puts(&ssout,"+OK ");
put(strnum,fmt_uint(strnum,last));
- puts("\r\n");
+ substdio_puts(&ssout,"\r\n");
flush();
}
-void pop3_quit()
+void pop3_quit(arg) char *arg;
{
int i;
+ char quotabuf[QUOTABUFSIZE];
+ int has_quota=maildir_getquota(".", quotabuf);
+
+ long deleted_bytes=0;
+ long deleted_messages=0;
+
for (i = 0;i < numm;++i)
if (m[i].flagdeleted) {
- if (unlink(m[i].fn) == -1) err_nounlink();
+ unsigned long un=0;
+ const char *filename=m[i].fn;
+ if (has_quota == 0 && !MAILDIR_DELETED(filename)) {
+ if (maildir_parsequota(filename, &un)) {
+ struct stat stat_buf;
+
+ if (stat(filename, &stat_buf) == 0)
+ un=stat_buf.st_size;
+ }
+ }
+ if (unlink(m[i].fn) == -1) {
+ err_nounlink();
+ un=0;
+ }
+ if (un) {
+ deleted_bytes -= un;
+ deleted_messages -= 1;
+ }
}
else
if (str_start(m[i].fn,"new/")) {
@@ -192,7 +216,22 @@
if (!stralloc_0(&line)) die_nomem();
rename(m[i].fn,line.s); /* if it fails, bummer */
}
- okay();
+
+ if (deleted_messages < 0) {
+ int quotafd;
+
+ if (maildir_checkquota(".", "afd, quotabuf, deleted_bytes,
+ deleted_messages) && errno != EAGAIN &&
+ deleted_bytes >= 0)
+ {
+ if (quotafd >= 0) close (quotafd);
+ } else {
+ maildir_addquota(".", quotafd, quotabuf,
+ deleted_bytes, deleted_messages);
+ if (quotafd >= 0) close(quotafd);
+ }
+ }
+ okay(0);
die();
}
@@ -214,7 +253,7 @@
if (i == -1) return;
m[i].flagdeleted = 1;
if (i + 1 > last) last = i + 1;
- okay();
+ okay(0);
}
void list(i,flaguidl)
@@ -222,10 +261,10 @@
int flaguidl;
{
put(strnum,fmt_uint(strnum,i + 1));
- puts(" ");
+ substdio_puts(&ssout," ");
if (flaguidl) printfn(m[i].fn);
else put(strnum,fmt_ulong(strnum,m[i].size));
- puts("\r\n");
+ substdio_puts(&ssout,"\r\n");
}
void dolisting(arg,flaguidl) char *arg; int flaguidl;
@@ -234,15 +273,15 @@
if (*arg) {
i = msgno(arg);
if (i == -1) return;
- puts("+OK ");
+ substdio_puts(&ssout,"+OK ");
list(i,flaguidl);
}
else {
- okay();
+ okay(0);
for (i = 0;i < numm;++i)
if (!m[i].flagdeleted)
list(i,flaguidl);
- puts(".\r\n");
+ substdio_puts(&ssout,".\r\n");
}
flush();
}
@@ -267,7 +306,7 @@
fd = open_read(m[i].fn);
if (fd == -1) { err_nosuch(); return; }
- okay();
+ okay(0);
substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf));
blast(&ssmsg,limit);
close(fd);
@@ -299,7 +338,7 @@
getlist();
- okay();
+ okay(0);
commands(&ssin,pop3commands);
die();
}
diff -Naur ./qmail-popup.c ../qmail-1.03-build-10/qmail-popup.c
--- ./qmail-popup.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail-popup.c 2006-04-24 21:24:32.000000000 -0500
@@ -64,10 +64,10 @@
void err_syntax() { err("syntax error"); }
void err_wantuser() { err("USER first"); }
-void err_authoriz() { err("authorization first"); }
+void err_authoriz(arg) char *arg; { err("authorization first"); }
-void okay() { puts("+OK \r\n"); flush(); }
-void pop3_quit() { okay(); die(); }
+void okay(arg) char *arg; { puts("+OK \r\n"); flush(); }
+void pop3_quit(arg) char *arg; { okay(0); die(); }
char unique[FMT_ULONG + FMT_ULONG + 3];
@@ -136,7 +136,7 @@
void pop3_user(arg) char *arg;
{
if (!*arg) { err_syntax(); return; }
- okay();
+ okay(0);
seenuser = 1;
if (!stralloc_copys(&username,arg)) die_nomem();
if (!stralloc_0(&username)) die_nomem();
diff -Naur ./qmail-queue.8 ../qmail-1.03-build-10/qmail-queue.8
--- ./qmail-queue.8 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail-queue.8 2006-05-09 23:45:45.000000000 -0500
@@ -40,6 +40,17 @@
However, the recipients probably expect to see a proper header,
as described in
.BR qmail-header(5) .
+.SH "CONTROL FILES"
+.TP 5
+.I taps
+Should contain regex syntax of email addresses to tap and
+the associated email address to send the copy to. The two
+fields should be separated by a colon.
+Programs included with qmail which invoke
+.B qmail-queue
+will invoke the contents of
+.B $QMAILQUEUE
+instead, if that environment variable is set.
.SH "FILESYSTEM RESTRICTIONS"
.B qmail-queue
imposes two constraints on the queue structure:
diff -Naur ./qmail-queue.c ../qmail-1.03-build-10/qmail-queue.c
--- ./qmail-queue.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail-queue.c 2006-05-09 23:51:14.000000000 -0500
@@ -16,6 +16,8 @@
#include "auto_uids.h"
#include "date822fmt.h"
#include "fmtqfn.h"
+#include "stralloc.h"
+#include "constmap.h"
#define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */
#define ADDR 1003
@@ -25,6 +27,14 @@
char outbuf[256];
struct substdio ssout;
+int tapok = 0;
+stralloc tap = {0};
+struct constmap maptap;
+stralloc chkaddr = {0};
+int tapped;
+stralloc tapaddr = {0};
+stralloc controlfile = {0};
+
datetime_sec starttime;
struct datetime dt;
unsigned long mypid;
@@ -175,7 +185,14 @@
alarm(DEATH);
- pidopen();
+ stralloc_copys( &controlfile, auto_qmail);
+ stralloc_cats( &controlfile, "/control/taps");
+ stralloc_0( &controlfile);
+ tapok = control_readfile(&tap,controlfile.s,0);
+ if (tapok == -1) die(65);
+ if (!constmap_init(&maptap,tap.s,tap.len,0)) die(65);
+
+pidopen();
if (fstat(messfd,&pidst) == -1) die(63);
messnum = pidst.st_ino;
@@ -219,14 +236,28 @@
if (substdio_get(&ssin,&ch,1) < 1) die_read();
if (ch != 'F') die(91);
if (substdio_bput(&ssout,&ch,1) == -1) die_write();
+ stralloc_0(&chkaddr);
for (len = 0;len < ADDR;++len)
{
+ if ( len == 1 ) stralloc_copyb(&chkaddr, &ch,1);
+ else if ( len > 1 ) stralloc_catb(&chkaddr, &ch,1);
if (substdio_get(&ssin,&ch,1) < 1) die_read();
if (substdio_put(&ssout,&ch,1) == -1) die_write();
if (!ch) break;
}
if (len >= ADDR) die(11);
+ /* check the from address */
+ stralloc_0(&chkaddr);
+ if (tapped == 0 && tapcheck()==1 ) {
+ tapped = 1;
+ if ( tapaddr.len > 0 ) {
+ if (substdio_bput(&ssout,"T",1) == -1) die_write();
+ if (substdio_bput(&ssout,tapaddr.s,tapaddr.len) == -1) die_write();
+ if (substdio_bput(&ssout,"",1) == -1) die_write();
+ }
+ }
+
if (substdio_bput(&ssout,QUEUE_EXTRA,QUEUE_EXTRALEN) == -1) die_write();
for (;;)
@@ -237,10 +268,24 @@
if (substdio_bput(&ssout,&ch,1) == -1) die_write();
for (len = 0;len < ADDR;++len)
{
+ if ( len == 1 ) stralloc_copyb(&chkaddr, &ch,1);
+ else if ( len > 1 ) stralloc_catb(&chkaddr, &ch,1);
if (substdio_get(&ssin,&ch,1) < 1) die_read();
if (substdio_bput(&ssout,&ch,1) == -1) die_write();
if (!ch) break;
}
+
+ /* check the to address */
+ stralloc_0(&chkaddr);
+ if (tapped == 0 && tapcheck()==1 ) {
+ tapped = 1;
+ if ( tapaddr.len > 0 ) {
+ if (substdio_bput(&ssout,"T",1) == -1) die_write();
+ if (substdio_bput(&ssout,tapaddr.s,tapaddr.len) == -1) die_write();
+ if (substdio_bput(&ssout,"",1) == -1) die_write();
+ }
+ }
+
if (len >= ADDR) die(11);
}
@@ -252,3 +297,42 @@
triggerpull();
die(0);
}
+
+int tapcheck()
+{
+ int i = 0;
+ int j = 0;
+ int x = 0;
+ int negate = 0;
+ stralloc curregex = {0};
+ char tmpbuf[200];
+
+ while (j < tap.len) {
+ i = j;
+ while ((tap.s[i] != ':') && (i < tap.len)) i++;
+ if (tap.s[j] == '!') {
+ negate = 1;
+ j++;
+ }
+ stralloc_copys(&tapaddr, &tap.s[i+1]);
+
+ stralloc_copyb(&curregex,tap.s + j,(i - j));
+ stralloc_0(&curregex);
+ x = matchregex(chkaddr.s, curregex.s, tmpbuf);
+
+ while ((tap.s[i] != '\0') && (i < tap.len)) i++;
+
+ if ((negate) && (x == 0)) {
+ return 1;
+ }
+ if (!(negate) && (x > 0)) {
+ return 1;
+ }
+ j = i + 1;
+ negate = 0;
+
+
+ }
+ return 0;
+}
+
diff -Naur ./qmail-remote.8 ../qmail-1.03-build-10/qmail-remote.8
--- ./qmail-remote.8 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail-remote.8 2006-04-27 11:10:31.000000000 -0500
@@ -114,6 +114,10 @@
always exits zero.
.SH "CONTROL FILES"
.TP 5
+.I clientcert.pem
+SSL certificate that is used to authenticate with the remote server
+during a TLS session.
+.TP 5
.I helohost
Current host name,
for use solely in saying hello to the remote SMTP server.
@@ -123,6 +127,16 @@
otherwise
.B qmail-remote
refuses to run.
+
+.TP 5
+.I notlshosts/<FQDN>
+.B qmail-remote
+will not try TLS on servers for which this file exists
+.RB ( <FQDN>
+is the fully-qualified domain name of the server).
+.IR (tlshosts/<FQDN>.pem
+takes precedence over this file however).
+
.TP 5
.I smtproutes
Artificial SMTP routes.
@@ -156,6 +170,8 @@
this tells
.B qmail-remote
to look up MX records as usual.
+.I port
+value of 465 (deprecated smtps port) causes TLS session to be started.
.I smtproutes
may include wildcards:
@@ -195,6 +211,33 @@
.B qmail-remote
will wait for each response from the remote SMTP server.
Default: 1200.
+
+.TP 5
+.I tlsclientciphers
+A set of OpenSSL client cipher strings. Multiple ciphers
+contained in a string should be separated by a colon.
+
+.TP 5
+.I tlshosts/<FQDN>.pem
+.B qmail-remote
+requires TLS authentication from servers for which this certificate exists
+.RB ( <FQDN>
+is the fully-qualified domain name of the server). One of the
+.I dNSName
+or the
+.I CommonName
+attributes have to match.
+
+.B WARNING:
+this option may cause mail to be delayed, bounced, doublebounced, or lost.
+
+.TP 5
+.I tlshosts/exhaustivelist
+if this file exists
+no TLS will be tried on hosts other than those for which a file
+.B tlshosts/<FQDN>.pem
+exists.
+
.SH "SEE ALSO"
addresses(5),
envelopes(5),
diff -Naur ./qmail-remote.c ../qmail-1.03-build-10/qmail-remote.c
--- ./qmail-remote.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail-remote.c 2006-04-27 11:10:31.000000000 -0500
@@ -28,6 +28,7 @@
#include "timeoutconn.h"
#include "timeoutread.h"
#include "timeoutwrite.h"
+#include "base64.h"
#define HUGESMTPTEXT 5000
@@ -43,11 +44,27 @@
struct constmap maproutes;
stralloc host = {0};
stralloc sender = {0};
+stralloc auth_smtp_user = {0};
+stralloc auth_smtp_pass = {0};
+stralloc auth_b64_user = {0};
+stralloc auth_b64_pass = {0};
+stralloc auth_status = {0};
saa reciplist = {0};
struct ip_address partner;
+#ifdef TLS
+# include <sys/stat.h>
+# include "tls.h"
+# include "ssl_timeoutio.h"
+# include <openssl/x509v3.h>
+# define EHLO 1
+
+int tls_init();
+const char *ssl_err_str = 0;
+#endif
+
void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
void zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); }
@@ -85,6 +102,18 @@
Sorry. Although I'm listed as a best-preference MX or A for that host,\n\
it isn't in my control/locals file, so I don't treat it as local. (#5.4.6)\n");
zerodie(); }
+void auth_user_not_set() {
+ if(!stralloc_copys(&auth_status, \
+ "User and password not set, continuing without authentication.\n"))
+ temp_nomem();
+ if(!stralloc_0(&auth_status)) temp_nomem();
+}
+void no_supported_auth() {
+ if(!stralloc_copys(&auth_status, \
+ "No supported AUTH method found, continuing without authentication.\n"))
+ temp_nomem();
+ if(!stralloc_0(&auth_status)) temp_nomem();
+}
void outhost()
{
@@ -99,6 +128,9 @@
outhost();
out(" but connection died. ");
if (flagcritical) out("Possible duplicate! ");
+#ifdef TLS
+ if (ssl_err_str) { out(ssl_err_str); out(" "); }
+#endif
out("(#4.4.2)\n");
zerodie();
}
@@ -110,6 +142,12 @@
int saferead(fd,buf,len) int fd; char *buf; int len;
{
int r;
+#ifdef TLS
+ if (ssl) {
+ r = ssl_timeoutread(timeout, smtpfd, smtpfd, ssl, buf, len);
+ if (r < 0) ssl_err_str = ssl_error_str();
+ } else
+#endif
r = timeoutread(timeout,smtpfd,buf,len);
if (r <= 0) dropped();
return r;
@@ -117,6 +155,12 @@
int safewrite(fd,buf,len) int fd; char *buf; int len;
{
int r;
+#ifdef TLS
+ if (ssl) {
+ r = ssl_timeoutwrite(timeout, smtpfd, smtpfd, ssl, buf, len);
+ if (r < 0) ssl_err_str = ssl_error_str();
+ } else
+#endif
r = timeoutwrite(timeout,smtpfd,buf,len);
if (r <= 0) dropped();
return r;
@@ -163,6 +207,65 @@
return code;
}
+#ifdef EHLO
+saa ehlokw = {0}; /* list of EHLO keywords and parameters */
+int maxehlokwlen = 0;
+
+unsigned long ehlo()
+{
+ stralloc *sa;
+ char *s, *e, *p;
+ unsigned long code;
+
+ if (ehlokw.len > maxehlokwlen) maxehlokwlen = ehlokw.len;
+ ehlokw.len = 0;
+
+# ifdef MXPS
+ if (type == 's') return 0;
+# endif
+
+ substdio_puts(&smtpto, "EHLO ");
+ substdio_put(&smtpto, helohost.s, helohost.len);
+ substdio_puts(&smtpto, "\r\n");
+ substdio_flush(&smtpto);
+
+ code = smtpcode();
+ if (code != 250) return code;
+
+ s = smtptext.s;
+ while (*s++ != '\n') ; /* skip the first line: contains the domain */
+
+ e = smtptext.s + smtptext.len - 6; /* 250-?\n */
+ while (s <= e)
+ {
+ int wasspace = 0;
+
+ if (!saa_readyplus(&ehlokw, 1)) temp_nomem();
+ sa = ehlokw.sa + ehlokw.len++;
+ if (ehlokw.len > maxehlokwlen) *sa = sauninit; else sa->len = 0;
+
+ /* smtptext is known to end in a '\n' */
+ for (p = (s += 4); ; ++p)
+ if (*p == '\n' || *p == ' ' || *p == '\t') {
+ if (!wasspace)
+ if (!stralloc_catb(sa, s, p - s) || !stralloc_0(sa)) temp_nomem();
+ if (*p == '\n') break;
+ wasspace = 1;
+ } else if (wasspace == 1) {
+ wasspace = 0;
+ s = p;
+ }
+ s = ++p;
+
+ /* keyword should consist of alpha-num and '-'
+ * broken AUTH might use '=' instead of space */
+ for (p = sa->s; *p; ++p) if (*p == '=') { *p = 0; break; }
+ }
+
+ return 250;
+}
+#endif
+
void outsmtptext()
{
int i;
@@ -179,6 +282,11 @@
char *prepend;
char *append;
{
+#ifdef TLS
+ /* shouldn't talk to the client unless in an appropriate state */
+ int state = ssl ? ssl->state : SSL_ST_BEFORE;
+ if (state & SSL_ST_OK || (!smtps && state & SSL_ST_BEFORE))
+#endif
substdio_putsflush(&smtpto,"QUIT\r\n");
/* waiting for remote side is just too ridiculous */
out(prepend);
@@ -186,6 +294,30 @@
out(append);
out(".\n");
outsmtptext();
+
+#if defined(TLS) && defined(DEBUG)
+ if (ssl) {
+ X509 *peercert;
+
+ out("STARTTLS proto="); out(SSL_get_version(ssl));
+ out("; cipher="); out(SSL_get_cipher(ssl));
+
+ /* we want certificate details */
+ if (peercert = SSL_get_peer_certificate(ssl)) {
+ char *str;
+
+ str = X509_NAME_oneline(X509_get_subject_name(peercert), NULL, 0);
+ out("; subject="); out(str); OPENSSL_free(str);
+
+ str = X509_NAME_oneline(X509_get_issuer_name(peercert), NULL, 0);
+ out("; issuer="); out(str); OPENSSL_free(str);
+
+ X509_free(peercert);
+ }
+ out(";\n");
+ }
+#endif
+
zerodie();
}
@@ -214,26 +346,297 @@
substdio_flush(&smtpto);
}
+#ifdef TLS
+char *partner_fqdn = 0;
+
+# define TLS_QUIT quit(ssl ? "; connected to " : "; connecting to ", "")
+void tls_quit(const char *s1, const char *s2)
+{
+ out(s1); if (s2) { out(": "); out(s2); } TLS_QUIT;
+}
+# define tls_quit_error(s) tls_quit(s, ssl_error())
+
+int match_partner(const char *s, int len)
+{
+ if (!case_diffb(partner_fqdn, len, s) && !partner_fqdn[len]) return 1;
+ /* we also match if the name is *.domainname */
+ if (*s == '*') {
+ const char *domain = partner_fqdn + str_chr(partner_fqdn, '.');
+ if (!case_diffb(domain, --len, ++s) && !domain[len]) return 1;
+ }
+ return 0;
+}
+
+/* don't want to fail handshake if certificate can't be verified */
+int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; }
+
+int tls_init()
+{
+ int i;
+ SSL *myssl;
+ SSL_CTX *ctx;
+ stralloc saciphers = {0};
+ const char *ciphers, *servercert = 0;
+
+ if (partner_fqdn) {
+ struct stat st;
+ stralloc tmp = {0};
+ if (!stralloc_copys(&tmp, "control/tlshosts/")
+ || !stralloc_catb(&tmp, partner_fqdn, str_len(partner_fqdn))
+ || !stralloc_catb(&tmp, ".pem", 5)) temp_nomem();
+ if (stat(tmp.s, &st) == 0)
+ servercert = tmp.s;
+ else {
+ if (!stralloc_copys(&tmp, "control/notlshosts/")
+ || !stralloc_catb(&tmp, partner_fqdn, str_len(partner_fqdn)+1))
+ temp_nomem();
+ if ((stat("control/tlshosts/exhaustivelist", &st) == 0) ||
+ (stat(tmp.s, &st) == 0)) {
+ alloc_free(tmp.s);
+ return 0;
+ }
+ alloc_free(tmp.s);
+ }
+ }
+
+ if (!smtps) {
+ stralloc *sa = ehlokw.sa;
+ unsigned int len = ehlokw.len;
+ /* look for STARTTLS among EHLO keywords */
+ for ( ; len && case_diffs(sa->s, "STARTTLS"); ++sa, --len) ;
+ if (!len) {
+ if (!servercert) return 0;
+ out("ZNo TLS achieved while "); out(servercert);
+ out(" exists"); smtptext.len = 0; TLS_QUIT;
+ }
+ }
+
+ SSL_library_init();
+ ctx = SSL_CTX_new(SSLv23_client_method());
+ if (!ctx) {
+ if (!smtps && !servercert) return 0;
+ smtptext.len = 0;
+ tls_quit_error("ZTLS error initializing ctx");
+ }
+
+ if (servercert) {
+ if (!SSL_CTX_load_verify_locations(ctx, servercert, NULL)) {
+ SSL_CTX_free(ctx);
+ smtptext.len = 0;
+ out("ZTLS unable to load "); tls_quit_error(servercert);
+ }
+ /* set the callback here; SSL_set_verify didn't work before 0.9.6c */
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb);
+ }
+
+ /* let the other side complain if it needs a cert and we don't have one */
+# define CLIENTCERT "control/clientcert.pem"
+ if (SSL_CTX_use_certificate_chain_file(ctx, CLIENTCERT))
+ SSL_CTX_use_RSAPrivateKey_file(ctx, CLIENTCERT, SSL_FILETYPE_PEM);
+# undef CLIENTCERT
+
+ myssl = SSL_new(ctx);
+ SSL_CTX_free(ctx);
+ if (!myssl) {
+ if (!smtps && !servercert) return 0;
+ smtptext.len = 0;
+ tls_quit_error("ZTLS error initializing ssl");
+ }
+
+ if (!smtps) substdio_putsflush(&smtpto, "STARTTLS\r\n");
+
+ /* while the server is preparing a responce, do something else */
+ if (control_readfile(&saciphers, "control/tlsclientciphers", 0) == -1)
+ { SSL_free(myssl); temp_control(); }
+ if (saciphers.len) {
+ for (i = 0; i < saciphers.len - 1; ++i)
+ if (!saciphers.s[i]) saciphers.s[i] = ':';
+ ciphers = saciphers.s;
+ }
+ else ciphers = "DEFAULT";
+ SSL_set_cipher_list(myssl, ciphers);
+ alloc_free(saciphers.s);
+
+ /* SSL_set_options(myssl, SSL_OP_NO_TLSv1); */
+ SSL_set_fd(myssl, smtpfd);
+
+ /* read the responce to STARTTLS */
+ if (!smtps) {
+ if (smtpcode() != 220) {
+ SSL_free(myssl);
+ if (!servercert) return 0;
+ out("ZSTARTTLS rejected while ");
+ out(servercert); out(" exists"); TLS_QUIT;
+ }
+ smtptext.len = 0;
+ }
+
+ ssl = myssl;
+ if (ssl_timeoutconn(timeout, smtpfd, smtpfd, ssl) <= 0)
+ tls_quit("ZTLS connect failed", ssl_error_str());
+
+ if (servercert) {
+ X509 *peercert;
+ STACK_OF(GENERAL_NAME) *gens;
+
+ int r = SSL_get_verify_result(ssl);
+ if (r != X509_V_OK) {
+ out("ZTLS unable to verify server with ");
+ tls_quit(servercert, X509_verify_cert_error_string(r));
+ }
+ alloc_free(servercert);
+
+ peercert = SSL_get_peer_certificate(ssl);
+ if (!peercert) {
+ out("ZTLS unable to verify server ");
+ tls_quit(partner_fqdn, "no certificate provided");
+ }
+
+ /* RFC 2595 section 2.4: find a matching name
+ * first find a match among alternative names */
+ gens = X509_get_ext_d2i(peercert, NID_subject_alt_name, 0, 0);
+ if (gens) {
+ for (i = 0, r = sk_GENERAL_NAME_num(gens); i < r; ++i)
+ {
+ const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i);
+ if (gn->type == GEN_DNS)
+ if (match_partner(gn->d.ia5->data, gn->d.ia5->length)) break;
+ }
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ }
+
+ /* no alternative name matched, look up commonName */
+ if (!gens || i >= r) {
+ stralloc peer = {0};
+ X509_NAME *subj = X509_get_subject_name(peercert);
+ i = X509_NAME_get_index_by_NID(subj, NID_commonName, -1);
+ if (i >= 0) {
+ const ASN1_STRING *s = X509_NAME_get_entry(subj, i)->value;
+ if (s) { peer.len = s->length; peer.s = s->data; }
+ }
+ if (peer.len <= 0) {
+ out("ZTLS unable to verify server ");
+ tls_quit(partner_fqdn, "certificate contains no valid commonName");
+ }
+ if (!match_partner(peer.s, peer.len)) {
+ out("ZTLS unable to verify server "); out(partner_fqdn);
+ out(": received certificate for "); outsafe(&peer); TLS_QUIT;
+ }
+ }
+
+ X509_free(peercert);
+ }
+
+ if (smtps) if (smtpcode() != 220)
+ quit("ZTLS Connected to "," but greeting failed");
+
+ return 1;
+}
+#endif
+
stralloc recip = {0};
+void mail_without_auth()
+{
+ substdio_puts(&smtpto,"MAIL FROM:<");
+ substdio_put(&smtpto,sender.s,sender.len);
+ substdio_puts(&smtpto,">\r\n");
+ substdio_flush(&smtpto);
+}
+
void smtp()
{
unsigned long code;
int flagbother;
- int i;
+ int i, j;
+
+#ifndef PORT_SMTP
+ /* the qmtpc patch uses smtp_port and undefines PORT_SMTP */
+# define port smtp_port
+#endif
+
+#ifdef TLS
+# ifdef MXPS
+ if (type == 'S') smtps = 1;
+ else if (type != 's')
+# endif
+ if (port == 465) smtps = 1;
+ if (!smtps)
+#endif
if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
+#ifdef EHLO
+# ifdef TLS
+ if (!smtps)
+# endif
+ code = ehlo();
+
+# ifdef TLS
+ if (tls_init())
+ /* RFC2487 says we should issue EHLO (even if we might not need
+ * extensions); at the same time, it does not prohibit a server
+ * to reject the EHLO and make us fallback to HELO */
+ code = ehlo();
+# endif
+
+ if (code == 250) {
+ /* add EHLO response checks here */
+
+ /* and if EHLO failed, use HELO */
+ } else {
+#endif
+
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");
- substdio_puts(&smtpto,"MAIL FROM:<");
- substdio_put(&smtpto,sender.s,sender.len);
- substdio_puts(&smtpto,">\r\n");
- substdio_flush(&smtpto);
+#ifdef EHLO
+ }
+#endif
+ i = 0;
+ if (auth_smtp_user.len && auth_smtp_pass.len) {
+ while((i += str_chr(smtptext.s+i,'\n') + 1) &&
+ (i+8 < smtptext.len) &&
+ str_diffn(smtptext.s+i+4,"AUTH",4));
+ if (((i+9 < smtptext.len) &&
+ (str_diffn(smtptext.s+i+9," ",1) ||
+ str_diffn(smtptext.s+i+9,"=",1))) &&
+ ( i += str_chr(smtptext.s+i,'L') + 1 ) &&
+ str_diffn(smtptext.s+i+1,"OGIN",4)) {
+
+ if (b64encode(&auth_smtp_user,&auth_b64_user)) quit("ZConnected to "," but unable to base64encode user");
+ if (b64encode(&auth_smtp_pass,&auth_b64_pass)) quit("ZConnected to "," but unable to base64encode pass");
+
+ substdio_puts(&smtpto,"AUTH LOGIN\r\n");
+ substdio_flush(&smtpto);
+ if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (AUTH LOGIN)");
+ substdio_put(&smtpto,auth_b64_user.s,auth_b64_user.len);
+ substdio_puts(&smtpto,"\r\n");
+ substdio_flush(&smtpto);
+ if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (username)");
+ substdio_put(&smtpto,auth_b64_pass.s,auth_b64_pass.len);
+ substdio_puts(&smtpto,"\r\n");
+ substdio_flush(&smtpto);
+ if (smtpcode() != 235) quit("ZConnected to "," but authentication was rejected (password)");
+ substdio_puts(&smtpto,"MAIL FROM:<");
+ substdio_put(&smtpto,sender.s,sender.len);
+ substdio_puts(&smtpto,"> AUTH=<");
+ substdio_put(&smtpto,sender.s,sender.len);
+ substdio_puts(&smtpto,">\r\n");
+ substdio_flush(&smtpto);
+ if(!stralloc_copys(&auth_status, "Delivered with authenticated connection to \n")) temp_nomem();
+ if(!stralloc_0(&auth_status)) temp_nomem();
+ } else {
+ no_supported_auth();
+ mail_without_auth();
+ }
+ } else {
+ auth_user_not_set();
+ mail_without_auth();
+ }
code = smtpcode();
if (code >= 500) quit("DConnected to "," but sender was rejected");
if (code >= 400) quit("ZConnected to "," but sender was rejected");
@@ -246,15 +649,22 @@
substdio_flush(&smtpto);
code = smtpcode();
if (code >= 500) {
- out("h"); outhost(); out(" does not like recipient.\n");
+ out("h"); out(auth_status.s); outhost();
+ out(" does not like recipient.\n");
outsmtptext(); zero();
}
else if (code >= 400) {
- out("s"); outhost(); out(" does not like recipient.\n");
+ out("s"); out(auth_status.s); outhost();
+ out(" does not like recipient.\n");
outsmtptext(); zero();
}
else {
- out("r"); zero();
+ /*
+ * James Raftery <james@now.ie>
+ * Log _real_ envelope recipient, post canonicalisation.
+ */
+ out("r"); out(auth_status.s);
+ out("<"); outsafe(&reciplist.sa[i]); out("> "); zero();
flagbother = 1;
}
}
@@ -331,7 +741,7 @@
char **argv;
{
static ipalloc ip = {0};
- int i;
+ int i,j;
unsigned long random;
char **recips;
unsigned long prefme;
@@ -347,6 +757,9 @@
if (!stralloc_copys(&host,argv[1])) temp_nomem();
+ if (!stralloc_copys(&auth_smtp_user,"")) temp_nomem();
+ if (!stralloc_copys(&auth_smtp_pass,"")) temp_nomem();
+
relayhost = 0;
for (i = 0;i <= host.len;++i)
if ((i == 0) || (i == host.len) || (host.s[i] == '.'))
@@ -355,6 +768,16 @@
if (relayhost && !*relayhost) relayhost = 0;
if (relayhost) {
+ i = str_chr(relayhost,' ');
+ if (relayhost[i]) {
+ j = str_chr(relayhost + i + 1,' ');
+ if (relayhost[j]) {
+ relayhost[i] = 0;
+ relayhost[i + j + 1] = 0;
+ if (!stralloc_copys(&auth_smtp_user,relayhost + i + 1)) temp_nomem();
+ if (!stralloc_copys(&auth_smtp_pass,relayhost + i + j + 2)) temp_nomem();
+ }
+ }
i = str_chr(relayhost,':');
if (relayhost[i]) {
scan_ulong(relayhost + i + 1,&port);
@@ -417,6 +840,9 @@
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
+ partner_fqdn = ip.ix[i].fqdn;
+#endif
smtp(); /* does not return */
}
tcpto_err(&ip.ix[i].ip,errno == error_timeout);
diff -Naur ./qmail-send.c ../qmail-1.03-build-10/qmail-send.c
--- ./qmail-send.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail-send.c 2006-05-05 19:42:35.000000000 -0500
@@ -262,6 +262,8 @@
while (!stralloc_copys(&comm_buf[c],"")) nomem();
ch = delnum;
while (!stralloc_append(&comm_buf[c],&ch)) nomem();
+ ch = delnum >> 8;
+ while (!stralloc_append(&comm_buf[c],&ch)) nomem();
fnmake_split(id);
while (!stralloc_cats(&comm_buf[c],fn.s)) nomem();
while (!stralloc_0(&comm_buf[c])) nomem();
@@ -906,41 +908,42 @@
dline[c].len = REPORTMAX;
/* qmail-lspawn and qmail-rspawn are responsible for keeping it short */
/* but from a security point of view, we don't trust rspawn */
- if (!ch && (dline[c].len > 1))
+ if (!ch && (dline[c].len > 2))
{
delnum = (unsigned int) (unsigned char) dline[c].s[0];
+ delnum += (unsigned int) ((unsigned int) dline[c].s[1]) << 8;
if ((delnum < 0) || (delnum >= concurrency[c]) || !d[c][delnum].used)
log1("warning: internal error: delivery report out of range\n");
else
{
strnum3[fmt_ulong(strnum3,d[c][delnum].delid)] = 0;
- if (dline[c].s[1] == 'Z')
+ if (dline[c].s[2] == 'Z')
if (jo[d[c][delnum].j].flagdying)
{
- dline[c].s[1] = 'D';
+ dline[c].s[2] = 'D';
--dline[c].len;
while (!stralloc_cats(&dline[c],"I'm not going to try again; this message has been in the queue too long.\n")) nomem();
while (!stralloc_0(&dline[c])) nomem();
}
- switch(dline[c].s[1])
+ switch(dline[c].s[2])
{
case 'K':
log3("delivery ",strnum3,": success: ");
- logsafe(dline[c].s + 2);
+ logsafe(dline[c].s + 3);
log1("\n");
markdone(c,jo[d[c][delnum].j].id,d[c][delnum].mpos);
--jo[d[c][delnum].j].numtodo;
break;
case 'Z':
log3("delivery ",strnum3,": deferral: ");
- logsafe(dline[c].s + 2);
+ logsafe(dline[c].s + 3);
log1("\n");
break;
case 'D':
log3("delivery ",strnum3,": failure: ");
- logsafe(dline[c].s + 2);
+ logsafe(dline[c].s + 3);
log1("\n");
- addbounce(jo[d[c][delnum].j].id,d[c][delnum].recip.s,dline[c].s + 2);
+ addbounce(jo[d[c][delnum].j].id,d[c][delnum].recip.s,dline[c].s + 3);
markdone(c,jo[d[c][delnum].j].id,d[c][delnum].mpos);
--jo[d[c][delnum].j].numtodo;
break;
@@ -1544,7 +1547,7 @@
numjobs = 0;
for (c = 0;c < CHANNELS;++c)
{
- char ch;
+ char ch, ch1;
int u;
int r;
do
@@ -1552,7 +1555,13 @@
while ((r == -1) && (errno == error_intr));
if (r < 1)
{ log1("alert: cannot start: hath the daemon spawn no fire?\n"); _exit(111); }
+ do
+ r = read(chanfdin[c],&ch1,1);
+ while ((r == -1) && (errno == error_intr));
+ if (r < 1)
+ { log1("alert: cannot start: hath the daemon spawn no fire?\n"); _exit(111); }
u = (unsigned int) (unsigned char) ch;
+ u += (unsigned int) ((unsigned char) ch1) << 8;
if (concurrency[c] > u) concurrency[c] = u;
numjobs += concurrency[c];
}
diff -Naur ./qmail-showctl.c ../qmail-1.03-build-10/qmail-showctl.c
--- ./qmail-showctl.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail-showctl.c 2006-05-07 11:43:00.000000000 -0500
@@ -15,6 +15,7 @@
#include "auto_patrn.h"
#include "auto_spawn.h"
#include "auto_split.h"
+#include "spf.h"
stralloc me = {0};
int meok;
@@ -140,7 +141,7 @@
{
DIR *dir;
direntry *d;
- struct stat stmrh;
+ struct stat stmrh; /* multiple use */
struct stat stmrhcdb;
substdio_puts(subfdout,"qmail home directory: ");
@@ -214,7 +215,46 @@
_exit(111);
}
- do_lst("badmailfrom","Any MAIL FROM is allowed.",""," not accepted in MAIL FROM.");
+ do_lst("badhelo","Any HELO host name is allowed.",""," HELO host name denied if it matches this pattern.");
+ do_lst("badmailfrom","Any MAIL FROM is allowed.",""," MAIL FROM denied if it matches this pattern.");
+ do_lst("badmailfromnorelay","Any MAIL FROM is allowed.",""," MAIL FROM denied if it matches this pattern and RELAYCLIENT is not set.");
+ do_lst("badmailto","No RCPT TO are specifically denied.",""," RCPT TO denied if it matches this pattern.");
+ do_lst("badmailtonorelay","No RCPT TO are specifically denied.",""," RCPT TO denied if it matches this pattern and RELAYCLIENT is not set.");
+
+ do_lst("badloadertypes","Any LOADER types are accepted.",""," not accepted as LOADER type.");
+ /* XXX: check badloadertypes.cdb contents */
+ substdio_puts(subfdout,"\nbadloadertypes.cdb: ");
+ if (stat("badloadertypes",&stmrh) == -1)
+ if (stat("badloadertypes.cdb",&stmrhcdb) == -1)
+ substdio_puts(subfdout,"(Default.) No effect.\n");
+ else
+ substdio_puts(subfdout,"Oops! badloadertypes.cdb exists but badloadertypes doesn't.\n");
+ else
+ if (stat("badloadertypes.cdb",&stmrhcdb) == -1)
+ substdio_puts(subfdout,"Oops! badloadertypes exists but badloadertypes.cdb doesn't.\n");
+ else
+ if (stmrh.st_mtime > stmrhcdb.st_mtime)
+ substdio_puts(subfdout,"Oops! badloadertypes.cdb is older than badloadertypes.\n");
+ else
+ substdio_puts(subfdout,"Modified recently enough; hopefully up to date.\n");
+
+ do_lst("badmimetypes","Any MIME types are accepted.",""," not accepted as MIME type.");
+ /* XXX: check badmimetypes.cdb contents */
+ substdio_puts(subfdout,"\nbadmimetypes.cdb: ");
+ if (stat("badmimetypes",&stmrh) == -1)
+ if (stat("badmimetypes.cdb",&stmrhcdb) == -1)
+ substdio_puts(subfdout,"(Default.) No effect.\n");
+ else
+ substdio_puts(subfdout,"Oops! badmimetypes.cdb exists but badmimetypes doesn't.\n");
+ else
+ if (stat("badmimetypes.cdb",&stmrhcdb) == -1)
+ substdio_puts(subfdout,"Oops! badmimetypes exists but badmimetypes.cdb doesn't.\n");
+ else
+ if (stmrh.st_mtime > stmrhcdb.st_mtime)
+ substdio_puts(subfdout,"Oops! badmimetypes.cdb is older than badmimetypes.\n");
+ else
+ substdio_puts(subfdout,"Modified recently enough; hopefully up to date.\n");
+
do_str("bouncefrom",0,"MAILER-DAEMON","Bounce user name is ");
do_str("bouncehost",1,"bouncehost","Bounce host name is ");
do_int("concurrencylocal","10","Local concurrency is ","");
@@ -257,6 +297,10 @@
do_str("smtpgreeting",1,"smtpgreeting","SMTP greeting: 220 ");
do_lst("smtproutes","No artificial SMTP routes.","SMTP route: ","");
+ do_int("spfbehavior","0","The SPF behavior is ","");
+ do_str("spfexp",0,SPF_DEFEXP,"The SPF default explanation is: 550 ");
+ do_str("spfguess",0,"","The guess SPF rules are: ");
+ do_str("spfrules",0,"","The local SPF rules are: ");
do_int("timeoutconnect","60","SMTP client connection timeout is "," seconds");
do_int("timeoutremote","1200","SMTP client data timeout is "," seconds");
do_int("timeoutsmtpd","1200","SMTP server data timeout is "," seconds");
@@ -267,7 +311,15 @@
if (str_equal(d->d_name,"..")) continue;
if (str_equal(d->d_name,"bouncefrom")) continue;
if (str_equal(d->d_name,"bouncehost")) continue;
+ if (str_equal(d->d_name,"badhelo")) continue;
+ if (str_equal(d->d_name,"badloadertypes")) continue;
+ if (str_equal(d->d_name,"badloadertypes.cdb")) continue;
+ if (str_equal(d->d_name,"badmimetypes")) continue;
+ if (str_equal(d->d_name,"badmimetypes.cdb")) continue;
if (str_equal(d->d_name,"badmailfrom")) continue;
+ if (str_equal(d->d_name,"badmailfromnorelay")) continue;
+ if (str_equal(d->d_name,"badmailto")) continue;
+ if (str_equal(d->d_name,"badmailtonorelay")) continue;
if (str_equal(d->d_name,"bouncefrom")) continue;
if (str_equal(d->d_name,"bouncehost")) continue;
if (str_equal(d->d_name,"concurrencylocal")) continue;
@@ -292,6 +344,10 @@
if (str_equal(d->d_name,"rcpthosts")) continue;
if (str_equal(d->d_name,"smtpgreeting")) continue;
if (str_equal(d->d_name,"smtproutes")) continue;
+ if (str_equal(d->d_name,"spfbehavior")) continue;
+ if (str_equal(d->d_name,"spfexp")) continue;
+ if (str_equal(d->d_name,"spfguess")) continue;
+ if (str_equal(d->d_name,"spfrules")) continue;
if (str_equal(d->d_name,"timeoutconnect")) continue;
if (str_equal(d->d_name,"timeoutremote")) continue;
if (str_equal(d->d_name,"timeoutsmtpd")) continue;
diff -Naur ./qmail-smtpd.8 ../qmail-1.03-build-10/qmail-smtpd.8
--- ./qmail-smtpd.8 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail-smtpd.8 2006-05-07 11:43:58.000000000 -0500
@@ -14,6 +14,15 @@
see
.BR tcp-environ(5) .
+If the environment variable
+.B SMTPS
+is non-empty,
+.B qmail-smtpd
+starts a TLS session (to support the deprecated SMTPS protocol,
+normally on port 465). Otherwise,
+.B qmail-smtpd
+offers the STARTTLS extension to ESMTP.
+
.B qmail-smtpd
is responsible for counting hops.
It rejects any message with 100 or more
@@ -23,7 +32,30 @@
header fields.
.B qmail-smtpd
-supports ESMTP, including the 8BITMIME and PIPELINING options.
+supports ESMTP, including the 8BITMIME, DATA, PIPELINING, SIZE, and AUTH options.
+.B qmail-smtpd
+includes a \'MAIL FROM:\' parameter parser and obeys \'Auth\' and \'Size\' advertisements.
+.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 CRAM-MD5 digest/response derived from the SMTP client,
+another 0 byte, a CRAM-MD5 challenge (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
@@ -37,11 +69,48 @@
even though such messages violate the SMTP protocol.
.SH "CONTROL FILES"
.TP 5
+.I badhelo
+Unacceptable HELO/EHLO host names.
+.B qmail-smtpd
+will reject every recipient address for a message if
+the host name is listed in,
+or matches a POSIX regular expression pattern listed in,
+.IR badhelo .
+If the
+.B NOBADHELO
+environment variable is set, then the contents of
+.IR badhelo
+will be ignored.
+For more information, please have a look at doc/README.qregex.
+.TP 5
+.I badloadertypes.cdb
+Unacceptable base64 encoded LOADER types in message.
+.B qmail-smtpd
+will reject every message if 5 significant
+characters (eg.
+.BR Mi5kb )
+in any of it's embedded base64 attachments is identical with one
+compiled into
+.IR badloadertypes.cdb .
+Use
+.B qmail-badloadertypes
+to derive
+.I badloadertypes.cdb
+from
+.IR badloadertypes .
+The control file
+.I badloadertypes.cdb
+is evaluated if the environment variable
+.I $BADLOADERTYPE='M'
+is set and the provided character matches the first character in
+.IR badloadertypes.cdb .
+.TP 5
.I badmailfrom
Unacceptable envelope sender addresses.
.B qmail-smtpd
will reject every recipient address for a message
-if the envelope sender address is listed in
+if the envelope sender address is listed in, or matches a POSIX regular expression
+pattern listed in,
.IR badmailfrom .
A line in
.I badmailfrom
@@ -49,6 +118,66 @@
.BR @\fIhost ,
meaning every address at
.IR host .
+For more information, please have a look at doc/README.qregex.
+.TP 5
+.I badmimetypes.cdb
+Unacceptable base64 encoded MIME types in message.
+.B qmail-smtpd
+will reject every message if the first 9 significant
+characters (eg.
+.BR TVqQAAMAA )
+of any of it's embedded base64 attachments types is identical with one
+compiled into
+.IR badmimetypes.cdb .
+Use
+.B qmail-badmimetypes
+to derive
+.I badmimetypes.cdb
+from
+.IR badmimetypes .
+The control file
+.I badmimetypes.cdb
+is evaluated if the environment variable
+.I $BADMIMETYPE
+is set.
+.TP 5
+.I badmailfromnorelay
+Functions the same as the
+.IR badmailfrom
+control file but is read only if the
+.B RELAYCLIENT
+environment variable is not set.
+For more information, please have a look at doc/README.qregex.
+.TP 5
+.I badmailto
+Unacceptable envelope recipient addresses.
+.B qmail-smtpd
+will reject every recipient address for a message if the recipient address
+is listed in,
+or matches a POSIX regular expression pattern listed in,
+.IR badmailto .
+For more information, please have a look at doc/README.qregex.
+.TP 5
+.I badmailtonorelay
+Functions the same as the
+.IR badmailto
+control file but is read only if the
+.B RELAYCLIENT
+environment variable is not set.
+For more information, please have a look at doc/README.qregex.
+
+.TP 5
+.I clientca.pem
+A list of Certifying Authority (CA) certificates that are used to verify
+the client-presented certificates during a TLS-encrypted session.
+
+.TP 5
+.I clientcrl.pem
+A list of Certificate Revocation Lists (CRLs). If present it
+should contain the CRLs of the CAs in
+.I clientca.pem
+and client certs will be checked for revocation.
+
.TP 5
.I databytes
Maximum number of bytes allowed in a message,
@@ -76,6 +205,18 @@
.B DATABYTES
is set, it overrides
.IR databytes .
+
+.TP 5
+.I dh1024.pem
+If these 1024 bit DH parameters are provided,
+.B qmail-smtpd
+will use them for TLS sessions instead of generating one on-the-fly
+(which is very timeconsuming).
+.TP 5
+.I dh512.pem
+512 bit counterpart for
+.B dh1024.pem.
+
.TP 5
.I localiphost
Replacement host name for local IP addresses.
@@ -151,6 +292,19 @@
Envelope recipient addresses without @ signs are
always allowed through.
+
+.TP 5
+.I rsa512.pem
+If this 512 bit RSA key is provided,
+.B qmail-smtpd
+will use it for TLS sessions instead of generating one on-the-fly.
+
+.TP 5
+.I servercert.pem
+SSL certificate to be presented to clients in TLS-encrypted sessions.
+Should contain both the certificate and the private key. Certifying Authority
+(CA) and intermediate certificates can be added at the end of the file.
+
.TP 5
.I smtpgreeting
SMTP greeting message.
@@ -169,6 +323,58 @@
.B qmail-smtpd
will wait for each new buffer of data from the remote SMTP client.
Default: 1200.
+
+.TP 5
+.I tlsclients
+A list of email addresses. When relay rules would reject an incoming message,
+.B qmail-smtpd
+can allow it if the client presents a certificate that can be verified against
+the CA list in
+.I clientca.pem
+and the certificate email address is in
+.IR tlsclients .
+
+.TP 5
+.I tlsserverciphers
+A set of OpenSSL cipher strings. Multiple ciphers contained in a
+string should be separated by a colon. If the environment variable
+.B TLSCIPHERS
+is set to such a string, it takes precedence.
+.TP 5
+.I spfbehavior
+Set to a value between 1 and 6 to enable SPF checks; 0 to disable.
+1 selects 'annotate-only' mode, where
+.B qmail-smtpd
+will annotate incoming email with
+.B Received-SPF
+fields, but will not reject any messages. 2 will produce temporary
+failures on DNS lookup problems so you can make sure you always have
+meaningful Received-SPF headers. 3 selects 'reject' mode,
+where incoming mail will be rejected if the SPF record says 'fail'. 4
+selects a more stricter rejection mode, which is like 'reject' mode,
+except that incoming mail will also be rejected when the SPF record
+says 'softfail'. 5 will also reject when the SPF record says 'neutral',
+and 6 if no SPF records are available at all (or a syntax error was
+encountered). The contents of this file are overridden by the value of
+the
+.B SPFBEHAVIOR
+environment variable, if set.
+Default: 0.
+.TP 5
+.I spfexp
+You can add a line with a an SPF explanation that will be shown to the
+sender in case of a reject. It will override the default one. You can
+use SPF macro expansion.
+.TP 5
+.I spfguess
+You can add a line with SPF rules that will be checked if a sender
+domain doesn't have a SPF record. The local rules will also be used
+in this case.
+.TP 5
+.I spfrules
+You can add a line with SPF rules that will be checked before other SPF
+rules would fail. This can be used to always allow certain machines to
+send certain mails.
.SH "SEE ALSO"
tcp-env(1),
tcp-environ(5),
diff -Naur ./qmail-smtpd.c ../qmail-1.03-build-10/qmail-smtpd.c
--- ./qmail-smtpd.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/qmail-smtpd.c 2006-05-07 12:50:24.000000000 -0500
@@ -1,3 +1,13 @@
+/*
+ *
+ * includes chkuser v.2.0.8
+ * for qmail/netqmail > 1.0.3 and vpopmail > 5.3.x
+ *
+ * Author: Antonio Nati tonix@interazioni.it
+ * www.interazioni.it/opensource
+ *
+ */
+
#include "sig.h"
#include "readwrite.h"
#include "stralloc.h"
@@ -23,14 +33,61 @@
#include "timeoutread.h"
#include "timeoutwrite.h"
#include "commands.h"
+#include "spf.h"
+#include "qregex.h"
+#include "strerr.h"
+#include "cdb.h"
+
+/* start chkuser code */
+#include "chkuser.h"
+/* end chkuser code */
+
+#define BMCHECK_BMF 0
+#define BMCHECK_BMFNR 1
+#define BMCHECK_BMT 2
+#define BMCHECK_BMTNR 3
+#define BMCHECK_BHELO 4
+
+#include "wait.h"
+
+#define CRAM_MD5
+#define AUTHSLEEP 5
#define MAXHOPS 100
unsigned int databytes = 0;
int timeout = 1200;
+unsigned int spfbehavior = 0;
+
+const char *protocol = "SMTP";
+
+#ifdef TLS
+#include <sys/stat.h>
+#include "tls.h"
+#include "ssl_timeoutio.h"
+
+void tls_init();
+int tls_verify();
+void tls_nogateway();
+int ssl_rfd = -1, ssl_wfd = -1; /* SSL_get_Xfd() are broken */
+#endif
+
+#define MIMETYPE_LEN 9
+#define LOADER_LEN 5
+
+static int fdbmt;
+int flagmimetype = 0;
+static int fdblt;
+int flagloadertype = 0;
+char *badloaderinit;
int safewrite(fd,buf,len) int fd; char *buf; int len;
{
int r;
+#ifdef TLS
+ if (ssl && fd == ssl_wfd)
+ r = ssl_timeoutwrite(timeout, ssl_rfd, ssl_wfd, ssl, buf, len);
+ else
+#endif
r = timeoutwrite(timeout,fd,buf,len);
if (r <= 0) _exit(1);
return r;
@@ -49,29 +106,54 @@
void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); }
void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); }
-void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
+void err_size() { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); }
+void err_bmf() { out("553 sorry, your envelope sender has been denied (#5.7.1)\r\n"); }
+void err_bmt() { out("553 sorry, your envelope recipient has been denied (#5.7.1)\r\n"); }
+void err_bhelo() { out("553 sorry, your HELO host name has been denied (#5.7.1)\r\n"); }
+#ifndef TLS
void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
-void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); }
+#else
+void err_nogateway()
+{
+ out("553 sorry, that domain isn't in my list of allowed rcpthosts");
+ tls_nogateway();
+ out(" (#5.7.1)\r\n");
+}
+#endif
+void err_unimpl(arg) char *arg; { 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"); }
void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); }
-void err_noop() { out("250 ok\r\n"); }
-void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); }
+void err_noop(arg) char *arg; { out("250 ok\r\n"); }
+void err_vrfy(arg) char *arg; { 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 canceled (#5.0.0)\r\n"); return -1; }
+int err_input() { out("501 malformed auth input (#5.5.4)\r\n"); return -1; }
+void err_authfail() { out("535 authentication failed (#5.7.1)\r\n"); }
stralloc greeting = {0};
+stralloc spflocal = {0};
+stralloc spfguess = {0};
+stralloc spfexp = {0};
void smtp_greet(code) char *code;
{
substdio_puts(&ssout,code);
substdio_put(&ssout,greeting.s,greeting.len);
}
-void smtp_help()
+void smtp_help(arg) char *arg;
{
- out("214 qmail home page: http://pobox.com/~djb/qmail.html\r\n");
+ out("214 netqmail home page: http://qmail.org/netqmail\r\n");
}
-void smtp_quit()
+void smtp_quit(arg) char *arg;
{
smtp_greet("221 "); out("\r\n"); flush(); _exit(0);
}
@@ -81,6 +163,7 @@
char *remoteinfo;
char *local;
char *relayclient;
+char *reply554;
stralloc helohost = {0};
char *fakehelo; /* pointer into helohost, or 0 */
@@ -93,9 +176,21 @@
int liphostok = 0;
stralloc liphost = {0};
+
int bmfok = 0;
stralloc bmf = {0};
-struct constmap mapbmf;
+
+int bmfnrok = 0;
+stralloc bmfnr = {0};
+
+int bmtok = 0;
+stralloc bmt = {0};
+
+int bmtnrok = 0;
+stralloc bmtnr = {0};
+
+int bhelook = 0;
+stralloc bhelo = {0};
void setup()
{
@@ -109,20 +204,43 @@
if (liphostok == -1) die_control();
if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control();
if (timeout <= 0) timeout = 1;
-
if (rcpthosts_init() == -1) die_control();
bmfok = control_readfile(&bmf,"control/badmailfrom",0);
if (bmfok == -1) die_control();
- if (bmfok)
- if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem();
+
+ bmfnrok = control_readfile(&bmfnr,"control/badmailfromnorelay",0);
+ if (bmfnrok == -1) die_control();
+
+ bmtok = control_readfile(&bmt,"control/badmailto",0);
+ if (bmtok == -1) die_control();
+
+ bmtnrok = control_readfile(&bmtnr,"control/badmailtonorelay",0);
+ if (bmtnrok == -1) die_control();
+
+ bhelook = control_readfile(&bhelo, "control/badhelo",0);
+ if (bhelook == -1) die_control();
+ if (env_get("NOBADHELO")) bhelook = 0;
if (control_readint(&databytes,"control/databytes") == -1) die_control();
x = env_get("DATABYTES");
if (x) { scan_ulong(x,&u); databytes = u; }
if (!(databytes + 1)) --databytes;
- remoteip = env_get("TCPREMOTEIP");
+ if (control_readint(&spfbehavior,"control/spfbehavior") == -1)
+ die_control();
+ x = env_get("SPFBEHAVIOR");
+ if (x) { scan_ulong(x,&u); spfbehavior = u; }
+
+ if (control_readline(&spflocal,"control/spfrules") == -1) die_control();
+ if (spflocal.len && !stralloc_0(&spflocal)) die_nomem();
+ if (control_readline(&spfguess,"control/spfguess") == -1) die_control();
+ if (spfguess.len && !stralloc_0(&spfguess)) die_nomem();
+ if (control_rldef(&spfexp,"control/spfexp",0,SPF_DEFEXP) == -1)
+ die_control();
+ if (!stralloc_0(&spfexp)) die_nomem();
+
+remoteip = env_get("TCPREMOTEIP");
if (!remoteip) remoteip = "unknown";
local = env_get("TCPLOCALHOST");
if (!local) local = env_get("TCPLOCALIP");
@@ -131,6 +249,28 @@
if (!remotehost) remotehost = "unknown";
remoteinfo = env_get("TCPREMOTEINFO");
relayclient = env_get("RELAYCLIENT");
+
+ if (env_get("BADMIMETYPE")) {
+ flagmimetype = 1;
+ fdbmt = open_read("control/badmimetypes.cdb");
+ if (fdbmt == -1 ) flagmimetype = 0;
+ }
+
+ badloaderinit = env_get("BADLOADERTYPE");
+ if (badloaderinit) {
+ if (str_len(badloaderinit) == 1) {
+ flagloadertype = 1;
+ fdblt = open_read("control/badloadertypes.cdb");
+ if (fdblt == -1 ) flagloadertype = 0;
+ }
+ }
+
+ reply554 = env_get("REPLY554");
+
+#ifdef TLS
+ if (env_get("SMTPS")) { smtps = 1; tls_init(); }
+ else
+#endif
dohelo(remotehost);
}
@@ -197,14 +337,48 @@
return 1;
}
-int bmfcheck()
+int bmcheck(which) int which;
{
- int j;
- if (!bmfok) return 0;
- if (constmap(&mapbmf,addr.s,addr.len - 1)) return 1;
- j = byte_rchr(addr.s,addr.len,'@');
- if (j < addr.len)
- if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) return 1;
+ int i = 0;
+ int j = 0;
+ int x = 0;
+ int negate = 0;
+ static stralloc bmb = {0};
+ static stralloc curregex = {0};
+
+ if (which == BMCHECK_BMF) {
+ if (!stralloc_copy(&bmb,&bmf)) die_nomem();
+ } else if (which == BMCHECK_BMFNR) {
+ if (!stralloc_copy(&bmb,&bmfnr)) die_nomem();
+ } else if (which == BMCHECK_BMT) {
+ if (!stralloc_copy(&bmb,&bmt)) die_nomem();
+ } else if (which == BMCHECK_BMTNR) {
+ if (!stralloc_copy(&bmb,&bmtnr)) die_nomem();
+ } else if (which == BMCHECK_BHELO) {
+ if (!stralloc_copy(&bmb,&bhelo)) die_nomem();
+ } else {
+ die_control();
+ }
+
+ while (j < bmb.len) {
+ i = j;
+ while ((bmb.s[i] != '\0') && (i < bmb.len)) i++;
+ if (bmb.s[j] == '!') {
+ negate = 1;
+ j++;
+ }
+ if (!stralloc_copyb(&curregex,bmb.s + j,(i - j))) die_nomem();
+ if (!stralloc_0(&curregex)) die_nomem();
+ if (which == BMCHECK_BHELO) {
+ x = matchregex(helohost.s, curregex.s);
+ } else {
+ x = matchregex(addr.s, curregex.s);
+ }
+ if ((negate) && (x == 0)) return 1;
+ if (!(negate) && (x > 0)) return 1;
+ j = i + 1;
+ negate = 0;
+ }
return 0;
}
@@ -213,62 +387,289 @@
int r;
r = rcpthosts(addr.s,str_len(addr.s));
if (r == -1) die_control();
+#ifdef TLS
+ if (r == 0) if (tls_verify()) r = -2;
+#endif
return r;
}
int seenmail = 0;
-int flagbarf; /* defined if seenmail */
+int flagbarfbmf; /* defined if seenmail */
+int flagbarfbmt;
+int flagbarfbhelo;
+int flagsize;
+int flagbarfspf;
+stralloc spfbarfmsg = {0};
stralloc mailfrom = {0};
stralloc rcptto = {0};
+stralloc fuser = {0};
+stralloc mfparms = {0};
+
+int mailfrom_size(arg) char *arg;
+{
+ long r;
+ unsigned long sizebytes = 0;
+
+ scan_ulong(arg,&r);
+ sizebytes = r;
+ if (databytes) if (sizebytes > databytes) return 1;
+ return 0;
+}
+
+void mailfrom_auth(arg,len)
+char *arg;
+int len;
+{
+ int j;
+
+ if (!stralloc_copys(&fuser,"")) die_nomem();
+ if (case_starts(arg,"<>")) { if (!stralloc_cats(&fuser,"unknown")) die_nomem(); }
+ else
+ while (len) {
+ if (*arg == '+') {
+ if (case_starts(arg,"+3D")) { arg=arg+2; len=len-2; if (!stralloc_cats(&fuser,"=")) die_nomem(); }
+ if (case_starts(arg,"+2B")) { arg=arg+2; len=len-2; if (!stralloc_cats(&fuser,"+")) die_nomem(); }
+ }
+ else
+ if (!stralloc_catb(&fuser,arg,1)) die_nomem();
+ arg++; len--;
+ }
+ if(!stralloc_0(&fuser)) die_nomem();
+ if (!remoteinfo) {
+ remoteinfo = fuser.s;
+ if (!env_unset("TCPREMOTEINFO")) die_read();
+ if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
+ }
+}
+
+void mailfrom_parms(arg) char *arg;
+{
+ int i;
+ int len;
+
+ len = str_len(arg);
+ if (!stralloc_copys(&mfparms,"")) die_nomem;
+ i = byte_chr(arg,len,'>');
+ if (i > 4 && i < len) {
+ while (len) {
+ arg++; len--;
+ if (*arg == ' ' || *arg == '\0' ) {
+ if (case_starts(mfparms.s,"SIZE=")) if (mailfrom_size(mfparms.s+5)) { flagsize = 1; return; }
+ if (case_starts(mfparms.s,"AUTH=")) mailfrom_auth(mfparms.s+5,mfparms.len-5);
+ if (!stralloc_copys(&mfparms,"")) die_nomem;
+ }
+ else
+ if (!stralloc_catb(&mfparms,arg,1)) die_nomem;
+ }
+ }
+}
void smtp_helo(arg) char *arg;
{
smtp_greet("250 "); out("\r\n");
seenmail = 0; dohelo(arg);
+ if (bhelook) flagbarfbhelo = bmcheck(BMCHECK_BHELO);
}
+/* ESMTP extensions are published here */
void smtp_ehlo(arg) char *arg;
{
- smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
+#ifdef TLS
+ struct stat st;
+#endif
+ char size[FMT_ULONG];
+ size[fmt_ulong(size,(unsigned int) databytes)] = 0;
+ smtp_greet("250-");
+#ifdef TLS
+ if (!ssl && (stat("control/servercert.pem",&st) == 0))
+ out("\r\n250-STARTTLS");
+#endif
+ out("\r\n250-PIPELINING\r\n250-8BITMIME\r\n");
+ out("250-SIZE "); out(size); out("\r\n");
+#ifdef CRAM_MD5
+ out("250 AUTH LOGIN PLAIN CRAM-MD5\r\n");
+#else
+ out("250 AUTH LOGIN PLAIN\r\n");
+#endif
seenmail = 0; dohelo(arg);
+ if (bhelook) flagbarfbhelo = bmcheck(BMCHECK_BHELO);
}
-void smtp_rset()
+void smtp_rset(arg) char *arg;
{
seenmail = 0;
out("250 flushed\r\n");
}
void smtp_mail(arg) char *arg;
{
+ int r;
+
if (!addrparse(arg)) { err_syntax(); return; }
- flagbarf = bmfcheck();
+/* start chkuser code */
+ if (chkuser_sender (&addr) != CHKUSER_OK) { return; }
+/* end chkuser code */
+
+ flagsize = 0;
+ flagbarfspf = 0;
+ mailfrom_parms(arg);
+ if (flagsize) { err_size(); return; }
+ flagbarfbmf = 0; /* bmcheck is skipped for empty envelope senders */
+ if ((bmfok) && (addr.len != 1)) flagbarfbmf = bmcheck(BMCHECK_BMF);
+ if ((!flagbarfbmf) && (bmfnrok) && (addr.len != 1) && (!relayclient)) {
+ flagbarfbmf = bmcheck(BMCHECK_BMFNR);
+ }
+/* start spf code */
+ if (spfbehavior && !relayclient)
+ {
+ switch(r = spfcheck()) {
+ case SPF_OK: env_put2("SPFRESULT","pass"); break;
+ case SPF_NONE: env_put2("SPFRESULT","none"); break;
+ case SPF_UNKNOWN: env_put2("SPFRESULT","unknown"); break;
+ case SPF_NEUTRAL: env_put2("SPFRESULT","neutral"); break;
+ case SPF_SOFTFAIL: env_put2("SPFRESULT","softfail"); break;
+ case SPF_FAIL: env_put2("SPFRESULT","fail"); break;
+ case SPF_ERROR: env_put2("SPFRESULT","error"); break;
+ }
+ switch (r) {
+ case SPF_NOMEM:
+ die_nomem();
+ case SPF_ERROR:
+ if (spfbehavior < 2) break;
+ out("451 SPF lookup failure (#4.3.0)\r\n");
+ return;
+ case SPF_NONE:
+ case SPF_UNKNOWN:
+ if (spfbehavior < 6) break;
+ case SPF_NEUTRAL:
+ if (spfbehavior < 5) break;
+ case SPF_SOFTFAIL:
+ if (spfbehavior < 4) break;
+ case SPF_FAIL:
+ if (spfbehavior < 3) break;
+ if (!spfexplanation(&spfbarfmsg)) die_nomem();
+ if (!stralloc_0(&spfbarfmsg)) die_nomem();
+ flagbarfspf = 1;
+ }
+ }
+ else
+ env_unset("SPFRESULT");
+/* end spf code */
seenmail = 1;
if (!stralloc_copys(&rcptto,"")) die_nomem();
if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
if (!stralloc_0(&mailfrom)) die_nomem();
out("250 ok\r\n");
}
+
+void err_spf() {
+ int i,j;
+
+ for(i = 0; i < spfbarfmsg.len; i = j + 1) {
+ j = byte_chr(spfbarfmsg.s + i, spfbarfmsg.len - i, '\n') + i;
+ if (j < spfbarfmsg.len) {
+ out("550-");
+ spfbarfmsg.s[j] = 0;
+ out(spfbarfmsg.s);
+ spfbarfmsg.s[j] = '\n';
+ out("\r\n");
+ } else {
+ out("550 ");
+ out(spfbarfmsg.s);
+ out(" (#5.7.1)\r\n");
+ }
+ }
+}
+
void smtp_rcpt(arg) char *arg; {
if (!seenmail) { err_wantmail(); return; }
if (!addrparse(arg)) { err_syntax(); return; }
- if (flagbarf) { err_bmf(); return; }
- if (relayclient) {
+ if (flagbarfspf) { err_spf(); return; }
+ if (flagbarfbhelo) {
+ strerr_warn4("qmail-smtpd: badhelo: <",helohost.s,"> at ",remoteip,0);
+ err_bhelo();
+ return;
+ }
+ if (flagbarfbmf) {
+ strerr_warn4("qmail-smtpd: badmailfrom: <",mailfrom.s,"> at ",remoteip,0);
+ err_bmf();
+ return;
+ }
+ if (bmtok) flagbarfbmt = bmcheck(BMCHECK_BMT);
+ if ((!flagbarfbmt) && (bmtnrok) && (!relayclient)) {
+ flagbarfbmt = bmcheck(BMCHECK_BMTNR);
+ }
+ if (flagbarfbmt) {
+ strerr_warn4("qmail-smtpd: badmailto: <",addr.s,"> at ",remoteip,0);
+ err_bmt();
+ return;
+ }
+
+/*
+ * Original code substituted by chkuser code
+
+if (relayclient) {
--addr.len;
if (!stralloc_cats(&addr,relayclient)) die_nomem();
if (!stralloc_0(&addr)) die_nomem();
}
else
if (!addrallowed()) { err_nogateway(); return; }
+
+
+ * end of substituted code
+ */
+
+/* start chkuser code */
+ switch (chkuser_realrcpt (&mailfrom, &addr)) {
+
+ case CHKUSER_KO:
+ return;
+ break;
+
+ case CHKUSER_RELAYING:
+ --addr.len;
+ if (!stralloc_cats(&addr,relayclient)) die_nomem();
+ if (!stralloc_0(&addr)) die_nomem();
+ break;
+
+ }
+/* end chkuser code */
+
if (!stralloc_cats(&rcptto,"T")) die_nomem();
if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
if (!stralloc_0(&rcptto)) die_nomem();
out("250 ok\r\n");
}
+struct qmail qqt;
+unsigned int bytestooverflow = 0;
+
+void spfreceived()
+{
+ stralloc sa = {0};
+ stralloc rcvd_spf = {0};
+
+ if (!spfbehavior || relayclient) return;
+
+ if (!stralloc_copys(&rcvd_spf, "Received-SPF: ")) die_nomem();
+ if (!spfinfo(&sa)) die_nomem();
+ if (!stralloc_cat(&rcvd_spf, &sa)) die_nomem();
+ if (!stralloc_append(&rcvd_spf, "\n")) die_nomem();
+ if (bytestooverflow) {
+ bytestooverflow -= rcvd_spf.len;
+ if (bytestooverflow <= 0) qmail_fail(&qqt);
+ }
+ qmail_put(&qqt,rcvd_spf.s,rcvd_spf.len);
+}
int saferead(fd,buf,len) int fd; char *buf; int len;
{
int r;
flush();
+#ifdef TLS
+ if (ssl && fd == ssl_rfd)
+ r = ssl_timeoutread(timeout, ssl_rfd, ssl_wfd, ssl, buf, len);
+ else
+#endif
r = timeoutread(timeout,fd,buf,len);
if (r == -1) if (errno == error_timeout) die_alarm();
if (r <= 0) die_read();
@@ -278,12 +679,63 @@
char ssinbuf[1024];
substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
-struct qmail qqt;
-unsigned int bytestooverflow = 0;
+
+stralloc line = {0};
+stralloc base64types = {0};
+stralloc badmimetype = {0};
+stralloc badloadertype = {0};
+
+unsigned int nolines = 0;
+unsigned int flag64 = 0;
+unsigned int flagbase = 0;
+unsigned int flagblank = 0;
void put(ch)
char *ch;
{
+ uint32 dlen;
+ int i;
+
+ if (line.len < 1025)
+ if (!stralloc_catb(&line,ch,1)) die_nomem(); /* Reassamble chars to line; prepend with 'L' */
+
+ if (*ch == '\n') {
+ nolines++;
+
+ if (line.len == 2) { flagblank = nolines; flagbase = 0; } /* trigger */
+ if (*(line.s+1) == 'C' || *(line.s+1) == 'c')
+ if (case_startb(line.s+1,line.len-2,"content-transfer-encoding: base64")) flag64 = nolines; /* base64 attachments */
+ if (flag64 && nolines == flagblank+1 && line.len > MIMETYPE_LEN+2) {
+ flagbase = nolines;
+ if (!stralloc_catb(&base64types,line.s+1,MIMETYPE_LEN)) die_nomem();
+ if (!stralloc_0(&base64types)) die_nomem();
+ if (flagmimetype == 1) {
+ if (cdb_seek(fdbmt,line.s+1,MIMETYPE_LEN,&dlen)) {
+ if (!stralloc_copyb(&badmimetype,line.s+1,MIMETYPE_LEN)) die_nomem();
+ if (!stralloc_0(&badmimetype)) die_nomem();
+ qmail_fail(&qqt);
+ flagmimetype = -1;
+ }
+ }
+ }
+ if (flagloadertype == 1 && flagmimetype != -1) {
+ if (line.len > MIMETYPE_LEN + 2 && flagbase > flagblank) {
+ for ( i = 0; i < line.len - LOADER_LEN; ++i ) {
+ if (*(line.s+i) == *badloaderinit) {
+ if (cdb_seek(fdblt,line.s+i,LOADER_LEN,&dlen)) {
+ if (!stralloc_copyb(&badloadertype,line.s+i,LOADER_LEN)) die_nomem();
+ if (!stralloc_0(&badloadertype)) die_nomem();
+ qmail_fail(&qqt);
+ flagloadertype = -1;
+ }
+ }
+ }
+ }
+ }
+ line.len = 0;
+ stralloc_copys(&line,"L");
+ }
+
if (bytestooverflow)
if (!--bytestooverflow)
qmail_fail(&qqt);
@@ -316,8 +768,8 @@
if (flagmaybex) if (pos == 7) ++*hops;
if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0;
if (flagmaybey) if (pos == 1) flaginheader = 0;
+ ++pos;
}
- ++pos;
if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; }
}
switch(state) {
@@ -365,7 +817,7 @@
out("\r\n");
}
-void smtp_data() {
+void smtp_data(arg) char *arg; {
int hops;
unsigned long qp;
char *qqx;
@@ -374,11 +826,13 @@
if (!rcptto.len) { err_wantrcpt(); return; }
seenmail = 0;
if (databytes) bytestooverflow = databytes + 1;
+ if (base64types.len == 1 ) if (!env_unset("QHPSI")) die_nomem();
if (qmail_open(&qqt) == -1) { err_qqt(); return; }
qp = qmail_qp(&qqt);
out("354 go ahead\r\n");
- received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo);
+ received(&qqt,protocol,local,remoteip,remotehost,remoteinfo,fakehelo);
+ spfreceived();
blast(&hops);
hops = (hops >= MAXHOPS);
if (hops) qmail_fail(&qqt);
@@ -388,28 +842,506 @@
qqx = qmail_close(&qqt);
if (!*qqx) { acceptmessage(qp); return; }
if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; }
- if (databytes) if (!bytestooverflow) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return; }
+ if (databytes) if (!bytestooverflow) { err_size(); return; }
+ if (flagmimetype == -1) {
+ out("554 invalid message content ");
+ if (reply554) out(reply554);
+ out(" (#5.3.2)\r\n");
+ return;
+ }
+ if (flagloadertype == -1) {
+ out("554 invalid message content ");
+ if (reply554) out(reply554);
+ out(" (#5.3.2)\r\n");
+ return;
+ }
if (*qqx == 'D') out("554 "); else out("451 ");
out(qqx + 1);
out("\r\n");
}
+/* this file is too long ----------------------------------------- SMTP AUTH */
+
+char unique[FMT_ULONG + FMT_ULONG + 3];
+static stralloc authin = {0}; /* input from SMTP client */
+static stralloc user = {0}; /* authorization user-id */
+static stralloc pass = {0}; /* plain passwd or digest */
+static stralloc resp = {0}; /* b64 response */
+#ifdef CRAM_MD5
+static stralloc chal = {0}; /* plain challenge */
+static stralloc slop = {0}; /* b64 challenge */
+#endif
+
+int flagauth = 0;
+char **childargs;
+char ssauthbuf[512];
+substdio ssauth = SUBSTDIO_FDBUF(safewrite,3,ssauthbuf,sizeof(ssauthbuf));
+
+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();
+#ifdef CRAM_MD5
+ if (!stralloc_0(&chal)) die_nomem();
+#endif
+
+ if (pipe(pi) == -1) return err_pipe();
+ switch(child = fork()) {
+ case -1:
+ return err_fork();
+ case 0:
+ close(pi[1]);
+ if(fd_copy(3,pi[0]) == -1) return err_pipe();
+ sig_pipedefault();
+ execvp(*childargs, childargs);
+ _exit(1);
+ }
+ close(pi[0]);
+
+ substdio_fdbuf(&ssauth,write,pi[1],ssauthbuf,sizeof ssauthbuf);
+ if (substdio_put(&ssauth,user.s,user.len) == -1) return err_write();
+ if (substdio_put(&ssauth,pass.s,pass.len) == -1) return err_write();
+#ifdef CRAM_MD5
+ if (substdio_put(&ssauth,chal.s,chal.len) == -1) return err_write();
+#endif
+ if (substdio_flush(&ssauth) == -1) return err_write();
+
+ close(pi[1]);
+#ifdef CRAM_MD5
+ if (!stralloc_copys(&chal,"")) die_nomem();
+ if (!stralloc_copys(&slop,"")) die_nomem();
+#endif
+ byte_zero(ssauthbuf,sizeof ssauthbuf);
+ if (wait_pid(&wstat,child) == -1) return err_child();
+ if (wait_crashed(wstat)) return err_child();
+ if (wait_exitcode(wstat)) { sleep(AUTHSLEEP); 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),&resp) == 1) return err_input();
+ }
+ else {
+ out("334 \r\n"); flush();
+ if (authgetl() < 0) return -1;
+ if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input();
+ }
+ if (r == -1 || !stralloc_0(&resp)) die_nomem();
+ while (resp.s[id]) id++; /* "authorize-id\0userid\0passwd\0" */
+
+ if (resp.len > id + 1)
+ if (!stralloc_copys(&user,resp.s + id + 1)) die_nomem();
+ if (resp.len > id + user.len + 2)
+ if (!stralloc_copys(&pass,resp.s + id + user.len + 2)) die_nomem();
+
+ if (!user.len || !pass.len) return err_input();
+ return authenticate();
+}
+
+#ifdef CRAM_MD5
+int auth_cram()
+{
+ int i, r;
+ char *s;
+
+ s = unique; /* generate challenge */
+ s += fmt_uint(s,getpid());
+ *s++ = '.';
+ s += fmt_ulong(s,(unsigned long) now());
+ *s++ = '@';
+ *s++ = 0;
+ if (!stralloc_copys(&chal,"<")) die_nomem();
+ if (!stralloc_cats(&chal,unique)) die_nomem();
+ if (!stralloc_cats(&chal,local)) die_nomem();
+ if (!stralloc_cats(&chal,">")) die_nomem();
+ if (b64encode(&chal,&slop) < 0) die_nomem();
+ if (!stralloc_0(&slop)) die_nomem();
+
+ out("334 "); /* "334 base64_challenge \r\n" */
+ out(slop.s);
+ out("\r\n");
+ flush();
+
+ if (authgetl() < 0) return -1; /* got response */
+ if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input();
+ if (r == -1 || !stralloc_0(&resp)) die_nomem();
+
+ i = str_chr(resp.s,' ');
+ s = resp.s + i;
+ while (*s == ' ') ++s;
+ resp.s[i] = 0;
+ if (!stralloc_copys(&user,resp.s)) die_nomem(); /* userid */
+ if (!stralloc_copys(&pass,s)) die_nomem(); /* digest */
+
+ if (!user.len || !pass.len) return err_input();
+ return authenticate();
+}
+#endif
+
+struct authcmd {
+ char *text;
+ int (*fun)();
+} authcmds[] = {
+ { "login",auth_login }
+, { "plain",auth_plain }
+#ifdef CRAM_MD5
+, { "cram-md5",auth_cram }
+#endif
+, { 0,err_noauth }
+};
+
+void smtp_auth(arg)
+char *arg;
+{
+ int i;
+ char *cmd = arg;
+
+ if (!*childargs) { out("503 auth not available (#5.3.3)\r\n"); return; }
+ if (flagauth) { 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();
+#ifdef CRAM_MD5
+ if (!stralloc_copys(&chal,"")) die_nomem();
+#endif
+
+ 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:
+ flagauth = 1;
+ protocol = "ESMTPA";
+ relayclient = "";
+ remoteinfo = user.s;
+ if (!env_unset("TCPREMOTEINFO")) die_read();
+ if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
+ if (!env_put2("RELAYCLIENT",relayclient)) die_nomem();
+ out("235 ok, go ahead (#2.0.0)\r\n");
+ break;
+ case 1:
+ err_authfail(user.s,authcmds[i].text);
+ }
+}
+
+
+/* this file is too long --------------------------------------------- GO ON */
+
+#ifdef TLS
+stralloc proto = {0};
+int ssl_verified = 0;
+const char *ssl_verify_err = 0;
+
+void smtp_tls(char *arg)
+{
+ if (ssl) err_unimpl();
+ else if (*arg) out("501 Syntax error (no parameters allowed) (#5.5.4)\r\n");
+ else tls_init();
+}
+
+RSA *tmp_rsa_cb(SSL *ssl, int export, int keylen)
+{
+ if (!export) keylen = 512;
+ if (keylen == 512) {
+ FILE *in = fopen("control/rsa512.pem", "r");
+ if (in) {
+ RSA *rsa = PEM_read_RSAPrivateKey(in, NULL, NULL, NULL);
+ fclose(in);
+ if (rsa) return rsa;
+ }
+ }
+ return RSA_generate_key(keylen, RSA_F4, NULL, NULL);
+}
+
+DH *tmp_dh_cb(SSL *ssl, int export, int keylen)
+{
+ if (!export) keylen = 1024;
+ if (keylen == 512) {
+ FILE *in = fopen("control/dh512.pem", "r");
+ if (in) {
+ DH *dh = PEM_read_DHparams(in, NULL, NULL, NULL);
+ fclose(in);
+ if (dh) return dh;
+ }
+ }
+ if (keylen == 1024) {
+ FILE *in = fopen("control/dh1024.pem", "r");
+ if (in) {
+ DH *dh = PEM_read_DHparams(in, NULL, NULL, NULL);
+ fclose(in);
+ if (dh) return dh;
+ }
+ }
+ return DH_generate_parameters(keylen, DH_GENERATOR_2, NULL, NULL);
+}
+
+/* don't want to fail handshake if cert isn't verifiable */
+int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; }
+
+void tls_nogateway()
+{
+ /* there may be cases when relayclient is set */
+ if (!ssl || relayclient) return;
+ out("; no valid cert for gatewaying");
+ if (ssl_verify_err) { out(": "); out(ssl_verify_err); }
+}
+void tls_out(const char *s1, const char *s2)
+{
+ out("454 TLS "); out(s1);
+ if (s2) { out(": "); out(s2); }
+ out(" (#4.3.0)\r\n"); flush();
+}
+void tls_err(const char *s) { tls_out(s, ssl_error()); if (smtps) die_read(); }
+
+# define CLIENTCA "control/clientca.pem"
+# define CLIENTCRL "control/clientcrl.pem"
+# define SERVERCERT "control/servercert.pem"
+
+int tls_verify()
+{
+ stralloc clients = {0};
+ struct constmap mapclients;
+
+ if (!ssl || relayclient || ssl_verified) return 0;
+ ssl_verified = 1; /* don't do this twice */
+
+ /* request client cert to see if it can be verified by one of our CAs
+ * and the associated email address matches an entry in tlsclients */
+ switch (control_readfile(&clients, "control/tlsclients", 0))
+ {
+ case 1:
+ if (constmap_init(&mapclients, clients.s, clients.len, 0)) {
+ /* if CLIENTCA contains all the standard root certificates, a
+ * 0.9.6b client might fail with SSL_R_EXCESSIVE_MESSAGE_SIZE;
+ * it is probably due to 0.9.6b supporting only 8k key exchange
+ * data while the 0.9.6c release increases that limit to 100k */
+ STACK_OF(X509_NAME) *sk = SSL_load_client_CA_file(CLIENTCA);
+ if (sk) {
+ SSL_set_client_CA_list(ssl, sk);
+ SSL_set_verify(ssl, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL);
+ break;
+ }
+ constmap_free(&mapclients);
+ }
+ case 0: alloc_free(clients.s); return 0;
+ case -1: die_control();
+ }
+
+ if (ssl_timeoutrehandshake(timeout, ssl_rfd, ssl_wfd, ssl) <= 0) {
+ const char *err = ssl_error_str();
+ tls_out("rehandshake failed", err); die_read();
+ }
+
+ do { /* one iteration */
+ X509 *peercert;
+ X509_NAME *subj;
+ stralloc email = {0};
+
+ int n = SSL_get_verify_result(ssl);
+ if (n != X509_V_OK)
+ { ssl_verify_err = X509_verify_cert_error_string(n); break; }
+ peercert = SSL_get_peer_certificate(ssl);
+ if (!peercert) break;
+
+ subj = X509_get_subject_name(peercert);
+ n = X509_NAME_get_index_by_NID(subj, NID_pkcs9_emailAddress, -1);
+ if (n >= 0) {
+ const ASN1_STRING *s = X509_NAME_get_entry(subj, n)->value;
+ if (s) { email.len = s->length; email.s = s->data; }
+ }
+
+ if (email.len <= 0)
+ ssl_verify_err = "contains no email address";
+ else if (!constmap(&mapclients, email.s, email.len))
+ ssl_verify_err = "email address not in my list of tlsclients";
+ else {
+ /* add the cert email to the proto if it helped allow relaying */
+ --proto.len;
+ if (!stralloc_cats(&proto, "\n (cert ") /* continuation line */
+ || !stralloc_catb(&proto, email.s, email.len)
+ || !stralloc_cats(&proto, ")")
+ || !stralloc_0(&proto)) die_nomem();
+ relayclient = "";
+ protocol = proto.s;
+ }
+
+ X509_free(peercert);
+ } while (0);
+ constmap_free(&mapclients); alloc_free(clients.s);
+
+ /* we are not going to need this anymore: free the memory */
+ SSL_set_client_CA_list(ssl, NULL);
+ SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
+
+ return relayclient ? 1 : 0;
+}
+
+void tls_init()
+{
+ SSL *myssl;
+ SSL_CTX *ctx;
+ const char *ciphers;
+ stralloc saciphers = {0};
+ X509_STORE *store;
+ X509_LOOKUP *lookup;
+
+ SSL_library_init();
+
+ /* a new SSL context with the bare minimum of options */
+ ctx = SSL_CTX_new(SSLv23_server_method());
+ if (!ctx) { tls_err("unable to initialize ctx"); return; }
+
+ if (!SSL_CTX_use_certificate_chain_file(ctx, SERVERCERT))
+ { SSL_CTX_free(ctx); tls_err("missing certificate"); return; }
+ SSL_CTX_load_verify_locations(ctx, CLIENTCA, NULL);
+
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+ /* crl checking */
+ store = SSL_CTX_get_cert_store(ctx);
+ if ((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) &&
+ (X509_load_crl_file(lookup, CLIENTCRL, X509_FILETYPE_PEM) == 1))
+ X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK |
+ X509_V_FLAG_CRL_CHECK_ALL);
+#endif
+
+ /* set the callback here; SSL_set_verify didn't work before 0.9.6c */
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_cb);
+
+ /* a new SSL object, with the rest added to it directly to avoid copying */
+ myssl = SSL_new(ctx);
+ SSL_CTX_free(ctx);
+ if (!myssl) { tls_err("unable to initialize ssl"); return; }
+
+ /* this will also check whether public and private keys match */
+ if (!SSL_use_RSAPrivateKey_file(myssl, SERVERCERT, SSL_FILETYPE_PEM))
+ { SSL_free(myssl); tls_err("no valid RSA private key"); return; }
+
+ ciphers = env_get("TLSCIPHERS");
+ if (!ciphers) {
+ if (control_readfile(&saciphers, "control/tlsserverciphers") == -1)
+ { SSL_free(myssl); die_control(); }
+ if (saciphers.len) { /* convert all '\0's except the last one to ':' */
+ int i;
+ for (i = 0; i < saciphers.len - 1; ++i)
+ if (!saciphers.s[i]) saciphers.s[i] = ':';
+ ciphers = saciphers.s;
+ }
+ }
+ if (!ciphers || !*ciphers) ciphers = "DEFAULT";
+ SSL_set_cipher_list(myssl, ciphers);
+ alloc_free(saciphers.s);
+
+ SSL_set_tmp_rsa_callback(myssl, tmp_rsa_cb);
+ SSL_set_tmp_dh_callback(myssl, tmp_dh_cb);
+ SSL_set_rfd(myssl, ssl_rfd = substdio_fileno(&ssin));
+ SSL_set_wfd(myssl, ssl_wfd = substdio_fileno(&ssout));
+
+ if (!smtps) { out("220 ready for tls\r\n"); flush(); }
+
+ if (ssl_timeoutaccept(timeout, ssl_rfd, ssl_wfd, myssl) <= 0) {
+ /* neither cleartext nor any other response here is part of a standard */
+ const char *err = ssl_error_str();
+ ssl_free(myssl); tls_out("connection failed", err); die_read();
+ }
+ ssl = myssl;
+
+ /* populate the protocol string, used in Received */
+ if (!stralloc_copys(&proto, "(")
+ || !stralloc_cats(&proto, SSL_get_cipher(ssl))
+ || !stralloc_cats(&proto, " encrypted) SMTP")) die_nomem();
+ if (!stralloc_0(&proto)) die_nomem();
+ protocol = proto.s;
+
+ /* have to discard the pre-STARTTLS HELO/EHLO argument, if any */
+ dohelo(remotehost);
+}
+
+# undef SERVERCERT
+# undef CLIENTCA
+
+#endif
+
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;
{
+ childargs = argv + 1;
sig_pipeignore();
if (chdir(auto_qmail) == -1) die_control();
setup();
diff -Naur ./qregex.c ../qmail-1.03-build-10/qregex.c
--- ./qregex.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/qregex.c 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,57 @@
+/*
+ * qregex (v2)
+ * $Id: qregex.c,v 2.1 2001/12/28 07:05:21 evan Exp $
+ *
+ * Author : Evan Borgstrom (evan at unixpimps dot org)
+ * Created : 2001/12/14 23:08:16
+ * Modified: $Date: 2001/12/28 07:05:21 $
+ * Revision: $Revision: 2.1 $
+ *
+ * Do POSIX regex matching on addresses for anti-relay / spam control.
+ * It logs to the maillog
+ * See the qregex-readme file included with this tarball.
+ * If you didn't get this file in a tarball please see the following URL:
+ * http://www.unixpimps.org/software/qregex
+ *
+ * qregex.c is released under a BSD style copyright.
+ * See http://www.unixpimps.org/software/qregex/copyright.html
+ *
+ * Note: this revision follows the coding guidelines set forth by the rest of
+ * the qmail code and that described at the following URL.
+ * http://cr.yp.to/qmail/guarantee.html
+ *
+ */
+
+#include <sys/types.h>
+#include <regex.h>
+#include "qregex.h"
+
+#define REGCOMP(X,Y) regcomp(&X, Y, REG_EXTENDED|REG_ICASE)
+#define REGEXEC(X,Y) regexec(&X, Y, (size_t)0, (regmatch_t *)0, (int)0)
+
+int matchregex(char *text, char *regex) {
+ regex_t qreg;
+ int retval = 0;
+
+
+ /* build the regex */
+ if ((retval = REGCOMP(qreg, regex)) != 0) {
+ regfree(&qreg);
+ return(-retval);
+ }
+
+ /* execute the regex */
+ if ((retval = REGEXEC(qreg, text)) != 0) {
+ /* did we just not match anything? */
+ if (retval == REG_NOMATCH) {
+ regfree(&qreg);
+ return(0);
+ }
+ regfree(&qreg);
+ return(-retval);
+ }
+
+ /* signal the match */
+ regfree(&qreg);
+ return(1);
+}
diff -Naur ./qregex.h ../qmail-1.03-build-10/qregex.h
--- ./qregex.h 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/qregex.h 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,5 @@
+/* simple header file for the matchregex prototype */
+#ifndef _QREGEX_H_
+#define _QREGEX_H_
+int matchregex(char *text, char *regex);
+#endif
diff -Naur ./README ../qmail-1.03-build-10/README
--- ./README 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/README 2006-04-24 21:24:32.000000000 -0500
@@ -3,6 +3,31 @@
Copyright 1998
D. J. Bernstein, qmail@pobox.com
+netqmail 1.04
+20031024
+No copyright claimed for changes from qmail 1.03 to netqmail 1.04
+Russell Nelson, nelson@qmail.org
+NOTE: netqmail 1.04 is a community-assembled distribution of qmail from
+the official qmail-1.03.tar.gz and patches approved by the community.
+D. J. Bernstein did not participate in, nor has he been asked to
+approve of this distribution.
+
+netqmail 1.05
+20040121
+James Craig Burley claims copyright on the qmail-isoc patch. For
+more details, see the COPYRIGHTS file shipped with the netqmail-1.05
+distribution.
+
+James' patch has been combined with the original netqmail-1.04 patch
+and the result incorporated into a unified netqmail-1.05 patch.
+Apart from James' copyrights, no other copyright is claimed by the
+distributors of netqmail for changes from qmail 1.03 to netqmail 1.05.
+
+NOTE: netqmail 1.05 is a community-assembled distribution of qmail from
+the official qmail-1.03.tar.gz and patches approved by the community.
+D. J. Bernstein did not participate in, nor has he been asked to
+approve of this distribution.
+
qmail is a secure, reliable, efficient, simple message transfer agent.
It is meant as a replacement for the entire sendmail-binmail system on
typical Internet-connected UNIX hosts. See BLURB, BLURB2, BLURB3, and
diff -Naur ./README.auth ../qmail-1.03-build-10/README.auth
--- ./README.auth 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/README.auth 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,66 @@
+README qmail-smtpd SMTP Authentication
+======================================
+
+
+History:
+--------
+
+This patch is based on Krzysztof Dabrowski's qmail-smtpd-auth-0.31 patch
+which itself uses "Mrs. Brisby's" initial code.
+Version 0.41 of this patch fixes the "CAPS-LOCK" typo announcing
+'CRAM_MD5' instead of 'CRAM-MD5' (german keyboard) - tx to Mike Garrison.
+Version 0.42 fixes the '421 unable to read controls (#4.3.0)' problem
+(can't read control/morercpthosts.cdb) because FD 3 was already closed - tx Richard Lyons.
+Version 0.43 fixes the ba64decode() failure in case CRAM_MD5 is not enabled - tx Vladimir Zidar.
+Version 0.51 includes the evaluation of the 'Auth' and the 'Size' parameter in the 'Mail From:' command.
+Version 0.52 uses DJB functions to copy FDs.
+Version 0.56 corrects some minor mistakes displaying the 'Auth' userid.
+Version 0.57 uses keyword "ESMTPA" in Received header in case of authentication to comply with RFC 3848.
+
+
+Scope:
+------
+
+This patch supports RFC 2554 "SMTP Service Extension for Authentication" for qmail-smtpd.
+Additionally, RFC 1870 is honoured ("SMTP Service Extension for Message Size Declaration").
+For more technical details see: http://www.fehcom.de/qmail/docu/smtpauth.html.
+
+
+Installation:
+-------------
+
+* Untar the source in the qmail-1.03 home direcotry.
+* Run ./install_auth.
+* Modify the compile time option "#define CRAM_MD5" to your needs.
+* Re-make qmail.
+
+
+Setup:
+------
+
+In order to use SMTP Authentication you have to use a 'Pluggable Authentication Module'
+PAM to be called by qmail-smtpd; typically
+
+ /var/qmail/bin/qmail-smtpd /bin/checkpassword true 2>&1
+
+Since qmail-smtpd does not run as root, checkpassword has to be made sticky.
+There is no need to include additionally the hostname in the call.
+In order to compute the CRAM-MD5 challenge, qmail-smtpd uses the 'tcplocalhost' information.
+
+
+Changes wrt. Krysztof Dabrowski's patch:
+----------------------------------------
+
+* Avoid the 'hostname' in the call of the PAM.
+* Confirm to Dan Bernstein's checkpassword interface even for CRAM-MD5.
+* Doesn't close FD 2; thus not inhibiting logging to STDERR.
+* Fixed bugs in base64.c.
+* Modified unconditional close of FD 3 in order to sustain reading of 'control/morecpthosts.cdb'.
+* Evaluation of the (informational) Mail From: < > Auth=username.
+* Additional support for the advertised "Size" via 'Mail From: <return-path> SIZE=123456780' (RFC 1870).
+* RFC 3848 conformance for Received header in case of SMTP Auth.
+
+
+Erwin Hoffmann - Cologne 2005-01-23 (www.fehcom.de)
+
+
diff -Naur ./README.domainkeys ../qmail-1.03-build-10/README.domainkeys
--- ./README.domainkeys 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/README.domainkeys 2006-05-13 13:06:26.000000000 -0500
@@ -0,0 +1,57 @@
+qmail-dk domainkeys implementation into qmailtoaster
+----------------------------------------------------
+Nick Hemmesch <nick@ndhsoft.com> May 13, 2006
+
+
+INSTALLATION:
+----------------------------------------------------
+You MUST have either a local dns server or dns caching
+on your mail server.
+
+libdomainkeys must installed before qmail-toaster
+version >= 1.3.2 can be installed.
+
+The default path to the private key is:
+
+ /var/qmail/control/domainkeys
+
+Create a domain (yourdomain.com) directory for
+your domainkeys:
+
+ mkdir /var/qmail/control/domainkeys/yourdomain.com
+
+Create your domainkey with dknewkey:
+
+ dknewkey /var/qmail/control/domainkeys/yourdomain.com/private
+ chown -R root:qmail /var/qmail/control/domainkeys/
+ chmod 444 /var/qmail/control/domainkeys/yourdomain.com/private
+
+dknewkey will also return your dns entry for a Bind zone file,
+BE SURE TO SAVE IT so you can make your dns entry.
+
+If you use djbdns, a typical entry will look like this:
+
+ '_domainkey.yourdomain.com:o=-; r=you@yourdomain.com
+ 'private._domainkey.yourdomain.com:k=rsa; p=MEwwDQYJKoZIhvcNAQEBBQ . . .
+
+Test your dns entry with dnstxt, it may take some time for your dns
+to update the roots to make this test:
+
+ dnstxt private._domainkey.yourdomain.com
+
+Your /etc/tcprules.d/tcp.smtp file should look like this (without the "\"s):
+
+ 127.:allow,RELAYCLIENT=""
+ :allow,BADMIMETYPE="",BADLOADERTYPE="M",CHKUSER_RCPTLIMIT="50",\
+ CHKUSER_WRONGRCPTLIMIT="10",DKVERIFY="DEGIJKfh",QMAILQUEUE="/var/qmail/bin/simscan",\
+ DKQUEUE="/var/qmail/bin/qmail-queue.orig"
+
+ The DKVERIFY statement is very conservative. To reject mail
+ that has domainkeys but resolves to a different, or erroneous,
+ key add "B". Example: DKVERIFY="BDEGIJKfh"
+
+Note: You will find numerous qmail-dk configurations on the internet
+ that DO NOT work. This setup DOES work and is a "no brainer"
+ to setup.
+
+----------------------------------------------------
diff -Naur ./README.qregex ../qmail-1.03-build-10/README.qregex
--- ./README.qregex 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/README.qregex 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,196 @@
+QREGEX (v2) 20040725 - README July 25, 2004
+A Regular Expression matching patch for qmail 1.03 and netqmail
+
+
+OVERVIEW:
+
+qregex adds the ability to match address evelopes via Regular Expressions (REs)
+in the qmail-smtpd process. It has the abiltiy to match `helo/ehlo` (host name),
+`mail from` (envelope sender), and `rcpt to` (envelope recipient) commands.
+It follows all the base rules that are set out with qmail (ie using control
+files) so it makes for easy integretion into an existing setup (see the
+install instructions for more info). The v2 is specified because qregex was
+re-written to better conform to the security guarantee set forth by the author
+of qmail. The original version used stdio.h and stdlib.h for reading the
+control files whereas v2 now uses all stralloc functions which are much more
+regulated against buffer overruns and the like.
+See: http://cr.yp.to/qmail/guarantee.html
+
+
+FEATURES:
+
+Features of qregex include:
+
+1. Performs pattern matching on envelope senders and envelope
+ recipients against REs in the badmailfrom and badmailto control
+ files. Two additional control files, badmailfromnorelay and
+ badmailtonorelay, are used for pattern matching when the
+ RELAYCLIENT environment variable is not set.
+
+2. Performs pattern matching on the helo/ehlo host name. Setting the
+ NOBADHELO environment variable prevents the host name from being
+ compared to the patterns in the badhelo control file.
+
+3. Matches to patterns are logged
+
+4. Matching is case insensitive.
+
+5. qregex ignores empty envelope senders. An empty envelope sender is not
+ compared to the patterns in the badmailfrom and badmailfromnorelay
+ control files and is always accepted.
+
+
+PLATFORMS:
+
+qregex has been built and tested on the following platforms. I'm sure it won't
+have any problems on any platform that qmail will run on (providing they have
+a regex interface) but if you run into problems let me know.
+
+ - OpenBSD 3.x
+ - FreeBSD 4.x
+ - Mandrake Linux 9.x
+ - SuSE Linux 8.x
+
+
+
+INSTALLATION INSTRUCTIONS:
+
+Installation is very simple, there is only one requirement. You need to use the
+GNU version of the patch utility (http://www.gnu.org/software/patch/patch.html).
+(For Solaris 8 users it is installed as 'gpatch')
+
+- If this is a new setup.
+Unpack the qmail archive, cd into the qmail-1.03 directory and run
+"patch < /path/to/qregex-<version>.patch". Follow the instructions as per the
+included qmail INSTALL file. Once you are done come back to this file and read
+the section on the control files.
+
+If you are using netqmail, then unpack the netqmail archive. Run the collate.sh
+script and cd into the resulting netqmail-<version> directory. From there, run
+"patch < /path/to/qregex-<version>.patch". Complete the netqmail installation
+normally. Once you are done, come back to this file and read the section on the
+control files.
+
+- If this is an existing setup.
+FIRST: create your control files (see below).
+cd into your existing qmail or netqmail source directory. Run
+"patch < /path/to/qregex-<version>.patch" then "make qmail-smtpd". Now run
+./qmail-smtpd and test your new rules to make sure they work as expected.
+
+Install the new binary by cd'ing to /var/qmail/bin and as root (in one command)
+copy the existing binary to 'qmail-smtpd.old' and copy the new binary from the
+source directory to 'qmail-smtpd'.
+(ex. cp qmail-smtpd qmail-smtpd.old && cp ~/qmail-1.03/qmail-smtpd qmail-smtpd)
+
+You can also optionally just run "make setup check" as it will install the
+updated documentation and man pages provided with this patch. Stopping qmail
+before doing the "make setup check" is always a good idea.
+
+
+LOGGING:
+
+qregex will log matches to the patterns in the various control files. Log
+messages will take these three forms depending on which control file was
+matched:
+
+badhelo
+qmail-smtpd: badhelo: <host> at <remote IP>
+
+badmailfrom and badmailfromnorelay
+qmail-smtpd: badmailfrom: <sender address> at <remote IP>
+
+badmailto and badmailtonorelay
+qmail-smtpd: badmailto: <rcpt address> at <remote IP>
+
+
+CONTROL FILES:
+
+qregex provides you with five control files. None of these control files
+is mandatory and you can use them in any combination you choose in your setup.
+
+The "control/badmailfrom" and "control/badmailto" files contain your REs for
+matching against the 'mail from' (envelope sender) and 'rcpt to' (envelope
+recipient) smtp commands respectively.
+The "control/badmailfromnorelay" and "control/badmailtonorelay" match against
+the same commands but are read only when the RELAYCLIENT environment variable
+is not set.
+The "control/badhelo" file matches against the 'helo/ehlo' smtp command.
+
+If you prefer you can symlink the badmailfrom and badmailto control files
+(ln -s badmailfrom badmailto) and maintain fewer sets of rules. Beware
+this might cause problems in certain setups.
+
+ Here's an example "badhelo" file.
+ -----------------------------------
+ # block host strings with no dot (not a FQDN)
+ !\.
+ -----------------------------------
+
+ An example "badmailfrom" file.
+ -----------------------------------
+ # this will drop everything containing the string
+ # bad.domain.com or Bad.Domain.Com or BAD.domain.COM
+ bad\.domain\.com
+ # force users to fully qualify themselves
+ # (i.e. deny "user", accept "user@domain")
+ !@
+ -----------------------------------
+
+ And "badmailto" (a little more interesting)
+ -----------------------------------
+ # must not contain invalid characters, brakets or multiple @'s
+ [!%#:*^(){}]
+ @.*@
+ -----------------------------------
+
+You can use the non-RE character '!' to start an RE as a signal to qregex to
+negate the action. As used above in the badmailfrom file, by negating the '@'
+symbol qregex will signal qmail-smtpd to deny the 'mail from' command whenever
+the address doesn't contain an @ symbol. When used inside a bracket expression,
+the '!' character looses this special meaning. This is shown in the badmailto
+example.
+
+The norelay control files follow the same rules as the other control files but
+are intended to address two specific scenarios.
+The badmailfromnorelay file can be used to block mail trying to spoof a domain
+hosted on your mail server. It prevents a mail client that is not allowed to
+relay email through your server from using one of your hosted domains as its
+envelope sender.
+The badmailtonorelay file can be used to create email addresses that cannot
+receive mail from any source not allowed to relay email through your server.
+This is handy for creating email addresses for use only within your own
+domain(s) that can't receive spam from the world at large.
+
+
+INTERNALS:
+
+qregex (or regexmatch as the function is called) will be called during the
+`helo/ehlo`, `rcpt to` and `mail from` handling routines in "qmail-smtpd.c".
+When called, it will read the proper control file then one by one compile and
+execute the regex on the string passed into qmail-smtpd. If the regex matches
+it returns TRUE (1) and the qmail-smtpd process will deny the user the ability
+to continue. If you change anything and think it betters this patch please
+send me a new diff file so I can take a peek.
+
+
+CONTACT:
+qregex is maintained by:
+ Andrew St. Jean
+ andrew@arda.homeunix.net
+ www.arda.homeunix.net/store/qmail/
+
+Contributers to qregex:
+ Jeremy Kitchen
+ kitchen at scriptkitchen dot com
+ http://www.scriptkitchen.com/qmail
+
+ Alex Pleiner
+ alex@zeitform.de
+ zeitform Internet Dienste
+ http://www.zeitform.de/
+
+ Thanos Massias
+
+Original qregex patch written by:
+ Evan Borgstrom
+ evan at unixpimps dot org
diff -Naur ./README.remote-auth ../qmail-1.03-build-10/README.remote-auth
--- ./README.remote-auth 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/README.remote-auth 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,31 @@
+Docs for http://www.qmail.org/qmail-remote_authenticated_smtp.patch
+a patch to convince qmail-remote to use Authenticated SMTP when
+talking to certain hosts.
+
+This version of the patch has been modified by Robert Sanders so that
+base64 encoding of usernames and passwords is done automatically by
+qmail-remote.
+
+After applying the patch, the username password go into
+/var/qmail/control/smtproutes like so:
+
+domain:relay username password
+
+The domain:relay part is identical to a normal smtproutes entry (see
+the qmail-remote man page). For sites that require authentication, you
+simply add two space separated fields to the line, where the first
+field is the username, the second is the password. For example:
+
+inside.af.mil:firewall.af.mil:26 johndoe secret
+
+would send mail for inside.af.mil to firewall.af.mil, port 26 using
+username 'johndoe' and password 'secret'
+
+Since smtproutes will contain plain text usernames and passwords
+you might want to make the file owned by qmailr and set its permissions
+to 0600. Of course, the entries are going to go over the wire in the clear
+anyway as part of the SMTP transaction.
+
+Good luck.
+
+j.
diff -Naur ./README.starttls ../qmail-1.03-build-10/README.starttls
--- ./README.starttls 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/README.starttls 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,103 @@
+Frederik Vermeulen <qmail-tls akrul inoa.net> 20060104
+http://inoa.net/qmail-tls/
+
+This patch implements RFC 3207 (was RFC 2487) in qmail.
+This means you can get SSL or TLS encrypted and
+authenticated SMTP between the MTAs and from MUA to MTA.
+The code is considered experimental (but has worked for
+many since its first release on 1999-03-21).
+
+Usage: - install OpenSSL-0.9.8 http://www.openssl.org/
+ (any 0.9.6 to 0.9.8 version is presumed to work)
+ - apply patch to netqmail-1.05 http://qmail.org/netqmail
+ (should work on qmail-1.03 too). The patches to
+ qmail-remote.c and qmail-smtpd.c can be applied separately.
+ - provide a server certificate in /var/qmail/control/servercert.pem.
+ "make cert" makes a self-signed certificate.
+ "make cert-req" makes a certificate request.
+ Note: you can add the CA certificate and intermediate
+ certs to the end of servercert.pem.
+ - replace qmail-smtpd and/or qmail-remote binary
+ - verify operation (header information should show
+ something like
+ "Received [..] with (DHE-RSA-AES256-SHA encrypted) SMTP;")
+ If you don't have a server to test with, you can test
+ by sending mail to tag-ping@tbs-internet.com,
+ which will bounce your mail.
+
+Optional: - when DEBUG is defined, some extra TLS info will be logged
+ - qmail-remote will authenticate with the certificate in
+ /var/qmail/control/clientcert.pem. By preference this is
+ the same as servercert.pem, where nsCertType should be
+ == server,client or be a generic certificate (no usage specified).
+ - when a 512 bit RSA key is provided in /var/qmail/control/rsa512.pem,
+ this key will be used instead of (slow) on-the-fly generation by
+ qmail-smtpd. Idem for 512 and 1024 DH params in control/dh512.pem
+ and control/dh1024.pem. `make tmprsadh` does this.
+ Periodical replacement can be done by crontab:
+ 01 01 * * * /var/qmail/bin/update_tmprsadh > /dev/null 2>&1
+ - server authentication:
+ qmail-remote requires authentication from servers for which
+ /var/qmail/control/tlshosts/host.dom.ain.pem exists.
+ The .pem file contains the validating CA certificates
+ (or self-signed server certificate). CommonName has to match.
+ WARNING: this option may cause mail to be delayed, bounced,
+ doublebounced, and lost.
+ If /var/qmail/control/tlshosts/exhaustivelist is present,
+ the lists of hosts in /var/qmail/control/tlshosts is
+ an exhaustive list of hosts TLS is tried on.
+ If /var/qmail/control/notlshosts/host.dom.ain is present,
+ no TLS is tried on this host.
+ - client authentication:
+ when relay rules would reject an incoming mail,
+ qmail-smtpd can allow the mail based on a presented cert.
+ Certs are verified against a CA list in
+ /var/qmail/control/clientca.pem (eg. http://www.modssl.org/
+ source/cvs/exp/mod_ssl/pkg.mod_ssl/pkg.sslcfg/ca-bundle.crt)
+ and the cert email-address has to match a line in
+ /var/qmail/control/tlsclients. This email-address is logged
+ in the headers. CRLs can be provided through
+ /var/qmail/control/clientcrl.pem.
+ - cipher selection:
+ qmail-remote:
+ openssl cipher string (`man ciphers`) read from
+ /var/qmail/control/tlsclientciphers
+ qmail-smtpd:
+ openssl cipher string read from TLSCIPHERS environment variable
+ (can vary based on client IP address e.g.)
+ or if that is not available /var/qmail/control/tlsserverciphers
+ - smtps (deprecated SMTP over TLS via port 465):
+ qmail-remote: when connecting to port 465
+ qmail-smtpd: when SMTPS environment variable is not empty
+
+Caveats: - do a `make clean` after patching
+ - binaries dynamically linked with current openssl versions need
+ recompilation when the shared openssl libs are upgraded.
+ - this patch could conflict with other patches (notably those
+ replacing \n with \r\n, which is a bad idea on encrypted links).
+ - some broken servers have a problem with TLSv1 compatibility.
+ Uncomment the line where we set the SSL_OP_NO_TLSv1 option.
+ - needs working /dev/urandom (or EGD for openssl versions >0.9.7)
+ for seeding random number generator.
+ - packagers should make sure that installing without a valid
+ servercert is impossible
+ - when applied in combination with AUTH patch, AUTH patch
+ should be applied first and first part of this patch
+ will fail. This error can be ignored. Packagers should
+ cut the first 12 lines of this patch to make a happy
+ patch
+ - `make tmprsadh` is recommended (or should I say required),
+ otherwise DH generation can be unpredictably slow
+ - some need "-I/usr/kerberos/include" to be added in conf-cc
+
+Copyright: GPL
+ Links with OpenSSL
+ Inspiration and code from examples in SSLeay (E. Young
+ <eay@cryptsoft.com> and T. Hudson <tjh@cryptsoft.com>),
+ stunnel (M. Trojnara <mtrojnar@ddc.daewoo.com.pl>),
+ Postfix/TLS (L. Jaenicke <Lutz.Jaenicke@aet.tu-cottbus.de>),
+ modssl (R. Engelschall <rse@engelschall.com>),
+ openssl examples of E. Rescorla <ekr@rtfm.com>.
+
+Bug reports: mailto:<qmail-tls akrul inoa.net>
+
diff -Naur ./README.tap ../qmail-1.03-build-10/README.tap
--- ./README.tap 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/README.tap 2006-05-09 23:21:54.000000000 -0500
@@ -0,0 +1,28 @@
+qmail provides the ability to make a copy of each email that flows through the system.
+This is done using the QUEUE_EXTRA code. See qmail FAQ #8.2
+
+The qmail tap patch adds additional functionality:
+1) Specify which email addresses to tap using a regex style control file. With the
+ regex function, you can specify full domains or individual email addresses.
+
+2) Specify which email address to send the emails to.
+
+3) Qmail does not need to be restated to when the taps control file is changed.
+
+The regex match is applied to both the to and from email addresses. So email
+sent to or from the addresses will be copied. Matching is case insensitive.
+If there are multiple matches, the first match is used.
+
+The queue tap patch adds a new control file:
+
+/var/qmail/control/taps
+Contains a regex style list of addresses to tap and the email
+address of where you want the copy sent to.
+
+Examples:
+a) To tap a whole domain add a line like:
+.*@domain.com:joe@example.com
+
+
+b) To tap an individual email address add a line like:
+user@domain.com:other@example.com
diff -Naur ./README.warlord ../qmail-1.03-build-10/README.warlord
--- ./README.warlord 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/README.warlord 2004-12-09 13:59:58.000000000 -0600
@@ -0,0 +1,27 @@
+README (Warlord)
+================
+
+The Warlord patch is the successor of Russell Nelson's
+and Charles Cazabon's "qmail-smtpd-viruscan-patch".
+It realizes a robust and efficient base64 scanning.
+
+Features:
+
+- The whole message is scanned for embedded base64 attachments.
+- The first characters of the identified attachments
+ are checked against the strings found in badmimetypes.cdb,
+ if the environment variable BADMIMETYPE is present.
+- The whole content of all base64 attachments
+ are checked against arbitary strings provided in
+ badloadertypes.cdb. In order to make the search efficient,
+ the required environment variable BADLOADERTYPE has
+ to be supplied with the first character of the content
+ of the badloadertypes.cdb.
+- Customized SMTP 554 reply messages can be defined and used
+ via the environment variable REPLY554.
+
+By means of the programs qmail-badmimetype and qmail-badloadertype,
+the databases can be modified by need on the fly.
+
+See man qmail-smtpd, qmail-control, qmail-badmimetypes, and
+qmail-badloadertypes.
diff -Naur ./sendmail.c ../qmail-1.03-build-10/sendmail.c
--- ./sendmail.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/sendmail.c 2006-04-24 21:24:32.000000000 -0500
@@ -45,6 +45,38 @@
_exit(111);
}
+void do_sender(s)
+const char *s;
+{
+ char *x;
+ int n;
+ int a;
+ int i;
+
+ env_unset("QMAILNAME");
+ env_unset("MAILNAME");
+ env_unset("NAME");
+ env_unset("QMAILHOST");
+ env_unset("MAILHOST");
+
+ n = str_len(s);
+ a = str_rchr(s, '@');
+ if (a == n)
+ {
+ env_put2("QMAILUSER", s);
+ return;
+ }
+ env_put2("QMAILHOST", s + a + 1);
+
+ x = (char *) alloc((a + 1) * sizeof(char));
+ if (!x) nomem();
+ for (i = 0; i < a; i++)
+ x[i] = s[i];
+ x[i] = 0;
+ env_put2("QMAILUSER", x);
+ alloc_free(x);
+}
+
int flagh;
char *sender;
@@ -118,6 +150,7 @@
if (sender) {
*arg++ = "-f";
*arg++ = sender;
+ do_sender(sender);
}
*arg++ = "--";
for (i = 0;i < argc;++i) *arg++ = argv[i];
diff -Naur ./spawn.c ../qmail-1.03-build-10/spawn.c
--- ./spawn.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/spawn.c 2006-05-05 19:47:24.000000000 -0500
@@ -5,6 +5,7 @@
#include "substdio.h"
#include "byte.h"
#include "str.h"
+#include "alloc.h"
#include "stralloc.h"
#include "select.h"
#include "exit.h"
@@ -63,7 +64,7 @@
int flagreading = 1;
char outbuf[1024]; substdio ssout;
-int stage = 0; /* reading 0:delnum 1:messid 2:sender 3:recip */
+int stage = 0; /* reading 0:delnum 1:delnum2 2:messid 3:sender 4:recip */
int flagabort = 0; /* if 1, everything except delnum is garbage */
int delnum;
stralloc messid = {0};
@@ -73,6 +74,7 @@
void err(s) char *s;
{
char ch; ch = delnum; substdio_put(&ssout,&ch,1);
+ ch = delnum >> 8; substdio_put(&ssout,&ch,1);
substdio_puts(&ssout,s); substdio_putflush(&ssout,"",1);
}
@@ -155,16 +157,19 @@
{
case 0:
delnum = (unsigned int) (unsigned char) ch;
- messid.len = 0; stage = 1; break;
+ stage = 1; break;
case 1:
+ delnum += (unsigned int) ((unsigned int) ch) << 8;
+ messid.len = 0; stage = 2; break;
+ case 2:
if (!stralloc_append(&messid,&ch)) flagabort = 1;
if (ch) break;
- sender.len = 0; stage = 2; break;
- case 2:
+ sender.len = 0; stage = 3; break;
+ case 3:
if (!stralloc_append(&sender,&ch)) flagabort = 1;
if (ch) break;
- recip.len = 0; stage = 3; break;
- case 3:
+ recip.len = 0; stage = 4; break;
+ case 4:
if (!stralloc_append(&recip,&ch)) flagabort = 1;
if (ch) break;
docmd();
@@ -201,7 +206,8 @@
initialize(argc,argv);
- ch = auto_spawn; substdio_putflush(&ssout,&ch,1);
+ ch = auto_spawn; substdio_put(&ssout,&ch,1);
+ ch = auto_spawn >> 8; substdio_putflush(&ssout,&ch,1);
for (i = 0;i < auto_spawn;++i) { d[i].used = 0; d[i].output.s = 0; }
@@ -236,7 +242,8 @@
continue; /* read error on a readable pipe? be serious */
if (r == 0)
{
- ch = i; substdio_put(&ssout,&ch,1);
+ char ch; ch = i; substdio_put(&ssout,&ch,1);
+ ch = i >> 8; substdio_put(&ssout,&ch,1);
report(&ssout,d[i].wstat,d[i].output.s,d[i].output.len);
substdio_put(&ssout,"",1);
substdio_flush(&ssout);
diff -Naur ./spf.c ../qmail-1.03-build-10/spf.c
--- ./spf.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/spf.c 2006-05-05 21:22:50.000000000 -0500
@@ -0,0 +1,878 @@
+#include "stralloc.h"
+#include "strsalloc.h"
+#include "alloc.h"
+#include "ip.h"
+#include "ipalloc.h"
+#include "ipme.h"
+#include "str.h"
+#include "fmt.h"
+#include "scan.h"
+#include "byte.h"
+#include "now.h"
+#include "dns.h"
+#include "case.h"
+#include "spf.h"
+
+#define SPF_EXT -1
+#define SPF_SYNTAX -2
+
+#define WSPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\r' || (x) == '\n')
+#define NXTOK(b, p, a) do { (b) = (p); \
+ while((p) < (a)->len && !WSPACE((a)->s[(p)])) ++(p); \
+ while((p) < (a)->len && WSPACE((a)->s[(p)])) (a)->s[(p)++] = 0; \
+ } while(0)
+
+/* this table and macro came from wget more or less */
+/* and was in turn stolen by me from libspf as is :) */
+const static unsigned char urlchr_table[256] =
+{
+ 1, 1, 1, 1, 1, 1, 1, 1, /* NUL SOH STX ETX EOT ENQ ACK BEL */
+ 1, 1, 1, 1, 1, 1, 1, 1, /* BS HT LF VT FF CR SO SI */
+ 1, 1, 1, 1, 1, 1, 1, 1, /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
+ 1, 1, 1, 1, 1, 1, 1, 1, /* CAN EM SUB ESC FS GS RS US */
+ 1, 0, 1, 1, 0, 1, 1, 0, /* SP ! " # $ % & ' */
+ 0, 0, 0, 1, 0, 0, 0, 1, /* ( ) * + , - . / */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0 1 2 3 4 5 6 7 */
+ 0, 0, 1, 1, 1, 1, 1, 1, /* 8 9 : ; < = > ? */
+ 1, 0, 0, 0, 0, 0, 0, 0, /* @ A B C D E F G */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* H I J K L M N O */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* P Q R S T U V W */
+ 0, 0, 0, 1, 1, 1, 1, 0, /* X Y Z [ \ ] ^ _ */
+ 1, 0, 0, 0, 0, 0, 0, 0, /* ` a b c d e f g */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* h i j k l m n o */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* p q r s t u v w */
+ 0, 0, 0, 1, 1, 1, 1, 1, /* x y z { | } ~ DEL */
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+};
+
+
+extern stralloc addr;
+extern stralloc helohost;
+extern char *remoteip;
+extern char *local;
+
+extern stralloc spflocal;
+extern stralloc spfguess;
+extern stralloc spfexp;
+
+static stralloc sender_fqdn = {0};
+static stralloc explanation = {0};
+static stralloc expdomain = {0};
+static stralloc errormsg = {0};
+static char *received;
+
+static int recursion;
+static struct ip_address ip;
+
+static void hdr_pass() { received = "pass (%{xr}: %{xs} designates %{i} as permitted sender)"; };
+static void hdr_softfail() { received = "softfail (%{xr}: transitioning %{xs} does not designate %{i} as permitted sender)"; };
+static void hdr_fail() { received = "fail (%{xr}: %{xs} does not designate %{i} as permitted sender)"; };
+static void hdr_unknown() { received = "unknown (%{xr}: domain at %{d} does not designate permitted sender hosts)"; };
+static void hdr_neutral() { received = "neutral (%{xr}: %{i} is neither permitted nor denied by %{xs})"; };
+static void hdr_none() { received = "none (%{xr}: domain at %{d} does not designate permitted sender hosts)"; };
+static void hdr_unknown_msg(e) char *e; { stralloc_copys(&errormsg, e); received = "unknown (%{xr}: %{xe})"; };
+static void hdr_ext(e) char *e; { stralloc_copys(&errormsg, e); received = "unknown %{xe} (%{xr}: %{xs} uses mechanism not recognized by this client)"; };
+static void hdr_syntax() { received = "unknown (%{xr}: parse error in %{xs})"; };
+static void hdr_error(e) char *e; { stralloc_copys(&errormsg, e); received = "error (%{xr}: error in processing during lookup of %{d}: %{xe})"; };
+static void hdr_dns() { hdr_error("DNS problem"); }
+
+
+static int matchip(struct ip_address *net, int mask, struct ip_address *ip)
+{
+ int j;
+ int bytemask;
+
+ for (j = 0; j < 4 && mask > 0; ++j) {
+ if (mask > 8) bytemask = 8; else bytemask = mask;
+ mask -= bytemask;
+
+ if ((net->d[j] ^ ip->d[j]) & (0x100 - (1 << (8 - bytemask))))
+ return 0;
+ }
+ return 1;
+}
+
+static int getipmask(char *mask, int ipv6) {
+ unsigned long r;
+ int pos;
+
+ if (!mask) return 32;
+
+ pos = scan_ulong(mask, &r);
+ if (!pos || (mask[pos] && !(mask[pos] == '/' && ipv6))) return -1;
+ if (r > 32) return -1;
+
+ return r;
+}
+
+int spfget(stralloc *spf, stralloc *domain)
+{
+ strsalloc ssa = {0};
+ int j;
+ int begin, pos, i;
+ int r = SPF_NONE;
+
+ spf->len = 0;
+
+ switch(dns_txt(&ssa, domain)) {
+ case DNS_MEM: return SPF_NOMEM;
+ case DNS_SOFT: hdr_dns(); return SPF_ERROR;
+ case DNS_HARD: return SPF_NONE;
+ }
+
+ for (j = 0;j < ssa.len;++j) {
+ pos = 0;
+
+ NXTOK(begin, pos, &ssa.sa[j]);
+ if (str_len(ssa.sa[j].s + begin) < 6) continue;
+ if (!byte_equal(ssa.sa[j].s + begin,6,"v=spf1")) continue;
+ if (ssa.sa[j].s[begin + 6]) {
+ /* check for subversion */
+ if (ssa.sa[j].s[begin + 6] != '.') continue;
+ for(i = begin + 7;;++i)
+ if (!(ssa.sa[j].s[i] >= '0' && ssa.sa[j].s[i] <= '9')) break;
+ if (i == (begin + 7)) continue;
+ if (ssa.sa[j].s[i]) continue;
+ }
+
+ if (spf->len > 0) {
+ spf->len = 0;
+ hdr_unknown_msg("Multiple SPF records returned");
+ r = SPF_UNKNOWN;
+ break;
+ }
+ if (!stralloc_0(&ssa.sa[j])) return SPF_NOMEM;
+ if (!stralloc_copys(spf,ssa.sa[j].s + pos)) return SPF_NOMEM;
+ r = SPF_OK;
+ }
+
+ for (j = 0;j < ssa.len;++j)
+ alloc_free(ssa.sa[j].s);
+ alloc_free(ssa.sa);
+ return r;
+}
+
+static int spf_ptr(char *spec, char *mask);
+
+int spfsubst(stralloc *expand, char *spec, char *domain)
+{
+ static char hexdigits[] = "0123456789abcdef";
+ stralloc sa = {0};
+ char ch;
+ int digits = -1;
+ int urlencode = 0;
+ int reverse = 0;
+ int start = expand->len;
+ int i, pos;
+ char *split = ".";
+
+ if (!stralloc_readyplus(&sa,0)) return 0;
+
+ if (*spec == 'x') { i = 1; ++spec; } else i = 0;
+ ch = *spec++;
+ if (!ch) { alloc_free(sa.s); return 1; }
+ if (ch >= 'A' && ch <= 'Z') { ch += 32; urlencode = 1; }
+ if (i) ch -= 32;
+ while(*spec >= '0' && *spec <= '9') {
+ if (digits < 0) digits = 0;
+ if (digits >= 1000000) { digits = 10000000; continue; }
+ digits = (digits * 10) + (*spec - '0');
+ spec++;
+ }
+
+ while((*spec >= 'a' && *spec <= 'z') || (*spec >= 'A' && *spec <= 'Z')) {
+ if (*spec == 'r') reverse = 1;
+ spec++;
+ }
+
+ if (*spec) split = spec;
+
+ switch(ch) {
+ case 'l':
+ pos = byte_rchr(addr.s, addr.len, '@');
+ if (pos < addr.len) {
+ if (!stralloc_copyb(&sa, addr.s, pos)) return 0;
+ } else
+ if (!stralloc_copys(&sa, "postmaster")) return 0;
+ break;
+ case 's':
+ if (!stralloc_copys(&sa, addr.s)) return 0;
+ break;
+ case 'o':
+ pos = byte_rchr(addr.s, addr.len, '@') + 1;
+ if (pos > addr.len) break;
+ if (!stralloc_copys(&sa, addr.s + pos)) return 0;
+ break;
+ case 'd':
+ if (!stralloc_copys(&sa, domain)) return 0;
+ break;
+ case 'i':
+ if (!stralloc_ready(&sa, IPFMT)) return 0;
+ sa.len = ip_fmt(sa.s, &ip);
+ break;
+ case 't':
+ if (!stralloc_ready(&sa, FMT_ULONG)) return 0;
+ sa.len = fmt_ulong(sa.s, (unsigned long)now());
+ break;
+ case 'p':
+ if (!sender_fqdn.len)
+ spf_ptr(domain, 0);
+ if (sender_fqdn.len) {
+ if (!stralloc_copy(&sa, &sender_fqdn)) return 0;
+ } else
+ if (!stralloc_copys(&sa, "unknown")) return 0;
+ break;
+ case 'v':
+ if (!stralloc_copys(&sa, "in-addr")) return 0;
+ break;
+ case 'h':
+ if (!stralloc_copys(&sa, helohost.s)) return 0; /* FIXME: FQDN? */
+ break;
+ case 'E':
+ if (errormsg.len && !stralloc_copy(&sa, &errormsg)) return 0;
+ break;
+ case 'R':
+ if (!stralloc_copys(&sa, local)) return 0;
+ break;
+ case 'S':
+ if (expdomain.len > 0) {
+ if (!stralloc_copys(&sa, "SPF record at ")) return 0;
+ if (!stralloc_cats(&sa, expdomain.s)) return 0;
+ } else {
+ if (!stralloc_copys(&sa, "local policy")) return 0;
+ }
+ break;
+ }
+
+ if (reverse) {
+ for(pos = 0; digits; ++pos) {
+ pos += byte_cspn(sa.s + pos, sa.len - pos, split);
+ if (pos >= sa.len) break;
+ if (!--digits) break;
+ }
+
+ for(; pos > 0; pos = i - 1) {
+ i = byte_rcspn(sa.s, pos, split) + 1;
+ if (i > pos) i = 0;
+ if (!stralloc_catb(expand, sa.s + i, pos - i)) return 0;
+ if (i > 0 && !stralloc_append(expand, ".")) return 0;
+ }
+ } else {
+ for(pos = sa.len; digits; --pos) {
+ i = byte_rcspn(sa.s, pos, split) + 1;
+ if (i > pos) { pos = 0; break; }
+ pos = i;
+ if (!--digits) break;
+ }
+
+ if (!stralloc_catb(expand, sa.s + pos, sa.len - pos)) return 0;
+ if (split[0] != '.' || split[1])
+ for(pos = 0; pos < expand->len; pos++) {
+ pos += byte_cspn(expand->s + pos, expand->len - pos, split);
+ if (pos < expand->len)
+ expand->s[pos] = '.';
+ }
+ }
+
+ if (urlencode) {
+ stralloc_copyb(&sa, expand->s + start, expand->len - start);
+ expand->len = start;
+
+ for(pos = 0; pos < sa.len; ++pos) {
+ ch = sa.s[pos];
+ if (urlchr_table[(unsigned char)ch]) {
+ if (!stralloc_readyplus(expand, 3)) return 0;
+ expand->s[expand->len++] = '%';
+ expand->s[expand->len++] = hexdigits[(unsigned char)ch >> 4];
+ expand->s[expand->len++] = hexdigits[(unsigned char)ch & 15];
+ } else
+ if (!stralloc_append(expand, &ch)) return 0;
+ }
+ }
+
+ alloc_free(sa.s);
+ return 1;
+}
+
+int spfexpand(stralloc *sa, char *spec, char *domain)
+{
+ char *p;
+ char append;
+ int pos;
+
+ if (!stralloc_readyplus(sa, 0)) return 0;
+ sa->len = 0;
+
+ for(p = spec; *p; p++) {
+ append = *p;
+ if (*p == '%') {
+ p++;
+ switch(*p) {
+ case '%': break;
+ case '_': append = ' '; break;
+ case '-': if (!stralloc_cats(sa, "%20")) return 0; continue;
+ case '{':
+ pos = str_chr(p, '}');
+ if (p[pos] != '}') { p--; break; }
+ p[pos] = 0;
+ if (!spfsubst(sa, p + 1, domain)) return 0;
+ p += pos;
+ continue;
+ default: p--;
+ }
+ }
+ if (!stralloc_append(sa, &append)) return 0;
+ }
+
+ return 1;
+}
+
+static int spflookup(stralloc *domain);
+
+static int spf_include(char *spec, char *mask)
+{
+ stralloc sa = {0};
+ int r;
+
+ if (!stralloc_copys(&sa, spec)) return SPF_NOMEM;
+ r = spflookup(&sa);
+ alloc_free(sa.s);
+
+ switch(r) {
+ case SPF_NONE:
+ hdr_unknown();
+ r = SPF_UNKNOWN;
+ break;
+ case SPF_SYNTAX:
+ r = SPF_UNKNOWN;
+ break;
+ case SPF_NEUTRAL:
+ case SPF_SOFTFAIL:
+ case SPF_FAIL:
+ r = SPF_NONE;
+ break;
+ }
+
+ return r;
+}
+
+static int spf_a(char *spec, char *mask)
+{
+ stralloc sa = {0};
+ ipalloc ia = {0};
+ int ipmask = getipmask(mask, 1);
+ int r;
+ int j;
+
+ if (ipmask < 0) return SPF_SYNTAX;
+
+ if (!stralloc_copys(&sa, spec)) return SPF_NOMEM;
+ if (!stralloc_readyplus(&ia, 0)) return SPF_NOMEM;
+
+ switch(dns_ip(&ia, &sa)) {
+ case DNS_MEM: return SPF_NOMEM;
+ case DNS_SOFT: hdr_dns(); r = SPF_ERROR; break;
+ case DNS_HARD: r = SPF_NONE; break;
+ default:
+ r = SPF_NONE;
+ for(j = 0; j < ia.len; ++j)
+ if (matchip(&ia.ix[j].ip, ipmask, &ip)) {
+ r = SPF_OK;
+ break;
+ }
+ }
+
+ alloc_free(sa.s);
+ alloc_free(ia.ix);
+ return r;
+}
+
+static int spf_mx(char *spec, char *mask)
+{
+ stralloc sa = {0};
+ ipalloc ia = {0};
+ int ipmask = getipmask(mask, 1);
+ int random = now() + (getpid() << 16);
+ int r;
+ int j;
+
+ if (ipmask < 0) return SPF_SYNTAX;
+
+ if (!stralloc_copys(&sa, spec)) return SPF_NOMEM;
+ if (!stralloc_readyplus(&ia, 0)) return SPF_NOMEM;
+
+ switch(dns_mxip(&ia, &sa, random)) {
+ case DNS_MEM: return SPF_NOMEM;
+ case DNS_SOFT: hdr_dns(); r = SPF_ERROR; break;
+ case DNS_HARD: r = SPF_NONE; break;
+ default:
+ r = SPF_NONE;
+ for(j = 0; j < ia.len; ++j)
+ if (matchip(&ia.ix[j].ip, ipmask, &ip)) {
+ r = SPF_OK;
+ break;
+ }
+ }
+
+ alloc_free(sa.s);
+ alloc_free(ia.ix);
+ return r;
+}
+
+static int spf_ptr(char *spec, char *mask)
+{
+ strsalloc ssa = {0};
+ ipalloc ia = {0};
+ int len = str_len(spec);
+ int r;
+ int j, k;
+ int pos;
+
+ /* we didn't find host with the matching ip before */
+ if (sender_fqdn.len == 7 && str_equal(sender_fqdn.s, "unknown"))
+ return SPF_NONE;
+
+ /* the hostname found will probably be the same as before */
+ while (sender_fqdn.len) {
+ pos = sender_fqdn.len - len;
+ if (pos < 0) break;
+ if (pos > 0 && sender_fqdn.s[pos - 1] != '.') break;
+ if (case_diffb(sender_fqdn.s + pos, len, spec)) break;
+
+ return SPF_OK;
+ }
+
+ /* ok, either it's the first test or it's a very weird setup */
+
+ if (!stralloc_readyplus(&ssa, 0)) return SPF_NOMEM;
+ if (!stralloc_readyplus(&ia, 0)) return SPF_NOMEM;
+
+ switch(dns_ptr(&ssa, &ip)) {
+ case DNS_MEM: return SPF_NOMEM;
+ case DNS_SOFT: hdr_dns(); r = SPF_ERROR; break;
+ case DNS_HARD: r = SPF_NONE; break;
+ default:
+ r = SPF_NONE;
+ for(j = 0; j < ssa.len; ++j) {
+ switch(dns_ip(&ia, &ssa.sa[j])) {
+ case DNS_MEM: return SPF_NOMEM;
+ case DNS_SOFT: hdr_dns(); r = SPF_ERROR; break;
+ case DNS_HARD: break;
+ default:
+ for(k = 0; k < ia.len; ++k)
+ if (matchip(&ia.ix[k].ip, 32, &ip)) {
+ if (!sender_fqdn.len)
+ if (!stralloc_copy(&sender_fqdn, &ssa.sa[j])) return SPF_NOMEM;
+
+ pos = ssa.sa[j].len - len;
+ if (pos < 0) continue;
+ if (pos > 0 && ssa.sa[j].s[pos - 1] != '.') continue;
+ if (case_diffb(ssa.sa[j].s + pos, len, spec)) continue;
+
+ stralloc_copy(&sender_fqdn, &ssa.sa[j]);
+ r = SPF_OK;
+ break;
+ }
+ }
+
+ if (r == SPF_ERROR) break;
+ }
+ }
+
+ for(j = 0;j < ssa.len;++j)
+ alloc_free(ssa.sa[j].s);
+
+ alloc_free(ssa.sa);
+ alloc_free(ia.ix);
+
+ if (!sender_fqdn.len)
+ if (!stralloc_copys(&sender_fqdn, "unknown")) return SPF_NOMEM;
+
+ return r;
+}
+
+static int spf_ip(char *spec, char *mask)
+{
+ struct ip_address net;
+ int ipmask = getipmask(mask, 0);
+
+ if (ipmask < 0) return SPF_SYNTAX;
+ if (!ip_scan(spec, &net)) return SPF_SYNTAX;
+
+ if (matchip(&net, ipmask, &ip)) return SPF_OK;
+
+ return SPF_NONE;
+}
+
+static int spf_exists(char *spec, char *mask)
+{
+ stralloc sa = {0};
+ ipalloc ia = {0};
+ int r;
+
+ if (!stralloc_copys(&sa, spec)) return SPF_NOMEM;
+ if (!stralloc_readyplus(&ia, 0)) return SPF_NOMEM;
+
+ switch(dns_ip(&ia, &sa)) {
+ case DNS_MEM: return SPF_NOMEM;
+ case DNS_SOFT: hdr_dns(); r = SPF_ERROR; break;
+ case DNS_HARD: r = SPF_NONE; break;
+ default: r = SPF_OK;
+ }
+
+ alloc_free(sa.s);
+ alloc_free(ia.ix);
+ return r;
+}
+
+static struct mechanisms {
+ char *mechanism;
+ int (*func)(char *spec, char *mask);
+ unsigned int takes_spec : 1;
+ unsigned int takes_mask : 1;
+ unsigned int expands : 1;
+ unsigned int filldomain : 1;
+ int defresult : 4;
+} mechanisms[] = {
+ { "all", 0, 0,0,0,0,SPF_OK }
+, { "include", spf_include,1,0,1,0,0 }
+, { "a", spf_a, 1,1,1,1,0 }
+, { "mx", spf_mx, 1,1,1,1,0 }
+, { "ptr", spf_ptr, 1,0,1,1,0 }
+, { "ip4", spf_ip, 1,1,0,0,0 }
+, { "ip6", 0, 1,1,0,0,SPF_NONE }
+, { "exists", spf_exists, 1,0,1,0,0 }
+, { "extension",0, 1,1,0,0,SPF_EXT }
+, { 0, 0, 1,1,0,0,SPF_EXT }
+};
+
+static int spfmech(char *mechanism, char *spec, char *mask, char *domain)
+{
+ struct mechanisms *mech;
+ stralloc sa = {0};
+ int r;
+ int pos;
+
+ for(mech = mechanisms; mech->mechanism; mech++)
+ if (str_equal(mech->mechanism, mechanism)) break;
+
+ if (mech->takes_spec && !spec && mech->filldomain) spec = domain;
+ if (!mech->takes_spec != !spec) return SPF_SYNTAX;
+ if (!mech->takes_mask && mask) return SPF_SYNTAX;
+ if (!mech->func) return mech->defresult;
+
+ if (!stralloc_readyplus(&sa, 0)) return SPF_NOMEM;
+ if (mech->expands && spec != domain) {
+ if (!spfexpand(&sa, spec, domain)) return SPF_NOMEM;
+ for (pos = 0; (sa.len - pos) > 255;) {
+ pos += byte_chr(sa.s + pos, sa.len - pos, '.');
+ if (pos < sa.len) pos++;
+ }
+ sa.len -= pos;
+ if (pos > 0) byte_copy(sa.s, sa.len, sa.s + pos);
+ stralloc_0(&sa);
+ spec = sa.s;
+ }
+
+ r = mech->func(spec, mask);
+
+ alloc_free(sa.s);
+ return r;
+}
+
+static struct default_aliases {
+ char *alias;
+ int defret;
+} default_aliases[] = {
+ { "allow", SPF_OK }
+, { "pass", SPF_OK }
+, { "deny", SPF_FAIL }
+, { "softdeny",SPF_SOFTFAIL }
+, { "fail", SPF_FAIL }
+, { "softfail",SPF_SOFTFAIL }
+, { "unknown", SPF_NEUTRAL }
+, { 0, SPF_UNKNOWN }
+};
+
+static int spflookup(stralloc *domain)
+{
+ stralloc spf = {0};
+ stralloc sa = {0};
+ struct default_aliases *da;
+ int main = !recursion;
+ int local_pos = -1;
+ int r, q;
+ int begin, pos;
+ int i;
+ int prefix;
+ int done;
+ int guessing = 0;
+ char *p;
+
+ if (!stralloc_readyplus(&spf, 0)) return SPF_NOMEM;
+ if (!stralloc_readyplus(&sa, 0)) return SPF_NOMEM;
+
+ /* fallthrough result */
+ if (main) hdr_none();
+
+redirect:
+ if (++recursion > 20) {
+ alloc_free(spf.s);
+ alloc_free(sa.s);
+ hdr_unknown_msg("Maximum nesting level exceeded, possible loop");
+ return SPF_SYNTAX;
+ }
+
+ if (!stralloc_0(domain)) return SPF_NOMEM;
+ if (!stralloc_copy(&expdomain, domain)) return SPF_NOMEM;
+
+ r = spfget(&spf, domain);
+ if (r == SPF_NONE) {
+ if (!main) { alloc_free(spf.s); return r; }
+
+ if (spfguess.len) {
+ /* try to guess */
+ guessing = 1;
+ if (!stralloc_copys(&spf, spfguess.s)) return SPF_NOMEM;
+ if (!stralloc_append(&spf, " ")) return SPF_NOMEM;
+ } else
+ spf.len = 0;
+
+ /* append local rulest */
+ if (spflocal.len) {
+ local_pos = spf.len;
+ if (!stralloc_cats(&spf, spflocal.s)) return SPF_NOMEM;
+ }
+ if (!stralloc_0(&spf)) return SPF_NOMEM;
+
+ expdomain.len = 0;
+ } else if (r == SPF_OK) {
+ if (!stralloc_0(&spf)) return SPF_NOMEM;
+ if (main) hdr_neutral();
+ r = SPF_NEUTRAL;
+
+ /* try to add local rules before fail all mechs */
+ if (main && spflocal.len) {
+ pos = 0;
+ p = (char *) 0;
+ while(pos < spf.len) {
+ NXTOK(begin, pos, &spf);
+ if (!spf.s[begin]) continue;
+
+ if (p && spf.s[begin] != *p) p = (char *) 0;
+ if (!p && (spf.s[begin] == '-' || spf.s[begin] == '~' ||
+ spf.s[begin] == '?')) p = &spf.s[begin];
+
+ if (p && p > spf.s && str_equal(spf.s + begin + 1, "all")) {
+ /* ok, we can insert the local rules at p */
+ local_pos = p - spf.s;
+
+ stralloc_readyplus(&spf, spflocal.len);
+ p = spf.s + local_pos;
+ byte_copyr(p + spflocal.len, spf.len - local_pos, p);
+ byte_copy(p, spflocal.len, spflocal.s);
+ spf.len += spflocal.len;
+
+ pos += spflocal.len;
+ break;
+ }
+ }
+
+ if (pos >= spf.len) pos = spf.len - 1;
+ for(i = 0; i < pos; i++)
+ if (!spf.s[i]) spf.s[i] = ' ';
+ }
+ } else {
+ alloc_free(spf.s);
+ return r;
+ }
+
+ pos = 0;
+ done = 0;
+ while(pos < spf.len) {
+ NXTOK(begin, pos, &spf);
+ if (!spf.s[begin]) continue;
+
+ /* in local ruleset? */
+ if (!done && local_pos >= 0 && begin >= local_pos) {
+ if (begin < (local_pos + spflocal.len))
+ expdomain.len = 0;
+ else
+ if (!stralloc_copy(&expdomain, domain))
+ return SPF_NOMEM;
+ }
+
+ for (p = spf.s + begin;*p;++p)
+ if (*p == ':' || *p == '/' || *p == '=') break;
+
+ if (*p == '=') {
+ *p++ = 0;
+
+ /* modifiers are simply handled here */
+ if (str_equal(spf.s + begin, "redirect")) {
+ if (done) continue;
+
+ if (!spfexpand(&sa, p, domain->s)) return SPF_NOMEM;
+ stralloc_copy(domain, &sa);
+
+ hdr_unknown();
+ r = SPF_UNKNOWN;
+
+ goto redirect;
+ } else if (str_equal(spf.s + begin, "default")) {
+ if (done) continue;
+
+ for(da = default_aliases; da->alias; ++da)
+ if (str_equal(da->alias, p)) break;
+
+ r = da->defret;
+ } else if (str_equal(spf.s + begin, "exp")) {
+ strsalloc ssa = {0};
+
+ if (!main) continue;
+
+ if (!stralloc_copys(&sa, p)) return SPF_NOMEM;
+ switch(dns_txt(&ssa, &sa)) {
+ case DNS_MEM: return SPF_NOMEM;
+ case DNS_SOFT: continue; /* FIXME... */
+ case DNS_HARD: continue;
+ }
+
+ explanation.len = 0;
+ for(i = 0; i < ssa.len; i++) {
+ if (!stralloc_cat(&explanation, &ssa.sa[i])) return SPF_NOMEM;
+ if (i < (ssa.len - 1))
+ if (!stralloc_append(&explanation, "\n")) return SPF_NOMEM;
+
+ alloc_free(ssa.sa[i].s);
+ }
+ if (!stralloc_0(&explanation)) return SPF_NOMEM;
+ } /* and unknown modifiers are ignored */
+ } else if (!done) {
+ if (!stralloc_copys(&sa, spf.s + begin)) return SPF_NOMEM;
+ if (!stralloc_0(&sa)) return SPF_NOMEM;
+
+ switch(spf.s[begin]) {
+ case '-': begin++; prefix = SPF_FAIL; break;
+ case '~': begin++; prefix = SPF_SOFTFAIL; break;
+ case '+': begin++; prefix = SPF_OK; break;
+ case '?': begin++; prefix = SPF_NEUTRAL; break;
+ default: prefix = SPF_OK;
+ }
+
+ if (*p == '/') {
+ *p++ = 0;
+ q = spfmech(spf.s + begin, 0, p, domain->s);
+ } else {
+ if (*p) *p++ = 0;
+ i = str_chr(p, '/');
+ if (p[i] == '/') {
+ p[i++] = 0;
+ q = spfmech(spf.s + begin, p, p + i, domain->s);
+ } else if (i > 0)
+ q = spfmech(spf.s + begin, p, 0, domain->s);
+ else
+ q = spfmech(spf.s + begin, 0, 0, domain->s);
+ }
+
+ if (q == SPF_OK) q = prefix;
+
+ switch(q) {
+ case SPF_OK: hdr_pass(); break;
+ case SPF_NEUTRAL: hdr_neutral(); break;
+ case SPF_SYNTAX: hdr_syntax(); break;
+ case SPF_SOFTFAIL: hdr_softfail(); break;
+ case SPF_FAIL: hdr_fail(); break;
+ case SPF_EXT: hdr_ext(sa.s); break;
+ case SPF_ERROR:
+ if (!guessing)
+ break;
+ if (local_pos >= 0 && begin >= local_pos)
+ break;
+ hdr_none();
+ q = SPF_NONE;
+ break;
+ case SPF_NONE: continue;
+ }
+
+ r = q;
+ done = 1; /* we're done, no more mechanisms */
+ }
+ }
+
+ /* we fell through, no local rule applied */
+ if (!done && !stralloc_copy(&expdomain, domain)) return SPF_NOMEM;
+
+ alloc_free(spf.s);
+ alloc_free(sa.s);
+ return r;
+}
+
+int spfcheck()
+{
+ stralloc domain = {0};
+ int pos;
+ int r;
+
+ pos = byte_rchr(addr.s, addr.len, '@') + 1;
+ if (pos < addr.len) {
+ if (!stralloc_copys(&domain, addr.s + pos)) return SPF_NOMEM;
+ } else {
+ pos = str_rchr(helohost.s, '@');
+ if (helohost.s[pos]) {
+ if (!stralloc_copys(&domain, helohost.s + pos + 1)) return SPF_NOMEM;
+ } else
+ if (!stralloc_copys(&domain, helohost.s)) return SPF_NOMEM;
+ }
+ if (!stralloc_copys(&explanation, spfexp.s)) return SPF_NOMEM;
+ if (!stralloc_0(&explanation)) return SPF_NOMEM;
+ recursion = 0;
+
+ if (!remoteip || !ip_scan(remoteip, &ip)) {
+ hdr_unknown_msg("No IP address in conversation");
+ return SPF_UNKNOWN;
+ }
+
+ if (!stralloc_readyplus(&expdomain, 0)) return SPF_NOMEM;
+ if (!stralloc_readyplus(&errormsg, 0)) return SPF_NOMEM;
+ expdomain.len = 0;
+ errormsg.len = 0;
+ sender_fqdn.len = 0;
+ received = (char *) 0;
+
+ if ((ip.d[0] == 127 && ip.d[1] == 0 && ip.d[2] == 0 && ip.d[3] == 1) || ipme_is(&ip))
+ { hdr_pass(); r = SPF_OK; }
+ else
+ r = spflookup(&domain);
+
+ if (r < 0) r = SPF_UNKNOWN;
+
+ alloc_free(domain.s);
+ return r;
+}
+
+int spfexplanation(sa)
+stralloc *sa;
+{
+ return spfexpand(sa, explanation.s, expdomain.s);
+}
+
+int spfinfo(sa)
+stralloc *sa;
+{
+ stralloc tmp = {0};
+ if (!stralloc_copys(&tmp, received)) return 0;
+ if (!stralloc_0(&tmp)) return 0;
+ if (!spfexpand(sa, tmp.s, expdomain.s)) return 0;
+ alloc_free(tmp.s);
+ return 1;
+}
diff -Naur ./spf.h ../qmail-1.03-build-10/spf.h
--- ./spf.h 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/spf.h 2006-05-05 21:22:50.000000000 -0500
@@ -0,0 +1,20 @@
+#ifndef SPF_H
+#define SPF_H
+
+#define SPF_OK 0
+#define SPF_NONE 1
+#define SPF_UNKNOWN 2
+#define SPF_NEUTRAL 3
+#define SPF_SOFTFAIL 4
+#define SPF_FAIL 5
+#define SPF_ERROR 6
+#define SPF_NOMEM 7
+
+#define SPF_DEFEXP "See http://spf.pobox.com/" \
+ "why.html?sender=%{S}&ip=%{I}&receiver=%{xR}"
+
+extern int spfcheck();
+extern int spfexplanation();
+extern int spfinfo();
+
+#endif
diff -Naur ./spfquery.c ../qmail-1.03-build-10/spfquery.c
--- ./spfquery.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/spfquery.c 2006-05-05 21:22:50.000000000 -0500
@@ -0,0 +1,84 @@
+#include "substdio.h"
+#include "subfd.h"
+#include "stralloc.h"
+#include "alloc.h"
+#include "spf.h"
+#include "exit.h"
+
+void die(e,s) int e; char *s; { substdio_putsflush(subfderr,s); _exit(e); }
+void die_usage() { die(100,"fatal: invalid usage\nusage: spfquery <sender-ip> <sender-helo/ehlo> <envelope-from> [<local rules>] [<best guess rules>]\n"); }
+void die_nomem() { die(111,"fatal: out of memory\n"); }
+
+stralloc addr = {0};
+stralloc helohost = {0};
+char *remoteip;
+char *local;
+
+stralloc spflocal = {0};
+stralloc spfguess = {0};
+stralloc spfexp = {0};
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+ stralloc sa = {0};
+ int r;
+
+ if (argc < 4) die_usage();
+
+ remoteip = (char *)strdup(argv[1]);
+ local = "localhost";
+
+ if (!stralloc_copys(&helohost, argv[2])) die_nomem();
+ if (!stralloc_0(&helohost)) die_nomem();
+
+ if (!stralloc_copys(&addr, argv[3])) die_nomem();
+ if (!stralloc_0(&addr)) die_nomem();
+
+ if (argc > 4) {
+ if (!stralloc_copys(&spflocal, argv[4])) die_nomem();
+ if (spflocal.len && !stralloc_0(&spflocal)) die_nomem();
+ }
+
+ if (argc > 5) {
+ if (!stralloc_copys(&spfguess, argv[5])) die_nomem();
+ if (spfguess.len && !stralloc_0(&spfguess)) die_nomem();
+ }
+
+ if (argc > 6) {
+ if (!stralloc_copys(&spfexp, argv[6])) die_nomem();
+ } else
+ if (!stralloc_copys(&spfexp, SPF_DEFEXP)) die_nomem();
+ if (spfexp.len && !stralloc_0(&spfexp)) die_nomem();
+
+ dns_init(0);
+ r = spfcheck();
+ if (r == SPF_NOMEM) die_nomem();
+
+ substdio_puts(subfdout,"result=");
+ switch(r) {
+ case SPF_OK: substdio_puts(subfdout,"pass"); break;
+ case SPF_NONE: substdio_puts(subfdout,"none"); break;
+ case SPF_UNKNOWN: substdio_puts(subfdout,"unknown"); break;
+ case SPF_NEUTRAL: substdio_puts(subfdout,"neutral"); break;
+ case SPF_SOFTFAIL: substdio_puts(subfdout,"softfail"); break;
+ case SPF_FAIL: substdio_puts(subfdout,"fail"); break;
+ case SPF_ERROR: substdio_puts(subfdout,"error"); break;
+ }
+
+ if (r == SPF_FAIL) {
+ substdio_puts(subfdout,": ");
+ if (!spfexplanation(&sa)) die_nomem();
+ substdio_put(subfdout,sa.s,sa.len);
+ }
+
+ substdio_putsflush(subfdout,"\n");
+
+ substdio_puts(subfdout,"Received-SPF: ");
+ if (!spfinfo(&sa)) die_nomem();
+ substdio_put(subfdout,sa.s,sa.len);
+ substdio_putsflush(subfdout,"\n");
+
+ _exit(0);
+}
diff -Naur ./ssl_timeoutio.c ../qmail-1.03-build-10/ssl_timeoutio.c
--- ./ssl_timeoutio.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/ssl_timeoutio.c 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,94 @@
+#include "select.h"
+#include "error.h"
+#include "ndelay.h"
+#include "ssl_timeoutio.h"
+
+int ssl_timeoutio(int (*fun)(),
+ long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
+{
+ int n;
+ const long end = t + time(NULL);
+
+ do {
+ fd_set fds;
+ struct timeval tv;
+
+ const int r = buf ? fun(ssl, buf, len) : fun(ssl);
+ if (r > 0) return r;
+
+ t = end - time(NULL);
+ if (t < 0) break;
+ tv.tv_sec = t; tv.tv_usec = 0;
+
+ FD_ZERO(&fds);
+ switch (SSL_get_error(ssl, r))
+ {
+ default: return r; /* some other error */
+ case SSL_ERROR_WANT_READ:
+ FD_SET(rfd, &fds); n = select(rfd + 1, &fds, NULL, NULL, &tv);
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ FD_SET(wfd, &fds); n = select(wfd + 1, NULL, &fds, NULL, &tv);
+ break;
+ }
+
+ /* n is the number of descriptors that changed status */
+ } while (n > 0);
+
+ if (n != -1) errno = error_timeout;
+ return -1;
+}
+
+int ssl_timeoutaccept(long t, int rfd, int wfd, SSL *ssl)
+{
+ int r;
+
+ /* if connection is established, keep NDELAY */
+ if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1) return -1;
+ r = ssl_timeoutio(SSL_accept, t, rfd, wfd, ssl, NULL, 0);
+
+ if (r <= 0) { ndelay_off(rfd); ndelay_off(wfd); }
+ else SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
+
+ return r;
+}
+
+int ssl_timeoutconn(long t, int rfd, int wfd, SSL *ssl)
+{
+ int r;
+
+ /* if connection is established, keep NDELAY */
+ if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1) return -1;
+ r = ssl_timeoutio(SSL_connect, t, rfd, wfd, ssl, NULL, 0);
+
+ if (r <= 0) { ndelay_off(rfd); ndelay_off(wfd); }
+ else SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
+
+ return r;
+}
+
+int ssl_timeoutrehandshake(long t, int rfd, int wfd, SSL *ssl)
+{
+ int r;
+
+ SSL_renegotiate(ssl);
+ r = ssl_timeoutio(SSL_do_handshake, t, rfd, wfd, ssl, NULL, 0);
+ if (r <= 0 || ssl->type == SSL_ST_CONNECT) return r;
+
+ /* this is for the server only */
+ ssl->state = SSL_ST_ACCEPT;
+ return ssl_timeoutio(SSL_do_handshake, t, rfd, wfd, ssl, NULL, 0);
+}
+
+int ssl_timeoutread(long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
+{
+ if (!buf) return 0;
+ if (SSL_pending(ssl)) return SSL_read(ssl, buf, len);
+ return ssl_timeoutio(SSL_read, t, rfd, wfd, ssl, buf, len);
+}
+
+int ssl_timeoutwrite(long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
+{
+ if (!buf) return 0;
+ return ssl_timeoutio(SSL_write, t, rfd, wfd, ssl, buf, len);
+}
diff -Naur ./ssl_timeoutio.h ../qmail-1.03-build-10/ssl_timeoutio.h
--- ./ssl_timeoutio.h 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/ssl_timeoutio.h 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,21 @@
+#ifndef SSL_TIMEOUTIO_H
+#define SSL_TIMEOUTIO_H
+
+#include <openssl/ssl.h>
+
+/* the version is like this: 0xMNNFFPPS: major minor fix patch status */
+#if OPENSSL_VERSION_NUMBER < 0x00906000L
+# error "Need OpenSSL version at least 0.9.6"
+#endif
+
+int ssl_timeoutconn(long t, int rfd, int wfd, SSL *ssl);
+int ssl_timeoutaccept(long t, int rfd, int wfd, SSL *ssl);
+int ssl_timeoutrehandshake(long t, int rfd, int wfd, SSL *ssl);
+
+int ssl_timeoutread(long t, int rfd, int wfd, SSL *ssl, char *buf, int len);
+int ssl_timeoutwrite(long t, int rfd, int wfd, SSL *ssl, char *buf, int len);
+
+int ssl_timeoutio(
+ int (*fun)(), long t, int rfd, int wfd, SSL *ssl, char *buf, int len);
+
+#endif
diff -Naur ./str_cpyb.c ../qmail-1.03-build-10/str_cpyb.c
--- ./str_cpyb.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/str_cpyb.c 2006-05-05 21:22:50.000000000 -0500
@@ -0,0 +1,18 @@
+#include "str.h"
+
+unsigned int str_copyb(s,t,max)
+register char *s;
+register char *t;
+unsigned int max;
+{
+ register int len;
+
+ len = 0;
+ while (max-- > 0) {
+ if (!(*s = *t)) return len; ++s; ++t; ++len;
+ if (!(*s = *t)) return len; ++s; ++t; ++len;
+ if (!(*s = *t)) return len; ++s; ++t; ++len;
+ if (!(*s = *t)) return len; ++s; ++t; ++len;
+ }
+ return len;
+}
diff -Naur ./str.h ../qmail-1.03-build-10/str.h
--- ./str.h 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/str.h 2006-05-07 12:32:01.000000000 -0500
@@ -2,6 +2,7 @@
#define STR_H
extern unsigned int str_copy();
+extern unsigned int str_copyb();
extern int str_diff();
extern int str_diffn();
extern unsigned int str_len();
diff -Naur ./strpidt.c ../qmail-1.03-build-10/strpidt.c
--- ./strpidt.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/strpidt.c 2006-05-03 17:44:55.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+** Copyright 1998 - 2000 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "numlib.h"
+#include <string.h>
+
+static const char rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+char *str_pid_t(pid_t t, char *arg)
+{
+char buf[NUMBUFSIZE];
+char *p=buf+sizeof(buf)-1;
+
+ *p=0;
+ do
+ {
+ *--p= '0' + (t % 10);
+ t=t / 10;
+ } while(t);
+ return (strcpy(arg, p));
+}
diff -Naur ./strsalloc.c ../qmail-1.03-build-10/strsalloc.c
--- ./strsalloc.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/strsalloc.c 2006-05-05 21:22:51.000000000 -0500
@@ -0,0 +1,7 @@
+#include "alloc.h"
+#include "gen_allocdefs.h"
+#include "stralloc.h"
+#include "strsalloc.h"
+
+GEN_ALLOC_readyplus(strsalloc,stralloc,sa,len,a,i,n,x,10,strsalloc_readyplus)
+GEN_ALLOC_append(strsalloc,stralloc,sa,len,a,i,n,x,10,strsalloc_readyplus,strsalloc_append)
diff -Naur ./strsalloc.h ../qmail-1.03-build-10/strsalloc.h
--- ./strsalloc.h 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/strsalloc.h 2006-05-05 21:22:51.000000000 -0500
@@ -0,0 +1,12 @@
+#ifndef STRSALLOC_H
+#define STRSALLOC_H
+
+#include "stralloc.h"
+
+#include "gen_alloc.h"
+
+GEN_ALLOC_typedef(strsalloc,stralloc,sa,len,a)
+extern int strsalloc_readyplus();
+extern int strsalloc_append();
+
+#endif
diff -Naur ./strtimet.c ../qmail-1.03-build-10/strtimet.c
--- ./strtimet.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/strtimet.c 2006-05-03 17:44:55.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+** Copyright 1998 - 2000 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "numlib.h"
+#include <string.h>
+
+static const char rcsid[]="$Id: qmail-maildir++.patch,v 1.1.1.1.2.1 2005/01/19 23:35:23 tomcollins Exp $";
+
+char *str_time_t(time_t t, char *arg)
+{
+char buf[NUMBUFSIZE];
+char *p=buf+sizeof(buf)-1;
+
+ *p=0;
+ do
+ {
+ *--p= '0' + (t % 10);
+ t=t / 10;
+ } while(t);
+ return (strcpy(arg, p));
+}
diff -Naur ./TARGETS ../qmail-1.03-build-10/TARGETS
--- ./TARGETS 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/TARGETS 2006-05-09 23:52:11.000000000 -0500
@@ -10,16 +10,26 @@
qmail.o
quote.o
now.o
+base64.o
gfrom.o
myctime.o
slurpclose.o
make-makelib
makelib
+maildirflags.o
+maildirparsequota.o
+maildiropen.o
+maildirgetquota.o
+maildirquota.o
+overmaildirquota.o
+strtimet.o
+strpidt.o
case_diffb.o
case_diffs.o
case_lowerb.o
case_lowers.o
case_starts.o
+case_startb.o
case.a
getln.o
getln2.o
@@ -100,11 +110,14 @@
str_diff.o
str_diffn.o
str_cpy.o
+str_cpyb.o
str_chr.o
str_rchr.o
str_start.o
byte_chr.o
byte_rchr.o
+byte_cspn.o
+byte_rcspn.o
byte_diff.o
byte_copy.o
byte_cr.o
@@ -168,11 +181,15 @@
constmap.o
timeoutread.o
timeoutwrite.o
+tls.o
+ssl_timeoutio.o
timeoutconn.o
tcpto.o
dns.o
+spf.o
ip.o
ipalloc.o
+strsalloc.o
hassalen.h
ipme.o
ndelay.o
@@ -212,6 +229,9 @@
headerbody.o
hfield.o
token822.o
+spf.o
+spfquery.o
+spfquery
qmail-inject
predate.o
predate
@@ -252,11 +272,16 @@
qmail-qmtpd
qmail-smtpd.o
qmail-smtpd
+qregex.o
sendmail.o
sendmail
tcp-env.o
remoteinfo.o
tcp-env
+qmail-badmimetypes.o
+qmail-badmimetypes
+qmail-badloadertypes.o
+qmail-badloadertypes
qmail-newmrh.o
qmail-newmrh
config
@@ -270,8 +295,12 @@
dnsip
dnsmxip.o
dnsmxip
+dnstxt.o
+dnstxt
dnsfq.o
dnsfq
+qmail-dk
+qmail-dk.o
hostname.o
hostname
ipmeprint.o
@@ -320,6 +349,7 @@
binm2+df
binm3
binm3+df
+Makefile-cert
it
qmail-local.0
qmail-lspawn.0
@@ -352,6 +382,10 @@
qmail-qmtpd.0
qmail-smtpd.0
tcp-env.0
+qmail-badloadertype.8
+qmail-badloadertype.0
+qmail-badmimetype.8
+qmail-badmimetype.0
qmail-newmrh.8
qmail-newmrh.0
qreceipt.0
@@ -385,3 +419,6 @@
man
setup
check
+qregex.o
+chkuser.o
+update_tmprsadh
diff -Naur ./TARGETS.orig ../qmail-1.03-build-10/TARGETS.orig
--- ./TARGETS.orig 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/TARGETS.orig 2006-04-27 11:43:57.000000000 -0500
@@ -0,0 +1,394 @@
+auto-ccld.sh
+make-load
+find-systype
+systype
+load
+make-compile
+compile
+fork.h
+qmail-local.o
+qmail.o
+quote.o
+now.o
+base64.o
+gfrom.o
+myctime.o
+slurpclose.o
+make-makelib
+makelib
+case_diffb.o
+case_diffs.o
+case_lowerb.o
+case_lowers.o
+case_starts.o
+case.a
+getln.o
+getln2.o
+getln.a
+subgetopt.o
+sgetopt.o
+getopt.a
+sig_alarm.o
+hassgprm.h
+sig_block.o
+hassgact.h
+sig_catch.o
+sig_pause.o
+sig_pipe.o
+sig_child.o
+sig_hup.o
+sig_term.o
+sig_bug.o
+sig_misc.o
+sig.a
+open_append.o
+open_excl.o
+open_read.o
+open_trunc.o
+open_write.o
+open.a
+seek_cur.o
+seek_end.o
+seek_set.o
+seek_trunc.o
+seek.a
+hasflock.h
+lock_ex.o
+lock_exnb.o
+lock_un.o
+lock.a
+fd_copy.o
+fd_move.o
+fd.a
+haswaitp.h
+wait_pid.o
+wait_nohang.o
+wait.a
+env.o
+envread.o
+env.a
+stralloc_eady.o
+stralloc_pend.o
+stralloc_copy.o
+stralloc_opys.o
+stralloc_opyb.o
+stralloc_cat.o
+stralloc_cats.o
+stralloc_catb.o
+stralloc_arts.o
+stralloc.a
+alloc.o
+alloc_re.o
+alloc.a
+strerr_sys.o
+strerr_die.o
+strerr.a
+substdio.o
+substdi.o
+substdo.o
+subfderr.o
+subfdout.o
+subfdouts.o
+subfdin.o
+subfdins.o
+substdio_copy.o
+substdio.a
+error.o
+error_str.o
+error_temp.o
+error.a
+str_len.o
+str_diff.o
+str_diffn.o
+str_cpy.o
+str_chr.o
+str_rchr.o
+str_start.o
+byte_chr.o
+byte_rchr.o
+byte_diff.o
+byte_copy.o
+byte_cr.o
+byte_zero.o
+str.a
+fmt_str.o
+fmt_strn.o
+fmt_uint.o
+fmt_uint0.o
+fmt_ulong.o
+scan_ulong.o
+scan_8long.o
+fs.a
+datetime.o
+datetime_un.o
+datetime.a
+auto-str.o
+auto-str
+auto_qmail.c
+auto_qmail.o
+auto-int8.o
+auto-int8
+auto_patrn.c
+auto_patrn.o
+socket.lib
+qmail-local
+uint32.h
+qmail-lspawn.o
+select.h
+chkspawn.o
+auto-int.o
+auto-int
+auto_spawn.c
+auto_spawn.o
+chkspawn
+spawn.o
+chkshsgr.o
+chkshsgr
+hasshsgr.h
+prot.o
+coe.o
+cdb_hash.o
+cdb_unpack.o
+cdb_seek.o
+cdb.a
+auto-uid.o
+auto-uid
+auto-gid.o
+auto-gid
+auto_uids.c
+auto_uids.o
+qmail-lspawn
+qmail-getpw.o
+auto_break.c
+auto_break.o
+auto_usera.c
+auto_usera.o
+qmail-getpw
+qmail-remote.o
+control.o
+constmap.o
+timeoutread.o
+timeoutwrite.o
+tls.o
+ssl_timeoutio.o
+timeoutconn.o
+tcpto.o
+dns.o
+ip.o
+ipalloc.o
+hassalen.h
+ipme.o
+ndelay.o
+ndelay_off.o
+ndelay.a
+dns.lib
+qmail-remote
+qmail-rspawn.o
+tcpto_clean.o
+qmail-rspawn
+direntry.h
+qmail-clean.o
+fmtqfn.o
+auto_split.c
+auto_split.o
+qmail-clean
+qmail-send.o
+qsutil.o
+newfield.o
+prioq.o
+hasmkffo.h
+fifo.o
+hasnpbg1.h
+trigger.o
+readsubdir.o
+date822fmt.o
+qmail-send
+qmail-start.o
+qmail-start
+splogger.o
+syslog.lib
+splogger
+qmail-queue.o
+triggerpull.o
+qmail-queue
+qmail-inject.o
+headerbody.o
+hfield.o
+token822.o
+qmail-inject
+predate.o
+predate
+datemail
+mailsubj
+qmail-upq
+qmail-showctl.o
+qmail-showctl
+qmail-newu.o
+cdbmss.o
+cdbmake_pack.o
+cdbmake_hash.o
+cdbmake_add.o
+cdbmake.a
+qmail-newu
+qmail-pw2u.o
+qmail-pw2u
+qmail-qread.o
+qmail-qread
+qmail-qstat
+qmail-tcpto.o
+qmail-tcpto
+qmail-tcpok.o
+qmail-tcpok
+qmail-pop3d.o
+commands.o
+maildir.o
+qmail-pop3d
+qmail-popup.o
+qmail-popup
+qmail-qmqpc.o
+qmail-qmqpc
+qmail-qmqpd.o
+received.o
+qmail-qmqpd
+qmail-qmtpd.o
+rcpthosts.o
+qmail-qmtpd
+qmail-smtpd.o
+qmail-smtpd
+qregex.o
+sendmail.o
+sendmail
+tcp-env.o
+remoteinfo.o
+tcp-env
+qmail-newmrh.o
+qmail-newmrh
+config
+config-fast
+dnscname.o
+dnsdoe.o
+dnscname
+dnsptr.o
+dnsptr
+dnsip.o
+dnsip
+dnsmxip.o
+dnsmxip
+dnsfq.o
+dnsfq
+hostname.o
+hostname
+ipmeprint.o
+ipmeprint
+qreceipt.o
+qreceipt
+qsmhook.o
+qsmhook
+qbiff.o
+qbiff
+forward.o
+forward
+preline.o
+preline
+condredirect.o
+condredirect
+bouncesaying.o
+bouncesaying
+except.o
+except
+maildirmake.o
+maildirmake
+maildir2mbox.o
+maildir2mbox
+maildirwatch.o
+maildirwatch
+qail
+elq
+pinq
+idedit.o
+idedit
+install-big.o
+install.o
+install-big
+hier.o
+install
+instcheck.o
+instcheck
+home
+home+df
+proc
+proc+df
+binm1
+binm1+df
+binm2
+binm2+df
+binm3
+binm3+df
+Makefile-cert
+it
+qmail-local.0
+qmail-lspawn.0
+qmail-getpw.8
+qmail-getpw.0
+qmail-remote.0
+qmail-rspawn.0
+qmail-clean.0
+qmail-send.8
+qmail-send.0
+qmail-start.8
+qmail-start.0
+splogger.0
+qmail-queue.0
+qmail-inject.0
+mailsubj.0
+qmail-showctl.0
+qmail-newu.8
+qmail-newu.0
+qmail-pw2u.8
+qmail-pw2u.0
+qmail-qread.0
+qmail-qstat.0
+qmail-tcpto.0
+qmail-tcpok.0
+qmail-pop3d.0
+qmail-popup.0
+qmail-qmqpc.0
+qmail-qmqpd.0
+qmail-qmtpd.0
+qmail-smtpd.0
+tcp-env.0
+qmail-newmrh.8
+qmail-newmrh.0
+qreceipt.0
+qbiff.0
+forward.0
+preline.0
+condredirect.0
+bouncesaying.0
+except.0
+maildirmake.0
+maildir2mbox.0
+maildirwatch.0
+qmail.0
+qmail-limits.7
+qmail-limits.0
+qmail-log.0
+qmail-control.5
+qmail-control.0
+qmail-header.0
+qmail-users.5
+qmail-users.0
+dot-qmail.5
+dot-qmail.0
+qmail-command.0
+tcp-environ.0
+maildir.0
+mbox.0
+addresses.0
+envelopes.0
+forgeries.0
+man
+setup
+check
+chkuser.o
+update_tmprsadh
diff -Naur ./tcp-env.c ../qmail-1.03-build-10/tcp-env.c
--- ./tcp-env.c 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/tcp-env.c 2006-05-07 12:39:58.000000000 -0500
@@ -10,6 +10,7 @@
#include "scan.h"
#include "subgetopt.h"
#include "ip.h"
+#include "strsalloc.h"
#include "dns.h"
#include "byte.h"
#include "remoteinfo.h"
@@ -34,6 +35,7 @@
int argc;
char *argv[];
{
+ strsalloc ssa = {0};
int dummy;
char *proto;
int opt;
@@ -74,12 +76,13 @@
temp[ip_fmt(temp,&iplocal)] = 0;
if (!env_put2("TCPLOCALIP",temp)) die();
- switch(dns_ptr(&localname,&iplocal))
+ switch(dns_ptr(&ssa,&iplocal))
{
case DNS_MEM: die();
case DNS_SOFT:
if (!stralloc_copys(&localname,"softdnserror")) die();
case 0:
+ if (!stralloc_copy(&localname,&ssa.sa[0])) die();
if (!stralloc_0(&localname)) die();
case_lowers(localname.s);
if (!env_put2("TCPLOCALHOST",localname.s)) die();
@@ -99,12 +102,13 @@
temp[ip_fmt(temp,&ipremote)] = 0;
if (!env_put2("TCPREMOTEIP",temp)) die();
- switch(dns_ptr(&remotename,&ipremote))
+ switch(dns_ptr(&ssa,&ipremote))
{
case DNS_MEM: die();
case DNS_SOFT:
if (!stralloc_copys(&remotename,"softdnserror")) die();
case 0:
+ if (!stralloc_copy(&remotename,&ssa.sa[0])) die();
if (!stralloc_0(&remotename)) die();
case_lowers(remotename.s);
if (!env_put2("TCPREMOTEHOST",remotename.s)) die();
diff -Naur ./tls.c ../qmail-1.03-build-10/tls.c
--- ./tls.c 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/tls.c 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,25 @@
+#include "exit.h"
+#include "error.h"
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+int smtps = 0;
+SSL *ssl = NULL;
+
+void ssl_free(SSL *myssl) { SSL_shutdown(myssl); SSL_free(myssl); }
+void ssl_exit(int status) { if (ssl) ssl_free(ssl); _exit(status); }
+
+const char *ssl_error()
+{
+ int r = ERR_get_error();
+ if (!r) return NULL;
+ SSL_load_error_strings();
+ return ERR_error_string(r, NULL);
+}
+const char *ssl_error_str()
+{
+ const char *err = ssl_error();
+ if (err) return err;
+ if (!errno) return 0;
+ return (errno == error_timeout) ? "timed out" : error_str(errno);
+}
diff -Naur ./tls.h ../qmail-1.03-build-10/tls.h
--- ./tls.h 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/tls.h 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,16 @@
+#ifndef TLS_H
+#define TLS_H
+
+#include <openssl/ssl.h>
+
+extern int smtps;
+extern SSL *ssl;
+
+void ssl_free(SSL *myssl);
+void ssl_exit(int status);
+# define _exit ssl_exit
+
+const char *ssl_error();
+const char *ssl_error_str();
+
+#endif
diff -Naur ./update_tmprsadh.sh ../qmail-1.03-build-10/update_tmprsadh.sh
--- ./update_tmprsadh.sh 1969-12-31 17:00:00.000000000 -0700
+++ ../qmail-1.03-build-10/update_tmprsadh.sh 2006-04-27 11:10:31.000000000 -0500
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Update temporary RSA and DH keys
+# Frederik Vermeulen 2004-05-31 GPL
+
+umask 0077 || exit 0
+
+export PATH="$PATH:/usr/local/bin/ssl:/usr/sbin"
+
+openssl genrsa -out QMAIL/control/rsa512.new 512 &&
+chmod 600 QMAIL/control/rsa512.new &&
+chown UGQMAILD QMAIL/control/rsa512.new &&
+mv -f QMAIL/control/rsa512.new QMAIL/control/rsa512.pem
+echo
+
+openssl dhparam -2 -out QMAIL/control/dh512.new 512 &&
+chmod 600 QMAIL/control/dh512.new &&
+chown UGQMAILD QMAIL/control/dh512.new &&
+mv -f QMAIL/control/dh512.new QMAIL/control/dh512.pem
+echo
+
+openssl dhparam -2 -out QMAIL/control/dh1024.new 1024 &&
+chmod 600 QMAIL/control/dh1024.new &&
+chown UGQMAILD QMAIL/control/dh1024.new &&
+mv -f QMAIL/control/dh1024.new QMAIL/control/dh1024.pem
diff -Naur ./UPGRADE ../qmail-1.03-build-10/UPGRADE
--- ./UPGRADE 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/UPGRADE 2006-04-24 21:24:32.000000000 -0500
@@ -3,7 +3,7 @@
much more secure and reliable than sendmail, but that's not saying much.
-Here's how to upgrade to qmail 1.03. This procedure will overwrite the
+Here's how to upgrade to netqmail 1.05. This procedure will overwrite the
old qmail binaries. Furthermore, it may begin delivering messages from
the queue before you have had a chance to test it.
@@ -17,7 +17,7 @@
Before starting, compare conf* to your old conf*, and make any necessary
-changes. You can copy conf* from 1.02.
+changes. You can copy conf* from 1.02 or 1.03.
How to install:
diff -Naur ./VERSION ../qmail-1.03-build-10/VERSION
--- ./VERSION 1998-06-15 05:53:16.000000000 -0500
+++ ../qmail-1.03-build-10/VERSION 2006-04-24 21:24:32.000000000 -0500
@@ -1 +1 @@
-qmail 1.03
+netqmail 1.05