diff options
Diffstat (limited to 'openvpn/src/openvpn')
-rw-r--r-- | openvpn/src/openvpn/misc.c | 21 | ||||
-rw-r--r-- | openvpn/src/openvpn/misc.h | 6 | ||||
-rw-r--r-- | openvpn/src/openvpn/openvpn.h | 2 | ||||
-rw-r--r-- | openvpn/src/openvpn/options.c | 12 | ||||
-rw-r--r-- | openvpn/src/openvpn/push.c | 7 | ||||
-rw-r--r-- | openvpn/src/openvpn/ssl_verify.c | 54 | ||||
-rw-r--r-- | openvpn/src/openvpn/ssl_verify_openssl.c | 12 | ||||
-rw-r--r-- | openvpn/src/openvpn/tun.c | 2 |
8 files changed, 102 insertions, 14 deletions
diff --git a/openvpn/src/openvpn/misc.c b/openvpn/src/openvpn/misc.c index 7f729390..d2882d81 100644 --- a/openvpn/src/openvpn/misc.c +++ b/openvpn/src/openvpn/misc.c @@ -2120,3 +2120,24 @@ sanitize_control_message(const char *src, struct gc_arena *gc) *dest = '\0'; return ret; } + +/** + * Will set or query for a global compat flag. To modify the compat flags + * the COMPAT_FLAG_SET must be bitwise ORed together with the flag to set. + * If no "operator" flag is given it defaults to COMPAT_FLAG_QUERY, + * which returns the flag state. + * + * @param flag Flag to be set/queried for bitwise ORed with the operator flag + * @return Returns 0 if the flag is not set, otherwise the 'flag' value is returned + */ +bool +compat_flag (unsigned int flag) +{ + static unsigned int compat_flags = 0; + + if (flag & COMPAT_FLAG_SET) + compat_flags |= (flag >> 1); + + return (compat_flags & (flag >> 1)); + +} diff --git a/openvpn/src/openvpn/misc.h b/openvpn/src/openvpn/misc.h index d4c8e33b..b6da3f4b 100644 --- a/openvpn/src/openvpn/misc.h +++ b/openvpn/src/openvpn/misc.h @@ -368,4 +368,10 @@ void argv_printf_cat (struct argv *a, const char *format, ...) #endif ; +#define COMPAT_FLAG_QUERY 0 /** compat_flags operator: Query for a flag */ +#define COMPAT_FLAG_SET (1<<0) /** compat_flags operator: Set a compat flag */ +#define COMPAT_NAMES (1<<1) /** compat flag: --compat-names set */ +#define COMPAT_NO_NAME_REMAPPING (1<<2) /** compat flag: --compat-names without char remapping */ +bool compat_flag (unsigned int flag); + #endif diff --git a/openvpn/src/openvpn/openvpn.h b/openvpn/src/openvpn/openvpn.h index 0732d0f8..7abfb087 100644 --- a/openvpn/src/openvpn/openvpn.h +++ b/openvpn/src/openvpn/openvpn.h @@ -448,7 +448,7 @@ struct context_2 /* --ifconfig endpoints to be pushed to client */ bool push_reply_deferred; bool push_ifconfig_defined; - bool sent_push_reply; + time_t sent_push_reply_expiry; in_addr_t push_ifconfig_local; in_addr_t push_ifconfig_remote_netmask; #ifdef ENABLE_CLIENT_NAT diff --git a/openvpn/src/openvpn/options.c b/openvpn/src/openvpn/options.c index 36fb4e30..47aaffcb 100644 --- a/openvpn/src/openvpn/options.c +++ b/openvpn/src/openvpn/options.c @@ -2132,6 +2132,9 @@ options_postprocess_verify_ce (const struct options *options, const struct conne if (options->stale_routes_check_interval) msg (M_USAGE, "--stale-routes-check requires --mode server"); + + if (compat_flag (COMPAT_FLAG_QUERY | COMPAT_NO_NAME_REMAPPING)) + msg (M_USAGE, "--compat-x509-names no-remapping requires --mode server"); } #endif /* P2MP_SERVER */ @@ -2248,7 +2251,7 @@ options_postprocess_verify_ce (const struct options *options, const struct conne const int sum = (options->cert_file != NULL) + #ifdef MANAGMENT_EXTERNAL_KEY ((options->priv_key_file != NULL) || (options->management_flags & MF_EXTERNAL_KEY)); -#else +#else (options->priv_key_file != NULL); #endif @@ -5550,6 +5553,13 @@ add_option (struct options *options, VERIFY_PERMISSION (OPT_P_GENERAL); options->ssl_flags |= SSLF_AUTH_USER_PASS_OPTIONAL; } + else if (streq (p[0], "compat-names")) + { + VERIFY_PERMISSION (OPT_P_GENERAL); + compat_flag (COMPAT_FLAG_SET | COMPAT_NAMES); + if (p[1] && streq (p[1], "no-remapping")) + compat_flag (COMPAT_FLAG_SET | COMPAT_NO_NAME_REMAPPING); + } else if (streq (p[0], "opt-verify")) { VERIFY_PERMISSION (OPT_P_GENERAL); diff --git a/openvpn/src/openvpn/push.c b/openvpn/src/openvpn/push.c index 8d7d23a5..05a38e0d 100644 --- a/openvpn/src/openvpn/push.c +++ b/openvpn/src/openvpn/push.c @@ -416,7 +416,10 @@ process_incoming_push_msg (struct context *c, } else if (!c->c2.push_reply_deferred && c->c2.context_auth == CAS_SUCCEEDED) { - if (c->c2.sent_push_reply) + time_t now; + + openvpn_time(&now); + if (c->c2.sent_push_reply_expiry > now) { ret = PUSH_MSG_ALREADY_REPLIED; } @@ -425,7 +428,7 @@ process_incoming_push_msg (struct context *c, if (send_push_reply (c)) { ret = PUSH_MSG_REQUEST; - c->c2.sent_push_reply = true; + c->c2.sent_push_reply_expiry = now + 30; } } } diff --git a/openvpn/src/openvpn/ssl_verify.c b/openvpn/src/openvpn/ssl_verify.c index 30fb05df..cac46e98 100644 --- a/openvpn/src/openvpn/ssl_verify.c +++ b/openvpn/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 diff --git a/openvpn/src/openvpn/ssl_verify_openssl.c b/openvpn/src/openvpn/ssl_verify_openssl.c index f5dce0dc..658f5f33 100644 --- a/openvpn/src/openvpn/ssl_verify_openssl.c +++ b/openvpn/src/openvpn/ssl_verify_openssl.c @@ -254,6 +254,18 @@ x509_get_subject (X509 *cert, struct gc_arena *gc) char *subject = NULL; int maxlen = 0; + /* + * Generate the subject string in OpenSSL proprietary format, + * when in --compat-names mode + */ + if (compat_flag (COMPAT_FLAG_QUERY | COMPAT_NAMES)) + { + subject = gc_malloc (256, false, gc); + X509_NAME_oneline (X509_get_subject_name (cert), subject, 256); + subject[255] = '\0'; + return subject; + } + subject_bio = BIO_new (BIO_s_mem ()); if (subject_bio == NULL) goto err; diff --git a/openvpn/src/openvpn/tun.c b/openvpn/src/openvpn/tun.c index cd61baf4..a56c997c 100644 --- a/openvpn/src/openvpn/tun.c +++ b/openvpn/src/openvpn/tun.c @@ -761,7 +761,7 @@ do_ifconfig (struct tuntap *tt, if ( do_ipv6 ) { argv_printf (&argv, - "%s %s inet6 add %s/%d", + "%s %s add %s/%d", IFCONFIG_PATH, actual, ifconfig_ipv6_local, |