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;