diff options
author | James Yonan <james@openvpn.net> | 2011-01-05 00:50:11 +0000 |
---|---|---|
committer | James Yonan <james@openvpn.net> | 2011-01-05 00:50:11 +0000 |
commit | 9356bae859938c30808aa0d2ee764bdcbb5dbe0d (patch) | |
tree | b06d38a722c06bc16ecb61c37ce6c6fd07192a40 | |
parent | Misc fixes to r6708. (diff) | |
download | openvpn-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.h | 1 | ||||
-rw-r--r-- | init.c | 4 | ||||
-rw-r--r-- | manage.c | 7 | ||||
-rw-r--r-- | openvpn.8 | 12 | ||||
-rw-r--r-- | options.c | 9 | ||||
-rw-r--r-- | options.h | 4 | ||||
-rw-r--r-- | ssl.c | 125 | ||||
-rw-r--r-- | ssl.h | 19 | ||||
-rw-r--r-- | syshead.h | 7 | ||||
-rw-r--r-- | version.m4 | 2 |
10 files changed, 186 insertions, 4 deletions
@@ -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 */ @@ -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) { @@ -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; @@ -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 @@ -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")) { @@ -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; @@ -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 */ @@ -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; }; @@ -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) @@ -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]) |