Hello,

It should be nice to enhance tls-verify check possibilities against peer
cert during a pending TLS connection like :
- OCSP verification
- check any X509 extensions of the peer certificate
- delta CRL verification
- ...

This patch add a new "tls-export-cert" option which allow to get peer
certificate in PEM format and to store it in an openvpn temporary file.
Peer certificate is stored before tls-script execution and deleted after.
The name of the related temporary file is available under tls-verify
script by an environment variable "peer_cert".

The patch was made from OpenVPN svn Beta21 branches.

Here is a very simple exemple of Tls-verify script which provide OCSP
support to OpenVPN (with tls-export-cert option) without any OpenVPN
"core" modification :



#!/bin/sh

X509=$2

# Perform OCSP check on peer certificate
openssl ocsp \
     -issuer /etc/openvpn/ssl.crt/RootCA.pem \
     -CAfile /etc/openvpn/ssl.capath/OpenVPNServeur-cafile.pem \
     -cert $peer_cert \
     -url http://your-ocsp-url
     if [ $? -ne 0 ]
     then
         echo "error : OCSP check failed for ${X509}" | logger -t
"tls-verify"
         exit 1
      fi


Regards
diff -ru openvpn/init.c openvpn-tls-export-cert/init.c
--- openvpn/init.c      2009-01-09 16:25:25.000000000 +0100
+++ openvpn-tls-export-cert/init.c      2009-01-09 16:28:34.000000000 +0100
@@ -1761,6 +1761,7 @@
 #endif

   to.verify_command = options->tls_verify;
+  to.verify_export_cert = options->tls_export_cert;
   to.verify_x509name = options->tls_remote;
   to.crl_file = options->crl_file;
   to.ns_cert_type = options->ns_cert_type;
diff -ru openvpn/options.c openvpn-tls-export-cert/options.c
--- openvpn/options.c   2009-01-09 16:25:25.000000000 +0100
+++ openvpn-tls-export-cert/options.c   2009-01-12 12:37:34.000000000 +0100
@@ -518,6 +518,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-export-cert [directory] : Get peer cert in PEM format and store it \n"
+  "                  in an openvpn temporary file in [directory]. Peer cert is 
\n"
+  "                  stored before tls-verify script execution and deleted 
after.\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"
@@ -1309,6 +1312,7 @@
 #endif
   SHOW_STR (cipher_list);
   SHOW_STR (tls_verify);
+  SHOW_STR (tls_export_cert);
   SHOW_STR (tls_remote);
   SHOW_STR (crl_file);
   SHOW_INT (ns_cert_type);
@@ -1902,6 +1906,7 @@
       MUST_BE_UNDEF (pkcs12_file);
       MUST_BE_UNDEF (cipher_list);
       MUST_BE_UNDEF (tls_verify);
+      MUST_BE_UNDEF (tls_export_cert);
       MUST_BE_UNDEF (tls_remote);
       MUST_BE_UNDEF (tls_timeout);
       MUST_BE_UNDEF (renegotiate_bytes);
@@ -5424,6 +5429,11 @@
        goto err;
       options->tls_verify = string_substitute (p[1], ',', ' ', &options->gc);
     }
+  else if (streq (p[0], "tls-export-cert") && p[1])
+    {
+      VERIFY_PERMISSION (OPT_P_GENERAL);
+      options->tls_export_cert = p[1];
+    }
   else if (streq (p[0], "tls-remote") && p[1])
     {
       VERIFY_PERMISSION (OPT_P_GENERAL);
diff -ru openvpn/options.h openvpn-tls-export-cert/options.h
--- openvpn/options.h   2009-01-09 16:25:25.000000000 +0100
+++ openvpn-tls-export-cert/options.h   2009-01-09 16:37:04.000000000 +0100
@@ -443,6 +443,7 @@
   const char *pkcs12_file;
   const char *cipher_list;
   const char *tls_verify;
+  const char *tls_export_cert;
   const char *tls_remote;
   const char *crl_file;

diff -ru openvpn/ssl.c openvpn-tls-export-cert/ssl.c
--- openvpn/ssl.c       2009-01-09 16:25:25.000000000 +0100
+++ openvpn-tls-export-cert/ssl.c       2009-01-09 17:29:51.000000000 +0100
@@ -589,6 +589,49 @@
     string_mod (str, restrictive_flags, 0, '_');
 }

+/* Get peer cert and store it in pem format in a temporary file
+ * in tmp_dir
+ */
+
+const char *
+get_peer_cert(X509_STORE_CTX *ctx, const char *tmp_dir, struct gc_arena *gc)
+{
+  X509 *peercert;
+  FILE *peercert_file;
+  const char *peercert_filename="";
+  
+  if(!tmp_dir)
+      return NULL;
+  
+  /* get peer cert */
+  peercert = X509_STORE_CTX_get_current_cert(ctx);
+  if(!peercert)
+    {
+      msg (M_ERR, "Unable to get peer certificate from current context");
+      return NULL;
+    }
+  
+  /* create tmp file to store peer cert */
+  peercert_filename = create_temp_filename (tmp_dir, "pcf", gc);
+  
+  /* write peer-cert in tmp-file */
+  peercert_file = fopen(peercert_filename, "w+");
+  if(!peercert_file)
+    {
+      msg (M_ERR, "Failed to open temporary file : %s", peercert_filename);
+      return NULL;
+    }
+  if(PEM_write_X509(peercert_file,peercert)<0)
+    {
+      msg (M_ERR, "Failed to write peer certificate in PEM format");
+      fclose(peercert_file);
+      return NULL;
+    }
+
+  fclose(peercert_file);
+  return peercert_filename;
+}
+
 /*
  * Our verify callback function -- check
  * that an incoming peer certificate is good.
@@ -777,10 +820,21 @@
   /* run --tls-verify script */
   if (opt->verify_command)
     {
+      const char *tmp_file;
+      struct gc_arena gc;
       int ret;

       setenv_str (opt->es, "script_type", "tls-verify");

+      if (opt->verify_export_cert)
+        {
+          gc = gc_new();
+          if (tmp_file=get_peer_cert(ctx, opt->verify_export_cert,&gc))
+           {
+             setenv_str(opt->es, "peer_cert", tmp_file);
+           }
+        }
+
       argv_printf (&argv, "%sc %d %s",
                   opt->verify_command,
                   ctx->error_depth,
@@ -788,6 +842,12 @@
       argv_msg_prefix (D_TLS_DEBUG, &argv, "TLS: executing verify command");
       ret = openvpn_execve (&argv, opt->es, S_SCRIPT);

+      if (opt->verify_export_cert)
+        {
+           delete_file(tmp_file);
+           gc_free(&gc);
+        }       
+
       if (system_ok (ret))
        {
          msg (D_HANDSHAKE, "VERIFY SCRIPT OK: depth=%d, %s",
diff -ru openvpn/ssl.h openvpn-tls-export-cert/ssl.h
--- openvpn/ssl.h       2009-01-09 16:25:25.000000000 +0100
+++ openvpn-tls-export-cert/ssl.h       2009-01-09 16:52:41.000000000 +0100
@@ -428,6 +428,7 @@

   /* cert verification parms */
   const char *verify_command;
+  const char *verify_export_cert;
   const char *verify_x509name;
   const char *crl_file;
   int ns_cert_type;


Reply via email to