summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/src/deliver.c32
-rw-r--r--src/src/globals.c1
-rw-r--r--src/src/globals.h3
-rw-r--r--src/src/structs.h1
-rw-r--r--src/src/tls-gnu.c7
-rw-r--r--src/src/tls-openssl.c36
-rw-r--r--src/src/transports/smtp.c7
7 files changed, 64 insertions, 23 deletions
diff --git a/src/src/deliver.c b/src/src/deliver.c
index fff0e2fd0..dd7f888fb 100644
--- a/src/src/deliver.c
+++ b/src/src/deliver.c
@@ -718,6 +718,7 @@ uschar *s; /* building log lines; */
void *reset_point; /* released afterwards. */
+DEBUG(D_deliver) debug_printf("B cipher %s\n", addr->cipher);
/* Log the delivery on the main log. We use an extensible string to build up
the log line, and reset the store afterwards. Remote deliveries should always
have a pointer to the host item that succeeded; local deliveries can have a
@@ -734,6 +735,7 @@ pointer to a single host item in their host list, for use by the transport. */
s = reset_point = store_get(size);
+DEBUG(D_deliver) debug_printf("C cipher %s\n", addr->cipher);
log_address = string_log_address(addr, (log_write_selector & L_all_parents) != 0, TRUE);
if (msg)
s = string_append(s, &size, &ptr, 3, host_and_ident(TRUE), US" ", log_address);
@@ -876,6 +878,7 @@ if (addr->transport->tpda_delivery_action)
DEBUG(D_deliver)
debug_printf(" TPDA(Delivery): tpda_deliver_action=|%s| tpda_delivery_IP=%s\n",
addr->transport->tpda_delivery_action, tpda_delivery_ip);
+DEBUG(D_deliver) debug_printf("D cipher %s\n", addr->cipher);
router_name = addr->router->name;
transport_name = addr->transport->name;
@@ -1088,6 +1091,11 @@ if (result == OK)
addr->ourcert = NULL;
tls_out.peercert = addr->peercert;
addr->peercert = NULL;
+
+DEBUG(D_deliver) debug_printf("A cipher %s\n", addr->cipher);
+ 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 +1111,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 +2998,7 @@ while (!done)
addr->cipher = string_copy(ptr);
while (*ptr++);
if (*ptr)
- {
addr->peerdn = string_copy(ptr);
- }
break;
case '2':
@@ -3003,6 +3012,14 @@ 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;
@@ -4132,7 +4149,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)
{
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/structs.h b/src/src/structs.h
index a6c78f4fc..aba579f89 100644
--- a/src/src/structs.h
+++ b/src/src/structs.h
@@ -543,6 +543,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..16612d300 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,7 +869,6 @@ 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.
@@ -888,6 +889,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 +904,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 +920,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 +932,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 +944,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/transports/smtp.c b/src/src/transports/smtp.c
index 9089d90c1..1232965b9 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -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;