aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Yonan <james@openvpn.net>2011-01-05 00:50:11 +0000
committerJames Yonan <james@openvpn.net>2011-01-05 00:50:11 +0000
commit9356bae859938c30808aa0d2ee764bdcbb5dbe0d (patch)
treeb06d38a722c06bc16ecb61c37ce6c6fd07192a40
parentMisc fixes to r6708. (diff)
downloadopenvpn-9356bae859938c30808aa0d2ee764bdcbb5dbe0d.tar.xz
Added --x509-track option.
Version 2.1.3e git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@6780 e7ae566f-a301-0410-adde-c780ea21d3b5
-rw-r--r--errlevel.h1
-rw-r--r--init.c4
-rw-r--r--manage.c7
-rw-r--r--openvpn.812
-rw-r--r--options.c9
-rw-r--r--options.h4
-rw-r--r--ssl.c125
-rw-r--r--ssl.h19
-rw-r--r--syshead.h7
-rw-r--r--version.m42
10 files changed, 186 insertions, 4 deletions
diff --git a/errlevel.h b/errlevel.h
index 75c3194..1d6e866 100644
--- a/errlevel.h
+++ b/errlevel.h
@@ -104,6 +104,7 @@
#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 0de2fcc..e694a70 100644
--- 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)
{
diff --git a/manage.c b/manage.c
index 310a70e..eabfb1f 100644
--- 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;
diff --git a/openvpn.8 b/openvpn.8
index 004a30b..3cdc07e 100644
--- 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
diff --git a/options.c b/options.c
index 95b6254..2ba18ec 100644
--- 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"))
{
diff --git a/options.h b/options.h
index fc5db58..4a56701 100644
--- 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 817ea9d..f1f0688 100644
--- 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 4373a80..eb059cc 100644
--- 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;
};
diff --git a/syshead.h b/syshead.h
index 3b835f7..4e6ef08 100644
--- a/syshead.h
+++ b/syshead.h
@@ -608,6 +608,13 @@ socket_defined (const socket_descriptor_t sd)
#endif
/*
+ * Enable x509-track feature?
+ */
+#if defined(USE_CRYPTO) && defined(USE_SSL)
+#define ENABLE_X509_TRACK
+#endif
+
+/*
* Is poll available on this platform?
*/
#if defined(HAVE_POLL) && defined(HAVE_SYS_POLL_H)
diff --git a/version.m4 b/version.m4
index 4d84e2b..44d9190 100644
--- a/version.m4
+++ b/version.m4
@@ -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])