]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Added --x509-track option.
authorJames Yonan <james@openvpn.net>
Wed, 5 Jan 2011 00:50:11 +0000 (00:50 +0000)
committerJames Yonan <james@openvpn.net>
Wed, 5 Jan 2011 00:50:11 +0000 (00:50 +0000)
Version 2.1.3e

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@6780 e7ae566f-a301-0410-adde-c780ea21d3b5

errlevel.h
init.c
manage.c
openvpn.8
options.c
options.h
ssl.c
ssl.h
syshead.h
version.m4

index 75c31940f9f305e26b4505d356b0816372bd0b3e..1d6e8660df659d9f6a2bbb1ec91d06f28a99dd3c 100644 (file)
 #define D_PACKET_TRUNC_ERR   LOGLEV(4, 55, 0)        /* PACKET_TRUNCATION_CHECK */
 #define D_PF_DROPPED         LOGLEV(4, 56, 0)        /* packet filter dropped a packet */
 #define D_MULTI_DROPPED      LOGLEV(4, 57, 0)        /* show point-to-multipoint packet drops */
+#define D_X509_ATTR          LOGLEV(4, 58, 0)        /* show x509-track attributes on connection */
 
 #define D_LOG_RW             LOGLEV(5, 0,  0)        /* Print 'R' or 'W' to stdout for read/write */
 
diff --git a/init.c b/init.c
index 0de2fcc3830d86bf535da2e6dd71455bfc6d7b8c..e694a70cc6ded4e503b46dc224a85365351344cc 100644 (file)
--- a/init.c
+++ b/init.c
@@ -2049,6 +2049,10 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
     to.client_config_dir_exclusive = options->client_config_dir;
 #endif
 
+#ifdef ENABLE_X509_TRACK
+  to.x509_track = options->x509_track;
+#endif
+
   /* TLS handshake authentication (--tls-auth) */
   if (options->tls_auth_file)
     {
index 310a70ebbe82a297b910beed0a42e0dff2fdb566..eabfb1fc83950f2a8fbf453c69f3aac26171d111 100644 (file)
--- a/manage.c
+++ b/manage.c
@@ -2274,14 +2274,17 @@ env_filter_match (const char *env_str, const int env_filter_level)
     "bytes_sent=",
     "bytes_received="
   };
-  if (env_filter_level >= 1)
+
+  if (env_filter_level >= 2 && !strncmp(env_str, "X509_", 5))
+    return true;
+  else if (env_filter_level >= 1)
     {
       size_t i;
       for (i = 0; i < SIZE(env_names); ++i)
        {
          const char *en = env_names[i];
          const size_t len = strlen(en);
-         if (strncmp(env_str, en, len) == 0)
+         if (!strncmp(env_str, en, len))
            return true;
        }
       return false;
index 004a30b0f951bed613ab70ef1b1235e8c6d6259f..3cdc07e653bf3ba26cc32aff655a59aa64d39653 100644 (file)
--- a/openvpn.8
+++ b/openvpn.8
@@ -4311,6 +4311,18 @@ works in a
 environment too.
 .\"*********************************************************
 .TP
+.B --x509-track attribute
+Save peer X509
+.B attribute
+value in environment for use by plugins and management interface.
+Prepend a '+' to
+.B attribute
+to save values from full cert chain.  Values will be encoded
+as X509_<depth>_<attribute>=<value>.  Multiple
+.B --x509-track
+options can be defined to track multiple attributes.
+.\"*********************************************************
+.TP
 .B --ns-cert-type client|server
 Require that peer certificate was signed with an explicit
 .B nsCertType
index 95b6254e77128092fb7703808c92c5fa2f3f4677..2ba18ec43defd0886f778d83ae74c99ee986cdff 100644 (file)
--- a/options.c
+++ b/options.c
@@ -540,6 +540,8 @@ static const char usage_message[] =
   "                  of verification.\n"
   "--ns-cert-type t: Require that peer certificate was signed with an explicit\n"
   "                  nsCertType designation t = 'client' | 'server'.\n"
+  "--x509-track x  : Save peer X509 attribute x in environment for use by\n"
+  "                  plugins and management interface.\n"
 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
   "--remote-cert-ku v ... : Require that the peer certificate was signed with\n"
   "                  explicit key usage, you can specify more than one value.\n"
@@ -3651,6 +3653,13 @@ add_option (struct options *options,
       options->management_flags |= MF_CLIENT_AUTH;
     }
 #endif
+#ifdef ENABLE_X509_TRACK
+  else if (streq (p[0], "x509-track") && p[1])
+    {
+      VERIFY_PERMISSION (OPT_P_GENERAL);
+      x509_track_add (&options->x509_track, p[1], msglevel, &options->gc);
+    }
+#endif
 #ifdef MANAGEMENT_PF
   else if (streq (p[0], "management-client-pf"))
     {
index fc5db58d65bf2739943c83cdd356c6f4ab8e8b1b..4a567017f4db1e9d456c3ea08be97a3221637fff 100644 (file)
--- a/options.h
+++ b/options.h
@@ -532,6 +532,10 @@ struct options
 #endif /* USE_SSL */
 #endif /* USE_CRYPTO */
 
+#ifdef ENABLE_X509_TRACK
+  const struct x509_track *x509_track;
+#endif
+
   /* special state parms */
   int foreign_option_index;
 
diff --git a/ssl.c b/ssl.c
index 817ea9dd0eccc97541b8d7ce7ee49d3e05b2c5d2..f1f0688b895ea3f7c56557359b4794ba74e0cb45 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -518,6 +518,99 @@ extract_x509_field_ssl (X509_NAME *x509, const char *field_name, char *out, int
   }
 }
 
+#ifdef ENABLE_X509_TRACK
+/*
+ * setenv_x509_track function -- save X509 fields to environment,
+ * using the naming convention:
+ *
+ *  X509_{cert_depth}_{name}={value}
+ *
+ * This function differs from setenv_x509 below in the following ways:
+ *
+ * (1) Only explicitly named attributes in xt are saved, per usage
+ *     of --x509-track program options.
+ * (2) Only the level 0 cert info is saved unless the XT_FULL_CHAIN
+ *     flag is set in xt->flags (corresponds with prepending a '+'
+ *     to the name when specified by --x509-track program option).
+ * (3) This function supports both X509 subject name fields as
+ *     well as X509 V3 extensions.
+ */
+
+/* worker method for setenv_x509_track */
+static void
+do_setenv_x509 (struct env_set *es, const char *name, char *value, int depth)
+{
+  char *name_expand;
+  size_t name_expand_size;
+
+  string_mod (value, CC_ANY, CC_CRLF, '?');
+  msg (D_X509_ATTR, "X509 ATTRIBUTE name='%s' value='%s' depth=%d", name, value, depth);
+  name_expand_size = 64 + strlen (name);
+  name_expand = (char *) malloc (name_expand_size);
+  check_malloc_return (name_expand);
+  openvpn_snprintf (name_expand, name_expand_size, "X509_%d_%s", depth, name);
+  setenv_str (es, name_expand, value);
+  free (name_expand);
+}
+
+static void
+setenv_x509_track (const struct x509_track *xt, struct env_set *es, const int depth, X509 *x509)
+{
+  X509_NAME *x509_name = X509_get_subject_name (x509);
+  const char nullc = '\0';
+  int i;
+
+  while (xt)
+    {
+      if (depth == 0 || (xt->flags & XT_FULL_CHAIN))
+       {
+         i = X509_NAME_get_index_by_NID(x509_name, xt->nid, -1);
+         if (i >= 0)
+           {
+             X509_NAME_ENTRY *ent = X509_NAME_get_entry(x509_name, i);
+             if (ent)
+               {
+                 ASN1_STRING *val = X509_NAME_ENTRY_get_data (ent);
+                 unsigned char *buf;
+                 buf = (unsigned char *)1; /* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */
+                 if (ASN1_STRING_to_UTF8 (&buf, val) > 0)
+                   {
+                     do_setenv_x509(es, xt->name, (char *)buf, depth);
+                     OPENSSL_free (buf);
+                   }
+               }
+           }
+         else
+           {
+             i = X509_get_ext_by_NID(x509, xt->nid, -1);
+             if (i >= 0)
+               {
+                 X509_EXTENSION *ext = X509_get_ext(x509, i);
+                 if (ext)
+                   {
+                     BIO *bio = BIO_new(BIO_s_mem());
+                     if (bio)
+                       {
+                         if (X509V3_EXT_print(bio, ext, 0, 0))
+                           {
+                             if (BIO_write(bio, &nullc, 1) == 1)
+                               {
+                                 char *str;
+                                 BIO_get_mem_data(bio, &str);
+                                 do_setenv_x509(es, xt->name, str, depth);
+                               }
+                           }
+                         BIO_free(bio);
+                       }
+                   }
+               }
+           }
+       }
+      xt = xt->next;
+    }
+}
+#endif
+
 /*
  * Save X509 fields to environment, using the naming convention:
  *
@@ -751,7 +844,12 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
     }
 
   /* Save X509 fields in environment */
-  setenv_x509 (opt->es, ctx->error_depth, X509_get_subject_name (ctx->current_cert));
+#ifdef ENABLE_X509_TRACK
+  if (opt->x509_track)
+    setenv_x509_track (opt->x509_track, opt->es, ctx->error_depth, ctx->current_cert);
+  else
+#endif
+    setenv_x509 (opt->es, ctx->error_depth, X509_get_subject_name (ctx->current_cert));
 
   /* enforce character class restrictions in X509 name */
   string_mod_sslname (subject, X509_NAME_CHAR_CLASS, opt->ssl_flags);
@@ -1066,6 +1164,31 @@ tls_lock_username (struct tls_multi *multi, const char *username)
   return true;
 }
 
+#ifdef ENABLE_X509_TRACK
+
+void
+x509_track_add (const struct x509_track **ll_head, const char *name, int msglevel, struct gc_arena *gc)
+{
+  struct x509_track *xt;
+  ALLOC_OBJ_CLEAR_GC (xt, struct x509_track, gc);
+  if (*name == '+')
+    {
+      xt->flags |= XT_FULL_CHAIN;
+      ++name;
+    }
+  xt->name = name;
+  xt->nid = OBJ_txt2nid(name);
+  if (xt->nid != NID_undef)
+    {
+      xt->next = *ll_head;
+      *ll_head = xt;
+    }
+  else
+    msg(msglevel, "x509_track: no such attribute '%s'", name);
+}
+
+#endif
+
 #ifdef ENABLE_DEF_AUTH
 /* key_state_test_auth_control_file return values,
    NOTE: acf_merge indexing depends on these values */
diff --git a/ssl.h b/ssl.h
index 4373a800ebbe40ebed7d4acb4469791cfba12567..eb059cc6d77177794f23d2afe0a7e08727a7cc7d 100644 (file)
--- a/ssl.h
+++ b/ssl.h
@@ -402,6 +402,21 @@ struct key_state
 #endif
 };
 
+#ifdef ENABLE_X509_TRACK
+
+struct x509_track
+{
+  const struct x509_track *next;
+  const char *name;
+# define XT_FULL_CHAIN (1<<0)
+  unsigned int flags;
+  int nid;
+};
+
+void x509_track_add (const struct x509_track **ll_head, const char *name, int msglevel, struct gc_arena *gc);
+
+#endif
+
 /*
  * Our const options, obtained directly or derived from
  * command line options.
@@ -494,6 +509,10 @@ struct tls_options
   struct man_def_auth_context *mda_context;
 #endif
 
+#ifdef ENABLE_X509_TRACK
+  const struct x509_track *x509_track;
+#endif
+
   /* --gremlin bits */
   int gremlin;
 };
index 3b835f797dd74a06f868b66f8cb0e0c3a5fc586b..4e6ef0896f486e715b07ec07cdf3d9757e1ee39b 100644 (file)
--- a/syshead.h
+++ b/syshead.h
@@ -607,6 +607,13 @@ socket_defined (const socket_descriptor_t sd)
 #define ENABLE_PKCS11
 #endif
 
+/*
+ * Enable x509-track feature?
+ */
+#if defined(USE_CRYPTO) && defined(USE_SSL)
+#define ENABLE_X509_TRACK
+#endif
+
 /*
  * Is poll available on this platform?
  */
index 4d84e2b61ab1f0b2f111d9897f36e955a40773eb..44d9190a710eb4a1bdafeb076854b10ec2943334 100644 (file)
@@ -1,5 +1,5 @@
 dnl define the OpenVPN version
-define(PRODUCT_VERSION,[2.1.3d])
+define(PRODUCT_VERSION,[2.1.3e])
 dnl define the TAP version
 define(PRODUCT_TAP_ID,[tap0901])
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])