/[smeserver]/rpms/qmail/sme9/qmail-1.03-tls-20021228-renato_v2-remote.patch
ViewVC logotype

Annotation of /rpms/qmail/sme9/qmail-1.03-tls-20021228-renato_v2-remote.patch

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (hide annotations) (download)
Mon Feb 25 04:29:22 2019 UTC (5 years, 8 months ago) by jpp
Branch: MAIN
CVS Tags: qmail-1_03-23_el6_sme, qmail-1_03-22_el6_sme, qmail-1_03-24_el6_sme, qmail-1_03-21_el6_sme, HEAD
* Sun Feb 24 2019 Jean-Philipe Pialasse <tests@pialasse.com> 1.03-21.sme
- add remote tls transport for qmail-remote [SME: 9349]
- used qmail-1.03-tls-20021228-renato_v2.patch without qmail-smtpd parts

1 jpp 1.1 Frederik Vermeulen <qmail-tls akrul inoa.net> 20021228-renato_v2
2     http://inoa.net/qmail/qmail-1.03-tls.patch
3    
4     This patch implements RFC2487 in qmail. This means you can
5     get SSL or TLS encrypted and authenticated SMTP between
6     the MTAs and from MUA to MTA.
7     The code is considered experimental (but has worked for
8     many since its first release on 1999-03-21).
9    
10     Usage: - install OpenSSL-0.9.6g http://www.openssl.org/
11     (any 0.9.6 version is presumed to work)
12     - apply patch to qmail-1.03 http://www.qmail.org/
13     The patches to qmail-remote.c
14     and qmail-smtpd.c can be applied separately.
15     - provide a server certificate in /var/qmail/control/servercert.pem.
16     "make cert" makes a self-signed certificate.
17     "make cert-req" makes a certificate request.
18     Note: you can add the CA certificate and intermediate
19     certs to the end of servercert.pem.
20     - replace qmail-smtpd and/or qmail-remote binary
21     - verify operation (header information should show
22     something like
23     "Received [..] with DES-CBC3-SHA encrypted SMTP;")
24     If you don't have a server to test with, you can test
25     by sending mail to tag-ping@tbs-internet.com,
26     which will bounce your mail.
27    
28     Optional: - when DEBUG is defined, some extra TLS info will be logged
29     - qmail-remote will authenticate with the certificate in
30     /var/qmail/control/clientcert.pem. By preference this is
31     the same as servercert.pem, where nsCertType should be
32     == server,client or be a generic certificate (no usage specified).
33     - when a 512 RSA key is provided in /var/qmail/control/rsa512.pem,
34     this key will be used instead of on-the-fly generation by
35     qmail-smtpd. Periodical replacement can be done by crontab:
36     01 01 * * * umask 0077; /usr/local/ssl/bin/openssl genrsa \
37     -out /var/qmail/control/rsa512.new 512 > /dev/null 2>&1 &&\
38     chown qmaild.qmail /var/qmail/control/rsa512.new && /bin/mv -f \
39     /var/qmail/control/rsa512.new /var/qmail/control/rsa512.pem
40     - server authentication:
41     qmail-remote requires authentication from servers for which
42     /var/qmail/control/tlshosts/host.dom.ain.pem exists.
43     The .pem file contains the validating CA certificates
44     (or self-signed server certificate).
45     CommonName has to match.
46     WARNING: this option may cause mail to be delayed, bounced,
47     doublebounced, and lost.
48     - client authentication:
49     when relay rules would reject an incoming mail,
50     qmail-smtpd can allow the mail based on a presented cert.
51     Certs are verified against a CA list in
52     /var/qmail/control/clientca.pem (eg. http://www.modssl.org/
53     source/cvs/exp/mod_ssl/pkg.mod_ssl/pkg.sslcfg/ca-bundle.crt)
54     and the cert email-address has to match a line in
55     /var/qmail/control/tlsclients. This email-address is logged
56     in the headers.
57     - cipher selection:
58     qmail-remote:
59     openssl cipher string (`man ciphers`) read from
60     /var/qmail/control/tlsclientciphers
61     qmail-smtpd:
62     openssl cipher string read from TLSCIPHERS environment variable
63     (can vary based on client IP address e.g.)
64     or if that is not available /var/qmail/control/tlsserverciphers
65     - smtps (deprecated SMTP over TLS via port 465):
66     qmail-remote: when connecting to port 465
67     qmail-smtpd: when SMTPS environment variable is not empty
68    
69     Caveats: - do a `make clean` after patching
70     - binaries dynamically linked with current openssl versions need
71     recompilation when the shared openssl libs are upgraded.
72     - this patch could conflict with other patches (notably those
73     replacing \n with \r\n, which is a bad idea on encrypted links).
74     - some broken servers have a problem with TLSv1 compatibility.
75     Uncomment the line where we set the SSL_OP_NO_TLSv1 option.
76     - needs working /dev/urandom (or EGD for openssl versions >0.9.7)
77     for seeding random number generator.
78     - packagers should make sure that installing without a valid
79     servercert is impossible
80     - when applied in combination with AUTH patch, AUTH patch
81     should be applied first and first part of this patch
82     will fail. This error can be ignored. Packagers should
83     cut the first 12 lines of this patch to make a happy
84     patch
85    
86     Copyright: GPL
87     Links with OpenSSL
88     Inspiration and code from examples in SSLeay (E. Young
89     <eay@cryptsoft.com> and T. Hudson <tjh@cryptsoft.com>),
90     stunnel (M. Trojnara <mtrojnar@ddc.daewoo.com.pl>),
91     Postfix/TLS (L. Jaenicke <Lutz.Jaenicke@aet.tu-cottbus.de>),
92     modssl (R. Engelschall <rse@engelschall.com>),
93     openssl examples of E. Rescorla <ekr@rtfm.com>.
94     Debug code, tlscipher selection, many feature suggestions,
95     French docs https://www.TBS-internet.com/ssl/qmail-tls.html
96     from Jean-Philippe Donnio <tag-ssl@tbs-internet.com>.
97     Openssl usage consulting from B. M"oller <bmoeller@acm.org>.
98     Bug report from A. Dustman <adustman@comstar.net>.
99     Ssl_timeoutio functions (non-blocking io, timeouts), smtps,
100     auth, qmtp, mxps patch compatibility, man pages, code cleanup,
101     improved error reporting, RFC2595 server identity check
102     from A. Meltzer <albertikm (a) hotmail.com>.
103     Bug report from Niall Richard Murphy, Tim Helton.
104    
105     Bug reports: mailto:<qmail-tls@inoa.net>
106     changelogs:
107     2019-02-24 JP Pialasse jp@koozali.org
108     removed qmail-smtpd patches
109    
110     >----< Cut the next 12 lines if applying over AUTH server patch >---<
111     --- qmail-1.03-orig/qmail-smtpd.c Mon Jun 15 03:53:16 1998
112     +++ qmail-1.03/qmail-smtpd.c Tue Jun 18 09:49:38 2002
113     @@ -229,7 +229,8 @@
114     }
115     void smtp_ehlo(arg) char *arg;
116     {
117     - smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
118     + smtp_greet("250-");
119     + out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
120     seenmail = 0; dohelo(arg);
121     }
122     void smtp_rset()
123     >----< Cut previous 12 lines if applying over AUTH server patch >---<
124    
125    
126    
127     >----< The next 89 lines are the qmail-remote EHLO patch >---<
128     --- qmail-1.03-orig/qmail-remote.c Mon Jun 15 03:53:16 1998
129     +++ qmail-1.03/qmail-remote.c Sun Nov 24 13:05:20 2002
130     @@ -163,6 +163,59 @@ unsigned long smtpcode()
131     return code;
132     }
133    
134     +#ifdef EHLO
135     +saa ehlokw = {0}; /* list of EHLO keywords and parameters */
136     +int maxehlokwlen = 0;
137     +
138     +unsigned long ehlo()
139     +{
140     + stralloc *sa;
141     + char *s, *e, *p;
142     + unsigned long code;
143     +
144     + if (ehlokw.len > maxehlokwlen) maxehlokwlen = ehlokw.len;
145     + ehlokw.len = 0;
146     +
147     +# ifdef MXPS
148     + if (type == 's') return 0;
149     +# endif
150     +
151     + substdio_puts(&smtpto, "EHLO ");
152     + substdio_put(&smtpto, helohost.s, helohost.len);
153     + substdio_puts(&smtpto, "\r\n");
154     + substdio_flush(&smtpto);
155     +
156     + code = smtpcode();
157     + if (code != 250) return code;
158     +
159     + s = smtptext.s;
160     + while (*s++ != '\n') ; /* skip the first line: contains the domain */
161     +
162     + e = smtptext.s + smtptext.len - 6; /* 250-?\n */
163     + while (s <= e)
164     + { int wasspace = 0;
165     + if (!saa_readyplus(&ehlokw, 1)) temp_nomem();
166     + sa = ehlokw.sa + ehlokw.len++;
167     + if (ehlokw.len > maxehlokwlen) *sa = sauninit; else sa->len = 0;
168     +
169     + /* smtptext is known to end in a '\n' */
170     + for (p = (s += 4); ; ++p)
171     + if (*p == '\n' || *p == ' ' || *p == '\t') {
172     + if (!wasspace) if (!stralloc_catb(sa, s, p - s) || !stralloc_0(sa)) temp_nomem();
173     + if (*p++ == '\n') break; wasspace = 1;
174     + }else if (wasspace == 1){
175     + wasspace = 0; s = p;
176     + }
177     + s = ++p;
178     + /* keyword should consist of alpha-num and '-'
179     + * broken AUTH might use '=' instead of space */
180     + for (p = sa->s; *p; ++p) if (*p == '=') { *p = 0; break; }
181     + }
182     +
183     + return 250;
184     +}
185     +#endif
186     +
187     void outsmtptext()
188     {
189     int i;
190     @@ -224,12 +277,26 @@ void smtp()
191    
192     if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
193    
194     +#ifdef EHLO
195     + code = ehlo();
196     +
197     + if (code == 250) {
198     + /* add EHLO response checks here */
199     +
200     + /* and if EHLO failed, use HELO */
201     + } else {
202     +#endif
203     +
204     substdio_puts(&smtpto,"HELO ");
205     substdio_put(&smtpto,helohost.s,helohost.len);
206     substdio_puts(&smtpto,"\r\n");
207     substdio_flush(&smtpto);
208     if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
209    
210     +#ifdef EHLO
211     + }
212     +#endif
213     +
214     substdio_puts(&smtpto,"MAIL FROM:<");
215     substdio_put(&smtpto,sender.s,sender.len);
216     substdio_puts(&smtpto,">\r\n");
217     >----< Previous 89 lines are the qmail-remote EHLO patch >---<
218    
219    
220     --- qmail-1.03-orig-orig/qmail-remote.c Sat Dec 28 14:11:34 2002
221     +++ qmail-1.03/qmail-remote.c Sun Dec 8 18:27:20 2002
222     @@ -48,6 +48,17 @@ saa reciplist = {0};
223    
224     struct ip_address partner;
225    
226     +#ifdef TLS
227     +# include <sys/stat.h>
228     +# include "tls.h"
229     +# include "ssl_timeoutio.h"
230     +# include <openssl/x509v3.h>
231     +# define EHLO 1
232     +
233     +int tls_init();
234     +const char *ssl_err_str = 0;
235     +#endif
236     +
237     void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
238     void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
239     void zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); }
240     @@ -99,6 +110,9 @@ void dropped() {
241     outhost();
242     out(" but connection died. ");
243     if (flagcritical) out("Possible duplicate! ");
244     +#ifdef TLS
245     + if (ssl_err_str) { out(ssl_err_str); out(" "); }
246     +#endif
247     out("(#4.4.2)\n");
248     zerodie();
249     }
250     @@ -110,6 +124,12 @@ int timeout = 1200;
251     int saferead(fd,buf,len) int fd; char *buf; int len;
252     {
253     int r;
254     +#ifdef TLS
255     + if (ssl) {
256     + r = ssl_timeoutread(timeout, smtpfd, smtpfd, ssl, buf, len);
257     + if (r < 0) ssl_err_str = ssl_strerror();
258     + } else
259     +#endif
260     r = timeoutread(timeout,smtpfd,buf,len);
261     if (r <= 0) dropped();
262     return r;
263     @@ -117,6 +137,12 @@ int saferead(fd,buf,len) int fd; char *b
264     int safewrite(fd,buf,len) int fd; char *buf; int len;
265     {
266     int r;
267     +#ifdef TLS
268     + if (ssl) {
269     + r = ssl_timeoutwrite(timeout, smtpfd, smtpfd, ssl, buf, len);
270     + if (r < 0) ssl_err_str = ssl_strerror();
271     + } else
272     +#endif
273     r = timeoutwrite(timeout,smtpfd,buf,len);
274     if (r <= 0) dropped();
275     return r;
276     @@ -232,6 +258,11 @@ void quit(prepend,append)
277     char *prepend;
278     char *append;
279     {
280     +#ifdef TLS
281     + /* shouldn't talk to the client unless in an appropriate state */
282     + int state = ssl ? ssl->state : SSL_ST_BEFORE;
283     + if (state & SSL_ST_OK || !smtps && state & SSL_ST_BEFORE)
284     +#endif
285     substdio_putsflush(&smtpto,"QUIT\r\n");
286     /* waiting for remote side is just too ridiculous */
287     out(prepend);
288     @@ -239,6 +270,30 @@ char *append;
289     out(append);
290     out(".\n");
291     outsmtptext();
292     +
293     +#if defined(TLS) && defined(DEBUG)
294     + if (ssl) {
295     + X509 *peercert;
296     +
297     + out("STARTTLS proto="); out(SSL_get_version(ssl));
298     + out("; cipher="); out(SSL_get_cipher(ssl));
299     +
300     + /* we want certificate details */
301     + if (peercert = SSL_get_peer_certificate(ssl)) {
302     + char *str;
303     +
304     + str = X509_NAME_oneline(X509_get_subject_name(peercert), NULL, 0);
305     + out("; subject="); out(str); OPENSSL_free(str);
306     +
307     + str = X509_NAME_oneline(X509_get_issuer_name(peercert), NULL, 0);
308     + out("; issuer="); out(str); OPENSSL_free(str);
309     +
310     + X509_free(peercert);
311     + }
312     + out(";\n");
313     + }
314     +#endif
315     +
316     zerodie();
317     }
318    
319     @@ -267,6 +322,182 @@ void blast()
320     substdio_flush(&smtpto);
321     }
322    
323     +#ifdef TLS
324     +char *partner_fqdn = 0;
325     +
326     +# define TLS_QUIT quit(ssl ? "; connected to " : "; connecting to ", "")
327     +void tls_quit(const char *s1, const char *s2)
328     +{
329     + out(s1); if (s2) { out(": "); out(s2); } TLS_QUIT;
330     +}
331     +# define tls_quit_error(s) tls_quit(s, ssl_error())
332     +
333     +int match_partner(const char *s, int len)
334     +{
335     + if (!case_diffb(partner_fqdn, len, s) && !partner_fqdn[len]) return 1;
336     + /* we also match if the name is *.domainname */
337     + if (*s == '*') {
338     + const char *domain = partner_fqdn + str_chr(partner_fqdn, '.');
339     + if (!case_diffb(domain, --len, ++s) && !domain[len]) return 1;
340     + }
341     + return 0;
342     +}
343     +
344     +/* don't want to fail handshake if certificate can't be verified */
345     +int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; }
346     +
347     +int tls_init()
348     +{
349     + int i;
350     + SSL *myssl;
351     + SSL_CTX *ctx;
352     + stralloc saciphers = {0};
353     + const char *ciphers, *servercert = 0;
354     +
355     + if (partner_fqdn) {
356     + struct stat st;
357     + stralloc tmp = {0};
358     + if (!stralloc_copys(&tmp, "control/tlshosts/")
359     + || !stralloc_catb(&tmp, partner_fqdn, str_len(partner_fqdn))
360     + || !stralloc_catb(&tmp, ".pem", 5)) temp_nomem();
361     + if (stat(tmp.s, &st)) alloc_free(tmp.s); else servercert = tmp.s;
362     + }
363     +
364     + if (!smtps) {
365     + stralloc *sa = ehlokw.sa;
366     + unsigned int len = ehlokw.len;
367     + /* look for STARTTLS among EHLO keywords */
368     + for ( ; len && case_diffs(sa->s, "STARTTLS"); ++sa, --len) ;
369     + if (!len) {
370     + if (!servercert) return 0;
371     + out("ZNo TLS achieved while "); out(servercert);
372     + out(" exists"); smtptext.len = 0; TLS_QUIT;
373     + }
374     + }
375     +
376     + SSL_library_init();
377     + ctx = SSL_CTX_new(SSLv23_client_method());
378     + if (!ctx) {
379     + if (!smtps && !servercert) return 0;
380     + smtptext.len = 0;
381     + tls_quit_error("ZTLS error initializing ctx");
382     + }
383     +
384     + if (servercert) {
385     + if (!SSL_CTX_load_verify_locations(ctx, servercert, NULL)) {
386     + SSL_CTX_free(ctx);
387     + smtptext.len = 0;
388     + out("ZTLS unable to load "); tls_quit_error(servercert);
389     + }
390     + /* set the callback here; SSL_set_verify didn't work before 0.9.6c */
391     + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb);
392     + }
393     +
394     + /* let the other side complain if it needs a cert and we don't have one */
395     +# define CLIENTCERT "control/clientcert.pem"
396     + if (SSL_CTX_use_certificate_chain_file(ctx, CLIENTCERT))
397     + SSL_CTX_use_RSAPrivateKey_file(ctx, CLIENTCERT, SSL_FILETYPE_PEM);
398     +# undef CLIENTCERT
399     +
400     + myssl = SSL_new(ctx);
401     + SSL_CTX_free(ctx);
402     + if (!myssl) {
403     + if (!smtps && !servercert) return 0;
404     + smtptext.len = 0;
405     + tls_quit_error("ZTLS error initializing ssl");
406     + }
407     +
408     + if (!smtps) substdio_putsflush(&smtpto, "STARTTLS\r\n");
409     +
410     + /* while the server is preparing a responce, do something else */
411     + if (control_readfile(&saciphers, "control/tlsclientciphers", 0) == -1)
412     + { SSL_free(myssl); temp_control(); }
413     + if (saciphers.len) {
414     + for (i = 0; i < saciphers.len - 1; ++i)
415     + if (!saciphers.s[i]) saciphers.s[i] = ':';
416     + ciphers = saciphers.s;
417     + }
418     + else ciphers = "DEFAULT";
419     + SSL_set_cipher_list(myssl, ciphers);
420     + alloc_free(saciphers.s);
421     +
422     + /* SSL_set_options(myssl, SSL_OP_NO_TLSv1); */
423     + SSL_set_fd(myssl, smtpfd);
424     +
425     + /* read the responce to STARTTLS */
426     + if (!smtps) {
427     + if (smtpcode() != 220) {
428     + SSL_free(myssl);
429     + if (!servercert) return 0;
430     + out("ZSTARTTLS rejected while ");
431     + out(servercert); out(" exists"); TLS_QUIT;
432     + }
433     + smtptext.len = 0;
434     + }
435     +
436     + ssl = myssl;
437     + if (ssl_timeoutconn(timeout, smtpfd, smtpfd, ssl) <= 0)
438     + tls_quit("ZTLS connect failed", ssl_strerror());
439     +
440     + if (servercert) {
441     + X509 *peercert;
442     + STACK_OF(GENERAL_NAME) *gens;
443     +
444     + int r = SSL_get_verify_result(ssl);
445     + if (r != X509_V_OK) {
446     + out("ZTLS unable to verify server with ");
447     + tls_quit(servercert, X509_verify_cert_error_string(r));
448     + }
449     + alloc_free(servercert);
450     +
451     + peercert = SSL_get_peer_certificate(ssl);
452     + if (!peercert) {
453     + out("ZTLS unable to verify server ");
454     + tls_quit(partner_fqdn, "no certificate provided");
455     + }
456     +
457     + /* RFC 2595 section 2.4: find a matching name
458     + * first find a match among alternative names */
459     + gens = X509_get_ext_d2i(peercert, NID_subject_alt_name, 0, 0);
460     + if (gens) {
461     + for (i = 0, r = sk_GENERAL_NAME_num(gens); i < r; ++i)
462     + {
463     + const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i);
464     + if (gn->type == GEN_DNS)
465     + if (match_partner(gn->d.ia5->data, gn->d.ia5->length)) break;
466     + }
467     + sk_GENERAL_NAME_free(gens);
468     + }
469     +
470     + /* no alternative name matched, look up commonName */
471     + if (!gens || i >= r) {
472     + stralloc peer = {0};
473     + X509_NAME *subj = X509_get_subject_name(peercert);
474     + i = X509_NAME_get_index_by_NID(subj, NID_commonName, -1);
475     + if (i >= 0) {
476     + const ASN1_STRING *s = X509_NAME_get_entry(subj, i)->value;
477     + if (s) { peer.len = s->length; peer.s = s->data; }
478     + }
479     + if (peer.len <= 0) {
480     + out("ZTLS unable to verify server ");
481     + tls_quit(partner_fqdn, "certificate contains no valid commonName");
482     + }
483     + if (!match_partner(peer.s, peer.len)) {
484     + out("ZTLS unable to verify server "); out(partner_fqdn);
485     + out(": received certificate for "); outsafe(&peer); TLS_QUIT;
486     + }
487     + }
488     +
489     + X509_free(peercert);
490     + }
491     +
492     + if (smtps) if (smtpcode() != 220)
493     + quit("ZTLS Connected to "," but greeting failed");
494     +
495     + return 1;
496     +}
497     +#endif
498     +
499     stralloc recip = {0};
500    
501     void smtp()
502     @@ -274,12 +505,37 @@ void smtp()
503     unsigned long code;
504     int flagbother;
505     int i;
506     +
507     +#ifndef PORT_SMTP
508     + /* the qmtpc patch uses smtp_port and undefines PORT_SMTP */
509     +# define port smtp_port
510     +#endif
511     +
512     +#ifdef TLS
513     +# ifdef MXPS
514     + if (type == 'S') smtps = 1;
515     + else if (type != 's')
516     +# endif
517     + if (port == 465) smtps = 1;
518     + if (!smtps)
519     +#endif
520    
521     if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
522    
523     #ifdef EHLO
524     +# ifdef TLS
525     + if (!smtps)
526     +# endif
527     code = ehlo();
528    
529     +# ifdef TLS
530     + if (tls_init())
531     + /* RFC2487 says we should issue EHLO (even if we might not need
532     + * extensions); at the same time, it does not prohibit a server
533     + * to reject the EHLO and make us fallback to HELO */
534     + code = ehlo();
535     +# endif
536     +
537     if (code == 250) {
538     /* add EHLO response checks here */
539    
540     @@ -484,6 +740,9 @@ char **argv;
541     if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) {
542     tcpto_err(&ip.ix[i].ip,0);
543     partner = ip.ix[i].ip;
544     +#ifdef TLS
545     + partner_fqdn = ip.ix[i].fqdn;
546     +#endif
547     smtp(); /* does not return */
548     }
549     tcpto_err(&ip.ix[i].ip,errno == error_timeout);
550     --- qmail-1.03-orig/qmail-remote.8 Mon Jun 15 10:53:16 1998
551     +++ qmail-1.03/qmail-remote.8 Sun Dec 8 18:27:20 2002
552     @@ -114,6 +114,10 @@ arguments.
553     always exits zero.
554     .SH "CONTROL FILES"
555     .TP 5
556     +.I clientcert.pem
557     +SSL certificate that is used to authenticate with the remote server
558     +during a TLS session.
559     +.TP 5
560     .I helohost
561     Current host name,
562     for use solely in saying hello to the remote SMTP server.
563     @@ -156,6 +160,8 @@ may be empty;
564     this tells
565     .B qmail-remote
566     to look up MX records as usual.
567     +.I port
568     +value of 465 (deprecated smtps port) causes TLS session to be started.
569     .I smtproutes
570     may include wildcards:
571    
572     @@ -195,6 +201,26 @@ Number of seconds
573     .B qmail-remote
574     will wait for each response from the remote SMTP server.
575     Default: 1200.
576     +
577     +.TP 5
578     +.I tlsclientciphers
579     +A set of OpenSSL client cipher strings. Multiple ciphers
580     +contained in a string should be separated by a colon.
581     +
582     +.TP 5
583     +.I tlshosts/<FQDN>.pem
584     +.B qmail-remote
585     +requires authentication from servers for which this certificate exists
586     +.RB ( <FQDN>
587     +is the fully-qualified domain name of the server). One of the
588     +.I dNSName
589     +or the
590     +.I CommonName
591     +attributes have to match.
592     +
593     +.B WARNING:
594     +this option may cause mail to be delayed, bounced, doublebounced, or lost.
595     +
596     .SH "SEE ALSO"
597     addresses(5),
598     envelopes(5),
599     --- qmail-1.03-orig/qmail-control.9 Mon Jun 15 10:53:16 1998
600     +++ qmail-1.03/qmail-control.9 Sun Dec 8 18:27:20 2002
601     @@ -43,6 +43,8 @@ control default used by
602     .I badmailfrom \fR(none) \fRqmail-smtpd
603     .I bouncefrom \fRMAILER-DAEMON \fRqmail-send
604     .I bouncehost \fIme \fRqmail-send
605     +.I clientca.pem \fR(none) \fRqmail-smtpd
606     +.I clientcert.pem \fR(none) \fRqmail-remote
607     .I concurrencylocal \fR10 \fRqmail-send
608     .I concurrencyremote \fR20 \fRqmail-send
609     .I defaultdomain \fIme \fRqmail-inject
610     @@ -61,11 +63,17 @@ control default used by
611     .I qmqpservers \fR(none) \fRqmail-qmqpc
612     .I queuelifetime \fR604800 \fRqmail-send
613     .I rcpthosts \fR(none) \fRqmail-smtpd
614     +.I rsa512.pem \fR(none) \fRqmail-smtpd
615     +.I servercert.pem \fR(none) \fRqmail-smtpd
616     .I smtpgreeting \fIme \fRqmail-smtpd
617     .I smtproutes \fR(none) \fRqmail-remote
618     .I timeoutconnect \fR60 \fRqmail-remote
619     .I timeoutremote \fR1200 \fRqmail-remote
620     .I timeoutsmtpd \fR1200 \fRqmail-smtpd
621     +.I tlsclients \fR(none) \fRqmail-smtpd
622     +.I tlsclientciphers \fR(none) \fRqmail-remote
623     +.I tlshosts/FQDN.pem \fR(none) \fRqmail-remote
624     +.I tlsserverciphers \fR(none) \fRqmail-smtpd
625     .I virtualdomains \fR(none) \fRqmail-send
626     .fi
627     .RE
628     --- qmail-1.03-orig/dns.c Mon Jun 15 10:53:16 1998
629     +++ qmail-1.03/dns.c Sun Dec 8 18:27:20 2002
630     @@ -269,12 +269,11 @@ stralloc *sa;
631     int pref;
632     {
633     int r;
634     - struct ip_mx ix;
635     + struct ip_mx ix = {0};
636    
637     if (!stralloc_copy(&glue,sa)) return DNS_MEM;
638     if (!stralloc_0(&glue)) return DNS_MEM;
639     if (glue.s[0]) {
640     - ix.pref = 0;
641     if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
642     {
643     if (!ipalloc_append(ia,&ix)) return DNS_MEM;
644     @@ -293,9 +292,16 @@ int pref;
645     ix.ip = ip;
646     ix.pref = pref;
647     if (r == DNS_SOFT) return DNS_SOFT;
648     - if (r == 1)
649     + if (r == 1) {
650     +#ifdef IX_FQDN
651     + ix.fqdn = glue.s;
652     +#endif
653     if (!ipalloc_append(ia,&ix)) return DNS_MEM;
654     }
655     + }
656     +#ifdef IX_FQDN
657     + glue.s = 0;
658     +#endif
659     return 0;
660     }
661    
662     @@ -315,7 +321,7 @@ unsigned long random;
663     {
664     int r;
665     struct mx { stralloc sa; unsigned short p; } *mx;
666     - struct ip_mx ix;
667     + struct ip_mx ix = {0};
668     int nummx;
669     int i;
670     int j;
671     @@ -327,7 +333,6 @@ unsigned long random;
672     if (!stralloc_copy(&glue,sa)) return DNS_MEM;
673     if (!stralloc_0(&glue)) return DNS_MEM;
674     if (glue.s[0]) {
675     - ix.pref = 0;
676     if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
677     {
678     if (!ipalloc_append(ia,&ix)) return DNS_MEM;
679     --- qmail-1.03-orig/ipalloc.h Mon Jun 15 10:53:16 1998
680     +++ qmail-1.03/ipalloc.h Sun Dec 8 18:27:20 2002
681     @@ -3,7 +3,15 @@
682    
683     #include "ip.h"
684    
685     +#ifdef TLS
686     +# define IX_FQDN 1
687     +#endif
688     +
689     +#ifdef IX_FQDN
690     +struct ip_mx { struct ip_address ip; int pref; char *fqdn; } ;
691     +#else
692     struct ip_mx { struct ip_address ip; int pref; } ;
693     +#endif
694    
695     #include "gen_alloc.h"
696    
697     --- qmail-1.03-orig/tls.c Sat Dec 28 14:11:34 2002
698     +++ qmail-1.03/tls.c Sun Dec 8 18:27:20 2002
699     @@ -0,0 +1,26 @@
700     +#include "exit.h"
701     +#include "error.h"
702     +#include <string.h>
703     +#include <openssl/ssl.h>
704     +#include <openssl/err.h>
705     +
706     +int smtps = 0;
707     +SSL *ssl = NULL;
708     +
709     +void ssl_free(SSL *myssl) { SSL_shutdown(myssl); SSL_free(myssl); }
710     +void ssl_exit(int status) { if (ssl) ssl_free(ssl); _exit(status); }
711     +
712     +const char *ssl_error()
713     +{
714     + int r = ERR_get_error();
715     + if (!r) return NULL;
716     + SSL_load_error_strings();
717     + return ERR_error_string(r, NULL);
718     +}
719     +const char *ssl_strerror()
720     +{
721     + const char *err = ssl_error();
722     + if (err) return err;
723     + if (!errno) return 0;
724     + return errno == error_timeout ? "timed out" : strerror(errno);
725     +}
726     --- qmail-1.03-orig/tls.h Sat Dec 28 14:11:34 2002
727     +++ qmail-1.03/tls.h Sun Dec 8 18:27:20 2002
728     @@ -0,0 +1,16 @@
729     +#ifndef TLS_H
730     +#define TLS_H
731     +
732     +#include <openssl/ssl.h>
733     +
734     +extern int smtps;
735     +extern SSL *ssl;
736     +
737     +void ssl_free(SSL *myssl);
738     +void ssl_exit(int status);
739     +# define _exit ssl_exit
740     +
741     +const char *ssl_error();
742     +const char *ssl_strerror();
743     +
744     +#endif
745     --- qmail-1.03-orig/ssl_timeoutio.c Sat Dec 28 14:11:34 2002
746     +++ qmail-1.03/ssl_timeoutio.c Sun Dec 8 18:27:20 2002
747     @@ -0,0 +1,94 @@
748     +#include "select.h"
749     +#include "error.h"
750     +#include "ndelay.h"
751     +#include "ssl_timeoutio.h"
752     +
753     +int ssl_timeoutio(int (*fun)(),
754     + long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
755     +{
756     + int n;
757     + const long end = t + time(NULL);
758     +
759     + do {
760     + fd_set fds;
761     + struct timeval tv;
762     +
763     + const int r = buf ? fun(ssl, buf, len) : fun(ssl);
764     + if (r > 0) return r;
765     +
766     + t = end - time(NULL);
767     + if (t < 0) break;
768     + tv.tv_sec = t; tv.tv_usec = 0;
769     +
770     + FD_ZERO(&fds);
771     + switch (SSL_get_error(ssl, r))
772     + {
773     + default: return r; /* some other error */
774     + case SSL_ERROR_WANT_READ:
775     + FD_SET(rfd, &fds); n = select(rfd + 1, &fds, NULL, NULL, &tv);
776     + break;
777     + case SSL_ERROR_WANT_WRITE:
778     + FD_SET(wfd, &fds); n = select(wfd + 1, NULL, &fds, NULL, &tv);
779     + break;
780     + }
781     +
782     + /* n is the number of descriptors that changed status */
783     + } while (n > 0);
784     +
785     + if (n != -1) errno = error_timeout;
786     + return -1;
787     +}
788     +
789     +int ssl_timeoutaccept(long t, int rfd, int wfd, SSL *ssl)
790     +{
791     + int r;
792     +
793     + /* if connection is established, keep NDELAY */
794     + if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1) return -1;
795     + r = ssl_timeoutio(SSL_accept, t, rfd, wfd, ssl, NULL, 0);
796     +
797     + if (r <= 0) { ndelay_off(rfd); ndelay_off(wfd); }
798     + else SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
799     +
800     + return r;
801     +}
802     +
803     +int ssl_timeoutconn(long t, int rfd, int wfd, SSL *ssl)
804     +{
805     + int r;
806     +
807     + /* if connection is established, keep NDELAY */
808     + if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1) return -1;
809     + r = ssl_timeoutio(SSL_connect, t, rfd, wfd, ssl, NULL, 0);
810     +
811     + if (r <= 0) { ndelay_off(rfd); ndelay_off(wfd); }
812     + else SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
813     +
814     + return r;
815     +}
816     +
817     +int ssl_timeoutrehandshake(long t, int rfd, int wfd, SSL *ssl)
818     +{
819     + int r;
820     +
821     + SSL_renegotiate(ssl);
822     + r = ssl_timeoutio(SSL_do_handshake, t, rfd, wfd, ssl, NULL, 0);
823     + if (r <= 0 || ssl->type == SSL_ST_CONNECT) return r;
824     +
825     + /* this is for the server only */
826     + ssl->state = SSL_ST_ACCEPT;
827     + return ssl_timeoutio(SSL_do_handshake, t, rfd, wfd, ssl, NULL, 0);
828     +}
829     +
830     +int ssl_timeoutread(long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
831     +{
832     + if (!buf) return 0;
833     + if (SSL_pending(ssl)) return SSL_read(ssl, buf, len);
834     + return ssl_timeoutio(SSL_read, t, rfd, wfd, ssl, buf, len);
835     +}
836     +
837     +int ssl_timeoutwrite(long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
838     +{
839     + if (!buf) return 0;
840     + return ssl_timeoutio(SSL_write, t, rfd, wfd, ssl, buf, len);
841     +}
842     --- qmail-1.03-orig/ssl_timeoutio.h Sat Dec 28 14:11:34 2002
843     +++ qmail-1.03/ssl_timeoutio.h Sun Dec 8 18:27:20 2002
844     @@ -0,0 +1,21 @@
845     +#ifndef SSL_TIMEOUTIO_H
846     +#define SSL_TIMEOUTIO_H
847     +
848     +#include <openssl/ssl.h>
849     +
850     +/* the version is like this: 0xMNNFFPPS: major minor fix patch status */
851     +#if OPENSSL_VERSION_NUMBER < 0x00906000L
852     +# error "Need OpenSSL version at least 0.9.6"
853     +#endif
854     +
855     +int ssl_timeoutconn(long t, int rfd, int wfd, SSL *ssl);
856     +int ssl_timeoutaccept(long t, int rfd, int wfd, SSL *ssl);
857     +int ssl_timeoutrehandshake(long t, int rfd, int wfd, SSL *ssl);
858     +
859     +int ssl_timeoutread(long t, int rfd, int wfd, SSL *ssl, char *buf, int len);
860     +int ssl_timeoutwrite(long t, int rfd, int wfd, SSL *ssl, char *buf, int len);
861     +
862     +int ssl_timeoutio(
863     + int (*fun)(), long t, int rfd, int wfd, SSL *ssl, char *buf, int len);
864     +
865     +#endif
866     --- qmail-1.03-orig/TARGETS Mon Jun 15 10:53:16 1998
867     +++ qmail-1.03/TARGETS Sun Dec 8 18:27:20 2002
868     @@ -168,6 +168,8 @@ control.o
869     constmap.o
870     timeoutread.o
871     timeoutwrite.o
872     +tls.o
873     +ssl_timeoutio.o
874     timeoutconn.o
875     tcpto.o
876     dns.o
877     @@ -320,6 +322,7 @@ binm2
878     binm2+df
879     binm3
880     binm3+df
881     +Makefile-cert
882     it
883     qmail-local.0
884     qmail-lspawn.0
885     --- qmail-1.03-orig/Makefile-cert.mk Sat Dec 28 14:11:34 2002
886     +++ qmail-1.03/Makefile-cert.mk Sat Aug 17 18:30:01 2002
887     @@ -0,0 +1,21 @@
888     +cert-req: req.pem
889     +cert cert-req: QMAIL/control/clientcert.pem
890     + @:
891     +
892     +QMAIL/control/clientcert.pem: QMAIL/control/servercert.pem
893     + ln -s $< $@
894     +
895     +QMAIL/control/servercert.pem:
896     + PATH=$$PATH:/usr/local/ssl/bin \
897     + openssl req -new -x509 -nodes -days 366 -out $@ -keyout $@
898     + chmod 640 $@
899     + chown qmaild.qmail $@
900     +
901     +req.pem:
902     + PATH=$$PATH:/usr/local/ssl/bin openssl req \
903     + -new -nodes -out $@ -keyout QMAIL/control/servercert.pem
904     + chmod 640 QMAIL/control/servercert.pem
905     + chown qmaild.qmail QMAIL/control/servercert.pem
906     + @echo
907     + @echo "Send req.pem to your CA to obtain signed_req.pem, and do:"
908     + @echo "cat signed_req.pem >> QMAIL/control/servercert.pem"
909     --- qmail-1.03-orig/conf-cc Mon Jun 15 10:53:16 1998
910     +++ qmail-1.03/conf-cc Sat Dec 28 13:59:33 2002
911     @@ -1,3 +1,3 @@
912     -cc -O2
913     +cc -O2 -DTLS=20021228 -I/usr/local/ssl/include
914    
915     This will be used to compile .c files.
916     --- qmail-1.03-orig/Makefile Mon Jun 15 10:53:16 1998
917     +++ qmail-1.03/Makefile Sun Dec 8 18:27:20 2002
918     @@ -1444,6 +1444,7 @@ ndelay.a case.a sig.a open.a lock.a seek
919     substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib
920     ./load qmail-remote control.o constmap.o timeoutread.o \
921     timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \
922     + tls.o ssl_timeoutio.o -L/usr/local/ssl/lib -lssl -lcrypto \
923     ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
924     lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
925     str.a fs.a auto_qmail.o `cat dns.lib` `cat socket.lib`
926     @@ -1539,6 +1540,7 @@ open.a sig.a case.a env.a stralloc.a all
927     fs.a auto_qmail.o socket.lib
928     ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
929     timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
930     + tls.o ssl_timeoutio.o ndelay.a -L/usr/local/ssl/lib -lssl -lcrypto \
931     received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
932     datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
933     alloc.a substdio.a error.a str.a fs.a auto_qmail.o `cat \
934     @@ -2108,6 +2110,19 @@ timeoutwrite.o: \
935     compile timeoutwrite.c timeoutwrite.h select.h error.h readwrite.h
936     ./compile timeoutwrite.c
937    
938     +qmail-smtpd: tls.o ssl_timeoutio.o ndelay.a
939     +qmail-remote: tls.o ssl_timeoutio.o
940     +qmail-smtpd.o: tls.h ssl_timeoutio.h
941     +qmail-remote.o: tls.h ssl_timeoutio.h
942     +
943     +tls.o: \
944     +compile tls.c exit.h error.h
945     + ./compile tls.c
946     +
947     +ssl_timeoutio.o: \
948     +compile ssl_timeoutio.c ssl_timeoutio.h select.h error.h ndelay.h
949     + ./compile ssl_timeoutio.c
950     +
951     token822.o: \
952     compile token822.c stralloc.h gen_alloc.h alloc.h str.h token822.h \
953     gen_alloc.h gen_allocdefs.h
954     @@ -2139,3 +2154,13 @@ compile wait_nohang.c haswaitp.h
955     wait_pid.o: \
956     compile wait_pid.c error.h haswaitp.h
957     ./compile wait_pid.c
958     +
959     +cert cert-req: \
960     +Makefile-cert
961     + @$(MAKE) -sf $< $@
962     +
963     +Makefile-cert: \
964     +conf-qmail Makefile-cert.mk
965     + @cat Makefile-cert.mk \
966     + | sed s}QMAIL}"`head -1 conf-qmail`"}g \
967     + > $@

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed