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
>

Reply via email to