summaryrefslogtreecommitdiffstats
path: root/src/openvpn/ssl_verify.c
diff options
context:
space:
mode:
authorHeiko Hund <heiko.hund@sophos.com>2012-09-11 17:34:24 +0200
committerDavid Sommerseth <davids@redhat.com>2012-09-12 15:08:10 +0200
commite7412ca3eee2f2a2fb0af5acbe968137cfd7e995 (patch)
tree70909046f97e8c108422b6ada53342bb42be856b /src/openvpn/ssl_verify.c
parent5d4f5435a421299ed047485d8d99bdf9a0d22fd1 (diff)
downloadopenvpn-e7412ca3eee2f2a2fb0af5acbe968137cfd7e995.tar.gz
openvpn-e7412ca3eee2f2a2fb0af5acbe968137cfd7e995.tar.xz
openvpn-e7412ca3eee2f2a2fb0af5acbe968137cfd7e995.zip
Add --compat-names option
With this option, users can basically undo the changes of the UTF-8 support commit 5e86fd93779482b90a191f929edebe414cd78a4f. It's here for short term compatibility and should be removed again as soon as possible. When OpenSSL is used, the subject strings will be in the proprietary format again. Generally username, X.509 CN, and X.509 subject will again be subject to '_' replacemant, unless the "no-remapping" flag is also specified. That flag ensures compatibility with setups using the --no-name-remapping option, that has been removed in 2.3. [v2: More comments related to compat_flags() added by DS plus using COMPAT_FLAG_QUERY expclit] [v3: Improved the man page entry for --compat-names, after suggestions from Bernhard R. Link] Signed-off-by: Heiko Hund <heiko.hund@sophos.com> Signed-off-by: David Sommerseth <davids@redhat.com> Acked-by: Gert Doering <gert@greenie.muc.de> Acked-by: David Sommerseth <davids@redhat.com> Message-Id: 1347377664-15462-1-git-send-email-dazo@users.sourceforge.net URL: http://article.gmane.org/gmane.network.openvpn.devel/7053
Diffstat (limited to 'src/openvpn/ssl_verify.c')
-rw-r--r--src/openvpn/ssl_verify.c54
1 files changed, 45 insertions, 9 deletions
diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c
index 30fb05d..cac46e9 100644
--- a/src/openvpn/ssl_verify.c
+++ b/src/openvpn/ssl_verify.c
@@ -49,6 +49,22 @@
/** Maximum length of common name */
#define TLS_USERNAME_LEN 64
+/** Legal characters in an X509 name with --compat-names */
+#define X509_NAME_CHAR_CLASS (CC_ALNUM|CC_UNDERBAR|CC_DASH|CC_DOT|CC_AT|CC_SLASH|CC_COLON|CC_EQUAL)
+
+/** Legal characters in a common name with --compat-names */
+#define COMMON_NAME_CHAR_CLASS (CC_ALNUM|CC_UNDERBAR|CC_DASH|CC_DOT|CC_AT|CC_SLASH)
+
+static void
+string_mod_remap_name (char *str, const unsigned int restrictive_flags)
+{
+ if (compat_flag (COMPAT_FLAG_QUERY | COMPAT_NAMES)
+ && !compat_flag (COMPAT_FLAG_QUERY | COMPAT_NO_NAME_REMAPPING))
+ string_mod (str, restrictive_flags, 0, '_');
+ else
+ string_mod (str, CC_PRINT, CC_CRLF, '_');
+}
+
/*
* Export the untrusted IP address and port to the environment
*/
@@ -591,7 +607,7 @@ verify_cert(struct tls_session *session, openvpn_x509_cert_t *cert, int cert_dep
}
/* enforce character class restrictions in X509 name */
- string_mod (subject, CC_PRINT, CC_CRLF, '_');
+ string_mod_remap_name (subject, X509_NAME_CHAR_CLASS);
string_replace_leading (subject, '-', '_');
/* extract the username (default is CN) */
@@ -611,7 +627,7 @@ verify_cert(struct tls_session *session, openvpn_x509_cert_t *cert, int cert_dep
}
/* enforce character class restrictions in common name */
- string_mod (common_name, CC_PRINT, CC_CRLF, '_');
+ string_mod_remap_name (common_name, COMMON_NAME_CHAR_CLASS);
/* warn if cert chain is too deep */
if (cert_depth >= MAX_CERT_DEPTH)
@@ -1003,7 +1019,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)
+verify_user_pass_plugin (struct tls_session *session, const struct user_pass *up, const char *raw_username)
{
int retval = OPENVPN_PLUGIN_FUNC_ERROR;
struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */
@@ -1012,7 +1028,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", up->username);
+ setenv_str (session->opt->es, "username", (raw_username ? raw_username : up->username));
setenv_str (session->opt->es, "password", up->password);
/* setenv incoming cert common name for script */
@@ -1036,6 +1052,8 @@ verify_user_pass_plugin (struct tls_session *session, const struct user_pass *up
#endif
setenv_del (session->opt->es, "password");
+ if (raw_username)
+ setenv_str (session->opt->es, "username", up->username);
}
else
{
@@ -1056,7 +1074,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)
+verify_user_pass_management (struct tls_session *session, const struct user_pass *up, const char *raw_username)
{
int retval = KMDA_ERROR;
struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */
@@ -1065,7 +1083,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", up->username);
+ setenv_str (session->opt->es, "username", (raw_username ? raw_username : up->username));
setenv_str (session->opt->es, "password", up->password);
/* setenv incoming cert common name for script */
@@ -1078,6 +1096,8 @@ 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");
+ if (raw_username)
+ setenv_str (session->opt->es, "username", up->username);
retval = KMDA_SUCCESS;
}
@@ -1101,6 +1121,9 @@ 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 = NULL;
+
#ifdef MANAGEMENT_DEF_AUTH
int man_def_auth = KMDA_UNDEF;
@@ -1108,17 +1131,28 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
man_def_auth = KMDA_DEF;
#endif
+ /*
+ * Preserve the raw username before string_mod remapping, for plugins
+ * and management clients when in --compat-names mode
+ */
+ if (compat_flag (COMPAT_FLAG_QUERY | COMPAT_NAMES))
+ {
+ 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 (up->username, CC_PRINT, CC_CRLF, '_');
+ string_mod_remap_name (up->username, COMMON_NAME_CHAR_CLASS);
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);
+ man_def_auth = verify_user_pass_management (session, up, raw_username);
#endif
if (plugin_defined (session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY))
- s1 = verify_user_pass_plugin (session, up);
+ s1 = verify_user_pass_plugin (session, up, raw_username);
if (session->opt->auth_user_pass_verify_script)
s2 = verify_user_pass_script (session, up);
@@ -1167,6 +1201,8 @@ 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