Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 675060 | Differences between
and this patch

Collapse All | Expand All

(-)../../netqmail-1.05-orig/netqmail-1.05/base64.c (+124 lines)
Line 0 Link Here
1
#include "base64.h"
2
#include "stralloc.h"
3
#include "substdio.h"
4
#include "str.h"
5
6
static char *b64alpha =
7
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
8
#define B64PAD '='
9
10
/* returns 0 ok, 1 illegal, -1 problem */
11
12
int b64decode(in,l,out)
13
const unsigned char *in;
14
int l;
15
stralloc *out; /* not null terminated */
16
{
17
  int p = 0;
18
  int n;
19
  unsigned int x;
20
  int i, j;
21
  char *s;
22
  unsigned char b[3];
23
24
  if (l == 0)
25
  {
26
    if (!stralloc_copys(out,"")) return -1;
27
    return 0;
28
  }
29
30
  while(in[l-1] == B64PAD) {
31
    p ++;
32
    l--;
33
  }
34
35
  n = (l + p) / 4;
36
  i = (n * 3) - p;
37
  if (!stralloc_ready(out,i)) return -1;
38
  out->len = i;
39
  s = out->s;
40
41
  for(i = 0; i < n - 1 ; i++) {
42
    x = 0;
43
    for(j = 0; j < 4; j++) {
44
      if(in[j] >= 'A' && in[j] <= 'Z')
45
        x = (x << 6) + (unsigned int)(in[j] - 'A' + 0);
46
      else if(in[j] >= 'a' && in[j] <= 'z')
47
        x = (x << 6) + (unsigned int)(in[j] - 'a' + 26);
48
      else if(in[j] >= '0' && in[j] <= '9')
49
        x = (x << 6) + (unsigned int)(in[j] - '0' + 52);
50
      else if(in[j] == '+')
51
        x = (x << 6) + 62;
52
      else if(in[j] == '/')
53
        x = (x << 6) + 63;
54
      else if(in[j] == '=')
55
        x = (x << 6);
56
    }
57
58
    s[2] = (unsigned char)(x & 255); x >>= 8;
59
    s[1] = (unsigned char)(x & 255); x >>= 8;
60
    s[0] = (unsigned char)(x & 255); x >>= 8;
61
    s += 3; in += 4;
62
  }
63
64
  x = 0;
65
  for(j = 0; j < 4; j++) {
66
    if(in[j] >= 'A' && in[j] <= 'Z')
67
      x = (x << 6) + (unsigned int)(in[j] - 'A' + 0);
68
    else if(in[j] >= 'a' && in[j] <= 'z')
69
      x = (x << 6) + (unsigned int)(in[j] - 'a' + 26);
70
    else if(in[j] >= '0' && in[j] <= '9')
71
      x = (x << 6) + (unsigned int)(in[j] - '0' + 52);
72
    else if(in[j] == '+')
73
      x = (x << 6) + 62;
74
    else if(in[j] == '/')
75
      x = (x << 6) + 63;
76
    else if(in[j] == '=')
77
      x = (x << 6);
78
  }
79
80
  b[2] = (unsigned char)(x & 255); x >>= 8;
81
  b[1] = (unsigned char)(x & 255); x >>= 8;
82
  b[0] = (unsigned char)(x & 255); x >>= 8;
83
84
  for(i = 0; i < 3 - p; i++)
85
    s[i] = b[i];
86
87
  return 0;
88
}
89
90
int b64encode(in,out)
91
stralloc *in;
92
stralloc *out; /* not null terminated */
93
{
94
  unsigned char a, b, c;
95
  int i;
96
  char *s;
97
98
  if (in->len == 0)
99
  {
100
    if (!stralloc_copys(out,"")) return -1;
101
    return 0;
102
  }
103
104
  i = in->len / 3 * 4 + 4;   
105
  if (!stralloc_ready(out,i)) return -1;
106
  s = out->s;
107
108
  for (i = 0;i < in->len;i += 3) {
109
    a = in->s[i];
110
    b = i + 1 < in->len ? in->s[i + 1] : 0;
111
    c = i + 2 < in->len ? in->s[i + 2] : 0;
112
113
    *s++ = b64alpha[a >> 2];
114
    *s++ = b64alpha[((a & 3 ) << 4) | (b >> 4)];
115
116
    if (i + 1 >= in->len) *s++ = B64PAD;
117
    else *s++ = b64alpha[((b & 15) << 2) | (c >> 6)];
118
119
    if (i + 2 >= in->len) *s++ = B64PAD;
120
    else *s++ = b64alpha[c & 63];
121
  }
122
  out->len = s - out->s;
123
  return 0;
124
}
(-)../../netqmail-1.05-orig/netqmail-1.05/base64.h (+7 lines)
Line 0 Link Here
1
#ifndef BASE64_H
2
#define BASE64_H
3
4
extern int b64decode();
5
extern int b64encode();
6
7
#endif
(-)../../netqmail-1.05-orig/netqmail-1.05/case_startb.c (+21 lines)
Line 0 Link Here
1
#include "case.h"
2
3
int case_startb(s,len,t)
4
register char *s;
5
unsigned int len;
6
register char *t;
7
{
8
  register unsigned char x;
9
  register unsigned char y;
10
11
  for (;;) {
12
    y = *t++ - 'A';
13
    if (y <= 'Z' - 'A') y += 'a'; else y += 'A';
14
    if (!y) return 1;
15
    if (!len) return 0;
16
    --len;
17
    x = *s++ - 'A';
18
    if (x <= 'Z' - 'A') x += 'a'; else x += 'A';
19
    if (x != y) return 0;
20
  }
21
}
(-)../../netqmail-1.05-orig/netqmail-1.05/conf-cc (-1 / +1 lines)
Lines 1-3 Link Here
1
cc -O2
1
cc -O2 -DTLS=20070408 -I/usr/local/ssl/include
2
2
3
This will be used to compile .c files.
3
This will be used to compile .c files.
(-)../../netqmail-1.05-orig/netqmail-1.05/dns.c (-5 / +10 lines)
Lines 267-278 Link Here
267
int pref;
267
int pref;
268
{
268
{
269
 int r;
269
 int r;
270
 struct ip_mx ix;
270
 struct ip_mx ix = {0};
271
271
272
 if (!stralloc_copy(&glue,sa)) return DNS_MEM;
272
 if (!stralloc_copy(&glue,sa)) return DNS_MEM;
273
 if (!stralloc_0(&glue)) return DNS_MEM;
273
 if (!stralloc_0(&glue)) return DNS_MEM;
274
 if (glue.s[0]) {
274
 if (glue.s[0]) {
275
   ix.pref = 0;
276
   if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
275
   if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
277
    {
276
    {
278
     if (!ipalloc_append(ia,&ix)) return DNS_MEM;
277
     if (!ipalloc_append(ia,&ix)) return DNS_MEM;
Lines 291-299 Link Here
291
   ix.ip = ip;
290
   ix.ip = ip;
292
   ix.pref = pref;
291
   ix.pref = pref;
293
   if (r == DNS_SOFT) return DNS_SOFT;
292
   if (r == DNS_SOFT) return DNS_SOFT;
294
   if (r == 1)
293
   if (r == 1) {
294
#ifdef IX_FQDN
295
     ix.fqdn = glue.s;
296
#endif
295
     if (!ipalloc_append(ia,&ix)) return DNS_MEM;
297
     if (!ipalloc_append(ia,&ix)) return DNS_MEM;
296
  }
298
  }
299
  }
300
#ifdef IX_FQDN
301
 glue.s = 0;
302
#endif
297
 return 0;
303
 return 0;
298
}
304
}
299
305
Lines 313-319 Link Here
313
{
319
{
314
 int r;
320
 int r;
315
 struct mx { stralloc sa; unsigned short p; } *mx;
321
 struct mx { stralloc sa; unsigned short p; } *mx;
316
 struct ip_mx ix;
322
 struct ip_mx ix = {0};
317
 int nummx;
323
 int nummx;
318
 int i;
324
 int i;
319
 int j;
325
 int j;
Lines 325-331 Link Here
325
 if (!stralloc_copy(&glue,sa)) return DNS_MEM;
331
 if (!stralloc_copy(&glue,sa)) return DNS_MEM;
326
 if (!stralloc_0(&glue)) return DNS_MEM;
332
 if (!stralloc_0(&glue)) return DNS_MEM;
327
 if (glue.s[0]) {
333
 if (glue.s[0]) {
328
   ix.pref = 0;
329
   if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
334
   if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
330
    {
335
    {
331
     if (!ipalloc_append(ia,&ix)) return DNS_MEM;
336
     if (!ipalloc_append(ia,&ix)) return DNS_MEM;
(-)../../netqmail-1.05-orig/netqmail-1.05/FILES.auth (+18 lines)
Line 0 Link Here
1
The qmail-smtpd Auth patch modifies the following QMAIL 1.03 files:
2
3
= TARGETS
4
= Makefile
5
= qmail-smtpd.c
6
= qmail-smtpd.8
7
8
Added files:
9
10
+ base64.c
11
+ base64.h
12
+ case_startb.c
13
14
Informational files:
15
16
% install_smtpd-auth.sh  (Installation shell script)
17
% README.auth
18
% README.auth.old (old description of SMTP Auth)
(-)../../netqmail-1.05-orig/netqmail-1.05/hier.c (+3 lines)
Lines 143-148 Link Here
143
  c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0755);
143
  c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0755);
144
  c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0755);
144
  c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0755);
145
  c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0755);
145
  c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0755);
146
#ifdef TLS
147
  c(auto_qmail,"bin","update_tmprsadh",auto_uido,auto_gidq,0755);
148
#endif
146
149
147
  c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644);
150
  c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644);
148
  c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644);
151
  c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644);
(-)../../netqmail-1.05-orig/netqmail-1.05/install_auth.sh (+99 lines)
Line 0 Link Here
1
#!/bin/sh
2
#
3
# qmail-smtpd AUTH (UN)INSTALL Script (install_auth.sh)
4
# -----------------------------------------------------
5
#
6
# Purpose:      To install and uninstall the qmail-smtpd Authentication Patch
7
#
8
# Parameters:   -u (uninstall)
9
#	        VRF (Version to be uninstalled)
10
#
11
# Usage:        ./install_auth.sh [-u] [Version]
12
#
13
#		Installation: 	./install_auth.sh
14
# 		Uninstallation: ./install_auth.sh -u 105
15
#
16
# Return Codes: 0 - Patches applied successfully
17
#		1 - Original QMAIL files not found (Patch not extracted in QMAIL source directory)
18
#		2 - Patch files not found 
19
#
20
# Output:	install_auth.log
21
#
22
# History:      1.0.0 - Erwin Hoffmann - Initial release
23
#		1.0.1 - 	       - grep fix; Gentoo fix
24
#		1.0.2 -			 removed '-v' optio for cp
25
#
26
#---------------------------------------------------------------------------------------
27
#
28
DATE=$(date)
29
LOCDIR=${PWD}
30
QMAILHOME=$(head -n 1 conf-qmail)
31
SOLARIS=$(sh ./find-systype.sh | grep -ci "SunOS")
32
LOGFILE=auth.log
33
TARGETS=FILES.auth
34
IFSKEEP=${IFS}
35
REL=057 # Should be identical to qmail-smtpd AUTH level
36
BUILD=2005024212941
37
38
39
if [ $# -eq 0 ] ; then
40
41
	echo "Installing qmail-smtpd AUTH $REL (Build $BUILD) at $DATE <<<" | tee -a $LOGFILE 2>&1 
42
43
	for FILE in $(grep "^= " ${TARGETS} | awk '{print $2}'); do
44
		echo "Targeting file $FILE ..." | tee -a $LOGFILE 2>&1
45
		if [ -s ${FILE} ] ; then
46
			cp ${FILE} ${FILE}.$REL | tee -a $LOGFILE 2>&1
47
			echo "--> ${FILE} copied to ${FILE}.$REL" | tee -a $LOGFILE 2>&1
48
		else
49
			echo "${FILE} not found !"
50
			exit 1
51
		fi
52
		if [ -s ${FILE}.patch ] ; then
53
			if [ ${SOLARIS} -gt 0 ]; then
54
				echo "--> Patching qmail source file ${FILE} for Solaris ...." | tee -a $LOGFILE 2>&1
55
				patch -i ${FILE}.patch ${FILE} 2>&1 | tee -a $LOGFILE
56
			else
57
				echo "--> Patching qmail source file ${FILE}  ...." | tee -a $LOGFILE 2>&1
58
				patch ${FILE} ${FILE}.patch 2>&1 | tee -a $LOGFILE
59
			fi
60
		else
61
			echo "!! ${FILE}.patch not found !"
62
			exit 2
63
		fi
64
	done 
65
66
67
	echo "Copying documentation and samples to ${QMAILHOME}/doc/ ..." | tee -a $LOGFILE 2>&1 
68
69
	cp README.auth* ${QMAILHOME}/doc/ | tee -a $LOGFILE 2>&1
70
	echo ""
71
	echo "If you dont wont CRAM-MD5 suport disable '#define CRAM_MD5' in qmail-smtpd !"
72
	echo "Installation of qmail-smtpd AUTH $REL (Build $BUILD) finished at $DATE <<<" | tee -a $LOGFILE 2>&1 
73
74
# Now go for the uninstallation....
75
76
elif [ "$1" = "-u" ] ; then
77
78
# Get the Version Number from INPUT 
79
80
	if [ $# -eq 2 ] ; then
81
		REL=$2
82
	fi
83
84
	echo "De-installing qmail-smtpd AUTH $REL (Build $BUILD) at $DATE <<<" | tee -a $LOGFILE 2>&1 
85
86
	for FILE in $(grep "^= " ${TARGETS} | awk '{print $2}'); do
87
		echo "Targeting file $FILE ..." | tee -a $LOGFILE 2>&1
88
		if [ -s ${FILE}.$REL ] ; then
89
			mv ${FILE}.$REL ${FILE} | tee -a $LOGFILE 2>&1
90
			touch ${FILE}
91
			echo "--> ${FILE}.$REL moved to ${FILE}" | tee -a $LOGFILE 2>&1
92
		else
93
			echo "!! ${FILE}.$REL not found !"
94
		fi
95
	done
96
	echo "De-installation of qmail-smtpd AUTH $REL (Build $BUILD) finished at $DATE <<<" | tee -a $LOGFILE 2>&1 
97
fi
98
99
exit 0
(-)../../netqmail-1.05-orig/netqmail-1.05/ipalloc.h (+8 lines)
Lines 3-9 Link Here
3
3
4
#include "ip.h"
4
#include "ip.h"
5
5
6
#ifdef TLS
7
# define IX_FQDN 1
8
#endif
9
10
#ifdef IX_FQDN
11
struct ip_mx { struct ip_address ip; int pref; char *fqdn; } ;
12
#else
6
struct ip_mx { struct ip_address ip; int pref; } ;
13
struct ip_mx { struct ip_address ip; int pref; } ;
14
#endif
7
15
8
#include "gen_alloc.h"
16
#include "gen_alloc.h"
9
17
(-)../../netqmail-1.05-orig/netqmail-1.05/Makefile (-5 / +48 lines)
Lines 136-141 Link Here
136
compile auto_usera.c
136
compile auto_usera.c
137
	./compile auto_usera.c
137
	./compile auto_usera.c
138
138
139
base64.o: \
140
compile base64.c base64.h stralloc.h substdio.h str.h
141
	./compile base64.c
142
139
binm1: \
143
binm1: \
140
binm1.sh conf-qmail
144
binm1.sh conf-qmail
141
	cat binm1.sh \
145
	cat binm1.sh \
Lines 808-814 Link Here
808
forward preline condredirect bouncesaying except maildirmake \
812
forward preline condredirect bouncesaying except maildirmake \
809
maildir2mbox maildirwatch qail elq pinq idedit install-big install \
813
maildir2mbox maildirwatch qail elq pinq idedit install-big install \
810
instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \
814
instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \
811
binm3 binm3+df
815
binm3 binm3+df update_tmprsadh
812
816
813
load: \
817
load: \
814
make-load warn-auto.sh systype
818
make-load warn-auto.sh systype
Lines 1444-1449 Link Here
1444
substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib
1448
substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib
1445
	./load qmail-remote control.o constmap.o timeoutread.o \
1449
	./load qmail-remote control.o constmap.o timeoutread.o \
1446
	timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \
1450
	timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \
1451
	tls.o ssl_timeoutio.o -L/usr/local/ssl/lib -lssl -lcrypto \
1447
	ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
1452
	ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
1448
	lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
1453
	lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
1449
	str.a fs.a auto_qmail.o  `cat dns.lib` `cat socket.lib`
1454
	str.a fs.a auto_qmail.o  `cat dns.lib` `cat socket.lib`
Lines 1536-1547 Link Here
1536
timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
1541
timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
1537
date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
1542
date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
1538
open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \
1543
open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \
1539
fs.a auto_qmail.o socket.lib
1544
fs.a auto_qmail.o base64.o socket.lib
1540
	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
1545
	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
1541
	timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
1546
	timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
1547
	tls.o ssl_timeoutio.o ndelay.a -L/usr/local/ssl/lib -lssl -lcrypto \
1542
	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
1548
	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
1543
	datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
1549
	datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
1544
	alloc.a substdio.a error.a str.a fs.a auto_qmail.o  `cat \
1550
	alloc.a substdio.a error.a str.a fs.a auto_qmail.o base64.o  `cat \
1545
	socket.lib`
1551
	socket.lib`
1546
1552
1547
qmail-smtpd.0: \
1553
qmail-smtpd.0: \
Lines 1553-1559 Link Here
1553
substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
1559
substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
1554
error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \
1560
error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \
1555
substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
1561
substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
1556
exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h
1562
exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h base64.h
1557
	./compile qmail-smtpd.c
1563
	./compile qmail-smtpd.c
1558
1564
1559
qmail-start: \
1565
qmail-start: \
Lines 1827-1833 Link Here
1827
ipalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h ndelay.c \
1833
ipalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h ndelay.c \
1828
ndelay_off.c direntry.3 direntry.h1 direntry.h2 trydrent.c prot.h \
1834
ndelay_off.c direntry.3 direntry.h1 direntry.h2 trydrent.c prot.h \
1829
prot.c chkshsgr.c warn-shsgr tryshsgr.c ipme.h ipme.c trysalen.c \
1835
prot.c chkshsgr.c warn-shsgr tryshsgr.c ipme.h ipme.c trysalen.c \
1830
maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c
1836
maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c \
1837
update_tmprsadh
1831
	shar -m `cat FILES` > shar
1838
	shar -m `cat FILES` > shar
1832
	chmod 400 shar
1839
	chmod 400 shar
1833
1840
Lines 2108-2113 Link Here
2108
compile timeoutwrite.c timeoutwrite.h select.h error.h readwrite.h
2115
compile timeoutwrite.c timeoutwrite.h select.h error.h readwrite.h
2109
	./compile timeoutwrite.c
2116
	./compile timeoutwrite.c
2110
2117
2118
qmail-smtpd: tls.o ssl_timeoutio.o ndelay.a
2119
qmail-remote: tls.o ssl_timeoutio.o
2120
qmail-smtpd.o: tls.h ssl_timeoutio.h
2121
qmail-remote.o: tls.h ssl_timeoutio.h
2122
2123
tls.o: \
2124
compile tls.c exit.h error.h
2125
	./compile tls.c
2126
2127
ssl_timeoutio.o: \
2128
compile ssl_timeoutio.c ssl_timeoutio.h select.h error.h ndelay.h
2129
	./compile ssl_timeoutio.c
2130
2111
token822.o: \
2131
token822.o: \
2112
compile token822.c stralloc.h gen_alloc.h alloc.h str.h token822.h \
2132
compile token822.c stralloc.h gen_alloc.h alloc.h str.h token822.h \
2113
gen_alloc.h gen_allocdefs.h
2133
gen_alloc.h gen_allocdefs.h
Lines 2139-2141 Link Here
2139
wait_pid.o: \
2159
wait_pid.o: \
2140
compile wait_pid.c error.h haswaitp.h
2160
compile wait_pid.c error.h haswaitp.h
2141
	./compile wait_pid.c
2161
	./compile wait_pid.c
2162
2163
cert cert-req: \
2164
Makefile-cert
2165
	@$(MAKE) -sf $< $@
2166
2167
Makefile-cert: \
2168
conf-qmail conf-users conf-groups Makefile-cert.mk
2169
	@cat Makefile-cert.mk \
2170
	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
2171
	> $@
2172
2173
update_tmprsadh: \
2174
conf-qmail conf-users conf-groups update_tmprsadh.sh
2175
	@cat update_tmprsadh.sh\
2176
	| sed s}UGQMAILD}"`head -2 conf-users|tail -1`:`head -1 conf-groups`"}g \
2177
	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
2178
	> $@
2179
	chmod 755 update_tmprsadh 
2180
2181
tmprsadh: \
2182
update_tmprsadh
2183
	echo "Creating new temporary RSA and DH parameters"
2184
	./update_tmprsadh
(-)../../netqmail-1.05-orig/netqmail-1.05/Makefile-cert.mk (+21 lines)
Line 0 Link Here
1
cert-req: req.pem
2
cert cert-req: QMAIL/control/clientcert.pem
3
	@:
4
5
QMAIL/control/clientcert.pem: QMAIL/control/servercert.pem
6
	ln -s $< $@
7
8
QMAIL/control/servercert.pem:
9
	PATH=$$PATH:/usr/local/ssl/bin \
10
		openssl req -new -x509 -nodes -days 366 -out $@ -keyout $@
11
	chmod 640 $@
12
	chown `head -2 conf-users | tail -1`:`head -1 conf-groups` $@
13
14
req.pem:
15
	PATH=$$PATH:/usr/local/ssl/bin openssl req \
16
		-new -nodes -out $@ -keyout QMAIL/control/servercert.pem
17
	chmod 640 QMAIL/control/servercert.pem
18
	chown `head -2 conf-users | tail -1`:`head -1 conf-groups` QMAIL/control/servercert.pem
19
	@echo
20
	@echo "Send req.pem to your CA to obtain signed_req.pem, and do:"
21
	@echo "cat signed_req.pem >> QMAIL/control/servercert.pem"
(-)../../netqmail-1.05-orig/netqmail-1.05/qmail-control.9 (+10 lines)
Lines 43-53 Link Here
43
.I badmailfrom	\fR(none)	\fRqmail-smtpd
43
.I badmailfrom	\fR(none)	\fRqmail-smtpd
44
.I bouncefrom	\fRMAILER-DAEMON	\fRqmail-send
44
.I bouncefrom	\fRMAILER-DAEMON	\fRqmail-send
45
.I bouncehost	\fIme	\fRqmail-send
45
.I bouncehost	\fIme	\fRqmail-send
46
.I clientca.pem	\fR(none)	\fRqmail-smtpd
47
.I clientcert.pem	\fR(none)	\fRqmail-remote
46
.I concurrencylocal	\fR10	\fRqmail-send
48
.I concurrencylocal	\fR10	\fRqmail-send
47
.I concurrencyremote	\fR20	\fRqmail-send
49
.I concurrencyremote	\fR20	\fRqmail-send
48
.I defaultdomain	\fIme	\fRqmail-inject
50
.I defaultdomain	\fIme	\fRqmail-inject
49
.I defaulthost	\fIme	\fRqmail-inject
51
.I defaulthost	\fIme	\fRqmail-inject
50
.I databytes	\fR0	\fRqmail-smtpd
52
.I databytes	\fR0	\fRqmail-smtpd
53
.I dh1024.pem	\fR(none)	\fRqmail-smtpd
54
.I dh512.pem	\fR(none)	\fRqmail-smtpd
51
.I doublebouncehost	\fIme	\fRqmail-send
55
.I doublebouncehost	\fIme	\fRqmail-send
52
.I doublebounceto	\fRpostmaster	\fRqmail-send
56
.I doublebounceto	\fRpostmaster	\fRqmail-send
53
.I envnoathost	\fIme	\fRqmail-send
57
.I envnoathost	\fIme	\fRqmail-send
Lines 61-71 Link Here
61
.I qmqpservers	\fR(none)	\fRqmail-qmqpc
65
.I qmqpservers	\fR(none)	\fRqmail-qmqpc
62
.I queuelifetime	\fR604800	\fRqmail-send
66
.I queuelifetime	\fR604800	\fRqmail-send
63
.I rcpthosts	\fR(none)	\fRqmail-smtpd
67
.I rcpthosts	\fR(none)	\fRqmail-smtpd
68
.I rsa512.pem	\fR(none)	\fRqmail-smtpd
69
.I servercert.pem	\fR(none)	\fRqmail-smtpd
64
.I smtpgreeting	\fIme	\fRqmail-smtpd
70
.I smtpgreeting	\fIme	\fRqmail-smtpd
65
.I smtproutes	\fR(none)	\fRqmail-remote
71
.I smtproutes	\fR(none)	\fRqmail-remote
66
.I timeoutconnect	\fR60	\fRqmail-remote
72
.I timeoutconnect	\fR60	\fRqmail-remote
67
.I timeoutremote	\fR1200	\fRqmail-remote
73
.I timeoutremote	\fR1200	\fRqmail-remote
68
.I timeoutsmtpd	\fR1200	\fRqmail-smtpd
74
.I timeoutsmtpd	\fR1200	\fRqmail-smtpd
75
.I tlsclients	\fR(none)	\fRqmail-smtpd
76
.I tlsclientciphers	\fR(none)	\fRqmail-remote
77
.I tlshosts/FQDN.pem	\fR(none)	\fRqmail-remote
78
.I tlsserverciphers	\fR(none)	\fRqmail-smtpd
69
.I virtualdomains	\fR(none)	\fRqmail-send
79
.I virtualdomains	\fR(none)	\fRqmail-send
70
.fi
80
.fi
71
.RE
81
.RE
(-)../../netqmail-1.05-orig/netqmail-1.05/qmail-remote.8 (+43 lines)
Lines 114-119 Link Here
114
always exits zero.
114
always exits zero.
115
.SH "CONTROL FILES"
115
.SH "CONTROL FILES"
116
.TP 5
116
.TP 5
117
.I clientcert.pem
118
SSL certificate that is used to authenticate with the remote server
119
during a TLS session.
120
.TP 5
117
.I helohost
121
.I helohost
118
Current host name,
122
Current host name,
119
for use solely in saying hello to the remote SMTP server.
123
for use solely in saying hello to the remote SMTP server.
Lines 123-128 Link Here
123
otherwise
127
otherwise
124
.B qmail-remote
128
.B qmail-remote
125
refuses to run.
129
refuses to run.
130
131
.TP 5
132
.I notlshosts/<FQDN>
133
.B qmail-remote
134
will not try TLS on servers for which this file exists
135
.RB ( <FQDN>
136
is the fully-qualified domain name of the server). 
137
.IR (tlshosts/<FQDN>.pem 
138
takes precedence over this file however).
139
126
.TP 5
140
.TP 5
127
.I smtproutes
141
.I smtproutes
128
Artificial SMTP routes.
142
Artificial SMTP routes.
Lines 156-161 Link Here
156
this tells
170
this tells
157
.B qmail-remote
171
.B qmail-remote
158
to look up MX records as usual.
172
to look up MX records as usual.
173
.I port 
174
value of 465 (deprecated smtps port) causes TLS session to be started.
159
.I smtproutes
175
.I smtproutes
160
may include wildcards:
176
may include wildcards:
161
177
Lines 195-200 Link Here
195
.B qmail-remote
211
.B qmail-remote
196
will wait for each response from the remote SMTP server.
212
will wait for each response from the remote SMTP server.
197
Default: 1200.
213
Default: 1200.
214
215
.TP 5
216
.I tlsclientciphers
217
A set of OpenSSL client cipher strings. Multiple ciphers
218
contained in a string should be separated by a colon.
219
220
.TP 5
221
.I tlshosts/<FQDN>.pem
222
.B qmail-remote
223
requires TLS authentication from servers for which this file exists
224
.RB ( <FQDN>
225
is the fully-qualified domain name of the server). One of the
226
.I dNSName
227
or the
228
.I CommonName
229
attributes have to match. The file contains the trusted CA certificates.
230
231
.B WARNING:
232
this option may cause mail to be delayed, bounced, doublebounced, or lost.
233
234
.TP 5
235
.I tlshosts/exhaustivelist
236
if this file exists
237
no TLS will be tried on hosts other than those for which a file
238
.B tlshosts/<FQDN>.pem
239
exists.
240
198
.SH "SEE ALSO"
241
.SH "SEE ALSO"
199
addresses(5),
242
addresses(5),
200
envelopes(5),
243
envelopes(5),
(-)../../netqmail-1.05-orig/netqmail-1.05/qmail-remote.c (+344 lines)
Lines 48-53 Link Here
48
48
49
struct ip_address partner;
49
struct ip_address partner;
50
50
51
#ifdef TLS
52
# include <sys/stat.h>
53
# include "tls.h"
54
# include "ssl_timeoutio.h"
55
# include <openssl/x509v3.h>
56
# define EHLO 1
57
58
int tls_init();
59
const char *ssl_err_str = 0;
60
#endif 
61
51
void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
62
void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
52
void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
63
void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
53
void zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); }
64
void zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); }
Lines 99-104 Link Here
99
  outhost();
110
  outhost();
100
  out(" but connection died. ");
111
  out(" but connection died. ");
101
  if (flagcritical) out("Possible duplicate! ");
112
  if (flagcritical) out("Possible duplicate! ");
113
#ifdef TLS
114
  if (ssl_err_str) { out(ssl_err_str); out(" "); }
115
#endif
102
  out("(#4.4.2)\n");
116
  out("(#4.4.2)\n");
103
  zerodie();
117
  zerodie();
104
}
118
}
Lines 110-115 Link Here
110
int saferead(fd,buf,len) int fd; char *buf; int len;
124
int saferead(fd,buf,len) int fd; char *buf; int len;
111
{
125
{
112
  int r;
126
  int r;
127
#ifdef TLS
128
  if (ssl) {
129
    r = ssl_timeoutread(timeout, smtpfd, smtpfd, ssl, buf, len);
130
    if (r < 0) ssl_err_str = ssl_error_str();
131
  } else
132
#endif
113
  r = timeoutread(timeout,smtpfd,buf,len);
133
  r = timeoutread(timeout,smtpfd,buf,len);
114
  if (r <= 0) dropped();
134
  if (r <= 0) dropped();
115
  return r;
135
  return r;
Lines 117-122 Link Here
117
int safewrite(fd,buf,len) int fd; char *buf; int len;
137
int safewrite(fd,buf,len) int fd; char *buf; int len;
118
{
138
{
119
  int r;
139
  int r;
140
#ifdef TLS
141
  if (ssl) {
142
    r = ssl_timeoutwrite(timeout, smtpfd, smtpfd, ssl, buf, len);
143
    if (r < 0) ssl_err_str = ssl_error_str();
144
  } else
145
#endif 
120
  r = timeoutwrite(timeout,smtpfd,buf,len);
146
  r = timeoutwrite(timeout,smtpfd,buf,len);
121
  if (r <= 0) dropped();
147
  if (r <= 0) dropped();
122
  return r;
148
  return r;
Lines 163-168 Link Here
163
  return code;
189
  return code;
164
}
190
}
165
191
192
#ifdef EHLO
193
saa ehlokw = {0}; /* list of EHLO keywords and parameters */
194
int maxehlokwlen = 0;
195
196
unsigned long ehlo()
197
{
198
  stralloc *sa;
199
  char *s, *e, *p;
200
  unsigned long code;
201
202
  if (ehlokw.len > maxehlokwlen) maxehlokwlen = ehlokw.len;
203
  ehlokw.len = 0;
204
205
# ifdef MXPS
206
  if (type == 's') return 0;
207
# endif
208
209
  substdio_puts(&smtpto, "EHLO ");
210
  substdio_put(&smtpto, helohost.s, helohost.len);
211
  substdio_puts(&smtpto, "\r\n");
212
  substdio_flush(&smtpto);
213
214
  code = smtpcode();
215
  if (code != 250) return code;
216
217
  s = smtptext.s;
218
  while (*s++ != '\n') ; /* skip the first line: contains the domain */
219
220
  e = smtptext.s + smtptext.len - 6; /* 250-?\n */
221
  while (s <= e)
222
  {
223
    int wasspace = 0;
224
225
    if (!saa_readyplus(&ehlokw, 1)) temp_nomem();
226
    sa = ehlokw.sa + ehlokw.len++;
227
    if (ehlokw.len > maxehlokwlen) *sa = sauninit; else sa->len = 0;
228
229
     /* smtptext is known to end in a '\n' */
230
     for (p = (s += 4); ; ++p)
231
       if (*p == '\n' || *p == ' ' || *p == '\t') {
232
         if (!wasspace)
233
           if (!stralloc_catb(sa, s, p - s) || !stralloc_0(sa)) temp_nomem();
234
         if (*p == '\n') break;
235
         wasspace = 1;
236
       } else if (wasspace == 1) {
237
         wasspace = 0;
238
         s = p;
239
       }
240
    s = ++p;
241
242
    /* keyword should consist of alpha-num and '-'
243
     * broken AUTH might use '=' instead of space */
244
    for (p = sa->s; *p; ++p) if (*p == '=') { *p = 0; break; }
245
  }
246
247
  return 250;
248
}
249
#endif
250
166
void outsmtptext()
251
void outsmtptext()
167
{
252
{
168
  int i; 
253
  int i; 
Lines 179-184 Link Here
179
char *prepend;
264
char *prepend;
180
char *append;
265
char *append;
181
{
266
{
267
#ifdef TLS
268
  /* shouldn't talk to the client unless in an appropriate state */
269
  int state = ssl ? SSL_get_state(ssl) : TLS_ST_BEFORE;
270
  if (state & TLS_ST_OK || (!smtps && state & TLS_ST_BEFORE))
271
#endif
182
  substdio_putsflush(&smtpto,"QUIT\r\n");
272
  substdio_putsflush(&smtpto,"QUIT\r\n");
183
  /* waiting for remote side is just too ridiculous */
273
  /* waiting for remote side is just too ridiculous */
184
  out(prepend);
274
  out(prepend);
Lines 186-191 Link Here
186
  out(append);
276
  out(append);
187
  out(".\n");
277
  out(".\n");
188
  outsmtptext();
278
  outsmtptext();
279
280
#if defined(TLS) && defined(DEBUG)
281
  if (ssl) {
282
    X509 *peercert;
283
284
    out("STARTTLS proto="); out(SSL_get_version(ssl));
285
    out("; cipher="); out(SSL_get_cipher(ssl));
286
287
    /* we want certificate details */
288
    if (peercert = SSL_get_peer_certificate(ssl)) {
289
      char *str;
290
291
      str = X509_NAME_oneline(X509_get_subject_name(peercert), NULL, 0);
292
      out("; subject="); out(str); OPENSSL_free(str);
293
294
      str = X509_NAME_oneline(X509_get_issuer_name(peercert), NULL, 0);
295
      out("; issuer="); out(str); OPENSSL_free(str);
296
297
      X509_free(peercert);
298
    }
299
    out(";\n");
300
  }
301
#endif
302
189
  zerodie();
303
  zerodie();
190
}
304
}
191
305
Lines 214-219 Link Here
214
  substdio_flush(&smtpto);
328
  substdio_flush(&smtpto);
215
}
329
}
216
330
331
#ifdef TLS
332
char *partner_fqdn = 0;
333
334
# define TLS_QUIT quit(ssl ? "; connected to " : "; connecting to ", "")
335
void tls_quit(const char *s1, const char *s2)
336
{
337
  out(s1); if (s2) { out(": "); out(s2); } TLS_QUIT;
338
}
339
# define tls_quit_error(s) tls_quit(s, ssl_error())
340
341
int match_partner(const char *s, int len)
342
{
343
  if (!case_diffb(partner_fqdn, len, s) && !partner_fqdn[len]) return 1;
344
  /* we also match if the name is *.domainname */
345
  if (*s == '*') {
346
    const char *domain = partner_fqdn + str_chr(partner_fqdn, '.');
347
    if (!case_diffb(domain, --len, ++s) && !domain[len]) return 1;
348
  }
349
  return 0;
350
}
351
352
/* don't want to fail handshake if certificate can't be verified */
353
int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; }
354
355
int tls_init()
356
{
357
  int i;
358
  SSL *myssl;
359
  SSL_CTX *ctx;
360
  stralloc saciphers = {0};
361
  const char *ciphers, *servercert = 0;
362
363
  if (partner_fqdn) {
364
    struct stat st;
365
    stralloc tmp = {0};
366
    if (!stralloc_copys(&tmp, "control/tlshosts/")
367
      || !stralloc_catb(&tmp, partner_fqdn, str_len(partner_fqdn))
368
      || !stralloc_catb(&tmp, ".pem", 5)) temp_nomem();
369
    if (stat(tmp.s, &st) == 0) 
370
      servercert = tmp.s;
371
    else {
372
      if (!stralloc_copys(&tmp, "control/notlshosts/")
373
        || !stralloc_catb(&tmp, partner_fqdn, str_len(partner_fqdn)+1))
374
        temp_nomem();
375
      if ((stat("control/tlshosts/exhaustivelist", &st) == 0) ||
376
	  (stat(tmp.s, &st) == 0)) {
377
         alloc_free(tmp.s);
378
         return 0;
379
      }
380
      alloc_free(tmp.s);
381
    }
382
  }
383
 
384
  if (!smtps) {
385
    stralloc *sa = ehlokw.sa;
386
    unsigned int len = ehlokw.len;
387
    /* look for STARTTLS among EHLO keywords */
388
    for ( ; len && case_diffs(sa->s, "STARTTLS"); ++sa, --len) ;
389
    if (!len) {
390
      if (!servercert) return 0;
391
      out("ZNo TLS achieved while "); out(servercert);
392
      out(" exists"); smtptext.len = 0; TLS_QUIT;
393
    }
394
  }
395
396
  SSL_library_init();
397
  ctx = SSL_CTX_new(SSLv23_client_method());
398
  if (!ctx) {
399
    if (!smtps && !servercert) return 0;
400
    smtptext.len = 0;
401
    tls_quit_error("ZTLS error initializing ctx");
402
  }
403
404
  if (servercert) {
405
    if (!SSL_CTX_load_verify_locations(ctx, servercert, NULL)) {
406
      SSL_CTX_free(ctx);
407
      smtptext.len = 0;
408
      out("ZTLS unable to load "); tls_quit_error(servercert);
409
    }
410
    /* set the callback here; SSL_set_verify didn't work before 0.9.6c */
411
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb);
412
  }
413
414
  /* let the other side complain if it needs a cert and we don't have one */
415
# define CLIENTCERT "control/clientcert.pem"
416
  if (SSL_CTX_use_certificate_chain_file(ctx, CLIENTCERT))
417
    SSL_CTX_use_RSAPrivateKey_file(ctx, CLIENTCERT, SSL_FILETYPE_PEM);
418
# undef CLIENTCERT
419
420
  myssl = SSL_new(ctx);
421
  SSL_CTX_free(ctx);
422
  if (!myssl) {
423
    if (!smtps && !servercert) return 0;
424
    smtptext.len = 0;
425
    tls_quit_error("ZTLS error initializing ssl");
426
  }
427
428
  if (!smtps) substdio_putsflush(&smtpto, "STARTTLS\r\n");
429
430
  /* while the server is preparing a responce, do something else */
431
  if (control_readfile(&saciphers, "control/tlsclientciphers", 0) == -1)
432
    { SSL_free(myssl); temp_control(); }
433
  if (saciphers.len) {
434
    for (i = 0; i < saciphers.len - 1; ++i)
435
      if (!saciphers.s[i]) saciphers.s[i] = ':';
436
    ciphers = saciphers.s;
437
  }
438
  else ciphers = "DEFAULT";
439
  SSL_set_cipher_list(myssl, ciphers);
440
  alloc_free(saciphers.s);
441
442
  /* SSL_set_options(myssl, SSL_OP_NO_TLSv1); */
443
  SSL_set_fd(myssl, smtpfd);
444
445
  /* read the responce to STARTTLS */
446
  if (!smtps) {
447
    if (smtpcode() != 220) {
448
      SSL_free(myssl);
449
      if (!servercert) return 0;
450
      out("ZSTARTTLS rejected while ");
451
      out(servercert); out(" exists"); TLS_QUIT;
452
    }
453
    smtptext.len = 0;
454
  }
455
456
  ssl = myssl;
457
  if (ssl_timeoutconn(timeout, smtpfd, smtpfd, ssl) <= 0)
458
    tls_quit("ZTLS connect failed", ssl_error_str());
459
460
  if (servercert) {
461
    X509 *peercert;
462
    STACK_OF(GENERAL_NAME) *gens;
463
464
    int r = SSL_get_verify_result(ssl);
465
    if (r != X509_V_OK) {
466
      out("ZTLS unable to verify server with ");
467
      tls_quit(servercert, X509_verify_cert_error_string(r));
468
    }
469
    alloc_free(servercert);
470
471
    peercert = SSL_get_peer_certificate(ssl);
472
    if (!peercert) {
473
      out("ZTLS unable to verify server ");
474
      tls_quit(partner_fqdn, "no certificate provided");
475
    }
476
477
    /* RFC 2595 section 2.4: find a matching name
478
     * first find a match among alternative names */
479
    gens = X509_get_ext_d2i(peercert, NID_subject_alt_name, 0, 0);
480
    if (gens) {
481
      for (i = 0, r = sk_GENERAL_NAME_num(gens); i < r; ++i)
482
      {
483
        const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i);
484
        if (gn->type == GEN_DNS)
485
          if (match_partner(gn->d.ia5->data, gn->d.ia5->length)) break;
486
      }
487
      sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
488
    }
489
490
    /* no alternative name matched, look up commonName */
491
    if (!gens || i >= r) {
492
      stralloc peer = {0};
493
      X509_NAME *subj = X509_get_subject_name(peercert);
494
      i = X509_NAME_get_index_by_NID(subj, NID_commonName, -1);
495
      if (i >= 0) {
496
        const ASN1_STRING *s = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i));
497
        if (s) { peer.len = s->length; peer.s = s->data; }
498
      }
499
      if (peer.len <= 0) {
500
        out("ZTLS unable to verify server ");
501
        tls_quit(partner_fqdn, "certificate contains no valid commonName");
502
      }
503
      if (!match_partner(peer.s, peer.len)) {
504
        out("ZTLS unable to verify server "); out(partner_fqdn);
505
        out(": received certificate for "); outsafe(&peer); TLS_QUIT;
506
      }
507
    }
508
509
    X509_free(peercert);
510
  }
511
512
  if (smtps) if (smtpcode() != 220)
513
    quit("ZTLS Connected to "," but greeting failed");
514
515
  return 1;
516
}
517
#endif
518
217
stralloc recip = {0};
519
stralloc recip = {0};
218
520
219
void smtp()
521
void smtp()
Lines 221-235 Link Here
221
  unsigned long code;
523
  unsigned long code;
222
  int flagbother;
524
  int flagbother;
223
  int i;
525
  int i;
526
527
#ifndef PORT_SMTP
528
  /* the qmtpc patch uses smtp_port and undefines PORT_SMTP */
529
# define port smtp_port
530
#endif
531
532
#ifdef TLS
533
# ifdef MXPS
534
  if (type == 'S') smtps = 1;
535
  else if (type != 's')
536
# endif
537
    if (port == 465) smtps = 1;
538
  if (!smtps)
539
#endif
224
 
540
 
225
  if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
541
  if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
226
 
542
 
543
#ifdef EHLO
544
# ifdef TLS
545
  if (!smtps)
546
# endif
547
  code = ehlo();
548
549
# ifdef TLS
550
  if (tls_init())
551
    /* RFC2487 says we should issue EHLO (even if we might not need
552
     * extensions); at the same time, it does not prohibit a server
553
     * to reject the EHLO and make us fallback to HELO */
554
    code = ehlo();
555
# endif
556
557
  if (code == 250) {
558
    /* add EHLO response checks here */
559
560
    /* and if EHLO failed, use HELO */
561
  } else {
562
#endif
563
 
227
  substdio_puts(&smtpto,"HELO ");
564
  substdio_puts(&smtpto,"HELO ");
228
  substdio_put(&smtpto,helohost.s,helohost.len);
565
  substdio_put(&smtpto,helohost.s,helohost.len);
229
  substdio_puts(&smtpto,"\r\n");
566
  substdio_puts(&smtpto,"\r\n");
230
  substdio_flush(&smtpto);
567
  substdio_flush(&smtpto);
231
  if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
568
  if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
232
 
569
 
570
#ifdef EHLO
571
  }
572
#endif
573
 
233
  substdio_puts(&smtpto,"MAIL FROM:<");
574
  substdio_puts(&smtpto,"MAIL FROM:<");
234
  substdio_put(&smtpto,sender.s,sender.len);
575
  substdio_put(&smtpto,sender.s,sender.len);
235
  substdio_puts(&smtpto,">\r\n");
576
  substdio_puts(&smtpto,">\r\n");
Lines 417-422 Link Here
417
    if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) {
758
    if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) {
418
      tcpto_err(&ip.ix[i].ip,0);
759
      tcpto_err(&ip.ix[i].ip,0);
419
      partner = ip.ix[i].ip;
760
      partner = ip.ix[i].ip;
761
#ifdef TLS
762
      partner_fqdn = ip.ix[i].fqdn;
763
#endif
420
      smtp(); /* does not return */
764
      smtp(); /* does not return */
421
    }
765
    }
422
    tcpto_err(&ip.ix[i].ip,errno == error_timeout);
766
    tcpto_err(&ip.ix[i].ip,errno == error_timeout);
(-)../../netqmail-1.05-orig/netqmail-1.05/qmail-smtpd.8 (-1 / +89 lines)
Lines 14-19 Link Here
14
see
14
see
15
.BR tcp-environ(5) .
15
.BR tcp-environ(5) .
16
16
17
If the environment variable
18
.B SMTPS
19
is non-empty,
20
.B qmail-smtpd
21
starts a TLS session (to support the deprecated SMTPS protocol,
22
normally on port 465). Otherwise,
23
.B qmail-smtpd
24
offers the STARTTLS extension to ESMTP.
25
17
.B qmail-smtpd
26
.B qmail-smtpd
18
is responsible for counting hops.
27
is responsible for counting hops.
19
It rejects any message with 100 or more 
28
It rejects any message with 100 or more 
Lines 23-29 Link Here
23
header fields.
32
header fields.
24
33
25
.B qmail-smtpd
34
.B qmail-smtpd
26
supports ESMTP, including the 8BITMIME and PIPELINING options.
35
supports ESMTP, including the 8BITMIME, DATA, PIPELINING, SIZE, and AUTH options.
36
.B qmail-smtpd
37
includes a \'MAIL FROM:\' parameter parser and obeys \'Auth\' and \'Size\' advertisements.
38
.B qmail-smtpd
39
can accept LOGIN, PLAIN, and CRAM-MD5 AUTH types. It invokes
40
.IR checkprogram ,
41
which reads on file descriptor 3 the username, a 0 byte, the password
42
or CRAM-MD5 digest/response derived from the SMTP client,
43
another 0 byte, a CRAM-MD5 challenge (if applicable to the AUTH type),
44
and a final 0 byte.
45
.I checkprogram
46
invokes
47
.I subprogram
48
upon successful authentication, which should in turn return 0 to
49
.BR qmail-smtpd ,
50
effectively setting the environment variables $RELAYCLIENT and $TCPREMOTEINFO
51
(any supplied value replaced with the authenticated username).
52
.B qmail-smtpd
53
will reject the authentication attempt if it receives a nonzero return
54
value from
55
.I checkprogram
56
or
57
.IR subprogram .
58
27
.SH TRANSPARENCY
59
.SH TRANSPARENCY
28
.B qmail-smtpd
60
.B qmail-smtpd
29
converts the SMTP newline convention into the UNIX newline convention
61
converts the SMTP newline convention into the UNIX newline convention
Lines 49-54 Link Here
49
.BR @\fIhost ,
81
.BR @\fIhost ,
50
meaning every address at
82
meaning every address at
51
.IR host .
83
.IR host .
84
85
.TP 5
86
.I clientca.pem
87
A list of Certifying Authority (CA) certificates that are used to verify
88
the client-presented certificates during a TLS-encrypted session.
89
90
.TP 5
91
.I clientcrl.pem
92
A list of Certificate Revocation Lists (CRLs). If present it
93
should contain the CRLs of the CAs in 
94
.I clientca.pem 
95
and client certs will be checked for revocation.
96
52
.TP 5
97
.TP 5
53
.I databytes
98
.I databytes
54
Maximum number of bytes allowed in a message,
99
Maximum number of bytes allowed in a message,
Lines 76-81 Link Here
76
.B DATABYTES
121
.B DATABYTES
77
is set, it overrides
122
is set, it overrides
78
.IR databytes .
123
.IR databytes .
124
125
.TP 5
126
.I dh1024.pem
127
If these 1024 bit DH parameters are provided,
128
.B qmail-smtpd
129
will use them for TLS sessions instead of generating one on-the-fly 
130
(which is very timeconsuming).
131
.TP 5
132
.I dh512.pem
133
512 bit counterpart for 
134
.B dh1024.pem. 
135
79
.TP 5
136
.TP 5
80
.I localiphost
137
.I localiphost
81
Replacement host name for local IP addresses.
138
Replacement host name for local IP addresses.
Lines 151-156 Link Here
151
208
152
Envelope recipient addresses without @ signs are
209
Envelope recipient addresses without @ signs are
153
always allowed through.
210
always allowed through.
211
212
.TP 5
213
.I rsa512.pem
214
If this 512 bit RSA key is provided,
215
.B qmail-smtpd
216
will use it for TLS sessions instead of generating one on-the-fly.
217
218
.TP 5
219
.I servercert.pem
220
SSL certificate to be presented to clients in TLS-encrypted sessions. 
221
Should contain both the certificate and the private key. Certifying Authority
222
(CA) and intermediate certificates can be added at the end of the file.
223
154
.TP 5
224
.TP 5
155
.I smtpgreeting
225
.I smtpgreeting
156
SMTP greeting message.
226
SMTP greeting message.
Lines 169-174 Link Here
169
.B qmail-smtpd
239
.B qmail-smtpd
170
will wait for each new buffer of data from the remote SMTP client.
240
will wait for each new buffer of data from the remote SMTP client.
171
Default: 1200.
241
Default: 1200.
242
243
.TP 5
244
.I tlsclients
245
A list of email addresses. When relay rules would reject an incoming message,
246
.B qmail-smtpd
247
can allow it if the client presents a certificate that can be verified against
248
the CA list in
249
.I clientca.pem
250
and the certificate email address is in
251
.IR tlsclients .
252
253
.TP 5
254
.I tlsserverciphers
255
A set of OpenSSL cipher strings. Multiple ciphers contained in a
256
string should be separated by a colon. If the environment variable
257
.B TLSCIPHERS
258
is set to such a string, it takes precedence.
259
172
.SH "SEE ALSO"
260
.SH "SEE ALSO"
173
tcp-env(1),
261
tcp-env(1),
174
tcp-environ(5),
262
tcp-environ(5),
(-)../../netqmail-1.05-orig/netqmail-1.05/qmail-smtpd.c (-5 / +607 lines)
Lines 23-36 Link Here
23
#include "timeoutread.h"
23
#include "timeoutread.h"
24
#include "timeoutwrite.h"
24
#include "timeoutwrite.h"
25
#include "commands.h"
25
#include "commands.h"
26
#include "wait.h"
27
28
#define CRAM_MD5
29
#define AUTHSLEEP 5
26
30
27
#define MAXHOPS 100
31
#define MAXHOPS 100
28
unsigned int databytes = 0;
32
unsigned int databytes = 0;
29
int timeout = 1200;
33
int timeout = 1200;
30
34
35
#ifdef TLS
36
#include <sys/stat.h>
37
#include "tls.h"
38
#include "ssl_timeoutio.h"
39
40
void tls_init();
41
int tls_verify();
42
void tls_nogateway();
43
int ssl_rfd = -1, ssl_wfd = -1; /* SSL_get_Xfd() are broken */
44
#endif
45
31
int safewrite(fd,buf,len) int fd; char *buf; int len;
46
int safewrite(fd,buf,len) int fd; char *buf; int len;
32
{
47
{
33
  int r;
48
  int r;
49
#ifdef TLS
50
  if (ssl && fd == ssl_wfd)
51
    r = ssl_timeoutwrite(timeout, ssl_rfd, ssl_wfd, ssl, buf, len);
52
  else
53
#endif
34
  r = timeoutwrite(timeout,fd,buf,len);
54
  r = timeoutwrite(timeout,fd,buf,len);
35
  if (r <= 0) _exit(1);
55
  if (r <= 0) _exit(1);
36
  return r;
56
  return r;
Lines 49-56 Link Here
49
void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); }
69
void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); }
50
void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); }
70
void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); }
51
71
72
void err_size() { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); }
52
void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
73
void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
74
#ifndef TLS
53
void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
75
void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
76
#else
77
void err_nogateway()
78
{
79
  out("553 sorry, that domain isn't in my list of allowed rcpthosts");
80
  tls_nogateway();
81
  out(" (#5.7.1)\r\n");
82
}
83
#endif
54
void err_unimpl(arg) char *arg; { out("502 unimplemented (#5.5.1)\r\n"); }
84
void err_unimpl(arg) char *arg; { out("502 unimplemented (#5.5.1)\r\n"); }
55
void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
85
void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
56
void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); }
86
void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); }
Lines 59-64 Link Here
59
void err_vrfy(arg) char *arg; { out("252 send some mail, i'll try my best\r\n"); }
89
void err_vrfy(arg) char *arg; { out("252 send some mail, i'll try my best\r\n"); }
60
void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); }
90
void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); }
61
91
92
int err_child() { out("454 oops, problem with child and I can't auth (#4.3.0)\r\n"); return -1; }
93
int err_fork() { out("454 oops, child won't start and I can't auth (#4.3.0)\r\n"); return -1; }
94
int err_pipe() { out("454 oops, unable to open pipe and I can't auth (#4.3.0)\r\n"); return -1; }
95
int err_write() { out("454 oops, unable to write pipe and I can't auth (#4.3.0)\r\n"); return -1; }
96
void err_authd() { out("503 you're already authenticated (#5.5.0)\r\n"); }
97
void err_authmail() { out("503 no auth during mail transaction (#5.5.0)\r\n"); }
98
int err_noauth() { out("504 auth type unimplemented (#5.5.1)\r\n"); return -1; }
99
int err_authabrt() { out("501 auth exchange canceled (#5.0.0)\r\n"); return -1; }
100
int err_input() { out("501 malformed auth input (#5.5.4)\r\n"); return -1; }
101
void err_authfail() { out("535 authentication failed (#5.7.1)\r\n"); }
62
102
63
stralloc greeting = {0};
103
stralloc greeting = {0};
64
104
Lines 76-81 Link Here
76
  smtp_greet("221 "); out("\r\n"); flush(); _exit(0);
116
  smtp_greet("221 "); out("\r\n"); flush(); _exit(0);
77
}
117
}
78
118
119
char *protocol;
79
char *remoteip;
120
char *remoteip;
80
char *remotehost;
121
char *remotehost;
81
char *remoteinfo;
122
char *remoteinfo;
Lines 109-115 Link Here
109
  if (liphostok == -1) die_control();
150
  if (liphostok == -1) die_control();
110
  if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control();
151
  if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control();
111
  if (timeout <= 0) timeout = 1;
152
  if (timeout <= 0) timeout = 1;
112
113
  if (rcpthosts_init() == -1) die_control();
153
  if (rcpthosts_init() == -1) die_control();
114
154
115
  bmfok = control_readfile(&bmf,"control/badmailfrom",0);
155
  bmfok = control_readfile(&bmf,"control/badmailfrom",0);
Lines 122-127 Link Here
122
  if (x) { scan_ulong(x,&u); databytes = u; }
162
  if (x) { scan_ulong(x,&u); databytes = u; }
123
  if (!(databytes + 1)) --databytes;
163
  if (!(databytes + 1)) --databytes;
124
 
164
 
165
  protocol = "SMTP";
125
  remoteip = env_get("TCPREMOTEIP");
166
  remoteip = env_get("TCPREMOTEIP");
126
  if (!remoteip) remoteip = "unknown";
167
  if (!remoteip) remoteip = "unknown";
127
  local = env_get("TCPLOCALHOST");
168
  local = env_get("TCPLOCALHOST");
Lines 131-136 Link Here
131
  if (!remotehost) remotehost = "unknown";
172
  if (!remotehost) remotehost = "unknown";
132
  remoteinfo = env_get("TCPREMOTEINFO");
173
  remoteinfo = env_get("TCPREMOTEINFO");
133
  relayclient = env_get("RELAYCLIENT");
174
  relayclient = env_get("RELAYCLIENT");
175
176
#ifdef TLS
177
  if (env_get("SMTPS")) { smtps = 1; tls_init(); }
178
  else
179
#endif
134
  dohelo(remotehost);
180
  dohelo(remotehost);
135
}
181
}
136
182
Lines 213-235 Link Here
213
  int r;
259
  int r;
214
  r = rcpthosts(addr.s,str_len(addr.s));
260
  r = rcpthosts(addr.s,str_len(addr.s));
215
  if (r == -1) die_control();
261
  if (r == -1) die_control();
262
#ifdef TLS
263
  if (r == 0) if (tls_verify()) r = -2;
264
#endif
216
  return r;
265
  return r;
217
}
266
}
218
267
219
268
220
int seenmail = 0;
269
int seenmail = 0;
221
int flagbarf; /* defined if seenmail */
270
int flagbarf; /* defined if seenmail */
271
int flagsize;
222
stralloc mailfrom = {0};
272
stralloc mailfrom = {0};
223
stralloc rcptto = {0};
273
stralloc rcptto = {0};
274
stralloc fuser = {0};
275
stralloc mfparms = {0};
276
277
int mailfrom_size(arg) char *arg;
278
{
279
  long r;
280
  unsigned long sizebytes = 0;
281
282
  scan_ulong(arg,&r);
283
  sizebytes = r;
284
  if (databytes) if (sizebytes > databytes) return 1;
285
  return 0;
286
}
287
288
void mailfrom_auth(arg,len) 
289
char *arg; 
290
int len;
291
{
292
  int j;
293
294
  if (!stralloc_copys(&fuser,"")) die_nomem();
295
  if (case_starts(arg,"<>")) { if (!stralloc_cats(&fuser,"unknown")) die_nomem(); }
296
  else 
297
    while (len) {
298
      if (*arg == '+') {
299
        if (case_starts(arg,"+3D")) { arg=arg+2; len=len-2; if (!stralloc_cats(&fuser,"=")) die_nomem(); }
300
        if (case_starts(arg,"+2B")) { arg=arg+2; len=len-2; if (!stralloc_cats(&fuser,"+")) die_nomem(); }
301
      }
302
      else
303
        if (!stralloc_catb(&fuser,arg,1)) die_nomem();
304
      arg++; len--;
305
    }
306
  if(!stralloc_0(&fuser)) die_nomem();
307
  if (!remoteinfo) {
308
    remoteinfo = fuser.s;
309
    if (!env_unset("TCPREMOTEINFO")) die_read();
310
    if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
311
  }
312
}
313
314
void mailfrom_parms(arg) char *arg;
315
{
316
  int i;
317
  int len;
318
319
    len = str_len(arg);
320
    if (!stralloc_copys(&mfparms,"")) die_nomem;
321
    i = byte_chr(arg,len,'>');
322
    if (i > 4 && i < len) {
323
      while (len) {
324
        arg++; len--; 
325
        if (*arg == ' ' || *arg == '\0' ) {
326
           if (case_starts(mfparms.s,"SIZE=")) if (mailfrom_size(mfparms.s+5)) { flagsize = 1; return; }
327
           if (case_starts(mfparms.s,"AUTH=")) mailfrom_auth(mfparms.s+5,mfparms.len-5);  
328
           if (!stralloc_copys(&mfparms,"")) die_nomem;
329
        }
330
        else
331
          if (!stralloc_catb(&mfparms,arg,1)) die_nomem; 
332
      }
333
    }
334
}
224
335
225
void smtp_helo(arg) char *arg;
336
void smtp_helo(arg) char *arg;
226
{
337
{
227
  smtp_greet("250 "); out("\r\n");
338
  smtp_greet("250 "); out("\r\n");
228
  seenmail = 0; dohelo(arg);
339
  seenmail = 0; dohelo(arg);
229
}
340
}
341
/* ESMTP extensions are published here */
230
void smtp_ehlo(arg) char *arg;
342
void smtp_ehlo(arg) char *arg;
231
{
343
{
232
  smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
344
#ifdef TLS
345
  struct stat st;
346
#endif
347
  char size[FMT_ULONG];
348
  smtp_greet("250-"); 
349
#ifdef TLS
350
  if (!ssl && (stat("control/servercert.pem",&st) == 0))
351
    out("\r\n250-STARTTLS");
352
#endif
353
  size[fmt_ulong(size,(unsigned int) databytes)] = 0;
354
  out("\r\n250-PIPELINING\r\n250-8BITMIME\r\n");
355
  out("250-SIZE "); out(size); out("\r\n");
356
#ifdef CRAM_MD5
357
  out("250 AUTH LOGIN PLAIN CRAM-MD5\r\n");
358
#else
359
  out("250 AUTH LOGIN PLAIN\r\n");
360
#endif
233
  seenmail = 0; dohelo(arg);
361
  seenmail = 0; dohelo(arg);
234
}
362
}
235
void smtp_rset(arg) char *arg;
363
void smtp_rset(arg) char *arg;
Lines 240-245 Link Here
240
void smtp_mail(arg) char *arg;
368
void smtp_mail(arg) char *arg;
241
{
369
{
242
  if (!addrparse(arg)) { err_syntax(); return; }
370
  if (!addrparse(arg)) { err_syntax(); return; }
371
  flagsize = 0;
372
  mailfrom_parms(arg);
373
  if (flagsize) { err_size(); return; }
243
  flagbarf = bmfcheck();
374
  flagbarf = bmfcheck();
244
  seenmail = 1;
375
  seenmail = 1;
245
  if (!stralloc_copys(&rcptto,"")) die_nomem();
376
  if (!stralloc_copys(&rcptto,"")) die_nomem();
Lines 269-274 Link Here
269
{
400
{
270
  int r;
401
  int r;
271
  flush();
402
  flush();
403
#ifdef TLS
404
  if (ssl && fd == ssl_rfd)
405
    r = ssl_timeoutread(timeout, ssl_rfd, ssl_wfd, ssl, buf, len);
406
  else
407
#endif
272
  r = timeoutread(timeout,fd,buf,len);
408
  r = timeoutread(timeout,fd,buf,len);
273
  if (r == -1) if (errno == error_timeout) die_alarm();
409
  if (r == -1) if (errno == error_timeout) die_alarm();
274
  if (r <= 0) die_read();
410
  if (r <= 0) die_read();
Lines 378-384 Link Here
378
  qp = qmail_qp(&qqt);
514
  qp = qmail_qp(&qqt);
379
  out("354 go ahead\r\n");
515
  out("354 go ahead\r\n");
380
 
516
 
381
  received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo);
517
  received(&qqt,protocol,local,remoteip,remotehost,remoteinfo,fakehelo);
382
  blast(&hops);
518
  blast(&hops);
383
  hops = (hops >= MAXHOPS);
519
  hops = (hops >= MAXHOPS);
384
  if (hops) qmail_fail(&qqt);
520
  if (hops) qmail_fail(&qqt);
Lines 388-415 Link Here
388
  qqx = qmail_close(&qqt);
524
  qqx = qmail_close(&qqt);
389
  if (!*qqx) { acceptmessage(qp); return; }
525
  if (!*qqx) { acceptmessage(qp); return; }
390
  if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; }
526
  if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; }
391
  if (databytes) if (!bytestooverflow) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return; }
527
  if (databytes) if (!bytestooverflow) { err_size(); return; }
392
  if (*qqx == 'D') out("554 "); else out("451 ");
528
  if (*qqx == 'D') out("554 "); else out("451 ");
393
  out(qqx + 1);
529
  out(qqx + 1);
394
  out("\r\n");
530
  out("\r\n");
395
}
531
}
396
532
533
/* this file is too long ----------------------------------------- SMTP AUTH */
534
535
char unique[FMT_ULONG + FMT_ULONG + 3];
536
static stralloc authin = {0};   /* input from SMTP client */
537
static stralloc user = {0};     /* authorization user-id */
538
static stralloc pass = {0};     /* plain passwd or digest */
539
static stralloc resp = {0};     /* b64 response */
540
#ifdef CRAM_MD5
541
static stralloc chal = {0};     /* plain challenge */
542
static stralloc slop = {0};     /* b64 challenge */
543
#endif
544
545
int flagauth = 0;
546
char **childargs;
547
char ssauthbuf[512];
548
substdio ssauth = SUBSTDIO_FDBUF(safewrite,3,ssauthbuf,sizeof(ssauthbuf));
549
550
int authgetl(void) {
551
  int i;
552
553
  if (!stralloc_copys(&authin,"")) die_nomem();
554
  for (;;) {
555
    if (!stralloc_readyplus(&authin,1)) die_nomem(); /* XXX */
556
    i = substdio_get(&ssin,authin.s + authin.len,1);
557
    if (i != 1) die_read();
558
    if (authin.s[authin.len] == '\n') break;
559
    ++authin.len;
560
  }
561
562
  if (authin.len > 0) if (authin.s[authin.len - 1] == '\r') --authin.len;
563
  authin.s[authin.len] = 0;
564
  if (*authin.s == '*' && *(authin.s + 1) == 0) { return err_authabrt(); }
565
  if (authin.len == 0) { return err_input(); }
566
  return authin.len;
567
}
568
569
int authenticate(void)
570
{
571
  int child;
572
  int wstat;
573
  int pi[2];
574
575
  if (!stralloc_0(&user)) die_nomem();
576
  if (!stralloc_0(&pass)) die_nomem();
577
#ifdef CRAM_MD5
578
  if (!stralloc_0(&chal)) die_nomem();
579
#endif
580
581
  if (pipe(pi) == -1) return err_pipe();
582
  switch(child = fork()) {
583
    case -1:
584
      return err_fork();
585
    case 0:
586
      close(pi[1]);
587
      if(fd_copy(3,pi[0]) == -1) return err_pipe();
588
      sig_pipedefault();
589
        execvp(*childargs, childargs);
590
      _exit(1);
591
  }
592
  close(pi[0]);
593
594
  substdio_fdbuf(&ssauth,write,pi[1],ssauthbuf,sizeof ssauthbuf);
595
  if (substdio_put(&ssauth,user.s,user.len) == -1) return err_write();
596
  if (substdio_put(&ssauth,pass.s,pass.len) == -1) return err_write();
597
#ifdef CRAM_MD5
598
  if (substdio_put(&ssauth,chal.s,chal.len) == -1) return err_write();
599
#endif
600
  if (substdio_flush(&ssauth) == -1) return err_write();
601
602
  close(pi[1]);
603
#ifdef CRAM_MD5
604
  if (!stralloc_copys(&chal,"")) die_nomem();
605
  if (!stralloc_copys(&slop,"")) die_nomem();
606
#endif
607
  byte_zero(ssauthbuf,sizeof ssauthbuf);
608
  if (wait_pid(&wstat,child) == -1) return err_child();
609
  if (wait_crashed(wstat)) return err_child();
610
  if (wait_exitcode(wstat)) { sleep(AUTHSLEEP); return 1; } /* no */
611
  return 0; /* yes */
612
}
613
614
int auth_login(arg) char *arg;
615
{
616
  int r;
617
618
  if (*arg) {
619
    if (r = b64decode(arg,str_len(arg),&user) == 1) return err_input();
620
  }
621
  else {
622
    out("334 VXNlcm5hbWU6\r\n"); flush();       /* Username: */
623
    if (authgetl() < 0) return -1;
624
    if (r = b64decode(authin.s,authin.len,&user) == 1) return err_input();
625
  }
626
  if (r == -1) die_nomem();
627
628
  out("334 UGFzc3dvcmQ6\r\n"); flush();         /* Password: */
629
630
  if (authgetl() < 0) return -1;
631
  if (r = b64decode(authin.s,authin.len,&pass) == 1) return err_input();
632
  if (r == -1) die_nomem();
633
634
  if (!user.len || !pass.len) return err_input();
635
  return authenticate();
636
}
637
638
int auth_plain(arg) char *arg;
639
{
640
  int r, id = 0;
641
642
  if (*arg) {
643
    if (r = b64decode(arg,str_len(arg),&resp) == 1) return err_input();
644
  }
645
  else {
646
    out("334 \r\n"); flush();
647
    if (authgetl() < 0) return -1;
648
    if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input();
649
  }
650
  if (r == -1 || !stralloc_0(&resp)) die_nomem();
651
  while (resp.s[id]) id++;                       /* "authorize-id\0userid\0passwd\0" */
652
653
  if (resp.len > id + 1)
654
    if (!stralloc_copys(&user,resp.s + id + 1)) die_nomem();
655
  if (resp.len > id + user.len + 2)
656
    if (!stralloc_copys(&pass,resp.s + id + user.len + 2)) die_nomem();
657
658
  if (!user.len || !pass.len) return err_input();
659
  return authenticate();
660
}
661
662
#ifdef CRAM_MD5
663
int auth_cram()
664
{
665
  int i, r;
666
  char *s;
667
668
  s = unique;                                           /* generate challenge */
669
  s += fmt_uint(s,getpid());
670
  *s++ = '.';
671
  s += fmt_ulong(s,(unsigned long) now());
672
  *s++ = '@';
673
  *s++ = 0;
674
  if (!stralloc_copys(&chal,"<")) die_nomem();
675
  if (!stralloc_cats(&chal,unique)) die_nomem();
676
  if (!stralloc_cats(&chal,local)) die_nomem();
677
  if (!stralloc_cats(&chal,">")) die_nomem();
678
  if (b64encode(&chal,&slop) < 0) die_nomem();
679
  if (!stralloc_0(&slop)) die_nomem();
680
681
  out("334 ");                                          /* "334 base64_challenge \r\n" */
682
  out(slop.s);
683
  out("\r\n");
684
  flush();
685
686
  if (authgetl() < 0) return -1;                        /* got response */
687
  if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input();
688
  if (r == -1 || !stralloc_0(&resp)) die_nomem();
689
690
  i = str_chr(resp.s,' ');
691
  s = resp.s + i;
692
  while (*s == ' ') ++s;
693
  resp.s[i] = 0;
694
  if (!stralloc_copys(&user,resp.s)) die_nomem();       /* userid */
695
  if (!stralloc_copys(&pass,s)) die_nomem();            /* digest */
696
697
  if (!user.len || !pass.len) return err_input();
698
  return authenticate();
699
}
700
#endif
701
702
struct authcmd {
703
  char *text;
704
  int (*fun)();
705
} authcmds[] = {
706
  { "login",auth_login }
707
,  { "plain",auth_plain }
708
#ifdef CRAM_MD5
709
, { "cram-md5",auth_cram }
710
#endif
711
, { 0,err_noauth }
712
};
713
714
void smtp_auth(arg)
715
char *arg;
716
{
717
  int i;
718
  char *cmd = arg;
719
720
  if (!*childargs) { out("503 auth not available (#5.3.3)\r\n"); return; }
721
  if (flagauth) { err_authd(); return; }
722
  if (seenmail) { err_authmail(); return; }
723
724
  if (!stralloc_copys(&user,"")) die_nomem();
725
  if (!stralloc_copys(&pass,"")) die_nomem();
726
  if (!stralloc_copys(&resp,"")) die_nomem();
727
#ifdef CRAM_MD5
728
  if (!stralloc_copys(&chal,"")) die_nomem();
729
#endif
730
731
  i = str_chr(cmd,' ');
732
  arg = cmd + i;
733
  while (*arg == ' ') ++arg;
734
  cmd[i] = 0;
735
736
  for (i = 0;authcmds[i].text;++i)
737
    if (case_equals(authcmds[i].text,cmd)) break;
738
739
  switch (authcmds[i].fun(arg)) {
740
    case 0:
741
      flagauth = 1;
742
      protocol = "ESMTPA";
743
      relayclient = "";
744
      remoteinfo = user.s;
745
      if (!env_unset("TCPREMOTEINFO")) die_read();
746
      if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
747
      if (!env_put2("RELAYCLIENT",relayclient)) die_nomem();
748
      out("235 ok, go ahead (#2.0.0)\r\n");
749
      break;
750
    case 1:
751
      err_authfail(user.s,authcmds[i].text);
752
  }
753
}
754
755
756
/* this file is too long --------------------------------------------- GO ON */
757
758
#ifdef TLS
759
stralloc proto = {0};
760
int ssl_verified = 0;
761
const char *ssl_verify_err = 0;
762
763
void smtp_tls(char *arg)
764
{
765
  if (ssl) err_unimpl();
766
  else if (*arg) out("501 Syntax error (no parameters allowed) (#5.5.4)\r\n");
767
  else tls_init();
768
}
769
770
RSA *tmp_rsa_cb(SSL *ssl, int export, int keylen)
771
{
772
  if (!export) keylen = 512;
773
  if (keylen == 512) {
774
    FILE *in = fopen("control/rsa512.pem", "r");
775
    if (in) {
776
      RSA *rsa = PEM_read_RSAPrivateKey(in, NULL, NULL, NULL);
777
      fclose(in);
778
      if (rsa) return rsa;
779
    }
780
  }
781
  return RSA_generate_key(keylen, RSA_F4, NULL, NULL);
782
}
783
784
DH *tmp_dh_cb(SSL *ssl, int export, int keylen)
785
{
786
  if (!export) keylen = 1024;
787
  if (keylen == 512) {
788
    FILE *in = fopen("control/dh512.pem", "r");
789
    if (in) {
790
      DH *dh = PEM_read_DHparams(in, NULL, NULL, NULL);
791
      fclose(in);
792
      if (dh) return dh;
793
    }
794
  }
795
  if (keylen == 1024) {
796
    FILE *in = fopen("control/dh1024.pem", "r");
797
    if (in) {
798
      DH *dh = PEM_read_DHparams(in, NULL, NULL, NULL);
799
      fclose(in);
800
      if (dh) return dh;
801
    }
802
  }
803
  return DH_generate_parameters(keylen, DH_GENERATOR_2, NULL, NULL);
804
} 
805
806
/* don't want to fail handshake if cert isn't verifiable */
807
int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; }
808
809
void tls_nogateway()
810
{
811
  /* there may be cases when relayclient is set */
812
  if (!ssl || relayclient) return;
813
  out("; no valid cert for gatewaying");
814
  if (ssl_verify_err) { out(": "); out(ssl_verify_err); }
815
}
816
void tls_out(const char *s1, const char *s2)
817
{
818
  out("454 TLS "); out(s1);
819
  if (s2) { out(": "); out(s2); }
820
  out(" (#4.3.0)\r\n"); flush();
821
}
822
void tls_err(const char *s) { tls_out(s, ssl_error()); if (smtps) die_read(); }
823
824
# define CLIENTCA "control/clientca.pem"
825
# define CLIENTCRL "control/clientcrl.pem"
826
# define SERVERCERT "control/servercert.pem"
827
828
int tls_verify()
829
{
830
  stralloc clients = {0};
831
  struct constmap mapclients;
832
833
  if (!ssl || relayclient || ssl_verified) return 0;
834
  ssl_verified = 1; /* don't do this twice */
835
836
  /* request client cert to see if it can be verified by one of our CAs
837
   * and the associated email address matches an entry in tlsclients */
838
  switch (control_readfile(&clients, "control/tlsclients", 0))
839
  {
840
  case 1:
841
    if (constmap_init(&mapclients, clients.s, clients.len, 0)) {
842
      /* if CLIENTCA contains all the standard root certificates, a
843
       * 0.9.6b client might fail with SSL_R_EXCESSIVE_MESSAGE_SIZE;
844
       * it is probably due to 0.9.6b supporting only 8k key exchange
845
       * data while the 0.9.6c release increases that limit to 100k */
846
      STACK_OF(X509_NAME) *sk = SSL_load_client_CA_file(CLIENTCA);
847
      if (sk) {
848
        SSL_set_client_CA_list(ssl, sk);
849
        SSL_set_verify(ssl, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL);
850
        break;
851
      }
852
      constmap_free(&mapclients);
853
    }
854
  case 0: alloc_free(clients.s); return 0;
855
  case -1: die_control();
856
  }
857
858
  if (ssl_timeoutrehandshake(timeout, ssl_rfd, ssl_wfd, ssl) <= 0) {
859
    const char *err = ssl_error_str();
860
    tls_out("rehandshake failed", err); die_read();
861
  }
862
863
  do { /* one iteration */
864
    X509 *peercert;
865
    X509_NAME *subj;
866
    stralloc email = {0};
867
868
    int n = SSL_get_verify_result(ssl);
869
    if (n != X509_V_OK)
870
      { ssl_verify_err = X509_verify_cert_error_string(n); break; }
871
    peercert = SSL_get_peer_certificate(ssl);
872
    if (!peercert) break;
873
874
    subj = X509_get_subject_name(peercert);
875
    n = X509_NAME_get_index_by_NID(subj, NID_pkcs9_emailAddress, -1);
876
    if (n >= 0) {
877
      const ASN1_STRING *s = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, n));
878
      if (s) { email.len = s->length; email.s = s->data; }
879
    }
880
881
    if (email.len <= 0)
882
      ssl_verify_err = "contains no email address";
883
    else if (!constmap(&mapclients, email.s, email.len))
884
      ssl_verify_err = "email address not in my list of tlsclients";
885
    else {
886
      /* add the cert email to the proto if it helped allow relaying */
887
      --proto.len;
888
      if (!stralloc_cats(&proto, "\n  (cert ") /* continuation line */
889
        || !stralloc_catb(&proto, email.s, email.len)
890
        || !stralloc_cats(&proto, ")")
891
        || !stralloc_0(&proto)) die_nomem();
892
      relayclient = "";
893
      protocol = proto.s;
894
    }
895
896
    X509_free(peercert);
897
  } while (0);
898
  constmap_free(&mapclients); alloc_free(clients.s);
899
900
  /* we are not going to need this anymore: free the memory */
901
  SSL_set_client_CA_list(ssl, NULL);
902
  SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
903
904
  return relayclient ? 1 : 0;
905
}
906
907
void tls_init()
908
{
909
  SSL *myssl;
910
  SSL_CTX *ctx;
911
  const char *ciphers;
912
  stralloc saciphers = {0};
913
  X509_STORE *store;
914
  X509_LOOKUP *lookup;
915
916
  SSL_library_init();
917
918
  /* a new SSL context with the bare minimum of options */
919
  ctx = SSL_CTX_new(SSLv23_server_method());
920
  if (!ctx) { tls_err("unable to initialize ctx"); return; }
921
922
  if (!SSL_CTX_use_certificate_chain_file(ctx, SERVERCERT))
923
    { SSL_CTX_free(ctx); tls_err("missing certificate"); return; }
924
  SSL_CTX_load_verify_locations(ctx, CLIENTCA, NULL);
925
926
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
927
  /* crl checking */
928
  store = SSL_CTX_get_cert_store(ctx);
929
  if ((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) &&
930
      (X509_load_crl_file(lookup, CLIENTCRL, X509_FILETYPE_PEM) == 1))
931
    X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK |
932
                                X509_V_FLAG_CRL_CHECK_ALL);
933
#endif
934
935
  /* set the callback here; SSL_set_verify didn't work before 0.9.6c */
936
  SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_cb);
937
938
  /* a new SSL object, with the rest added to it directly to avoid copying */
939
  myssl = SSL_new(ctx);
940
  SSL_CTX_free(ctx);
941
  if (!myssl) { tls_err("unable to initialize ssl"); return; }
942
943
  /* this will also check whether public and private keys match */
944
  if (!SSL_use_RSAPrivateKey_file(myssl, SERVERCERT, SSL_FILETYPE_PEM))
945
    { SSL_free(myssl); tls_err("no valid RSA private key"); return; }
946
947
  ciphers = env_get("TLSCIPHERS");
948
  if (!ciphers) {
949
    if (control_readfile(&saciphers, "control/tlsserverciphers", 0) == -1)
950
      { SSL_free(myssl); die_control(); }
951
    if (saciphers.len) { /* convert all '\0's except the last one to ':' */
952
      int i;
953
      for (i = 0; i < saciphers.len - 1; ++i)
954
        if (!saciphers.s[i]) saciphers.s[i] = ':';
955
      ciphers = saciphers.s;
956
    }
957
  }
958
  if (!ciphers || !*ciphers) ciphers = "DEFAULT";
959
  SSL_set_cipher_list(myssl, ciphers);
960
  alloc_free(saciphers.s);
961
962
  SSL_set_tmp_rsa_callback(myssl, tmp_rsa_cb);
963
  SSL_set_tmp_dh_callback(myssl, tmp_dh_cb);
964
  SSL_set_rfd(myssl, ssl_rfd = substdio_fileno(&ssin));
965
  SSL_set_wfd(myssl, ssl_wfd = substdio_fileno(&ssout));
966
967
  if (!smtps) { out("220 ready for tls\r\n"); flush(); }
968
969
  if (ssl_timeoutaccept(timeout, ssl_rfd, ssl_wfd, myssl) <= 0) {
970
    /* neither cleartext nor any other response here is part of a standard */
971
    const char *err = ssl_error_str();
972
    ssl_free(myssl); tls_out("connection failed", err); die_read();
973
  }
974
  ssl = myssl;
975
976
  /* populate the protocol string, used in Received */
977
  if (!stralloc_copys(&proto, "ESMTPS (")
978
    || !stralloc_cats(&proto, SSL_get_cipher(ssl))
979
    || !stralloc_cats(&proto, " encrypted)")) die_nomem();
980
  if (!stralloc_0(&proto)) die_nomem();
981
  protocol = proto.s;
982
983
  /* have to discard the pre-STARTTLS HELO/EHLO argument, if any */
984
  dohelo(remotehost);
985
}
986
987
# undef SERVERCERT
988
# undef CLIENTCA
989
990
#endif
991
397
struct commands smtpcommands[] = {
992
struct commands smtpcommands[] = {
398
  { "rcpt", smtp_rcpt, 0 }
993
  { "rcpt", smtp_rcpt, 0 }
399
, { "mail", smtp_mail, 0 }
994
, { "mail", smtp_mail, 0 }
400
, { "data", smtp_data, flush }
995
, { "data", smtp_data, flush }
996
, { "auth", smtp_auth, flush }
401
, { "quit", smtp_quit, flush }
997
, { "quit", smtp_quit, flush }
402
, { "helo", smtp_helo, flush }
998
, { "helo", smtp_helo, flush }
403
, { "ehlo", smtp_ehlo, flush }
999
, { "ehlo", smtp_ehlo, flush }
404
, { "rset", smtp_rset, 0 }
1000
, { "rset", smtp_rset, 0 }
405
, { "help", smtp_help, flush }
1001
, { "help", smtp_help, flush }
1002
#ifdef TLS
1003
, { "starttls", smtp_tls, flush }
1004
#endif
406
, { "noop", err_noop, flush }
1005
, { "noop", err_noop, flush }
407
, { "vrfy", err_vrfy, flush }
1006
, { "vrfy", err_vrfy, flush }
408
, { 0, err_unimpl, flush }
1007
, { 0, err_unimpl, flush }
409
} ;
1008
} ;
410
1009
411
void main()
1010
void main(argc,argv)
1011
int argc;
1012
char **argv;
412
{
1013
{
1014
  childargs = argv + 1;
413
  sig_pipeignore();
1015
  sig_pipeignore();
414
  if (chdir(auto_qmail) == -1) die_control();
1016
  if (chdir(auto_qmail) == -1) die_control();
415
  setup();
1017
  setup();
(-)../../netqmail-1.05-orig/netqmail-1.05/README.auth (+67 lines)
Line 0 Link Here
1
README qmail-smtpd SMTP Authentication
2
======================================
3
4
5
History:
6
--------
7
8
This patch is based on Krzysztof Dabrowski's qmail-smtpd-auth-0.31 patch 
9
which itself uses "Mrs. Brisby's" initial code. 
10
Version 0.41 of this patch fixes the "CAPS-LOCK" typo announcing
11
'CRAM_MD5' instead of 'CRAM-MD5' (german keyboard) - tx to Mike Garrison.
12
Version 0.42 fixes the '421 unable to read controls (#4.3.0)' problem
13
(can't read control/morercpthosts.cdb) because FD 3 was already closed - tx Richard Lyons.
14
Version 0.43 fixes the ba64decode() failure in case CRAM_MD5 is not enabled - tx Vladimir Zidar.
15
Version 0.51 includes the evaluation of the 'Auth' and the 'Size' parameter in the 'Mail From:' command.
16
Version 0.52 uses DJB functions to copy FDs.
17
Version 0.56 corrects some minor mistakes displaying the 'Auth' userid.
18
Version 0.57 uses keyword "ESMTPA" in Received header in case of authentication to comply with RFC 3848.
19
Version 0.58 fixes a potential problem with cc -O2 optimization within base64.c - tx John Simpson.
20
21
22
Scope:
23
------
24
25
This patch supports RFC 2554 "SMTP Service Extension for Authentication" for qmail-smtpd.
26
Additionally, RFC 1870 is honoured ("SMTP Service Extension for Message Size Declaration").
27
For more technical details see: http://www.fehcom.de/qmail/docu/smtpauth.html.
28
29
30
Installation:
31
-------------
32
33
* Untar the source in the qmail-1.03 home direcotry.
34
* Run ./install_auth.
35
* Modify the compile time option "#define CRAM_MD5" to your needs.
36
* Re-make qmail.
37
38
39
Setup:
40
------
41
42
In order to use SMTP Authentication you have to use a 'Pluggable Authentication Module'
43
PAM to be called by qmail-smtpd; typically
44
45
	/var/qmail/bin/qmail-smtpd /bin/checkpassword true 2>&1
46
47
Since qmail-smtpd does not run as root, checkpassword has to be made sticky.
48
There is no need to include additionally the hostname in the call.
49
In order to compute the CRAM-MD5 challenge, qmail-smtpd uses the 'tcplocalhost' information.
50
51
52
Changes wrt. Krysztof Dabrowski's patch:
53
----------------------------------------
54
55
* Avoid the 'hostname' in the call of the PAM.
56
* Confirm to Dan Bernstein's checkpassword interface even for CRAM-MD5.
57
* Doesn't close FD 2; thus not inhibiting logging to STDERR.
58
* Fixed bugs in base64.c.
59
* Modified unconditional close of FD 3 in order to sustain reading of 'control/morecpthosts.cdb'.
60
* Evaluation of the (informational) Mail From: < > Auth=username.
61
* Additional support for the advertised "Size" via 'Mail From: <return-path> SIZE=123456780' (RFC 1870).
62
* RFC 3848 conformance for Received header in case of SMTP Auth.
63
64
65
Erwin Hoffmann - Cologne 2006-12-28 (www.fehcom.de)
66
67
(-)../../netqmail-1.05-orig/netqmail-1.05/ssl_timeoutio.c (+95 lines)
Line 0 Link Here
1
#include "select.h"
2
#include "error.h"
3
#include "ndelay.h"
4
#include "now.h"
5
#include "ssl_timeoutio.h"
6
7
int ssl_timeoutio(int (*fun)(),
8
  int t, int rfd, int wfd, SSL *ssl, char *buf, int len)
9
{
10
  int n;
11
  const datetime_sec end = (datetime_sec)t + now();
12
13
  do {
14
    fd_set fds;
15
    struct timeval tv;
16
17
    const int r = buf ? fun(ssl, buf, len) : fun(ssl);
18
    if (r > 0) return r;
19
20
    t = end - now();
21
    if (t < 0) break;
22
    tv.tv_sec = (time_t)t; tv.tv_usec = 0;
23
24
    FD_ZERO(&fds);
25
    switch (SSL_get_error(ssl, r))
26
    {
27
    default: return r; /* some other error */
28
    case SSL_ERROR_WANT_READ:
29
      FD_SET(rfd, &fds); n = select(rfd + 1, &fds, NULL, NULL, &tv);
30
      break;
31
    case SSL_ERROR_WANT_WRITE:
32
      FD_SET(wfd, &fds); n = select(wfd + 1, NULL, &fds, NULL, &tv);
33
      break;
34
    }
35
36
    /* n is the number of descriptors that changed status */
37
  } while (n > 0);
38
39
  if (n != -1) errno = error_timeout;
40
  return -1;
41
}
42
43
int ssl_timeoutaccept(int t, int rfd, int wfd, SSL *ssl)
44
{
45
  int r;
46
47
  /* if connection is established, keep NDELAY */
48
  if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1) return -1;
49
  r = ssl_timeoutio(SSL_accept, t, rfd, wfd, ssl, NULL, 0);
50
51
  if (r <= 0) { ndelay_off(rfd); ndelay_off(wfd); }
52
  else SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
53
54
  return r;
55
}
56
57
int ssl_timeoutconn(int t, int rfd, int wfd, SSL *ssl)
58
{
59
  int r;
60
61
  /* if connection is established, keep NDELAY */
62
  if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1) return -1;
63
  r = ssl_timeoutio(SSL_connect, t, rfd, wfd, ssl, NULL, 0);
64
65
  if (r <= 0) { ndelay_off(rfd); ndelay_off(wfd); }
66
  else SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
67
68
  return r;
69
}
70
71
int ssl_timeoutrehandshake(int t, int rfd, int wfd, SSL *ssl)
72
{
73
  int r;
74
75
  SSL_renegotiate(ssl);
76
  r = ssl_timeoutio(SSL_do_handshake, t, rfd, wfd, ssl, NULL, 0);
77
  if (r <= 0 || SSL_get_state(ssl) == SSL_ST_CONNECT) return r;
78
79
  /* this is for the server only */
80
  SSL_set_accept_state(ssl);
81
  return ssl_timeoutio(SSL_do_handshake, t, rfd, wfd, ssl, NULL, 0);
82
}
83
84
int ssl_timeoutread(int t, int rfd, int wfd, SSL *ssl, char *buf, int len)
85
{
86
  if (!buf) return 0;
87
  if (SSL_pending(ssl)) return SSL_read(ssl, buf, len);
88
  return ssl_timeoutio(SSL_read, t, rfd, wfd, ssl, buf, len);
89
}
90
91
int ssl_timeoutwrite(int t, int rfd, int wfd, SSL *ssl, char *buf, int len)
92
{
93
  if (!buf) return 0;
94
  return ssl_timeoutio(SSL_write, t, rfd, wfd, ssl, buf, len);
95
}
(-)../../netqmail-1.05-orig/netqmail-1.05/ssl_timeoutio.h (+21 lines)
Line 0 Link Here
1
#ifndef SSL_TIMEOUTIO_H
2
#define SSL_TIMEOUTIO_H
3
4
#include <openssl/ssl.h>
5
6
/* the version is like this: 0xMNNFFPPS: major minor fix patch status */
7
#if OPENSSL_VERSION_NUMBER < 0x00906000L
8
# error "Need OpenSSL version at least 0.9.6"
9
#endif
10
11
int ssl_timeoutconn(int t, int rfd, int wfd, SSL *ssl);
12
int ssl_timeoutaccept(int t, int rfd, int wfd, SSL *ssl);
13
int ssl_timeoutrehandshake(int t, int rfd, int wfd, SSL *ssl);
14
15
int ssl_timeoutread(int t, int rfd, int wfd, SSL *ssl, char *buf, int len);
16
int ssl_timeoutwrite(int t, int rfd, int wfd, SSL *ssl, char *buf, int len);
17
18
int ssl_timeoutio(
19
  int (*fun)(), int t, int rfd, int wfd, SSL *ssl, char *buf, int len);
20
21
#endif
(-)../../netqmail-1.05-orig/netqmail-1.05/TARGETS (+5 lines)
Lines 10-15 Link Here
10
qmail.o
10
qmail.o
11
quote.o
11
quote.o
12
now.o
12
now.o
13
base64.o
13
gfrom.o
14
gfrom.o
14
myctime.o
15
myctime.o
15
slurpclose.o
16
slurpclose.o
Lines 168-173 Link Here
168
constmap.o
169
constmap.o
169
timeoutread.o
170
timeoutread.o
170
timeoutwrite.o
171
timeoutwrite.o
172
tls.o
173
ssl_timeoutio.o
171
timeoutconn.o
174
timeoutconn.o
172
tcpto.o
175
tcpto.o
173
dns.o
176
dns.o
Lines 320-325 Link Here
320
binm2+df
323
binm2+df
321
binm3
324
binm3
322
binm3+df
325
binm3+df
326
Makefile-cert
323
it
327
it
324
qmail-local.0
328
qmail-local.0
325
qmail-lspawn.0
329
qmail-lspawn.0
Lines 385-387 Link Here
385
man
389
man
386
setup
390
setup
387
check
391
check
392
update_tmprsadh
(-)../../netqmail-1.05-orig/netqmail-1.05/tls.c (+25 lines)
Line 0 Link Here
1
#include "exit.h"
2
#include "error.h"
3
#include <openssl/ssl.h>
4
#include <openssl/err.h>
5
6
int smtps = 0;
7
SSL *ssl = NULL;
8
9
void ssl_free(SSL *myssl) { SSL_shutdown(myssl); SSL_free(myssl); }
10
void ssl_exit(int status) { if (ssl) ssl_free(ssl); _exit(status); }
11
12
const char *ssl_error()
13
{
14
  int r = ERR_get_error();
15
  if (!r) return NULL;
16
  SSL_load_error_strings();
17
  return ERR_error_string(r, NULL);
18
}
19
const char *ssl_error_str()
20
{
21
  const char *err = ssl_error();
22
  if (err) return err;
23
  if (!errno) return 0;
24
  return (errno == error_timeout) ? "timed out" : error_str(errno);
25
}
(-)../../netqmail-1.05-orig/netqmail-1.05/tls.h (+16 lines)
Line 0 Link Here
1
#ifndef TLS_H
2
#define TLS_H
3
4
#include <openssl/ssl.h>
5
6
extern int smtps;
7
extern SSL *ssl;
8
9
void ssl_free(SSL *myssl);
10
void ssl_exit(int status);
11
# define _exit ssl_exit
12
13
const char *ssl_error();
14
const char *ssl_error_str();
15
16
#endif
(-)../../netqmail-1.05-orig/netqmail-1.05/update_tmprsadh.sh (+25 lines)
Line 0 Link Here
1
#!/bin/sh
2
3
# Update temporary RSA and DH keys
4
# Frederik Vermeulen 2004-05-31 GPL
5
6
umask 0077 || exit 0
7
8
export PATH="$PATH:/usr/local/bin/ssl:/usr/sbin"
9
10
openssl genrsa -out QMAIL/control/rsa512.new 512 &&
11
chmod 600 QMAIL/control/rsa512.new &&
12
chown UGQMAILD QMAIL/control/rsa512.new &&
13
mv -f QMAIL/control/rsa512.new QMAIL/control/rsa512.pem
14
echo
15
16
openssl dhparam -2 -out QMAIL/control/dh512.new 512 &&
17
chmod 600 QMAIL/control/dh512.new &&
18
chown UGQMAILD QMAIL/control/dh512.new &&
19
mv -f QMAIL/control/dh512.new QMAIL/control/dh512.pem
20
echo
21
22
openssl dhparam -2 -out QMAIL/control/dh1024.new 1024 &&
23
chmod 600 QMAIL/control/dh1024.new &&
24
chown UGQMAILD QMAIL/control/dh1024.new &&
25
mv -f QMAIL/control/dh1024.new QMAIL/control/dh1024.pem

Return to bug 675060