Support duplicate x509 field values in environment
PATCH 1/1 Support duplicate x509 field values in environment
As reported in trac #387, an x509 DN can contain duplicate fields. Previously, we would overwrite any previous field value with a new one if we would process a second same-name field. Now, instead, append _$N, starting at N=1 to the name for each consequent field to export all fields to the enviroment.
--- Changes.rst | 7 +++++++ src/openvpn/misc.c | 32 ++++++++++++++++++++++++++++++++ src/openvpn/misc.h | 7 +++++++ src/openvpn/ssl_verify_openssl.c | 2 +- src/openvpn/ssl_verify_polarssl.c | 2 +- 5 files changed, 48 insertions(+), 2 deletions(-)
Changes.rst +7 -0
@@ -36,6 +36,13 @@ LZ4 Compression User-visible Changes -------------------- +- For certificate DNs with duplicate fields, e.g. "OU=one,OU=two", both fields + are now exported to the environment, where each second and later occurrence + of a field get _$N appended to it's field name, starting at N=1. For the + example above, that would result in e.g. X509_0_OU=one, X509_0_OU_1=two. + Note that this breaks setups that rely on the fact that OpenVPN would + previously (incorrectly) only export the last occurence of a field. + - proto udp and proto tcp specify to use IPv4 and IPv6. The new options proto udp4 and tcp4 specify to use IPv4 only.
src/openvpn/misc.c +32 -0
@@ -607,6 +607,16 @@ env_set_add (struct env_set *es, const char *str)env_set_add_nolock (es, str); } +const char * +env_set_get (struct env_set *es,const char *name) +{ +struct env_item *item = es->list; +while (item && !env_string_equal (item->string, name)) { + item = item->next; + } +return item ? item->string :NULL ; +} +void env_set_print (int msglevel,const struct env_set *es) {
@@ -741,6 +751,28 @@ setenv_str_safe (struct env_set *es, const char *name, const char *value)msg (M_WARN ,"setenv_str_safe: name overflow" ); } +void setenv_str_incr (struct env_set *es,const char *name,const char *value) +{ +unsigned int counter =1 ; +const size_t tmpname_len =strlen (name) +5 ; +char *tmpname =gc_malloc (tmpname_len, true,NULL );/* 3 digits counter max */ +memcpy (tmpname, name,strlen (name)); +while (NULL !=env_set_get (es, tmpname) && counter <1000 ) + { +ASSERT (openvpn_snprintf (tmpname, tmpname_len,"%s_%u" , name, counter)); + counter++; + } +if (counter <1000 ) + { +setenv_str (es, tmpname, value); + } +else + { +msg (D_TLS_DEBUG_MED ,"Too many same-name env variables, ignoring: %s" , name); + } +free (tmpname); +} +void setenv_del (struct env_set *es,const char *name) {
src/openvpn/misc.h +7 -0
@@ -133,6 +133,12 @@ void setenv_str (struct env_set *es, const char *name, const char *value);void setenv_str_safe (struct env_set *es,const char *name,const char *value);void setenv_del (struct env_set *es,const char *name); +/** +* Store the supplied name value pair in the env_set. If the variable with the +* supplied name already exists, append _N to the name, starting at N=1. +*/ +void setenv_str_incr (struct env_set *es,const char *name,const char *value); +void setenv_int_i (struct env_set *es,const char *name,const int value,const int i);void setenv_str_i (struct env_set *es,const char *name,const char *value,const int i);
@@ -142,6 +148,7 @@ struct env_set *env_set_create (struct gc_arena *gc);void env_set_destroy (struct env_set *es);bool env_set_del (struct env_set *es,const char *str);void env_set_add (struct env_set *es,const char *str); +const char *env_set_get (struct env_set *es,const char *name);void env_set_print (int msglevel,const struct env_set *es);
src/openvpn/ssl_verify_openssl.c +1 -1
@@ -448,7 +448,7 @@ x509_setenv (struct env_set *es, int cert_depth, openvpn_x509_cert_t *peer_cert) objbuf);string_mod (name_expand,CC_PRINT ,CC_CRLF ,'_' );string_mod ((char *)buf,CC_PRINT ,CC_CRLF ,'_' ); -setenv_str (es, name_expand, (char *)buf); +setenv_str_incr (es, name_expand, (char *)buf);free (name_expand);OPENSSL_free (buf); }
src/openvpn/ssl_verify_polarssl.c +1 -1
@@ -245,7 +245,7 @@ x509_setenv (struct env_set *es, int cert_depth, openvpn_x509_cert_t *cert)/* Check both strings, set environment variable */ string_mod (name_expand,CC_PRINT ,CC_CRLF ,'_' );string_mod ((char *)s,CC_PRINT ,CC_CRLF ,'_' ); -setenv_str (es, name_expand, (char *)s); +setenv_str_incr (es, name_expand, (char *)s); name = name->next; }
Signature · 1 line
2.5.0
Hi,
Quoted 6 lines · Steffan Karger
As reported in trac #387, an x509 DN can contain duplicate fields. Previously, we would overwrite any previous field value with a new one if we would process a second same-name field. Now, instead, append _$N, starting at N=1 to the name for each consequent field to export all fields to the enviroment.
A useful change and clean code. A couple of places could benefit from const qualifiers, though:
--- a/src/openvpn/misc.c
src/openvpn/misc.c env_set_add (struct env_set *es, const char *str) · line 612
Quoted 8 lines
+++
b/src/openvpn/misc.csrc/openvpn/misc.c +2
-0@@ -607,6 +607,16 @@ env_set_add (struct env_set *es, const char *str)env_set_add_nolock (es, str); } +const char * +env_set_get (struct env_set *es,const char *name)
... (const struct env_set *es,.... ) <to be matched in misc.h>
+{
Review env_set_add (struct env_set *es, const char *str) · line 614
Quoted 2 lines
(quoted diff) +1
-0+ struct env_item *item = es->list;
const struct env_item *item = ...
+ while (item && !envstring_equal(item->string, name)) {
src/openvpn/misc.c env_set_add (struct env_set *es, const char *str)
Quoted 5 lines
src/openvpn/misc.c +4
-0+ item = item->next; + } +return item ? item->string :NULL ; +}
Thanks,
Selva
Hi,
Quoted 2 lines · Selva Nair
A useful change and clean code. A couple of places could benefit from const qualifiers, though
You're absolutely right. Thanks. Attached a v2 patch that adds the suggested const qualifiers.
Now that I was looking at my own code again, I also realized a strcpy() makes more sense in setenv_str_incr() than the memcpy() from the previous patch. (Both work just fine, but this should be easier to read.)
-Steffan
From 44a5af585953d5384d3bbd64e55c1de6343919d8 Mon Sep 17 00:00:00 2001
From: Steffan Karger <[email protected]>
Date: Sun, 29 Nov 2015 10:39:24 +0100
Subject: [PATCH] Support duplicate x509 field values in environment
As reported in trac #387, an x509 DN can contain duplicate fields. Previously, we would overwrite any previous field value with a new one if we would process a second same-name field. Now, instead, append _$N, starting at N=1 to the name for each consequent field to export all fields to the enviroment.
v2 - make better use of const qualifiers in env_set_get(), and use strcpy()
instead of memcpy() in setenv_str_incr()
--- Changes.rst | 7 +++++++ src/openvpn/misc.c | 32 ++++++++++++++++++++++++++++++++ src/openvpn/misc.h | 7 +++++++ src/openvpn/ssl_verify_openssl.c | 2 +- src/openvpn/ssl_verify_polarssl.c | 2 +- 5 files changed, 48 insertions(+), 2 deletions(-)
Changes.rst +7 -0
@@ -36,6 +36,13 @@ LZ4 Compression User-visible Changes -------------------- +- For certificate DNs with duplicate fields, e.g. "OU=one,OU=two", both fields + are now exported to the environment, where each second and later occurrence + of a field get _$N appended to it's field name, starting at N=1. For the + example above, that would result in e.g. X509_0_OU=one, X509_0_OU_1=two. + Note that this breaks setups that rely on the fact that OpenVPN would + previously (incorrectly) only export the last occurence of a field. + - proto udp and proto tcp specify to use IPv4 and IPv6. The new options proto udp4 and tcp4 specify to use IPv4 only.
src/openvpn/misc.c +32 -0
@@ -607,6 +607,16 @@ env_set_add (struct env_set *es, const char *str)env_set_add_nolock (es, str); } +const char * +env_set_get (const struct env_set *es,const char *name) +{ +const struct env_item *item = es->list; +while (item && !env_string_equal (item->string, name)) { + item = item->next; + } +return item ? item->string :NULL ; +} +void env_set_print (int msglevel,const struct env_set *es) {
@@ -741,6 +751,28 @@ setenv_str_safe (struct env_set *es, const char *name, const char *value)msg (M_WARN ,"setenv_str_safe: name overflow" ); } +void setenv_str_incr (struct env_set *es,const char *name,const char *value) +{ +unsigned int counter =1 ; +const size_t tmpname_len =strlen (name) +5 ;/* 3 digits counter max */ +char *tmpname =gc_malloc (tmpname_len, true,NULL ); +strcpy (tmpname, name); +while (NULL !=env_set_get (es, tmpname) && counter <1000 ) + { +ASSERT (openvpn_snprintf (tmpname, tmpname_len,"%s_%u" , name, counter)); + counter++; + } +if (counter <1000 ) + { +setenv_str (es, tmpname, value); + } +else + { +msg (D_TLS_DEBUG_MED ,"Too many same-name env variables, ignoring: %s" , name); + } +free (tmpname); +} +void setenv_del (struct env_set *es,const char *name) {
src/openvpn/misc.h +7 -0
@@ -133,6 +133,12 @@ void setenv_str (struct env_set *es, const char *name, const char *value);void setenv_str_safe (struct env_set *es,const char *name,const char *value);void setenv_del (struct env_set *es,const char *name); +/** +* Store the supplied name value pair in the env_set. If the variable with the +* supplied name already exists, append _N to the name, starting at N=1. +*/ +void setenv_str_incr (struct env_set *es,const char *name,const char *value); +void setenv_int_i (struct env_set *es,const char *name,const int value,const int i);void setenv_str_i (struct env_set *es,const char *name,const char *value,const int i);
@@ -142,6 +148,7 @@ struct env_set *env_set_create (struct gc_arena *gc);void env_set_destroy (struct env_set *es);bool env_set_del (struct env_set *es,const char *str);void env_set_add (struct env_set *es,const char *str); +const char *env_set_get (const struct env_set *es,const char *name);void env_set_print (int msglevel,const struct env_set *es);
src/openvpn/ssl_verify_openssl.c +1 -1
@@ -448,7 +448,7 @@ x509_setenv (struct env_set *es, int cert_depth, openvpn_x509_cert_t *peer_cert) objbuf);string_mod (name_expand,CC_PRINT ,CC_CRLF ,'_' );string_mod ((char *)buf,CC_PRINT ,CC_CRLF ,'_' ); -setenv_str (es, name_expand, (char *)buf); +setenv_str_incr (es, name_expand, (char *)buf);free (name_expand);OPENSSL_free (buf); }
src/openvpn/ssl_verify_polarssl.c +1 -1
@@ -245,7 +245,7 @@ x509_setenv (struct env_set *es, int cert_depth, openvpn_x509_cert_t *cert)/* Check both strings, set environment variable */ string_mod (name_expand,CC_PRINT ,CC_CRLF ,'_' );string_mod ((char *)s,CC_PRINT ,CC_CRLF ,'_' ); -setenv_str (es, name_expand, (char *)s); +setenv_str_incr (es, name_expand, (char *)s); name = name->next; }
Signature · 1 line
2.5.0
ACK on the changes v1->v2, keeping Selva's ACK for v1.
Your patch has been applied to the master branch.
commit 13b585e8a4c6f9681ff23bc7fb0af71ce9d0162f
Author: Steffan Karger Date: Sun Nov 29 10:39:24 2015 +0100
Support duplicate x509 field values in environment
Signed-off-by: Steffan Karger <[email protected]...>
Acked-by: Selva Nair <[email protected]...>
Acked-by: Gert Doering <[email protected]...>
Message-Id: <[email protected]...>
URL: http://article.gmane.org/gmane.network.openvpn.devel/10654
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering