UTF8: Cert namechecks always use a-label
[exim.git] / src / src / tls-openssl.c
index c23ac031f5b544f6486710e4e8b24344c0a539e6..530266d3674660fd82f1954b43eeb4fe960f468d 100644 (file)
@@ -123,10 +123,7 @@ typedef struct tls_ext_ctx_cb {
   uschar *server_cipher_list;
   /* only passed down to tls_error: */
   host_item *host;
-
-#ifdef EXPERIMENTAL_CERTNAMES
-  uschar * verify_cert_hostnames;
-#endif
+  const uschar * verify_cert_hostnames;
 #ifdef EXPERIMENTAL_EVENT
   uschar * event_action;
 #endif
@@ -248,6 +245,7 @@ for(i= 0; i<sk_X509_OBJECT_num(roots); i++)
     {
     X509 * current_cert= tmp_obj->data.x509;
     X509_NAME_oneline(X509_get_subject_name(current_cert), CS name, sizeof(name));
+       name[sizeof(name)-1] = '\0';
     debug_printf(" %s\n", name);
     }
   }
@@ -256,21 +254,58 @@ for(i= 0; i<sk_X509_OBJECT_num(roots); i++)
 */
 
 
+#ifdef EXPERIMENTAL_EVENT
+static int
+verify_event(tls_support * tlsp, X509 * cert, int depth, const uschar * dn,
+  BOOL *calledp, const BOOL *optionalp, const uschar * what)
+{
+uschar * ev;
+uschar * yield;
+X509 * old_cert;
+
+ev = tlsp == &tls_out ? client_static_cbinfo->event_action : event_action;
+if (ev)
+  {
+  old_cert = tlsp->peercert;
+  tlsp->peercert = X509_dup(cert);
+  /* NB we do not bother setting peerdn */
+  if ((yield = event_raise(ev, US"tls:cert", string_sprintf("%d", depth))))
+    {
+    log_write(0, LOG_MAIN, "[%s] %s verify denied by event-action: "
+               "depth=%d cert=%s: %s",
+             tlsp == &tls_out ? deliver_host_address : sender_host_address,
+             what, depth, dn, yield);
+    *calledp = TRUE;
+    if (!*optionalp)
+      {
+      if (old_cert) tlsp->peercert = old_cert; /* restore 1st failing cert */
+      return 1;                            /* reject (leaving peercert set) */
+      }
+    DEBUG(D_tls) debug_printf("Event-action verify failure overridden "
+      "(host in tls_try_verify_hosts)\n");
+    }
+  X509_free(tlsp->peercert);
+  tlsp->peercert = old_cert;
+  }
+return 0;
+}
+#endif
+
 /*************************************************
 *        Callback for verification               *
 *************************************************/
 
 /* The SSL library does certificate verification if set up to do so. This
 callback has the current yes/no state is in "state". If verification succeeded,
-we set up the tls_peerdn string. If verification failed, what happens depends
-on whether the client is required to present a verifiable certificate or not.
+we set the certificate-verified flag. If verification failed, what happens
+depends on whether the client is required to present a verifiable certificate
+or not.
 
 If verification is optional, we change the state to yes, but still log the
 verification error. For some reason (it really would help to have proper
 documentation of OpenSSL), this callback function then gets called again, this
-time with state = 1. In fact, that's useful, because we can set up the peerdn
-value, but we must take care not to set the private verified flag on the second
-time through.
+time with state = 1.  We must take care not to set the private verified flag on
+the second time through.
 
 Note: this function is not called if the client fails to present a certificate
 when asked. We get here only if a certificate has been received. Handling of
@@ -294,25 +329,24 @@ verify_callback(int state, X509_STORE_CTX *x509ctx,
 {
 X509 * cert = X509_STORE_CTX_get_current_cert(x509ctx);
 int depth = X509_STORE_CTX_get_error_depth(x509ctx);
-static uschar txt[256];
-#ifdef EXPERIMENTAL_EVENT
-uschar * ev;
-uschar * yield;
-#endif
+uschar dn[256];
 
-X509_NAME_oneline(X509_get_subject_name(cert), CS txt, sizeof(txt));
+X509_NAME_oneline(X509_get_subject_name(cert), CS dn, sizeof(dn));
+dn[sizeof(dn)-1] = '\0';
 
 if (state == 0)
   {
-  log_write(0, LOG_MAIN, "SSL verify error: depth=%d error=%s cert=%s",
+  log_write(0, LOG_MAIN, "[%s] SSL verify error: depth=%d error=%s cert=%s",
+       tlsp == &tls_out ? deliver_host_address : sender_host_address,
     depth,
     X509_verify_cert_error_string(X509_STORE_CTX_get_error(x509ctx)),
-    txt);
+    dn);
   *calledp = TRUE;
   if (!*optionalp)
     {
-    tlsp->peercert = X509_dup(cert);
-    return 0;                      /* reject */
+    if (!tlsp->peercert)
+      tlsp->peercert = X509_dup(cert); /* record failing cert */
+    return 0;                          /* reject */
     }
   DEBUG(D_tls) debug_printf("SSL verify failure overridden (host in "
     "tls_try_verify_hosts)\n");
@@ -320,7 +354,7 @@ if (state == 0)
 
 else if (depth != 0)
   {
-  DEBUG(D_tls) debug_printf("SSL verify ok: depth=%d SN=%s\n", depth, txt);
+  DEBUG(D_tls) debug_printf("SSL verify ok: depth=%d SN=%s\n", depth, dn);
 #ifndef DISABLE_OCSP
   if (tlsp == &tls_out && client_static_cbinfo->u_ocsp.client.verify_store)
     {  /* client, wanting stapling  */
@@ -333,105 +367,72 @@ else if (depth != 0)
     }
 #endif
 #ifdef EXPERIMENTAL_EVENT
-  ev = tlsp == &tls_out ? client_static_cbinfo->event_action : event_action;
-  if (ev)
-    {
-    tlsp->peercert = X509_dup(cert);
-    if ((yield = event_raise(ev, US"tls:cert", string_sprintf("%d", depth))))
-      {
-      log_write(0, LOG_MAIN, "SSL verify denied by event-action: "
-                             "depth=%d cert=%s: %s", depth, txt, yield);
-      *calledp = TRUE;
-      if (!*optionalp)
-       return 0;                           /* reject */
-      DEBUG(D_tls) debug_printf("Event-action verify failure overridden "
-       "(host in tls_try_verify_hosts)\n");
-      }
-    X509_free(tlsp->peercert);
-    tlsp->peercert = NULL;
-    }
+    if (verify_event(tlsp, cert, depth, dn, calledp, optionalp, US"SSL"))
+      return 0;                                /* reject, with peercert set */
 #endif
   }
 else
   {
-#ifdef EXPERIMENTAL_CERTNAMES
-  uschar * verify_cert_hostnames;
-#endif
-
-  tlsp->peerdn = txt;
-  tlsp->peercert = X509_dup(cert);
+  const uschar * verify_cert_hostnames;
 
-#ifdef EXPERIMENTAL_CERTNAMES
   if (  tlsp == &tls_out
      && ((verify_cert_hostnames = client_static_cbinfo->verify_cert_hostnames)))
        /* client, wanting hostname check */
-
-# if EXIM_HAVE_OPENSSL_CHECKHOST
-#  ifndef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
-#   define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 0
-#  endif
-#  ifndef X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS
-#   define X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS 0
-#  endif
     {
+
+#ifdef EXIM_HAVE_OPENSSL_CHECKHOST
+# ifndef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
+#  define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 0
+# endif
+# ifndef X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS
+#  define X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS 0
+# endif
     int sep = 0;
-    uschar * list = verify_cert_hostnames;
+    const uschar * list = verify_cert_hostnames;
     uschar * name;
     int rc;
     while ((name = string_nextinlist(&list, &sep, NULL, 0)))
       if ((rc = X509_check_host(cert, name, 0,
                  X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
-                 | X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS)))
+                 | X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS,
+                 NULL)))
        {
        if (rc < 0)
          {
-         log_write(0, LOG_MAIN, "SSL verify error: internal error\n");
+         log_write(0, LOG_MAIN, "[%s] SSL verify error: internal error",
+               tlsp == &tls_out ? deliver_host_address : sender_host_address);
          name = NULL;
          }
        break;
        }
     if (!name)
-      {
-      log_write(0, LOG_MAIN,
-       "SSL verify error: certificate name mismatch: \"%s\"\n", txt);
-      *calledp = TRUE;
-      if (!*optionalp)
-       return 0;                           /* reject */
-      DEBUG(D_tls) debug_printf("SSL verify failure overridden (host in "
-       "tls_try_verify_hosts)\n");
-      }
-    }
-# else
+#else
     if (!tls_is_name_for_cert(verify_cert_hostnames, cert))
+#endif
       {
       log_write(0, LOG_MAIN,
-       "SSL verify error: certificate name mismatch: \"%s\"\n", txt);
+               "[%s] SSL verify error: certificate name mismatch: \"%s\"",
+               tlsp == &tls_out ? deliver_host_address : sender_host_address,
+               dn);
       *calledp = TRUE;
       if (!*optionalp)
-       return 0;                           /* reject */
+       {
+       if (!tlsp->peercert)
+         tlsp->peercert = X509_dup(cert);      /* record failing cert */
+       return 0;                               /* reject */
+       }
       DEBUG(D_tls) debug_printf("SSL verify failure overridden (host in "
        "tls_try_verify_hosts)\n");
       }
-# endif
-#endif /*EXPERIMENTAL_CERTNAMES*/
+    }
 
 #ifdef EXPERIMENTAL_EVENT
-  ev = tlsp == &tls_out ? client_static_cbinfo->event_action : event_action;
-  if (ev)
-    if ((yield = event_raise(ev, US"tls:cert", US"0")))
-      {
-      log_write(0, LOG_MAIN, "SSL verify denied by event-action: "
-                             "depth=0 cert=%s: %s", txt, yield);
-      *calledp = TRUE;
-      if (!*optionalp)
-       return 0;                           /* reject */
-      DEBUG(D_tls) debug_printf("Event-action verify failure overridden "
-       "(host in tls_try_verify_hosts)\n");
-      }
+  if (verify_event(tlsp, cert, depth, dn, calledp, optionalp, US"SSL"))
+    return 0;                          /* reject, with peercert set */
 #endif
 
   DEBUG(D_tls) debug_printf("SSL%s verify ok: depth=0 SN=%s\n",
-    *calledp ? "" : " authenticated", txt);
+    *calledp ? "" : " authenticated", dn);
   if (!*calledp) tlsp->certificate_verified = TRUE;
   *calledp = TRUE;
   }
@@ -461,35 +462,22 @@ static int
 verify_callback_client_dane(int state, X509_STORE_CTX * x509ctx)
 {
 X509 * cert = X509_STORE_CTX_get_current_cert(x509ctx);
-static uschar txt[256];
+uschar dn[256];
 #ifdef EXPERIMENTAL_EVENT
 int depth = X509_STORE_CTX_get_error_depth(x509ctx);
 uschar * yield;
+BOOL dummy_called, optional = FALSE;
 #endif
 
-X509_NAME_oneline(X509_get_subject_name(cert), CS txt, sizeof(txt));
+X509_NAME_oneline(X509_get_subject_name(cert), CS dn, sizeof(dn));
+dn[sizeof(dn)-1] = '\0';
 
-DEBUG(D_tls) debug_printf("verify_callback_client_dane: %s\n", txt);
-tls_out.peerdn = txt;
-tls_out.peercert = X509_dup(cert);
+DEBUG(D_tls) debug_printf("verify_callback_client_dane: %s\n", dn);
 
 #ifdef EXPERIMENTAL_EVENT
-  if (client_static_cbinfo->event_action)
-    {
-    if ((yield = event_raise(client_static_cbinfo->event_action,
-                   US"tls:cert", string_sprintf("%d", depth))))
-      {
-      log_write(0, LOG_MAIN, "DANE verify denied by event-action: "
-                             "depth=%d cert=%s: %s", depth, txt, yield);
-      tls_out.certificate_verified = FALSE;
-      return 0;                            /* reject */
-      }
-    if (depth != 0)
-      {
-      X509_free(tls_out.peercert);
-      tls_out.peercert = NULL;
-      }
-    }
+  if (verify_event(&tls_out, cert, depth, dn,
+         &dummy_called, &optional, US"DANE"))
+    return 0;                          /* reject, with peercert set */
 #endif
 
 if (state == 1)
@@ -1217,7 +1205,7 @@ if (!RAND_status())
 /* Set up the information callback, which outputs if debugging is at a suitable
 level. */
 
-SSL_CTX_set_info_callback(*ctxp, (void (*)())info_callback);
+DEBUG(D_tls) SSL_CTX_set_info_callback(*ctxp, (void (*)())info_callback);
 
 /* Automatically re-try reads/writes after renegotiation. */
 (void) SSL_CTX_set_mode(*ctxp, SSL_MODE_AUTO_RETRY);
@@ -1289,9 +1277,7 @@ else                      /* client */
 # endif
 #endif
 
-#ifdef EXPERIMENTAL_CERTNAMES
 cbinfo->verify_cert_hostnames = NULL;
-#endif
 
 /* Set up the RSA callback */
 
@@ -1343,6 +1329,29 @@ DEBUG(D_tls) debug_printf("Cipher: %s\n", cipherbuf);
 }
 
 
+static void
+peer_cert(SSL * ssl, tls_support * tlsp, uschar * peerdn, unsigned bsize)
+{
+/*XXX we might consider a list-of-certs variable for the cert chain.
+SSL_get_peer_cert_chain(SSL*).  We'd need a new variable type and support
+in list-handling functions, also consider the difference between the entire
+chain and the elements sent by the peer. */
+
+/* Will have already noted peercert on a verify fail; possibly not the leaf */
+if (!tlsp->peercert)
+  tlsp->peercert = SSL_get_peer_certificate(ssl);
+/* Beware anonymous ciphers which lead to server_cert being NULL */
+if (tlsp->peercert)
+  {
+  X509_NAME_oneline(X509_get_subject_name(tlsp->peercert), CS peerdn, bsize);
+  peerdn[bsize-1] = '\0';
+  tlsp->peerdn = peerdn;               /*XXX a static buffer... */
+  }
+else
+  tlsp->peerdn = NULL;
+}
+
+
 
 
 
@@ -1375,50 +1384,65 @@ if (!expand_check(certs, US"tls_verify_certificates", &expcerts))
 
 if (expcerts != NULL && *expcerts != '\0')
   {
-  struct stat statbuf;
-  if (!SSL_CTX_set_default_verify_paths(sctx))
-    return tls_error(US"SSL_CTX_set_default_verify_paths", host, NULL);
-
-  if (Ustat(expcerts, &statbuf) < 0)
+  if (Ustrcmp(expcerts, "system") == 0)
     {
-    log_write(0, LOG_MAIN|LOG_PANIC,
-      "failed to stat %s for certificates", expcerts);
-    return DEFER;
+    /* Tell the library to use its compiled-in location for the system default
+    CA bundle, only */
+
+    if (!SSL_CTX_set_default_verify_paths(sctx))
+      return tls_error(US"SSL_CTX_set_default_verify_paths", host, NULL);
     }
   else
     {
-    uschar *file, *dir;
-    if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
-      { file = NULL; dir = expcerts; }
+    struct stat statbuf;
+
+    /* Tell the library to use its compiled-in location for the system default
+    CA bundle. Those given by the exim config are additional to these */
+
+    if (!SSL_CTX_set_default_verify_paths(sctx))
+      return tls_error(US"SSL_CTX_set_default_verify_paths", host, NULL);
+
+    if (Ustat(expcerts, &statbuf) < 0)
+      {
+      log_write(0, LOG_MAIN|LOG_PANIC,
+       "failed to stat %s for certificates", expcerts);
+      return DEFER;
+      }
     else
-      { file = expcerts; dir = NULL; }
-
-    /* If a certificate file is empty, the next function fails with an
-    unhelpful error message. If we skip it, we get the correct behaviour (no
-    certificates are recognized, but the error message is still misleading (it
-    says no certificate was supplied.) But this is better. */
-
-    if ((file == NULL || statbuf.st_size > 0) &&
-          !SSL_CTX_load_verify_locations(sctx, CS file, CS dir))
-      return tls_error(US"SSL_CTX_load_verify_locations", host, NULL);
-
-    /* Load the list of CAs for which we will accept certs, for sending
-    to the client.  This is only for the one-file tls_verify_certificates
-    variant.
-    If a list isn't loaded into the server, but
-    some verify locations are set, the server end appears to make
-    a wildcard reqest for client certs.
-    Meanwhile, the client library as deafult behaviour *ignores* the list
-    we send over the wire - see man SSL_CTX_set_client_cert_cb.
-    Because of this, and that the dir variant is likely only used for
-    the public-CA bundle (not for a private CA), not worth fixing.
-    */
-    if (file != NULL)
       {
-      STACK_OF(X509_NAME) * names = SSL_load_client_CA_file(CS file);
-DEBUG(D_tls) debug_printf("Added %d certificate authorities.\n",
-                                 sk_X509_NAME_num(names));
-      SSL_CTX_set_client_CA_list(sctx, names);
+      uschar *file, *dir;
+      if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
+       { file = NULL; dir = expcerts; }
+      else
+       { file = expcerts; dir = NULL; }
+
+      /* If a certificate file is empty, the next function fails with an
+      unhelpful error message. If we skip it, we get the correct behaviour (no
+      certificates are recognized, but the error message is still misleading (it
+      says no certificate was supplied.) But this is better. */
+
+      if ((file == NULL || statbuf.st_size > 0) &&
+           !SSL_CTX_load_verify_locations(sctx, CS file, CS dir))
+       return tls_error(US"SSL_CTX_load_verify_locations", host, NULL);
+
+      /* Load the list of CAs for which we will accept certs, for sending
+      to the client.  This is only for the one-file tls_verify_certificates
+      variant.
+      If a list isn't loaded into the server, but
+      some verify locations are set, the server end appears to make
+      a wildcard reqest for client certs.
+      Meanwhile, the client library as deafult behaviour *ignores* the list
+      we send over the wire - see man SSL_CTX_set_client_cert_cb.
+      Because of this, and that the dir variant is likely only used for
+      the public-CA bundle (not for a private CA), not worth fixing.
+      */
+      if (file != NULL)
+       {
+       STACK_OF(X509_NAME) * names = SSL_load_client_CA_file(CS file);
+  DEBUG(D_tls) debug_printf("Added %d certificate authorities.\n",
+                                   sk_X509_NAME_num(names));
+       SSL_CTX_set_client_CA_list(sctx, names);
+       }
       }
     }
 
@@ -1510,6 +1534,8 @@ tls_server_start(const uschar *require_ciphers)
 int rc;
 uschar *expciphers;
 tls_ext_ctx_cb *cbinfo;
+X509 * peercert;
+static uschar peerdn[256];
 static uschar cipherbuf[256];
 
 /* Check for previous activation */
@@ -1632,6 +1658,8 @@ DEBUG(D_tls) debug_printf("SSL_accept was successful\n");
 /* TLS has been set up. Adjust the input functions to read via TLS,
 and initialize things. */
 
+peer_cert(server_ssl, &tls_in, peerdn, sizeof(peerdn));
+
 construct_cipher_name(server_ssl, cipherbuf, sizeof(cipherbuf), &tls_in.bits);
 tls_in.cipher = cipherbuf;
 
@@ -1672,10 +1700,7 @@ return OK;
 
 static int
 tls_client_basic_ctx_init(SSL_CTX * ctx,
-    host_item * host, smtp_transport_options_block * ob
-#ifdef EXPERIMENTAL_CERTNAMES
-    , tls_ext_ctx_cb * cbinfo
-#endif
+    host_item * host, smtp_transport_options_block * ob, tls_ext_ctx_cb * cbinfo
                          )
 {
 int rc;
@@ -1683,13 +1708,13 @@ int rc;
    set but both tls_verify_hosts and tls_try_verify_hosts is not set. Check only
    the specified host patterns if one of them is defined */
 
-if (  (!ob->tls_verify_hosts && !ob->tls_try_verify_hosts)
-   || (verify_check_this_host(&ob->tls_verify_hosts, NULL,
-               host->name, host->address, NULL) == OK)
+if (  (  !ob->tls_verify_hosts
+      && (!ob->tls_try_verify_hosts || !*ob->tls_try_verify_hosts)
+      )
+   || (verify_check_given_host(&ob->tls_verify_hosts, host) == OK)
    )
   client_verify_optional = FALSE;
-else if (verify_check_this_host(&ob->tls_try_verify_hosts, NULL,
-               host->name, host->address, NULL) == OK)
+else if (verify_check_given_host(&ob->tls_try_verify_hosts, host) == OK)
   client_verify_optional = TRUE;
 else
   return OK;
@@ -1698,15 +1723,17 @@ if ((rc = setup_certs(ctx, ob->tls_verify_certificates,
       ob->tls_crl, host, client_verify_optional, verify_callback_client)) != OK)
   return rc;
 
-#ifdef EXPERIMENTAL_CERTNAMES
-if (verify_check_this_host(&ob->tls_verify_cert_hostnames, NULL,
-             host->name, host->address, NULL) == OK)
+if (verify_check_given_host(&ob->tls_verify_cert_hostnames, host) == OK)
   {
-  cbinfo->verify_cert_hostnames = host->name;
+  cbinfo->verify_cert_hostnames =
+#ifdef EXPERIMENTAL_INTERNATIONAL
+    string_domain_utf8_to_alabel(host->name, NULL);
+#else
+    host->name;
+#endif
   DEBUG(D_tls) debug_printf("Cert hostname to check: \"%s\"\n",
                    cbinfo->verify_cert_hostnames);
   }
-#endif
 return OK;
 }
 
@@ -1764,7 +1791,7 @@ if (found)
   return OK;
 
 log_write(0, LOG_MAIN, "DANE error: No usable TLSA records");
-return FAIL;
+return DEFER;
 }
 #endif /*EXPERIMENTAL_DANE*/
 
@@ -1798,9 +1825,8 @@ tls_client_start(int fd, host_item *host, address_item *addr,
 {
 smtp_transport_options_block * ob =
   (smtp_transport_options_block *)tb->options_block;
-static uschar txt[256];
+static uschar peerdn[256];
 uschar * expciphers;
-X509 * server_cert;
 int rc;
 static uschar cipherbuf[256];
 
@@ -1829,15 +1855,15 @@ tls_out.tlsa_usage = 0;
     }
 # endif
 
-  if ((require_ocsp = verify_check_this_host(&ob->hosts_require_ocsp,
-    NULL, host->name, host->address, NULL) == OK))
+  if ((require_ocsp =
+       verify_check_given_host(&ob->hosts_require_ocsp, host) == OK))
     request_ocsp = TRUE;
   else
 # ifdef EXPERIMENTAL_DANE
     if (!request_ocsp)
 # endif
-      request_ocsp = verify_check_this_host(&ob->hosts_request_ocsp,
-         NULL, host->name, host->address, NULL) == OK;
+      request_ocsp =
+       verify_check_given_host(&ob->hosts_request_ocsp, host) == OK;
   }
 #endif
 
@@ -1885,11 +1911,8 @@ else
 
 #endif
 
-  if ((rc = tls_client_basic_ctx_init(client_ctx, host, ob
-#ifdef EXPERIMENTAL_CERTNAMES
-                               , client_static_cbinfo
-#endif
-                               )) != OK)
+  if ((rc = tls_client_basic_ctx_init(client_ctx, host, ob, client_static_cbinfo))
+      != OK)
     return rc;
 
 if ((client_ssl = SSL_new(client_ctx)) == NULL)
@@ -1940,11 +1963,9 @@ if (request_ocsp)
     {  /* Re-eval now $tls_out_tlsa_usage is populated.  If
        this means we avoid the OCSP request, we wasted the setup
        cost in tls_init(). */
-    require_ocsp = verify_check_this_host(&ob->hosts_require_ocsp,
-      NULL, host->name, host->address, NULL) == OK;
-    request_ocsp = require_ocsp ? TRUE
-      : verify_check_this_host(&ob->hosts_request_ocsp,
-         NULL, host->name, host->address, NULL) == OK;
+    require_ocsp = verify_check_given_host(&ob->hosts_require_ocsp, host) == OK;
+    request_ocsp = require_ocsp
+      || verify_check_given_host(&ob->hosts_request_ocsp, host) == OK;
     }
   }
 # endif
@@ -1979,17 +2000,7 @@ if (rc <= 0)
 
 DEBUG(D_tls) debug_printf("SSL_connect succeeded\n");
 
-/* Beware anonymous ciphers which lead to server_cert being NULL */
-/*XXX server_cert is never freed... use X509_free() */
-server_cert = SSL_get_peer_certificate (client_ssl);
-if (server_cert)
-  {
-  tls_out.peerdn = US X509_NAME_oneline(X509_get_subject_name(server_cert),
-    CS txt, sizeof(txt));
-  tls_out.peerdn = txt;                /*XXX a static buffer... */
-  }
-else
-  tls_out.peerdn = NULL;
+peer_cert(client_ssl, &tls_out, peerdn, sizeof(peerdn));
 
 construct_cipher_name(client_ssl, cipherbuf, sizeof(cipherbuf), &tls_out.bits);
 tls_out.cipher = cipherbuf;