As this is inserted into environment, what happens if locale is not unicode enabled? I think this may break some configurations.
On Wed, Nov 23, 2011 at 4:14 PM, Heiko Hund <heiko.h...@sophos.com> wrote: > The UTF-8 support that came with commit 2627335 does allow international > usernames and passwords. This patch introduces UTF-8 support for X.509 DNs. > Additionally, instead of using the legacy openssl format, DNs are now > displayed in RFC 2253 format; "/C=ru/L=\xD0\x9C\xD0\xBE\xD1\x81\xD0\xBA\xD0 > \xB2\xD0\xB0/O=\xD0\x9A\xD1\x80\xD0\xB5\xD0\xBC\xD0\xBB\xD1\x8C/CN=kreml.ru" > becomes "C=ru, L=Москва, O=Кремль, CN=kreml.ru". > > Since the specific character classes for X.509 names are removed, the > "no-name-remapping" configuration option has no use anymore and is removed > as well. > > Signed-off-by: Heiko Hund <heiko.h...@sophos.com> > --- > openvpn.8 | 23 +---------------------- > options.c | 12 +----------- > pkcs11_openssl.c | 2 +- > sample-scripts/verify-cn | 6 +++--- > ssl_openssl.c | 36 ++++++++++++++++++++++++++++++++++++ > ssl_openssl.h | 1 + > ssl_verify.c | 45 +++++++++------------------------------------ > ssl_verify_openssl.c | 4 ++-- > 8 files changed, 54 insertions(+), 75 deletions(-) > > diff --git a/openvpn.8 b/openvpn.8 > index b8594e1..e96c1e4 100644 > --- a/openvpn.8 > +++ b/openvpn.8 > @@ -3322,27 +3322,6 @@ the authenticated username as the common name, > rather than the common name from the client cert. > .\"********************************************************* > .TP > -.B \-\-no-name-remapping > -Allow Common Name, X509 Subject, and username strings to include > -any printable character including space, but excluding control > -characters such as tab, newline, and carriage-return. > - > -By default, OpenVPN will remap > -any character other than alphanumeric, underbar ('_'), dash > -('-'), dot ('.'), and slash ('/') to underbar ('_'). The X509 > -Subject string as returned by the > -.B tls_id > -environmental variable, can additionally contain colon (':') or > -equal ('='). > - > -While name remapping is performed for security reasons to reduce > -the possibility of introducing string expansion security vulnerabilities > -in user-defined authentication > -scripts, this option is provided for those cases where it is desirable to > -disable the remapping feature. Don't use this option unless you > -know what you are doing! > -.\"********************************************************* > -.TP > .B \-\-port-share host port [dir] > When run in TCP server mode, share the OpenVPN port with > another application, such as an HTTPS server. If OpenVPN > @@ -4463,7 +4442,7 @@ When > .B cmd > is executed two arguments are appended, as follows: > > -.B cmd certificate_depth X509_NAME_oneline > +.B cmd certificate_depth subject > > These arguments are, respectively, the current certificate depth and > the X509 common name (cn) of the peer. > diff --git a/options.c b/options.c > index 0d86cd0..a01ae76 100644 > --- a/options.c > +++ b/options.c > @@ -597,7 +597,7 @@ static const char usage_message[] = > " pending TLS connection that has otherwise passed all > other\n" > " 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" > + " executed as 'cmd certificate_depth subject')\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" > @@ -2160,9 +2160,6 @@ options_postprocess_verify_ce (const struct options > *options, const struct conne > if ((options->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) && !ccnr) > msg (M_USAGE, "--auth-user-pass-optional %s", postfix); > } > - > - if ((options->ssl_flags & SSLF_NO_NAME_REMAPPING) && script_method == > SM_SYSTEM) > - msg (M_USAGE, "--script-security method='system' cannot be combined > with --no-name-remapping"); > } > else > { > @@ -2197,8 +2194,6 @@ options_postprocess_verify_ce (const struct options > *options, const struct conne > msg (M_USAGE, "--username-as-common-name requires --mode server"); > if (options->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) > msg (M_USAGE, "--auth-user-pass-optional requires --mode server"); > - if (options->ssl_flags & SSLF_NO_NAME_REMAPPING) > - msg (M_USAGE, "--no-name-remapping requires --mode server"); > if (options->ssl_flags & SSLF_OPT_VERIFY) > msg (M_USAGE, "--opt-verify requires --mode server"); > if (options->server_flags & SF_TCP_NODELAY_HELPER) > @@ -5389,11 +5384,6 @@ add_option (struct options *options, > VERIFY_PERMISSION (OPT_P_GENERAL); > options->ssl_flags |= SSLF_AUTH_USER_PASS_OPTIONAL; > } > - else if (streq (p[0], "no-name-remapping")) > - { > - VERIFY_PERMISSION (OPT_P_GENERAL); > - options->ssl_flags |= SSLF_NO_NAME_REMAPPING; > - } > else if (streq (p[0], "opt-verify")) > { > VERIFY_PERMISSION (OPT_P_GENERAL); > diff --git a/pkcs11_openssl.c b/pkcs11_openssl.c > index e3463dc..943b90f 100644 > --- a/pkcs11_openssl.c > +++ b/pkcs11_openssl.c > @@ -129,7 +129,7 @@ pkcs11_certificate_dn (pkcs11h_certificate_t certificate, > char *dn, > goto cleanup; > } > > - X509_NAME_oneline (X509_get_subject_name (x509), dn, dn_len); > + openssl_get_subject (x509, dn, dn_len); > > ret = 0; > > diff --git a/sample-scripts/verify-cn b/sample-scripts/verify-cn > index f9fea0f..6e747ef 100755 > --- a/sample-scripts/verify-cn > +++ b/sample-scripts/verify-cn > @@ -3,7 +3,7 @@ > # verify-cn -- a sample OpenVPN tls-verify script > # > # Return 0 if cn matches the common name component of > -# X509_NAME_oneline, 1 otherwise. > +# subject, 1 otherwise. > # > # For example in OpenVPN, you could use the directive: > # > @@ -13,7 +13,7 @@ > # the client common name is listed on a line in the > # allowed_clients file. > > -die "usage: verify-cn cnfile certificate_depth X509_NAME_oneline" if (@ARGV > != 3); > +die "usage: verify-cn cnfile certificate_depth subject" if (@ARGV != 3); > > # Parse out arguments: > # cnfile -- The file containing the list of common names, one per > @@ -37,7 +37,7 @@ if ($depth == 0) { > # If so, parse out the common name substring in > # the X509 subject string. > > - if ($x509 =~ /\/CN=([^\/]+)/) { > + if ($x509 =~ / CN=([^,]+)/) { > $cn = $1; > # Accept the connection if the X509 common name > # string matches the passed cn argument. > diff --git a/ssl_openssl.c b/ssl_openssl.c > index 2e9fc4d..536b5f0 100644 > --- a/ssl_openssl.c > +++ b/ssl_openssl.c > @@ -1290,4 +1290,40 @@ get_highest_preference_tls_cipher (char *buf, int size) > SSL_CTX_free (ctx); > } > > +char * > +openssl_get_subject (X509 *cert, char *buf, int size) > +{ > + BIO *subject_bio; > + BUF_MEM *subject_mem; > + char *subject = buf; > + int maxlen = size; > + > + subject_bio = BIO_new (BIO_s_mem ()); > + if (subject_bio == NULL) > + goto out; > + > + X509_NAME_print_ex (subject_bio, X509_get_subject_name (cert), > + 0, XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_FN_SN | > + ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_CTRL); > + > + if (BIO_eof (subject_bio)) > + goto out_free; > + > + BIO_get_mem_ptr (subject_bio, &subject_mem); > + if (subject == NULL) > + { > + maxlen = subject_mem->length + 1; > + subject = malloc (maxlen); > + check_malloc_return (subject); > + } > + > + memcpy (subject, subject_mem->data, maxlen); > + subject[maxlen - 1] = '\0'; > + > +out_free: > + BIO_free (subject_bio); > +out: > + return subject; > +} > + > #endif /* defined(USE_SSL) && defined(USE_OPENSSL) */ > diff --git a/ssl_openssl.h b/ssl_openssl.h > index fc2052c..e5e303a 100644 > --- a/ssl_openssl.h > +++ b/ssl_openssl.h > @@ -54,5 +54,6 @@ struct key_state_ssl { > extern int mydata_index; /* GLOBAL */ > > void openssl_set_mydata_index (void); > +char *openssl_get_subject (X509 *cert, char *buf, int size); > > #endif /* SSL_OPENSSL_H_ */ > diff --git a/ssl_verify.c b/ssl_verify.c > index 326b005..0b2a1fb 100644 > --- a/ssl_verify.c > +++ b/ssl_verify.c > @@ -40,24 +40,9 @@ > #include "ssl_verify_openssl.h" > #endif > > -/** Legal characters in an X509 name */ > -#define X509_NAME_CHAR_CLASS > (CC_ALNUM|CC_UNDERBAR|CC_DASH|CC_DOT|CC_AT|CC_COLON|CC_SLASH|CC_EQUAL) > - > -/** Legal characters in a common name */ > -#define COMMON_NAME_CHAR_CLASS > (CC_ALNUM|CC_UNDERBAR|CC_DASH|CC_DOT|CC_AT|CC_SLASH) > - > /** Maximum length of common name */ > #define TLS_USERNAME_LEN 64 > > -static void > -string_mod_sslname (char *str, const unsigned int restrictive_flags, const > unsigned int ssl_flags) > -{ > - if (ssl_flags & SSLF_NO_NAME_REMAPPING) > - string_mod (str, CC_PRINT, CC_CRLF, '_'); > - else > - string_mod (str, restrictive_flags, 0, '_'); > -} > - > /* > * Export the untrusted IP address and port to the environment > */ > @@ -595,7 +580,7 @@ verify_cert(struct tls_session *session, x509_cert_t > *cert, int cert_depth) > } > > /* enforce character class restrictions in X509 name */ > - string_mod_sslname (subject, X509_NAME_CHAR_CLASS, opt->ssl_flags); > + string_mod (subject, CC_PRINT, CC_CRLF, '_'); > string_replace_leading (subject, '-', '_'); > > /* extract the username (default is CN) */ > @@ -615,7 +600,7 @@ verify_cert(struct tls_session *session, x509_cert_t > *cert, int cert_depth) > } > > /* enforce character class restrictions in common name */ > - string_mod_sslname (common_name, COMMON_NAME_CHAR_CLASS, opt->ssl_flags); > + string_mod (common_name, CC_PRINT, CC_CRLF, '_'); > > /* warn if cert chain is too deep */ > if (cert_depth >= MAX_CERT_DEPTH) > @@ -1005,7 +990,7 @@ verify_user_pass_script (struct tls_session *session, > const struct user_pass *up > * Verify the username and password using a plugin > */ > static int > -verify_user_pass_plugin (struct tls_session *session, const struct user_pass > *up, const char *raw_username) > +verify_user_pass_plugin (struct tls_session *session, const struct user_pass > *up) > { > int retval = OPENVPN_PLUGIN_FUNC_ERROR; > struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ > @@ -1014,7 +999,7 @@ verify_user_pass_plugin (struct tls_session *session, > const struct user_pass *up > if ((session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) || strlen > (up->username)) > { > /* set username/password in private env space */ > - setenv_str (session->opt->es, "username", raw_username); > + setenv_str (session->opt->es, "username", up->username); > setenv_str (session->opt->es, "password", up->password); > > /* setenv incoming cert common name for script */ > @@ -1038,7 +1023,6 @@ verify_user_pass_plugin (struct tls_session *session, > const struct user_pass *up > #endif > > setenv_del (session->opt->es, "password"); > - setenv_str (session->opt->es, "username", up->username); > } > else > { > @@ -1059,7 +1043,7 @@ verify_user_pass_plugin (struct tls_session *session, > const struct user_pass *up > #define KMDA_DEF 3 > > static int > -verify_user_pass_management (struct tls_session *session, const struct > user_pass *up, const char *raw_username) > +verify_user_pass_management (struct tls_session *session, const struct > user_pass *up) > { > int retval = KMDA_ERROR; > struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ > @@ -1068,7 +1052,7 @@ verify_user_pass_management (struct tls_session > *session, const struct user_pass > if ((session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) || strlen > (up->username)) > { > /* set username/password in private env space */ > - setenv_str (session->opt->es, "username", raw_username); > + setenv_str (session->opt->es, "username", up->username); > setenv_str (session->opt->es, "password", up->password); > > /* setenv incoming cert common name for script */ > @@ -1081,7 +1065,6 @@ verify_user_pass_management (struct tls_session > *session, const struct user_pass > management_notify_client_needing_auth (management, ks->mda_key_id, > session->opt->mda_context, session->opt->es); > > setenv_del (session->opt->es, "password"); > - setenv_str (session->opt->es, "username", up->username); > > retval = KMDA_SUCCESS; > } > @@ -1105,9 +1088,6 @@ verify_user_pass(struct user_pass *up, struct tls_multi > *multi, > bool s2 = true; > struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ > > - struct gc_arena gc = gc_new (); > - char *raw_username; > - > #ifdef MANAGEMENT_DEF_AUTH > int man_def_auth = KMDA_UNDEF; > > @@ -1115,22 +1095,17 @@ verify_user_pass(struct user_pass *up, struct > tls_multi *multi, > man_def_auth = KMDA_DEF; > #endif > > - /* preserve raw username before string_mod remapping, for plugins */ > - ALLOC_ARRAY_CLEAR_GC (raw_username, char, USER_PASS_LEN, &gc); > - strcpy (raw_username, up->username); > - string_mod (raw_username, CC_PRINT, CC_CRLF, '_'); > - > /* enforce character class restrictions in username/password */ > - string_mod_sslname (up->username, COMMON_NAME_CHAR_CLASS, > session->opt->ssl_flags); > + string_mod (up->username, CC_PRINT, CC_CRLF, '_'); > string_mod (up->password, CC_PRINT, CC_CRLF, '_'); > > /* call plugin(s) and/or script */ > #ifdef MANAGEMENT_DEF_AUTH > if (man_def_auth == KMDA_DEF) > - man_def_auth = verify_user_pass_management (session, up, raw_username); > + man_def_auth = verify_user_pass_management (session, up); > #endif > if (plugin_defined (session->opt->plugins, > OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)) > - s1 = verify_user_pass_plugin (session, up, raw_username); > + s1 = verify_user_pass_plugin (session, up); > if (session->opt->auth_user_pass_verify_script) > s2 = verify_user_pass_script (session, up); > > @@ -1179,8 +1154,6 @@ verify_user_pass(struct user_pass *up, struct tls_multi > *multi, > { > msg (D_TLS_ERRORS, "TLS Auth Error: Auth Username/Password verification > failed for peer"); > } > - > - gc_free (&gc); > } > > void > diff --git a/ssl_verify_openssl.c b/ssl_verify_openssl.c > index 13c2f4e..7a99469 100644 > --- a/ssl_verify_openssl.c > +++ b/ssl_verify_openssl.c > @@ -248,14 +248,14 @@ x509_free_sha1_hash (unsigned char *hash) > char * > x509_get_subject (X509 *cert) > { > - return X509_NAME_oneline (X509_get_subject_name (cert), NULL, 0); > + return openssl_get_subject (cert, NULL, 0); > } > > void > x509_free_subject (char *subject) > { > if (subject) > - OPENSSL_free(subject); > + free(subject); > } > > > -- > 1.7.5.4 > > > ------------------------------------------------------------------------------ > All the data continuously generated in your IT infrastructure > contains a definitive record of customers, application performance, > security threats, fraudulent activity, and more. Splunk takes this > data and makes sense of it. IT sense. And common sense. > http://p.sf.net/sfu/splunk-novd2d > _______________________________________________ > Openvpn-devel mailing list > Openvpn-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/openvpn-devel >