diff options
author | Todd Lyons <tlyons@exim.org> | 2014-05-12 08:12:17 -0700 |
---|---|---|
committer | Todd Lyons <tlyons@exim.org> | 2014-05-12 08:12:17 -0700 |
commit | 9aa512a1898155484e00ee089057d28f2432b30e (patch) | |
tree | 231b6a3479c59e09a15f63f1350d31fb60f360b6 /src | |
parent | a37a8eec3f4c73e604c23d73c9264c8ae95a0037 (diff) | |
parent | 783b385fe846f97aa5d7a7675cc0600e917b8795 (diff) |
Merge branch 'master' of ssh://git.exim.org/home/git/exim
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 1 | ||||
-rw-r--r-- | src/OS/os.c-Linux | 2 | ||||
-rw-r--r-- | src/src/deliver.c | 56 | ||||
-rw-r--r-- | src/src/expand.c | 31 | ||||
-rw-r--r-- | src/src/functions.h | 1 | ||||
-rw-r--r-- | src/src/globals.c | 1 | ||||
-rw-r--r-- | src/src/globals.h | 3 | ||||
-rw-r--r-- | src/src/host.c | 48 | ||||
-rw-r--r-- | src/src/malware.c | 14 | ||||
-rw-r--r-- | src/src/route.c | 1 | ||||
-rw-r--r-- | src/src/string.c | 2 | ||||
-rw-r--r-- | src/src/structs.h | 4 | ||||
-rw-r--r-- | src/src/tls-gnu.c | 7 | ||||
-rw-r--r-- | src/src/tls-openssl.c | 37 | ||||
-rw-r--r-- | src/src/tlscert-gnu.c | 6 | ||||
-rw-r--r-- | src/src/tlscert-openssl.c | 16 | ||||
-rw-r--r-- | src/src/transport.c | 1 | ||||
-rw-r--r-- | src/src/transports/smtp.c | 12 |
18 files changed, 176 insertions, 67 deletions
diff --git a/src/Makefile b/src/Makefile index b913aec8a..99f4ab308 100644 --- a/src/Makefile +++ b/src/Makefile @@ -94,6 +94,7 @@ cscope.files: FRC -o -name "os.h*" -print \ -o -name "*akefile*" -print \ -o -name EDITME -print >> $@ + ls OS/* >> $@ FRC: diff --git a/src/OS/os.c-Linux b/src/OS/os.c-Linux index 1e8a6f47d..df0dff9db 100644 --- a/src/OS/os.c-Linux +++ b/src/OS/os.c-Linux @@ -94,7 +94,7 @@ ip_address_item *last = NULL; ip_address_item *next; char addr6p[8][5]; unsigned int plen, scope, dad_status, if_idx; -char devname[20]; +char devname[20+1]; FILE *f; #endif diff --git a/src/src/deliver.c b/src/src/deliver.c index fff0e2fd0..777ff8dc7 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -730,6 +730,7 @@ pointer to a single host item in their host list, for use by the transport. */ tpda_delivery_local_part = NULL; tpda_delivery_domain = NULL; tpda_delivery_confirmation = NULL; + lookup_dnssec_authenticated = NULL; #endif s = reset_point = store_get(size); @@ -793,7 +794,7 @@ if (addr->transport->info->local) else { - if (addr->host_used != NULL) + if (addr->host_used) { s = d_hostlog(s, &size, &ptr, addr); if (continue_sequence > 1) @@ -806,6 +807,11 @@ else tpda_delivery_local_part = addr->local_part; tpda_delivery_domain = addr->domain; tpda_delivery_confirmation = addr->message; + + /* DNS lookup status */ + lookup_dnssec_authenticated = addr->host_used->dnssec==DS_YES ? US"yes" + : addr->host_used->dnssec==DS_NO ? US"no" + : NULL; #endif } @@ -1088,6 +1094,10 @@ if (result == OK) addr->ourcert = NULL; tls_out.peercert = addr->peercert; addr->peercert = NULL; + + tls_out.cipher = addr->cipher; + tls_out.peerdn = addr->peerdn; + tls_out.ocsp = addr->ocsp; #endif delivery_log(LOG_MAIN, addr, logchar, NULL); @@ -1103,6 +1113,9 @@ if (result == OK) tls_free_cert(tls_out.peercert); tls_out.peercert = NULL; } + tls_out.cipher = NULL; + tls_out.peerdn = NULL; + tls_out.ocsp = OCSP_NOT_REQ; #endif } @@ -2987,9 +3000,7 @@ while (!done) addr->cipher = string_copy(ptr); while (*ptr++); if (*ptr) - { addr->peerdn = string_copy(ptr); - } break; case '2': @@ -3003,10 +3014,18 @@ while (!done) if (*ptr) (void) tls_import_cert(ptr, &addr->ourcert); break; + + #ifdef EXPERIMENTAL_OCSP + case '4': + addr->ocsp = OCSP_NOT_REQ; + if (*ptr) + addr->ocsp = *ptr - '0'; + break; + #endif } while (*ptr++); break; - #endif + #endif /*SUPPORT_TLS*/ case 'C': /* client authenticator information */ switch (*ptr++) @@ -3026,7 +3045,7 @@ while (!done) #ifdef EXPERIMENTAL_PRDR case 'P': - addr->flags |= af_prdr_used; break; + addr->flags |= af_prdr_used; break; #endif case 'A': @@ -3053,7 +3072,7 @@ while (!done) addr->user_message = (*ptr)? string_copy(ptr) : NULL; while(*ptr++); - /* Always two strings for host information, followed by the port number */ + /* Always two strings for host information, followed by the port number and DNSSEC mark */ if (*ptr != 0) { @@ -3064,6 +3083,10 @@ while (!done) while(*ptr++); memcpy(&(h->port), ptr, sizeof(h->port)); ptr += sizeof(h->port); + h->dnssec = *ptr == '2' ? DS_YES + : *ptr == '1' ? DS_NO + : DS_UNK; + ptr++; addr->host_used = h; } else ptr++; @@ -4091,11 +4114,9 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) retry_item *r; /* The certificate verification status goes into the flags */ - if (tls_out.certificate_verified) setflag(addr, af_cert_verified); /* Use an X item only if there's something to send */ - #ifdef SUPPORT_TLS if (addr->cipher) { @@ -4132,7 +4153,16 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) *ptr++ = 0; rmt_dlv_checked_write(fd, big_buffer, ptr - big_buffer); } - #endif + # ifdef EXPERIMENTAL_OCSP + if (addr->ocsp > OCSP_NOT_REQ) + { + ptr = big_buffer; + sprintf(CS ptr, "X4%c", addr->ocsp + '0'); + while(*ptr++); + rmt_dlv_checked_write(fd, big_buffer, ptr - big_buffer); + } + # endif + #endif /*SUPPORT_TLS*/ if (client_authenticator) { @@ -4157,7 +4187,8 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) } #ifdef EXPERIMENTAL_PRDR - if (addr->flags & af_prdr_used) rmt_dlv_checked_write(fd, "P", 1); + if (addr->flags & af_prdr_used) + rmt_dlv_checked_write(fd, "P", 1); #endif /* Retry information: for most success cases this will be null. */ @@ -4211,6 +4242,11 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) while(*ptr++); memcpy(ptr, &(addr->host_used->port), sizeof(addr->host_used->port)); ptr += sizeof(addr->host_used->port); + + /* DNS lookup status */ + *ptr++ = addr->host_used->dnssec==DS_YES ? '2' + : addr->host_used->dnssec==DS_NO ? '1' : '0'; + } rmt_dlv_checked_write(fd, big_buffer, ptr - big_buffer); } diff --git a/src/src/expand.c b/src/src/expand.c index 01c6e05f4..9afc036fa 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -205,6 +205,7 @@ static uschar *op_table_main[] = { US"rxquote", US"s", US"sha1", + US"sha256", US"stat", US"str2b64", US"strlen", @@ -242,6 +243,7 @@ enum { EOP_RXQUOTE, EOP_S, EOP_SHA1, + EOP_SHA256, EOP_STAT, EOP_STR2B64, EOP_STRLEN, @@ -5365,8 +5367,6 @@ while (*s != 0) #ifdef SUPPORT_TLS case EITEM_CERTEXTRACT: { - int i; - int field_number = 1; uschar *save_lookup_value = lookup_value; uschar *sub[2]; int save_expand_nmax = @@ -5382,7 +5382,6 @@ while (*s != 0) /* strip spaces fore & aft */ { int len; - int x = 0; uschar *p = sub[0]; while (isspace(*p)) p++; @@ -5725,7 +5724,7 @@ while (*s != 0) int c; uschar *arg = NULL; uschar *sub; - var_entry *vp; + var_entry *vp = NULL; /* Owing to an historical mis-design, an underscore may be part of the operator name, or it may introduce arguments. We therefore first scan the @@ -5748,8 +5747,9 @@ while (*s != 0) switch(c) { #ifdef SUPPORT_TLS - case EOP_SHA1: case EOP_MD5: + case EOP_SHA1: + case EOP_SHA256: if (s[1] == '$') { uschar * s1 = s; @@ -5763,7 +5763,6 @@ while (*s != 0) break; } } - vp = NULL; /*FALLTHROUGH*/ #endif default: @@ -5861,7 +5860,7 @@ while (*s != 0) if (vp && *(void **)vp->value) { uschar * cp = tls_cert_fprt_md5(*(void **)vp->value); - yield = string_cat(yield, &size, &ptr, cp, (int)strlen(cp)); + yield = string_cat(yield, &size, &ptr, cp, Ustrlen(cp)); } else #endif @@ -5882,7 +5881,7 @@ while (*s != 0) if (vp && *(void **)vp->value) { uschar * cp = tls_cert_fprt_sha1(*(void **)vp->value); - yield = string_cat(yield, &size, &ptr, cp, (int)strlen(cp)); + yield = string_cat(yield, &size, &ptr, cp, Ustrlen(cp)); } else #endif @@ -5898,6 +5897,18 @@ while (*s != 0) } continue; + case EOP_SHA256: +#ifdef SUPPORT_TLS + if (vp && *(void **)vp->value) + { + uschar * cp = tls_cert_fprt_sha256(*(void **)vp->value); + yield = string_cat(yield, &size, &ptr, cp, (int)strlen(cp)); + } + else +#endif + expand_string_message = US"sha256 only supported for certificates"; + continue; + /* Convert hex encoding to base64 encoding */ case EOP_HEX2B64: @@ -6349,7 +6360,7 @@ while (*s != 0) case EOP_UTF8CLEAN: { int seq_len, index = 0; - int bytes_left = 0; + int bytes_left = 0; uschar seq_buff[4]; /* accumulate utf-8 here */ while (*sub != 0) @@ -6360,7 +6371,7 @@ while (*s != 0) complete = 0; c = *sub++; - if(bytes_left) + if (bytes_left) { if ((c & 0xc0) != 0x80) { diff --git a/src/src/functions.h b/src/src/functions.h index 38ba7f39d..792f3df4d 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -41,6 +41,7 @@ extern uschar * tls_cert_version(void *, uschar * mod); extern uschar * tls_cert_fprt_md5(void *); extern uschar * tls_cert_fprt_sha1(void *); +extern uschar * tls_cert_fprt_sha256(void *); extern int tls_client_start(int, host_item *, address_item *, void *); diff --git a/src/src/globals.c b/src/src/globals.c index af2903525..a2cc50313 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -341,6 +341,7 @@ address_item address_defaults = { NULL, /* ourcert */ NULL, /* peercert */ NULL, /* peerdn */ + OCSP_NOT_REQ, /* ocsp */ #endif NULL, /* authenticator */ NULL, /* auth_id */ diff --git a/src/src/globals.h b/src/src/globals.h index 9a42fe27e..8b55321f9 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -92,7 +92,8 @@ typedef struct { enum { OCSP_NOT_REQ=0, /* not requested */ OCSP_NOT_RESP, /* no response to request */ - OCSP_NOT_VFY, /* response not verified */ + OCSP_VFY_NOT_TRIED, /* response not verified */ + OCSP_FAILED, /* verify failed */ OCSP_VFIED /* verified */ } ocsp; /* Stapled OCSP status */ } tls_support; diff --git a/src/src/host.c b/src/src/host.c index a1db7717e..a59c4381b 100644 --- a/src/src/host.c +++ b/src/src/host.c @@ -2065,6 +2065,7 @@ for (i = 1; i <= times; host->port = PORT_NONE; host->status = hstatus_unknown; host->why = hwhy_unknown; + host->dnssec = DS_UNK; last = host; } @@ -2080,6 +2081,7 @@ for (i = 1; i <= times; next->port = PORT_NONE; next->status = hstatus_unknown; next->why = hwhy_unknown; + next->dnssec = DS_UNK; next->last_try = 0; next->next = last->next; last->next = next; @@ -2475,10 +2477,12 @@ int ind_type = 0; int yield; dns_answer dnsa; dns_scan dnss; -BOOL dnssec_request = match_isinlist(host->name, &dnssec_request_domains, - 0, NULL, NULL, MCL_DOMAIN, TRUE, NULL) == OK; BOOL dnssec_require = match_isinlist(host->name, &dnssec_require_domains, 0, NULL, NULL, MCL_DOMAIN, TRUE, NULL) == OK; +BOOL dnssec_request = dnssec_require + || match_isinlist(host->name, &dnssec_request_domains, + 0, NULL, NULL, MCL_DOMAIN, TRUE, NULL) == OK; +dnssec_status_t dnssec; /* Set the default fully qualified name to the incoming name, initialize the resolver if necessary, set up the relevant options, and initialize the flag @@ -2487,7 +2491,7 @@ that gets set for DNS syntax check errors. */ if (fully_qualified_name != NULL) *fully_qualified_name = host->name; dns_init((whichrrs & HOST_FIND_QUALIFY_SINGLE) != 0, (whichrrs & HOST_FIND_SEARCH_PARENTS) != 0, - dnssec_request || dnssec_require + dnssec_request ); host_find_failed_syntax = FALSE; @@ -2509,9 +2513,17 @@ if ((whichrrs & HOST_FIND_BY_SRV) != 0) the input name, pass back the new original domain, without the prepended magic. */ + dnssec = DS_UNK; + lookup_dnssec_authenticated = NULL; rc = dns_lookup(&dnsa, buffer, ind_type, &temp_fully_qualified_name); - lookup_dnssec_authenticated = !dnssec_request ? NULL - : dns_is_secure(&dnsa) ? US"yes" : US"no"; + + if (dnssec_request) + { + if (dns_is_secure(&dnsa)) + { dnssec = DS_YES; lookup_dnssec_authenticated = US"yes"; } + else + { dnssec = DS_NO; lookup_dnssec_authenticated = US"no"; } + } if (temp_fully_qualified_name != buffer && fully_qualified_name != NULL) *fully_qualified_name = temp_fully_qualified_name + prefix_length; @@ -2547,9 +2559,17 @@ listed as one for which we continue. */ if (rc != DNS_SUCCEED && (whichrrs & HOST_FIND_BY_MX) != 0) { ind_type = T_MX; + dnssec = DS_UNK; + lookup_dnssec_authenticated = NULL; rc = dns_lookup(&dnsa, host->name, ind_type, fully_qualified_name); - lookup_dnssec_authenticated = !dnssec_request ? NULL - : dns_is_secure(&dnsa) ? US"yes" : US"no"; + + if (dnssec_request) + { + if (dns_is_secure(&dnsa)) + { dnssec = DS_YES; lookup_dnssec_authenticated = US"yes"; } + else + { dnssec = DS_NO; lookup_dnssec_authenticated = US"no"; } + } switch (rc) { @@ -2593,9 +2613,19 @@ if (rc != DNS_SUCCEED) last = host; /* End of local chainlet */ host->mx = MX_NONE; host->port = PORT_NONE; + dnssec = DS_UNK; + lookup_dnssec_authenticated = NULL; rc = set_address_from_dns(host, &last, ignore_target_hosts, FALSE, fully_qualified_name, dnssec_request, dnssec_require); + if (dnssec_request) + { + if (dns_is_secure(&dnsa)) + { dnssec = DS_YES; lookup_dnssec_authenticated = US"yes"; } + else + { dnssec = DS_NO; lookup_dnssec_authenticated = US"no"; } + } + /* If one or more address records have been found, check that none of them are local. Since we know the host items all have their IP addresses inserted, host_scan_for_local_hosts() can only return HOST_FOUND or @@ -2665,9 +2695,7 @@ for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); the same precedence to sort randomly. */ if (ind_type == T_MX) - { weight = random_number(500); - } /* SRV records are specified with a port and a weight. The weight is used in a special algorithm. However, to start with, we just use it to order the @@ -2731,6 +2759,7 @@ for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); host->sort_key = precedence * 1000 + weight; host->status = hstatus_unknown; host->why = hwhy_unknown; + host->dnssec = dnssec; last = host; } @@ -2747,6 +2776,7 @@ for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); next->sort_key = sort_key; next->status = hstatus_unknown; next->why = hwhy_unknown; + next->dnssec = dnssec; next->last_try = 0; /* Handle the case when we have to insert before the first item. */ diff --git a/src/src/malware.c b/src/src/malware.c index aaf3fcb7e..2d2a8c892 100644 --- a/src/src/malware.c +++ b/src/src/malware.c @@ -42,7 +42,7 @@ static struct scan #define MAX_CLAMD_ADDRESS_LENGTH_S "64" typedef struct clamd_address_container { - uschar tcp_addr[MAX_CLAMD_ADDRESS_LENGTH]; + uschar tcp_addr[MAX_CLAMD_ADDRESS_LENGTH+1]; unsigned int tcp_port; } clamd_address_container; @@ -401,6 +401,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking) case MC_TCP: sock = m_tcpsocket_fromdef(scanner_options, &errstr); break; case MC_UNIX: sock = m_unixsocket(scanner_options, &errstr); break; case MC_STRM: sock = m_streamsocket(scanner_options, &errstr); break; + default: /* compiler quietening */ break; } if (sock < 0) return m_errlog_defer(scanent, errstr); @@ -944,12 +945,10 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking) sep = pclose(scanner_out); signal(SIGCHLD,eximsigchld); signal(SIGPIPE,eximsigpipe); if (sep != 0) - if (sep == -1) return m_errlog_defer(scanent, - string_sprintf("running scanner failed: %s", strerror(sep))); - else - return m_errlog_defer(scanent, - string_sprintf("scanner returned error code: %d", sep)); + sep == -1 + ? string_sprintf("running scanner failed: %s", strerror(sep)) + : string_sprintf("scanner returned error code: %d", sep)); if (trigger) { uschar * s; @@ -1270,8 +1269,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking) { free(clamav_fbuf); return m_errlog_defer_3(scanent, - string_sprintf("unable to send file body to socket (%s:%u)", - hostname, port), + string_sprintf("unable to send file body to socket (%s)", hostname), sock); } #endif diff --git a/src/src/route.c b/src/src/route.c index 271175e4b..0116e12af 100644 --- a/src/src/route.c +++ b/src/src/route.c @@ -1941,6 +1941,7 @@ DEBUG(D_route) if (h->mx >= 0) debug_printf(" MX=%d", h->mx); else if (h->mx != MX_NONE) debug_printf(" rgroup=%d", h->mx); if (h->port != PORT_NONE) debug_printf(" port=%d", h->port); + /* if (h->dnssec != DS_UNK) debug_printf(" dnssec=%s", h->dnssec==DS_YES ? "yes" : "no"); */ debug_printf("\n"); } } diff --git a/src/src/string.c b/src/src/string.c index f216e5a86..914390255 100644 --- a/src/src/string.c +++ b/src/src/string.c @@ -998,7 +998,7 @@ if (list) new = string_cat(new, &sz, &off, &sep, 1); } -while (sp = Ustrchr(ele, sep)) +while((sp = Ustrchr(ele, sep))) { new = string_cat(new, &sz, &off, ele, sp-ele+1); new = string_cat(new, &sz, &off, &sep, 1); diff --git a/src/src/structs.h b/src/src/structs.h index a6c78f4fc..989653e30 100644 --- a/src/src/structs.h +++ b/src/src/structs.h @@ -55,6 +55,8 @@ typedef struct ugid_block { but also used when checking lists of hosts and when transporting. Looking up host addresses is done using this structure. */ +typedef enum {DS_UNK=-1, DS_NO, DS_YES} dnssec_status_t; + typedef struct host_item { struct host_item *next; uschar *name; /* Host name */ @@ -65,6 +67,7 @@ typedef struct host_item { int status; /* Usable, unusable, or unknown */ int why; /* Why host is unusable */ int last_try; /* Time of last try if known */ + dnssec_status_t dnssec; } host_item; /* Chain of rewrite rules, read from the rewrite config, or parsed from the @@ -543,6 +546,7 @@ typedef struct address_item { void *ourcert; /* Certificate offered to peer, binary */ void *peercert; /* Certificate from peer, binary */ uschar *peerdn; /* DN of server's certificate */ + int ocsp; /* OCSP status of peer cert */ #endif uschar *authenticator; /* auth driver name used by transport */ diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index b0b67d820..3c926c0d4 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -1446,15 +1446,15 @@ server_ocsp_stapling_cb(gnutls_session_t session, void * ptr, { int ret; -tls_in.ocsp = OCSP_NOT_RESP; if ((ret = gnutls_load_file(ptr, ocsp_response)) < 0) { DEBUG(D_tls) debug_printf("Failed to load ocsp stapling file %s\n", (char *)ptr); + tls_in.ocsp = OCSP_NOT_RESP; return GNUTLS_E_NO_CERTIFICATE_STATUS; } -tls_in.ocsp = OCSP_NOT_VFY; +tls_in.ocsp = OCSP_VFY_NOT_TRIED; return 0; } @@ -1778,7 +1778,10 @@ if (require_ocsp) } if (gnutls_ocsp_status_request_is_checked(state->session, 0) == 0) + { + tls_out.ocsp = OCSP_FAILED; return tls_error(US"certificate status check failed", NULL, state->host); + } DEBUG(D_tls) debug_printf("Passed OCSP checking\n"); tls_out.ocsp = OCSP_VFIED; } diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index fd257f3c6..db2544c03 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -572,21 +572,21 @@ if (!OCSP_check_validity(thisupd, nextupd, EXIM_OCSP_SKEW_SECONDS, EXIM_OCSP_MAX } supply_response: -cbinfo->u_ocsp.server.response = resp; + cbinfo->u_ocsp.server.response = resp; return; bad: -if (running_in_test_harness) - { - extern char ** environ; - uschar ** p; - for (p = USS environ; *p != NULL; p++) - if (Ustrncmp(*p, "EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK", 42) == 0) - { - DEBUG(D_tls) debug_printf("Supplying known bad OCSP response\n"); - goto supply_response; - } - } + if (running_in_test_harness) + { + extern char ** environ; + uschar ** p; + for (p = USS environ; *p != NULL; p++) + if (Ustrncmp(*p, "EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK", 42) == 0) + { + DEBUG(D_tls) debug_printf("Supplying known bad OCSP response\n"); + goto supply_response; + } + } return; } #endif /*EXPERIMENTAL_OCSP*/ @@ -844,9 +844,10 @@ if(!p) DEBUG(D_tls) debug_printf(" null\n"); return cbinfo->u_ocsp.client.verify_required ? 0 : 1; } -tls_out.ocsp = OCSP_NOT_VFY; + if(!(rsp = d2i_OCSP_RESPONSE(NULL, &p, len))) { + tls_out.ocsp = OCSP_FAILED; if (log_extra_selector & LX_tls_cipher) log_write(0, LOG_MAIN, "Received TLS status response, parse error"); else @@ -856,6 +857,7 @@ if(!(rsp = d2i_OCSP_RESPONSE(NULL, &p, len))) if(!(bs = OCSP_response_get1_basic(rsp))) { + tls_out.ocsp = OCSP_FAILED; if (log_extra_selector & LX_tls_cipher) log_write(0, LOG_MAIN, "Received TLS status response, error parsing response"); else @@ -867,14 +869,12 @@ if(!(bs = OCSP_response_get1_basic(rsp))) /* We'd check the nonce here if we'd put one in the request. */ /* However that would defeat cacheability on the server so we don't. */ - /* This section of code reworked from OpenSSL apps source; The OpenSSL Project retains copyright: Copyright (c) 1999 The OpenSSL Project. All rights reserved. */ { BIO * bp = NULL; - OCSP_CERTID *id; int status, reason; ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; @@ -888,6 +888,7 @@ if(!(bs = OCSP_response_get1_basic(rsp))) if ((i = OCSP_basic_verify(bs, NULL, cbinfo->u_ocsp.client.verify_store, 0)) <= 0) { + tls_out.ocsp = OCSP_FAILED; BIO_printf(bp, "OCSP response verify failure\n"); ERR_print_errors(bp); i = cbinfo->u_ocsp.client.verify_required ? 0 : 1; @@ -902,6 +903,7 @@ if(!(bs = OCSP_response_get1_basic(rsp))) if (sk_OCSP_SINGLERESP_num(sresp) != 1) { + tls_out.ocsp = OCSP_FAILED; log_write(0, LOG_MAIN, "OCSP stapling " "with multiple responses not handled"); i = cbinfo->u_ocsp.client.verify_required ? 0 : 1; @@ -917,6 +919,7 @@ if(!(bs = OCSP_response_get1_basic(rsp))) if (!OCSP_check_validity(thisupd, nextupd, EXIM_OCSP_SKEW_SECONDS, EXIM_OCSP_MAX_AGE)) { + tls_out.ocsp = OCSP_FAILED; DEBUG(D_tls) ERR_print_errors(bp); log_write(0, LOG_MAIN, "Server OSCP dates invalid"); i = cbinfo->u_ocsp.client.verify_required ? 0 : 1; @@ -928,10 +931,11 @@ if(!(bs = OCSP_response_get1_basic(rsp))) switch(status) { case V_OCSP_CERTSTATUS_GOOD: - i = 1; tls_out.ocsp = OCSP_VFIED; + i = 1; break; case V_OCSP_CERTSTATUS_REVOKED: + tls_out.ocsp = OCSP_FAILED; log_write(0, LOG_MAIN, "Server certificate revoked%s%s", reason != -1 ? "; reason: " : "", reason != -1 ? OCSP_crl_reason_str(reason) : ""); @@ -939,6 +943,7 @@ if(!(bs = OCSP_response_get1_basic(rsp))) i = cbinfo->u_ocsp.client.verify_required ? 0 : 1; break; default: + tls_out.ocsp = OCSP_FAILED; log_write(0, LOG_MAIN, "Server certificate status unknown, in OCSP stapling"); i = cbinfo->u_ocsp.client.verify_required ? 0 : 1; diff --git a/src/src/tlscert-gnu.c b/src/src/tlscert-gnu.c index 32b1986b8..5a4c231bb 100644 --- a/src/src/tlscert-gnu.c +++ b/src/src/tlscert-gnu.c @@ -421,6 +421,12 @@ tls_cert_fprt_sha1(void * cert) return fingerprint((gnutls_x509_crt_t)cert, GNUTLS_DIG_SHA1); } +uschar * +tls_cert_fprt_sha256(void * cert) +{ +return fingerprint((gnutls_x509_crt_t)cert, GNUTLS_DIG_SHA256); +} + /* vi: aw ai sw=2 */ diff --git a/src/src/tlscert-openssl.c b/src/src/tlscert-openssl.c index cddde4cdc..9903f08f3 100644 --- a/src/src/tlscert-openssl.c +++ b/src/src/tlscert-openssl.c @@ -81,7 +81,7 @@ X509_free((X509 *)cert); static uschar * bio_string_copy(BIO * bp, int len) { -uschar * cp = ""; +uschar * cp = US""; len = len > 0 ? (int) BIO_get_mem_data(bp, &cp) : 0; cp = string_copyn(cp, len); BIO_free(bp); @@ -164,7 +164,7 @@ return cp; uschar * tls_cert_signature_algorithm(void * cert, uschar * mod) { -return string_copy(OBJ_nid2ln(X509_get_signature_type((X509 *)cert))); +return string_copy(US OBJ_nid2ln(X509_get_signature_type((X509 *)cert))); } uschar * @@ -182,7 +182,7 @@ return string_sprintf("%d", X509_get_version((X509 *)cert)); uschar * tls_cert_ext_by_oid(void * cert, uschar * oid, int idx) { -int nid = OBJ_create(oid, "", ""); +int nid = OBJ_create(CS oid, "", ""); int nidx = X509_get_ext_by_NID((X509 *)cert, nid, idx); X509_EXTENSION * ex = X509_get_ext((X509 *)cert, nidx); ASN1_OCTET_STRING * adata = X509_EXTENSION_get_data(ex); @@ -201,7 +201,7 @@ cp3 = cp2 = store_get(len*3+1); while(len) { - sprintf(cp2, "%.2x ", *cp1++); + sprintf(CS cp2, "%.2x ", *cp1++); cp2 += 3; len--; } @@ -341,7 +341,7 @@ if (!X509_digest(cert,fdig,md,&n)) return NULL; } cp = store_get(n*2+1); -for (j = 0; j < (int)n; j++) sprintf(cp+2*j, "%02X", md[j]); +for (j = 0; j < (int)n; j++) sprintf(CS cp+2*j, "%02X", md[j]); return(cp); } @@ -357,6 +357,12 @@ tls_cert_fprt_sha1(void * cert) return fingerprint((X509 *)cert, EVP_sha1()); } +uschar * +tls_cert_fprt_sha256(void * cert) +{ +return fingerprint((X509 *)cert, EVP_sha256()); +} + /* vi: aw ai sw=2 */ diff --git a/src/src/transport.c b/src/src/transport.c index 92de4b92b..00b8fa9d8 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -837,7 +837,6 @@ internal_transport_write_message(address_item *addr, int fd, int options, { int written = 0; int len; -header_line *h; BOOL use_crlf = (options & topt_use_crlf) != 0; /* Initialize pointer in output buffer. */ diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 9089d90c1..020f76cac 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -636,7 +636,7 @@ tpda_defer_errstr = addr->message ? string_sprintf("%s: %s", addr->message, strerror(addr->basic_errno)) : string_copy(addr->message) : addr->basic_errno > 0 - ? string_copy(strerror(addr->basic_errno)) + ? string_copy(US strerror(addr->basic_errno)) : NULL; DEBUG(D_transport) @@ -1232,6 +1232,7 @@ tls_out.peerdn = NULL; #if defined(SUPPORT_TLS) && !defined(USE_GNUTLS) tls_out.sni = NULL; #endif +tls_out.ocsp = OCSP_NOT_REQ; /* Flip the legacy TLS-related variables over to the outbound set in case they're used in the context of the transport. Don't bother resetting @@ -1242,8 +1243,8 @@ tls_modify_variables(&tls_out); #ifndef SUPPORT_TLS if (smtps) { - set_errno(addrlist, 0, US"TLS support not available", DEFER, FALSE); - return ERROR; + set_errno(addrlist, 0, US"TLS support not available", DEFER, FALSE); + return ERROR; } #endif @@ -1475,6 +1476,7 @@ if (tls_offered && !suppress_tls && addr->ourcert = tls_out.ourcert; addr->peercert = tls_out.peercert; addr->peerdn = tls_out.peerdn; + addr->ocsp = tls_out.ocsp; } } } @@ -2514,6 +2516,7 @@ for (addr = addrlist; addr != NULL; addr = addr->next) addr->ourcert = NULL; addr->peercert = NULL; addr->peerdn = NULL; + addr->ocsp = OCSP_NOT_REQ; #endif } return first_addr; @@ -2916,6 +2919,9 @@ for (cutoff_retry = 0; expired && deliver_host = host->name; deliver_host_address = host->address; + lookup_dnssec_authenticated = host->dnssec == DS_YES ? US"yes" + : host->dnssec == DS_NO ? US"no" + : US""; /* Set up a string for adding to the retry key if the port number is not the standard SMTP port. A host may have its own port setting that overrides |