diff options
Diffstat (limited to 'qmail-remote.c')
| -rw-r--r-- | qmail-remote.c | 96 |
1 files changed, 91 insertions, 5 deletions
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(); |
