Hi! It is very useful to also export the verification depth
to the ssl-verify script. This patch adds it:

--- openvpn-2.0-new/ssl.c       Mon May  9 19:03:19 2005
+++ openvpn-2.0-new2/ssl.c      Tue May 10 16:17:00 2005
@@ -586,6 +586,7 @@
             { 
               setenv_str(opt->es, "peer_cert", peer_cert);
               free(peer_cert);
+              setenv_int(opt->es, "peer_cert_depth", ctx->error_depth);
             }
         }

regards, Tom


* Rottler Tamas [Mon, 2005 May 09 22:37:27 +0200]:
> Hi! I needed support in OpenVPN to let an external script
> verify peer certificates in multi-client mode. I need this
> to be able to accept individual client certificates signed
> by different CAs or even self signed certificates, so that
> I can control exatly who may connect when I do not operate
> a CA.
> 
> I attached a patch for this against OpenVPN 2.0. It adds a
> new configuration option --tls-verify-cert. When it is
> turned on, the normal OpenSSL certificate preverification
> is ignored and an environment variable named peer_cert is
> exported for the tls-verify script, containing the peer's
> certificate in base64 encoded form.
> 
> This is not PEM format because of the missing header, foo-
> ter and line breaks. Instead if you un-base64 it, you'll
> get the DER-form certificate.
> 
> I hope this patch can be useful to someone, or someday be
> included in OpenVPN.
> 
> regards, Tom

> diff -ur openvpn-2.0/init.c openvpn-2.0-new/init.c
> --- openvpn-2.0/init.c        Mon Apr 11 05:43:56 2005
> +++ openvpn-2.0-new/init.c    Mon May  9 18:57:45 2005
> @@ -1305,6 +1305,7 @@
>  #endif
>  
>    to.verify_command = options->tls_verify;
> +  to.verify_export_cert = options->tls_verify_cert;
>    to.verify_x509name = options->tls_remote;
>    to.crl_file = options->crl_file;
>    to.ns_cert_type = options->ns_cert_type;
> diff -ur openvpn-2.0/options.c openvpn-2.0-new/options.c
> --- openvpn-2.0/options.c     Sun Apr 17 00:03:15 2005
> +++ openvpn-2.0-new/options.c Mon May  9 18:19:02 2005
> @@ -426,6 +426,9 @@
>    "                  tests of certification.  cmd should return 0 to allow\n"
>    "                  TLS handshake to proceed, or 1 to fail.  (cmd is\n"
>    "                  executed as 'cmd certificate_depth 
> X509_NAME_oneline')\n"
> +  "--tls-verify-cert: Let --tls-verify script verify the peer certificate\n"
> +  "                  and disable openssl's built in verification (possibly\n"
> +  "                  dangerous!)\n"
>    "--tls-remote x509name: Accept connections only from a host with X509 
> name\n"
>    "                  x509name. The remote host must also pass all other 
> tests\n"
>    "                  of verification.\n"
> @@ -1105,6 +1108,7 @@
>  #endif
>    SHOW_STR (cipher_list);
>    SHOW_STR (tls_verify);
> +  SHOW_BOOL (tls_verify_cert);
>    SHOW_STR (tls_remote);
>    SHOW_STR (crl_file);
>    SHOW_INT (ns_cert_type);
> @@ -1625,6 +1629,7 @@
>        MUST_BE_UNDEF (pkcs12_file);
>        MUST_BE_UNDEF (cipher_list);
>        MUST_BE_UNDEF (tls_verify);
> +      MUST_BE_UNDEF (tls_verify_cert);
>        MUST_BE_UNDEF (tls_remote);
>        MUST_BE_UNDEF (tls_timeout);
>        MUST_BE_UNDEF (renegotiate_bytes);
> @@ -4355,6 +4360,11 @@
>        if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
>       goto err;
>        options->tls_verify = string_substitute (p[1], ',', ' ', &options->gc);
> +    }
> +  else if (streq (p[0], "tls-verify-cert"))
> +    {
> +      VERIFY_PERMISSION (OPT_P_GENERAL);
> +      options->tls_verify_cert = true;
>      }
>    else if (streq (p[0], "tls-remote") && p[1])
>      {
> diff -ur openvpn-2.0/options.h openvpn-2.0-new/options.h
> --- openvpn-2.0/options.h     Mon Apr 11 05:43:57 2005
> +++ openvpn-2.0-new/options.h Mon May  9 18:17:35 2005
> @@ -362,6 +362,7 @@
>    const char *pkcs12_file;
>    const char *cipher_list;
>    const char *tls_verify;
> +  bool tls_verify_cert; /* Verify peer cert in tls-verify script _only_ */
>    const char *tls_remote;
>    const char *crl_file;
>    int ns_cert_type; /* set to 0, NS_SSL_SERVER, or NS_SSL_CLIENT */
> diff -ur openvpn-2.0/ssl.c openvpn-2.0-new/ssl.c
> --- openvpn-2.0/ssl.c Mon Apr 11 05:43:55 2005
> +++ openvpn-2.0-new/ssl.c     Mon May  9 19:03:19 2005
> @@ -52,6 +52,7 @@
>  #include "perf.h"
>  #include "status.h"
>  #include "gremlin.h"
> +#include "base64.h"
>  
>  #ifdef WIN32
>  #include "cryptoapi.h"
> @@ -398,6 +399,31 @@
>      }
>  }
>  
> +static int get_peer_cert(X509_STORE_CTX *ctx, char **out)
> +{
> +  X509 *peercert;
> +  int len, b64len;
> +  char *buf, *bufp, *b64buf;
> +
> +  peercert = X509_STORE_CTX_get_current_cert(ctx);
> +  len = i2d_X509(peercert, NULL);
> +  buf = malloc(len);
> +  if (!buf) {
> +    *out = NULL;
> +    return false;
> +  }
> +  bufp = buf;
> +  i2d_X509(peercert, (unsigned char **) &bufp);
> +  b64len = base64_encode(buf, len, &b64buf);
> +  free(buf);
> +  if (b64len <= 0) {
> +    *out = NULL;
> +    return false;
> +  }
> +  *out = b64buf;
> +  return true;
> +}
> +
>  /*
>   * Our verify callback function -- check
>   * that an incoming peer certificate is good.
> @@ -413,6 +439,7 @@
>    struct tls_session *session;
>    const struct tls_options *opt;
>    const int max_depth = 8;
> +  char *peer_cert;
>  
>    /* get the tls_session pointer */
>    ssl = X509_STORE_CTX_get_ex_data (ctx, 
> SSL_get_ex_data_X509_STORE_CTX_idx());
> @@ -445,9 +472,18 @@
>    if (!preverify_ok)
>      {
>        /* Remote site specified a certificate, but it's not correct */
> -      msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, error=%s: %s",
> -        ctx->error_depth, X509_verify_cert_error_string (ctx->error), 
> subject);
> -      goto err;                      /* Reject connection */
> +      if (opt->verify_export_cert)
> +        {
> +          msg (D_TLS_ERRORS, "IGNORED VERIFY ERROR: depth=%d, error=%s: %s",
> +            ctx->error_depth, X509_verify_cert_error_string (ctx->error), 
> subject);
> +          /* continue checking */
> +        }
> +      else
> +        {
> +          msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, error=%s: %s",
> +            ctx->error_depth, X509_verify_cert_error_string (ctx->error), 
> subject);
> +          goto err;                  /* Reject connection */
> +        }
>      }
>  
>    /* warn if cert chain is too deep */
> @@ -544,6 +580,14 @@
>        int ret;
>  
>        setenv_str (opt->es, "script_type", "tls-verify");
> +      if (opt->verify_export_cert)
> +        {
> +          if (get_peer_cert(ctx, &peer_cert))
> +            {
> +              setenv_str(opt->es, "peer_cert", peer_cert);
> +              free(peer_cert);
> +            }
> +        }
>  
>        buf_set_write (&out, (uint8_t*)command, sizeof (command));
>        buf_printf (&out, "%s %d %s",
> diff -ur openvpn-2.0/ssl.h openvpn-2.0-new/ssl.h
> --- openvpn-2.0/ssl.h Mon Apr 11 05:43:56 2005
> +++ openvpn-2.0-new/ssl.h     Mon May  9 19:05:41 2005
> @@ -407,6 +407,7 @@
>  
>    /* cert verification parms */
>    const char *verify_command;
> +  bool verify_export_cert;
>    const char *verify_x509name;
>    const char *crl_file;
>    int ns_cert_type;


Reply via email to