diff options
| -rw-r--r-- | Makefile | 13 | ||||
| -rw-r--r-- | conf-cc | 2 | ||||
| -rw-r--r-- | qmail-remote.c | 96 | ||||
| -rw-r--r-- | qmail-smtpd.c | 23 | ||||
| -rw-r--r-- | qmail-spp.h | 1 | ||||
| -rw-r--r-- | qsutil.c | 4 |
6 files changed, 126 insertions, 13 deletions
| @@ -221,9 +221,9 @@ compile byte_zero.c byte.h | |||
| 221 | 221 | ||
| 222 | case.a: \ | 222 | case.a: \ |
| 223 | makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \ | 223 | makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \ |
| 224 | case_starts.o | 224 | case_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 | ||
| 228 | case_diffb.o: \ | 228 | case_diffb.o: \ |
| 229 | compile case_diffb.c case.h | 229 | compile case_diffb.c case.h |
| @@ -241,6 +241,10 @@ case_lowers.o: \ | |||
| 241 | compile case_lowers.c case.h | 241 | compile case_lowers.c case.h |
| 242 | ./compile case_lowers.c | 242 | ./compile case_lowers.c |
| 243 | 243 | ||
| 244 | case_startb.o: \ | ||
| 245 | compile case_startb.c case.h | ||
| 246 | ./compile case_startb.c | ||
| 247 | |||
| 244 | case_starts.o: \ | 248 | case_starts.o: \ |
| 245 | compile case_starts.c case.h | 249 | compile 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 | ||
| 1522 | qmail-remote.0: \ | 1526 | qmail-remote.0: \ |
| 1523 | qmail-remote.8 | 1527 | qmail-remote.8 |
| @@ -1633,7 +1637,8 @@ compile qmail-smtpd.c sig.h readwrite.h stralloc.h gen_alloc.h \ | |||
| 1633 | substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \ | 1637 | substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \ |
| 1634 | error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h qmail-spp.h \ | 1638 | error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h qmail-spp.h \ |
| 1635 | substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \ | 1639 | substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \ |
| 1636 | exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h base64.h | 1640 | exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h base64.h open.h \ |
| 1641 | fd.h fork.h | ||
| 1637 | ./compile qmail-smtpd.c | 1642 | ./compile qmail-smtpd.c |
| 1638 | 1643 | ||
| 1639 | qmail-start: \ | 1644 | qmail-start: \ |
| @@ -1,3 +1,3 @@ | |||
| 1 | gcc -O2 -pipe -DTLS -fno-builtin-puts -fno-builtin-log2 | 1 | gcc -O2 -pipe -DTLS -DSMTPUTF8 -fno-builtin-puts -fno-builtin-log2 |
| 2 | 2 | ||
| 3 | This will be used to compile .c files. | 3 | This 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}; | |||
| 46 | stralloc routes = {0}; | 46 | stralloc routes = {0}; |
| 47 | struct constmap maproutes; | 47 | struct constmap maproutes; |
| 48 | stralloc host = {0}; | 48 | stralloc host = {0}; |
| 49 | stralloc idnhost = {0}; | ||
| 49 | stralloc sender = {0}; | 50 | stralloc sender = {0}; |
| 50 | stralloc auth_smtp_user = {0}; | 51 | stralloc auth_smtp_user = {0}; |
| 51 | stralloc auth_smtp_pass = {0}; | 52 | stralloc auth_smtp_pass = {0}; |
| @@ -77,13 +78,19 @@ struct val_danestatus *dane_status = NULL; | |||
| 77 | struct val_ssl_data *dane_ssl_data = NULL; | 78 | struct val_ssl_data *dane_ssl_data = NULL; |
| 78 | #endif | 79 | #endif |
| 79 | 80 | ||
| 81 | #ifdef SMTPUTF8 | ||
| 82 | # include <idn2.h> | ||
| 83 | int flagutf8 = 0; | ||
| 84 | stralloc header = {0}; | ||
| 85 | #endif | ||
| 86 | |||
| 80 | void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); } | 87 | void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); } |
| 81 | void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); } | 88 | void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); } |
| 82 | void zeroflush() { zero(); substdio_flush(subfdoutsmall); } | 89 | void zeroflush() { zero(); substdio_flush(subfdoutsmall); } |
| 83 | void zerodie() { zeroflush(); _exit(0); } | 90 | void zerodie() { zeroflush(); _exit(0); } |
| 84 | void outsafe(sa) stralloc *sa; { int i; char ch; | 91 | void outsafe(sa) stralloc *sa; { int i; unsigned char ch; |
| 85 | for (i = 0;i < sa->len;++i) { | 92 | for (i = 0;i < sa->len;++i) { |
| 86 | ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126) ch = '?'; | 93 | ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126 && ch <= 127) ch = '?'; |
| 87 | if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } } | 94 | if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } } |
| 88 | 95 | ||
| 89 | void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); } | 96 | void 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 | ||
| 635 | stralloc recip = {0}; | 646 | stralloc recip = {0}; |
| 636 | 647 | ||
| 648 | #ifdef SMTPUTF8 | ||
| 649 | int 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 | |||
| 657 | int 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 | |||
| 637 | void mail_without_auth() | 692 | void 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 */ | |||
| 902 | char *s; | 967 | char *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 | ||
| 33 | int spp_val; | 37 | int spp_val; |
| 34 | 38 | ||
| @@ -511,6 +515,7 @@ stralloc mailfrom = {0}; | |||
| 511 | stralloc rcptto = {0}; | 515 | stralloc rcptto = {0}; |
| 512 | stralloc fuser = {0}; | 516 | stralloc fuser = {0}; |
| 513 | stralloc mfparms = {0}; | 517 | stralloc mfparms = {0}; |
| 518 | int smtputf8 = 0; | ||
| 514 | int recipcount; | 519 | int recipcount; |
| 515 | 520 | ||
| 516 | int mailfrom_size(arg) char *arg; | 521 | int 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(); | |||
| 8 | extern void spp_rset(); | 8 | extern void spp_rset(); |
| 9 | extern int spp_mail(); | 9 | extern int spp_mail(); |
| 10 | extern int spp_rcpt(); | 10 | extern int spp_rcpt(); |
| 11 | extern void spp_rcpt_accepted(); | ||
| 11 | extern int spp_data(); | 12 | extern int spp_data(); |
| 12 | extern int spp_auth(); | 13 | extern int spp_auth(); |
| 13 | 14 | ||
| @@ -24,11 +24,11 @@ void nomem() { log1("alert: out of memory, sleeping...\n"); sleep(10); } | |||
| 24 | void pausedir(dir) char *dir; | 24 | void 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 | ||
| 27 | static int issafe(ch) char ch; | 27 | static 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 | ||
