summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2017-08-17 13:17:22 +0200
committermanuel <manuel@mausz.at>2017-08-17 13:17:22 +0200
commit1cafb5eab0b30e5f5a05737a075123af53153cb1 (patch)
treec6d4774169f7676385eca916eef3e4087693e0a2
parent3ee3b980a23b79479a650343a0fa876f68cad4bc (diff)
downloadqmail-1cafb5eab0b30e5f5a05737a075123af53153cb1.tar.gz
qmail-1cafb5eab0b30e5f5a05737a075123af53153cb1.tar.bz2
qmail-1cafb5eab0b30e5f5a05737a075123af53153cb1.zip
add support for SMTPUTF8
-rw-r--r--Makefile13
-rw-r--r--conf-cc2
-rw-r--r--qmail-remote.c96
-rw-r--r--qmail-smtpd.c23
-rw-r--r--qmail-spp.h1
-rw-r--r--qsutil.c4
6 files changed, 126 insertions, 13 deletions
diff --git a/Makefile b/Makefile
index abf6a05..a13882b 100644
--- a/Makefile
+++ b/Makefile
@@ -221,9 +221,9 @@ compile byte_zero.c byte.h
221 221
222case.a: \ 222case.a: \
223makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \ 223makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \
224case_starts.o 224case_startb.o case_starts.o
225 ./makelib case.a case_diffb.o case_diffs.o case_lowerb.o \ 225 ./makelib case.a case_diffb.o case_diffs.o case_lowerb.o \
226 case_lowers.o case_starts.o 226 case_lowers.o case_startb.o case_starts.o
227 227
228case_diffb.o: \ 228case_diffb.o: \
229compile case_diffb.c case.h 229compile case_diffb.c case.h
@@ -241,6 +241,10 @@ case_lowers.o: \
241compile case_lowers.c case.h 241compile case_lowers.c case.h
242 ./compile case_lowers.c 242 ./compile case_lowers.c
243 243
244case_startb.o: \
245compile case_startb.c case.h
246 ./compile case_startb.c
247
244case_starts.o: \ 248case_starts.o: \
245compile case_starts.c case.h 249compile case_starts.c case.h
246 ./compile case_starts.c 250 ./compile case_starts.c
@@ -1517,7 +1521,7 @@ dns.lib socket.lib
1517 ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \ 1521 ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
1518 lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \ 1522 lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
1519 env.a str.a fs.a auto_qmail.o base64.o \ 1523 env.a str.a fs.a auto_qmail.o base64.o \
1520 `cat dns.lib` `cat socket.lib` -lval -lsres 1524 `cat dns.lib` `cat socket.lib` -lval -lsres -lidn2
1521 1525
1522qmail-remote.0: \ 1526qmail-remote.0: \
1523qmail-remote.8 1527qmail-remote.8
@@ -1633,7 +1637,8 @@ compile qmail-smtpd.c sig.h readwrite.h stralloc.h gen_alloc.h \
1633substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \ 1637substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
1634error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h qmail-spp.h \ 1638error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h qmail-spp.h \
1635substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \ 1639substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
1636exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h base64.h 1640exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h base64.h open.h \
1641fd.h fork.h
1637 ./compile qmail-smtpd.c 1642 ./compile qmail-smtpd.c
1638 1643
1639qmail-start: \ 1644qmail-start: \
diff --git a/conf-cc b/conf-cc
index 245d8c5..a1f3fe6 100644
--- a/conf-cc
+++ b/conf-cc
@@ -1,3 +1,3 @@
1gcc -O2 -pipe -DTLS -fno-builtin-puts -fno-builtin-log2 1gcc -O2 -pipe -DTLS -DSMTPUTF8 -fno-builtin-puts -fno-builtin-log2
2 2
3This will be used to compile .c files. 3This will be used to compile .c files.
diff --git a/qmail-remote.c b/qmail-remote.c
index 94c6c0d..f8e60ad 100644
--- a/qmail-remote.c
+++ b/qmail-remote.c
@@ -46,6 +46,7 @@ stralloc helohost = {0};
46stralloc routes = {0}; 46stralloc routes = {0};
47struct constmap maproutes; 47struct constmap maproutes;
48stralloc host = {0}; 48stralloc host = {0};
49stralloc idnhost = {0};
49stralloc sender = {0}; 50stralloc sender = {0};
50stralloc auth_smtp_user = {0}; 51stralloc auth_smtp_user = {0};
51stralloc auth_smtp_pass = {0}; 52stralloc auth_smtp_pass = {0};
@@ -77,13 +78,19 @@ struct val_danestatus *dane_status = NULL;
77struct val_ssl_data *dane_ssl_data = NULL; 78struct val_ssl_data *dane_ssl_data = NULL;
78#endif 79#endif
79 80
81#ifdef SMTPUTF8
82# include <idn2.h>
83int flagutf8 = 0;
84stralloc header = {0};
85#endif
86
80void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); } 87void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
81void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); } 88void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
82void zeroflush() { zero(); substdio_flush(subfdoutsmall); } 89void zeroflush() { zero(); substdio_flush(subfdoutsmall); }
83void zerodie() { zeroflush(); _exit(0); } 90void zerodie() { zeroflush(); _exit(0); }
84void outsafe(sa) stralloc *sa; { int i; char ch; 91void outsafe(sa) stralloc *sa; { int i; unsigned char ch;
85for (i = 0;i < sa->len;++i) { 92for (i = 0;i < sa->len;++i) {
86ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126) ch = '?'; 93ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126 && ch <= 127) ch = '?';
87if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } } 94if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } }
88 95
89void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); } 96void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); }
@@ -346,6 +353,10 @@ void blast()
346 int r; 353 int r;
347 char ch; 354 char ch;
348 355
356#ifdef SMTPUTF8
357 substdio_put(&smtpto,header.s,header.len);
358#endif
359
349 for (;;) { 360 for (;;) {
350 r = substdio_get(&ssin,&ch,1); 361 r = substdio_get(&ssin,&ch,1);
351 if (r == 0) break; 362 if (r == 0) break;
@@ -634,11 +645,60 @@ int tls_init()
634 645
635stralloc recip = {0}; 646stralloc recip = {0};
636 647
648#ifdef SMTPUTF8
649int utf8string(unsigned char *ch, int len)
650{
651 int i = 0;
652 while (i < len)
653 if (ch[i++] > 127) return 1;
654 return 0;
655}
656
657int utf8received()
658{
659 int r, i, received = 0;
660 char ch;
661 stralloc receivedline = {0};
662
663 for (;;) { /* we consider only our own last written header */
664 r = substdio_get(&ssin,&ch,1);
665 if (r == 0) break;
666 if (r == -1) temp_read();
667
668 if (ch == '\n') {
669 if (!stralloc_append(&header,"\r")) temp_nomem(); /* received.c does not add '\r' */
670 if (!stralloc_append(&header,"\n")) temp_nomem();
671 if (case_startb(receivedline.s,5,"Date:")) return 0; /* header to quit asap */
672 if (case_startb(receivedline.s,14,"Received: from")) received++; /* found Received header */
673 if (received) {
674 if (case_startb(receivedline.s,5," by ")) {
675 for (i = 6; i < receivedline.len-6; ++i)
676 if (*(receivedline.s+i) == ' ')
677 if (case_startb(receivedline.s+i+1,9,"with UTF8")) return 1;
678 return 0;
679 }
680 }
681 if (!stralloc_copys(&receivedline,"")) temp_nomem();
682 receivedline.len = 0;
683 } else {
684 if (!stralloc_append(&header,&ch)) temp_nomem();
685 if (!stralloc_catb(&receivedline,&ch,1)) temp_nomem();
686 }
687 }
688 return 0;
689}
690#endif
691
637void mail_without_auth() 692void mail_without_auth()
638{ 693{
639 substdio_puts(&smtpto,"MAIL FROM:<"); 694 substdio_puts(&smtpto,"MAIL FROM:<");
640 substdio_put(&smtpto,sender.s,sender.len); 695 substdio_put(&smtpto,sender.s,sender.len);
641 substdio_puts(&smtpto,">\r\n"); 696 substdio_put(&smtpto,">",1);
697#ifdef SMTPUTF8
698 if (flagutf8 || utf8received())
699 substdio_puts(&smtpto, " SMTPUTF8");
700#endif
701 substdio_puts(&smtpto,"\r\n");
642 substdio_flush(&smtpto); 702 substdio_flush(&smtpto);
643} 703}
644 704
@@ -730,7 +790,12 @@ void smtp()
730 substdio_put(&smtpto,sender.s,sender.len); 790 substdio_put(&smtpto,sender.s,sender.len);
731 substdio_puts(&smtpto,"> AUTH=<"); 791 substdio_puts(&smtpto,"> AUTH=<");
732 substdio_put(&smtpto,sender.s,sender.len); 792 substdio_put(&smtpto,sender.s,sender.len);
733 substdio_puts(&smtpto,">\r\n"); 793 substdio_put(&smtpto,">",1);
794#ifdef SMTPUTF8
795 if (flagutf8 || utf8received())
796 substdio_puts(&smtpto, " SMTPUTF8");
797#endif
798 substdio_puts(&smtpto,"\r\n");
734 substdio_flush(&smtpto); 799 substdio_flush(&smtpto);
735 if(!stralloc_copys(&auth_status, "Delivered with authenticated connection to \n")) temp_nomem(); 800 if(!stralloc_copys(&auth_status, "Delivered with authenticated connection to \n")) temp_nomem();
736 if(!stralloc_0(&auth_status)) temp_nomem(); 801 if(!stralloc_0(&auth_status)) temp_nomem();
@@ -902,7 +967,12 @@ stralloc *saout; /* host has to be canonical, box has to be quoted */
902char *s; 967char *s;
903{ 968{
904 int j; 969 int j;
905 970
971#ifdef SMTPUTF8
972 if (!flagutf8)
973 flagutf8 = utf8string(s, str_len(s));
974#endif
975
906 j = str_rchr(s,'@'); 976 j = str_rchr(s,'@');
907 if (!s[j]) { 977 if (!s[j]) {
908 if (!stralloc_copys(saout,s)) temp_nomem(); 978 if (!stralloc_copys(saout,s)) temp_nomem();
@@ -983,6 +1053,18 @@ char **argv;
983 relayhost[i] = 0; 1053 relayhost[i] = 0;
984 } 1054 }
985 if (!stralloc_copys(&host,relayhost)) temp_nomem(); 1055 if (!stralloc_copys(&host,relayhost)) temp_nomem();
1056 } else {
1057#ifdef SMTPUTF8
1058 char *asciihost = 0;
1059 if (!stralloc_0(&host)) temp_nomem();
1060 switch (idn2_lookup_u8(host.s,(uint8_t**)&asciihost,IDN2_NFC_INPUT)) {
1061 case IDN2_OK: break;
1062 case IDN2_MALLOC: temp_nomem();
1063 default: perm_dns();
1064 }
1065 if (!stralloc_copys(&idnhost,asciihost)) temp_nomem();
1066 if (!stralloc_0(&idnhost)) temp_nomem();
1067#endif
986 } 1068 }
987 1069
988 1070
@@ -1002,7 +1084,11 @@ char **argv;
1002 1084
1003 1085
1004 random = now() + (getpid() << 16); 1086 random = now() + (getpid() << 16);
1087#ifdef SMTPUTF8
1088 switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&idnhost,random)) {
1089#else
1005 switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,random)) { 1090 switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,random)) {
1091#endif
1006 case DNS_MEM: temp_nomem(); 1092 case DNS_MEM: temp_nomem();
1007 case DNS_SOFT: temp_dns(); 1093 case DNS_SOFT: temp_dns();
1008 case DNS_HARD: perm_dns(); 1094 case DNS_HARD: perm_dns();
diff --git a/qmail-smtpd.c b/qmail-smtpd.c
index 35630ac..db0e16b 100644
--- a/qmail-smtpd.c
+++ b/qmail-smtpd.c
@@ -29,6 +29,10 @@
29#include "cdb.h" 29#include "cdb.h"
30#include "qmail-spp.h" 30#include "qmail-spp.h"
31#include "dns.h" 31#include "dns.h"
32#include "base64.h"
33#include "open.h"
34#include "fd.h"
35#include "fork.h"
32 36
33int spp_val; 37int spp_val;
34 38
@@ -511,6 +515,7 @@ stralloc mailfrom = {0};
511stralloc rcptto = {0}; 515stralloc rcptto = {0};
512stralloc fuser = {0}; 516stralloc fuser = {0};
513stralloc mfparms = {0}; 517stralloc mfparms = {0};
518int smtputf8 = 0;
514int recipcount; 519int recipcount;
515 520
516int mailfrom_size(arg) char *arg; 521int mailfrom_size(arg) char *arg;
@@ -562,6 +567,9 @@ void mailfrom_parms(arg) char *arg;
562 while (len) { 567 while (len) {
563 arg++; len--; 568 arg++; len--;
564 if (*arg == ' ' || *arg == '\0' ) { 569 if (*arg == ' ' || *arg == '\0' ) {
570#ifdef SMTPUTF8
571 if (case_starts(mfparms.s,"SMTPUTF8")) smtputf8 = 1;
572#endif
565 if (case_starts(mfparms.s,"SIZE=")) if (mailfrom_size(mfparms.s+5)) { flagsize = 1; return; } 573 if (case_starts(mfparms.s,"SIZE=")) if (mailfrom_size(mfparms.s+5)) { flagsize = 1; return; }
566 if (case_starts(mfparms.s,"AUTH=")) mailfrom_auth(mfparms.s+5,mfparms.len-5); 574 if (case_starts(mfparms.s,"AUTH=")) mailfrom_auth(mfparms.s+5,mfparms.len-5);
567 if (!stralloc_copys(&mfparms,"")) die_nomem; 575 if (!stralloc_copys(&mfparms,"")) die_nomem;
@@ -596,7 +604,11 @@ void smtp_ehlo(arg) char *arg;
596 if (!ssl && (stat(servercert, &st) == 0)) 604 if (!ssl && (stat(servercert, &st) == 0))
597 out("\r\n250-STARTTLS"); 605 out("\r\n250-STARTTLS");
598#endif 606#endif
607#ifdef SMTPUTF8
608 out("\r\n250-PIPELINING\r\n250-SMTPUTF8\r\n250-8BITMIME\r\n");
609#else
599 out("\r\n250-PIPELINING\r\n250-8BITMIME\r\n"); 610 out("\r\n250-PIPELINING\r\n250-8BITMIME\r\n");
611#endif
600#if defined(TLS) 612#if defined(TLS)
601 if(!tls_before_auth || (tls_before_auth && ssl)) smtp_authout(); 613 if(!tls_before_auth || (tls_before_auth && ssl)) smtp_authout();
602#else 614#else
@@ -827,7 +839,16 @@ void smtp_data(arg) char *arg; {
827 if (qmail_open(&qqt) == -1) { err_qqt(); return; } 839 if (qmail_open(&qqt) == -1) { err_qqt(); return; }
828 qp = qmail_qp(&qqt); 840 qp = qmail_qp(&qqt);
829 out("354 go ahead\r\n"); 841 out("354 go ahead\r\n");
830 842
843 if (smtputf8) {
844 stralloc utf8proto = {0};
845 if (*protocol == 'E') ++protocol;
846 if (!stralloc_copys(&utf8proto, "UTF8")) die_nomem();
847 if (!stralloc_cats(&utf8proto, protocol)) die_nomem();
848 if (!stralloc_0(&utf8proto)) die_nomem();
849 protocol = utf8proto.s;
850 }
851
831 received(&qqt,protocol,local,remoteip,remotehost,remoteinfo,fakehelo); 852 received(&qqt,protocol,local,remoteip,remotehost,remoteinfo,fakehelo);
832 qmail_put(&qqt,sppheaders.s,sppheaders.len); /* set in qmail-spp.c */ 853 qmail_put(&qqt,sppheaders.s,sppheaders.len); /* set in qmail-spp.c */
833 spp_rset(); 854 spp_rset();
diff --git a/qmail-spp.h b/qmail-spp.h
index b4d7154..e2c03d8 100644
--- a/qmail-spp.h
+++ b/qmail-spp.h
@@ -8,6 +8,7 @@ extern int spp_helo();
8extern void spp_rset(); 8extern void spp_rset();
9extern int spp_mail(); 9extern int spp_mail();
10extern int spp_rcpt(); 10extern int spp_rcpt();
11extern void spp_rcpt_accepted();
11extern int spp_data(); 12extern int spp_data();
12extern int spp_auth(); 13extern int spp_auth();
13 14
diff --git a/qsutil.c b/qsutil.c
index a769829..43890d0 100644
--- a/qsutil.c
+++ b/qsutil.c
@@ -24,11 +24,11 @@ void nomem() { log1("alert: out of memory, sleeping...\n"); sleep(10); }
24void pausedir(dir) char *dir; 24void pausedir(dir) char *dir;
25{ log3("alert: unable to opendir ",dir,", sleeping...\n"); sleep(10); } 25{ log3("alert: unable to opendir ",dir,", sleeping...\n"); sleep(10); }
26 26
27static int issafe(ch) char ch; 27static int issafe(ch) unsigned char ch;
28{ 28{
29 if (ch == '%') return 0; /* general principle: allman's code is crap */ 29 if (ch == '%') return 0; /* general principle: allman's code is crap */
30 if (ch < 33) return 0; 30 if (ch < 33) return 0;
31 if (ch > 126) return 0; 31 if (ch > 126 && ch <= 127) return 0;
32 return 1; 32 return 1;
33} 33}
34 34