diff options
author | Alberto Gonzalez Iniesta <agi@inittab.org> | 2016-12-27 18:25:47 +0100 |
---|---|---|
committer | Alberto Gonzalez Iniesta <agi@inittab.org> | 2016-12-27 18:25:47 +0100 |
commit | 79f3537f69e125f19f59c36aa090120a63186a54 (patch) | |
tree | 2089a3b7dac990841dbc2e4d9b2f535b82dbb0af /src/openvpn/ssl_verify.c | |
parent | f2137fedb30cb87448eb03b2f288920df6187571 (diff) | |
parent | 3a2bbdb05ca6a6996e424c9fb225cb0d53804125 (diff) |
Merge tag 'upstream/2.4.0'
Upstream version 2.4.0
Diffstat (limited to 'src/openvpn/ssl_verify.c')
-rw-r--r-- | src/openvpn/ssl_verify.c | 1789 |
1 files changed, 957 insertions, 832 deletions
diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c index 4328828..334eb29 100644 --- a/src/openvpn/ssl_verify.c +++ b/src/openvpn/ssl_verify.c @@ -5,8 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2010-2017 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -58,36 +58,40 @@ #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) +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, '_'); + 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 */ static void -setenv_untrusted (struct tls_session *session) +setenv_untrusted(struct tls_session *session) { - setenv_link_socket_actual (session->opt->es, "untrusted", &session->untrusted_addr, SA_IP_PORT); + setenv_link_socket_actual(session->opt->es, "untrusted", &session->untrusted_addr, SA_IP_PORT); } /* * Remove authenticated state from all sessions in the given tunnel */ static void -tls_deauthenticate (struct tls_multi *multi) +tls_deauthenticate(struct tls_multi *multi) { - if (multi) + if (multi) { - int i, j; - for (i = 0; i < TM_SIZE; ++i) - for (j = 0; j < KS_SIZE; ++j) - multi->session[i].key[j].authenticated = false; + int i, j; + for (i = 0; i < TM_SIZE; ++i) + for (j = 0; j < KS_SIZE; ++j) + multi->session[i].key[j].authenticated = false; } } @@ -95,28 +99,32 @@ tls_deauthenticate (struct tls_multi *multi) * Set the given session's common_name */ static void -set_common_name (struct tls_session *session, const char *common_name) +set_common_name(struct tls_session *session, const char *common_name) { - if (session->common_name) + if (session->common_name) { - free (session->common_name); - session->common_name = NULL; + free(session->common_name); + session->common_name = NULL; #ifdef ENABLE_PF - session->common_name_hashval = 0; + session->common_name_hashval = 0; #endif } - if (common_name) + if (common_name) { - /* FIXME: Last alloc will never be freed */ - session->common_name = string_alloc (common_name, NULL); + /* FIXME: Last alloc will never be freed */ + session->common_name = string_alloc(common_name, NULL); #ifdef ENABLE_PF - { - const uint32_t len = (uint32_t) strlen (common_name); - if (len) - session->common_name_hashval = hash_func ((const uint8_t*)common_name, len+1, 0); - else - session->common_name_hashval = 0; - } + { + const uint32_t len = (uint32_t) strlen(common_name); + if (len) + { + session->common_name_hashval = hash_func((const uint8_t *)common_name, len+1, 0); + } + else + { + session->common_name_hashval = 0; + } + } #endif } } @@ -127,174 +135,208 @@ set_common_name (struct tls_session *session, const char *common_name) * null is false. */ const char * -tls_common_name (const struct tls_multi *multi, const bool null) +tls_common_name(const struct tls_multi *multi, const bool null) { - const char *ret = NULL; - if (multi) - ret = multi->session[TM_ACTIVE].common_name; - if (ret && strlen (ret)) - return ret; - else if (null) - return NULL; - else - return "UNDEF"; + const char *ret = NULL; + if (multi) + { + ret = multi->session[TM_ACTIVE].common_name; + } + if (ret && strlen(ret)) + { + return ret; + } + else if (null) + { + return NULL; + } + else + { + return "UNDEF"; + } } /* * Lock the common name for the given tunnel. */ void -tls_lock_common_name (struct tls_multi *multi) +tls_lock_common_name(struct tls_multi *multi) { - const char *cn = multi->session[TM_ACTIVE].common_name; - if (cn && !multi->locked_cn) - multi->locked_cn = string_alloc (cn, NULL); + const char *cn = multi->session[TM_ACTIVE].common_name; + if (cn && !multi->locked_cn) + { + multi->locked_cn = string_alloc(cn, NULL); + } } /* * Lock the username for the given tunnel */ static bool -tls_lock_username (struct tls_multi *multi, const char *username) +tls_lock_username(struct tls_multi *multi, const char *username) { - if (multi->locked_username) + if (multi->locked_username) { - if (!username || strcmp (username, multi->locked_username)) - { - msg (D_TLS_ERRORS, "TLS Auth Error: username attempted to change from '%s' to '%s' -- tunnel disabled", - multi->locked_username, - np(username)); + if (!username || strcmp(username, multi->locked_username)) + { + msg(D_TLS_ERRORS, "TLS Auth Error: username attempted to change from '%s' to '%s' -- tunnel disabled", + multi->locked_username, + np(username)); - /* disable the tunnel */ - tls_deauthenticate (multi); - return false; - } + /* disable the tunnel */ + tls_deauthenticate(multi); + return false; + } } - else + else { - if (username) - multi->locked_username = string_alloc (username, NULL); + if (username) + { + multi->locked_username = string_alloc(username, NULL); + } } - return true; + return true; } const char * -tls_username (const struct tls_multi *multi, const bool null) +tls_username(const struct tls_multi *multi, const bool null) { - const char *ret = NULL; - if (multi) - ret = multi->locked_username; - if (ret && strlen (ret)) - return ret; - else if (null) - return NULL; - else - return "UNDEF"; + const char *ret = NULL; + if (multi) + { + ret = multi->locked_username; + } + if (ret && strlen(ret)) + { + return ret; + } + else if (null) + { + return NULL; + } + else + { + return "UNDEF"; + } } void -cert_hash_remember (struct tls_session *session, const int error_depth, - const struct buffer *cert_hash) +cert_hash_remember(struct tls_session *session, const int error_depth, + const struct buffer *cert_hash) { - if (error_depth >= 0 && error_depth < MAX_CERT_DEPTH) + if (error_depth >= 0 && error_depth < MAX_CERT_DEPTH) { - if (!session->cert_hash_set) - { - ALLOC_OBJ_CLEAR (session->cert_hash_set, struct cert_hash_set); - } - if (!session->cert_hash_set->ch[error_depth]) - { - ALLOC_OBJ (session->cert_hash_set->ch[error_depth], struct cert_hash); - } + if (!session->cert_hash_set) + { + ALLOC_OBJ_CLEAR(session->cert_hash_set, struct cert_hash_set); + } + if (!session->cert_hash_set->ch[error_depth]) + { + ALLOC_OBJ(session->cert_hash_set->ch[error_depth], struct cert_hash); + } - struct cert_hash *ch = session->cert_hash_set->ch[error_depth]; - ASSERT (sizeof (ch->sha256_hash) == BLEN (cert_hash)); - memcpy (ch->sha256_hash, BPTR (cert_hash), sizeof (ch->sha256_hash)); + struct cert_hash *ch = session->cert_hash_set->ch[error_depth]; + ASSERT(sizeof(ch->sha256_hash) == BLEN(cert_hash)); + memcpy(ch->sha256_hash, BPTR(cert_hash), sizeof(ch->sha256_hash)); } } void -cert_hash_free (struct cert_hash_set *chs) +cert_hash_free(struct cert_hash_set *chs) { - if (chs) + if (chs) { - int i; - for (i = 0; i < MAX_CERT_DEPTH; ++i) - free (chs->ch[i]); - free (chs); + int i; + for (i = 0; i < MAX_CERT_DEPTH; ++i) + free(chs->ch[i]); + free(chs); } } bool -cert_hash_compare (const struct cert_hash_set *chs1, const struct cert_hash_set *chs2) +cert_hash_compare(const struct cert_hash_set *chs1, const struct cert_hash_set *chs2) { - if (chs1 && chs2) - { - int i; - for (i = 0; i < MAX_CERT_DEPTH; ++i) - { - const struct cert_hash *ch1 = chs1->ch[i]; - const struct cert_hash *ch2 = chs2->ch[i]; - - if (!ch1 && !ch2) - continue; - else if (ch1 && ch2 && !memcmp (ch1->sha256_hash, ch2->sha256_hash, - sizeof(ch1->sha256_hash))) - continue; - else - return false; - } - return true; - } - else if (!chs1 && !chs2) - return true; - else - return false; + if (chs1 && chs2) + { + int i; + for (i = 0; i < MAX_CERT_DEPTH; ++i) + { + const struct cert_hash *ch1 = chs1->ch[i]; + const struct cert_hash *ch2 = chs2->ch[i]; + + if (!ch1 && !ch2) + { + continue; + } + else if (ch1 && ch2 && !memcmp(ch1->sha256_hash, ch2->sha256_hash, + sizeof(ch1->sha256_hash))) + { + continue; + } + else + { + return false; + } + } + return true; + } + else if (!chs1 && !chs2) + { + return true; + } + else + { + return false; + } } static struct cert_hash_set * -cert_hash_copy (const struct cert_hash_set *chs) +cert_hash_copy(const struct cert_hash_set *chs) { - struct cert_hash_set *dest = NULL; - if (chs) - { - int i; - ALLOC_OBJ_CLEAR (dest, struct cert_hash_set); - for (i = 0; i < MAX_CERT_DEPTH; ++i) - { - const struct cert_hash *ch = chs->ch[i]; - if (ch) - { - ALLOC_OBJ (dest->ch[i], struct cert_hash); - memcpy (dest->ch[i]->sha256_hash, ch->sha256_hash, - sizeof(dest->ch[i]->sha256_hash)); - } - } - } - return dest; + struct cert_hash_set *dest = NULL; + if (chs) + { + int i; + ALLOC_OBJ_CLEAR(dest, struct cert_hash_set); + for (i = 0; i < MAX_CERT_DEPTH; ++i) + { + const struct cert_hash *ch = chs->ch[i]; + if (ch) + { + ALLOC_OBJ(dest->ch[i], struct cert_hash); + memcpy(dest->ch[i]->sha256_hash, ch->sha256_hash, + sizeof(dest->ch[i]->sha256_hash)); + } + } + } + return dest; } void -tls_lock_cert_hash_set (struct tls_multi *multi) +tls_lock_cert_hash_set(struct tls_multi *multi) { - const struct cert_hash_set *chs = multi->session[TM_ACTIVE].cert_hash_set; - if (chs && !multi->locked_cert_hash_set) - multi->locked_cert_hash_set = cert_hash_copy (chs); + const struct cert_hash_set *chs = multi->session[TM_ACTIVE].cert_hash_set; + if (chs && !multi->locked_cert_hash_set) + { + multi->locked_cert_hash_set = cert_hash_copy(chs); + } } /* * Returns the string associated with the given certificate type. */ static const char * -print_nsCertType (int type) +print_nsCertType(int type) { - switch (type) + switch (type) { - case NS_CERT_CHECK_SERVER: - return "SERVER"; - case NS_CERT_CHECK_CLIENT: - return "CLIENT"; - default: - return "?"; + case NS_CERT_CHECK_SERVER: + return "SERVER"; + + case NS_CERT_CHECK_CLIENT: + return "CLIENT"; + + default: + return "?"; } } @@ -308,72 +350,74 @@ print_nsCertType (int type) */ static result_t verify_peer_cert(const struct tls_options *opt, openvpn_x509_cert_t *peer_cert, - const char *subject, const char *common_name) + const char *subject, const char *common_name) { - /* verify certificate nsCertType */ - if (opt->ns_cert_type != NS_CERT_CHECK_NONE) - { - if (SUCCESS == x509_verify_ns_cert_type (peer_cert, opt->ns_cert_type)) - { - msg (D_HANDSHAKE, "VERIFY OK: nsCertType=%s", - print_nsCertType (opt->ns_cert_type)); - } - else - { - msg (D_HANDSHAKE, "VERIFY nsCertType ERROR: %s, require nsCertType=%s", - subject, print_nsCertType (opt->ns_cert_type)); - return FAILURE; /* Reject connection */ - } - } - - /* verify certificate ku */ - if (opt->remote_cert_ku[0] != 0) - { - if (SUCCESS == x509_verify_cert_ku (peer_cert, opt->remote_cert_ku, MAX_PARMS)) - { - msg (D_HANDSHAKE, "VERIFY KU OK"); - } + /* verify certificate nsCertType */ + if (opt->ns_cert_type != NS_CERT_CHECK_NONE) + { + if (SUCCESS == x509_verify_ns_cert_type(peer_cert, opt->ns_cert_type)) + { + msg(D_HANDSHAKE, "VERIFY OK: nsCertType=%s", + print_nsCertType(opt->ns_cert_type)); + } else { - msg (D_HANDSHAKE, "VERIFY KU ERROR"); - return FAILURE; /* Reject connection */ - } + msg(D_HANDSHAKE, "VERIFY nsCertType ERROR: %s, require nsCertType=%s", + subject, print_nsCertType(opt->ns_cert_type)); + return FAILURE; /* Reject connection */ + } + } + + /* verify certificate ku */ + if (opt->remote_cert_ku[0] != 0) + { + if (SUCCESS == x509_verify_cert_ku(peer_cert, opt->remote_cert_ku, MAX_PARMS)) + { + msg(D_HANDSHAKE, "VERIFY KU OK"); + } + else + { + msg(D_HANDSHAKE, "VERIFY KU ERROR"); + return FAILURE; /* Reject connection */ + } + } + + /* verify certificate eku */ + if (opt->remote_cert_eku != NULL) + { + if (SUCCESS == x509_verify_cert_eku(peer_cert, opt->remote_cert_eku)) + { + msg(D_HANDSHAKE, "VERIFY EKU OK"); + } + else + { + msg(D_HANDSHAKE, "VERIFY EKU ERROR"); + return FAILURE; /* Reject connection */ + } } - /* verify certificate eku */ - if (opt->remote_cert_eku != NULL) + /* verify X509 name or username against --verify-x509-[user]name */ + if (opt->verify_x509_type != VERIFY_X509_NONE) { - if (SUCCESS == x509_verify_cert_eku (peer_cert, opt->remote_cert_eku)) + if ( (opt->verify_x509_type == VERIFY_X509_SUBJECT_DN + && strcmp(opt->verify_x509_name, subject) == 0) + || (opt->verify_x509_type == VERIFY_X509_SUBJECT_RDN + && strcmp(opt->verify_x509_name, common_name) == 0) + || (opt->verify_x509_type == VERIFY_X509_SUBJECT_RDN_PREFIX + && strncmp(opt->verify_x509_name, common_name, + strlen(opt->verify_x509_name)) == 0) ) { - msg (D_HANDSHAKE, "VERIFY EKU OK"); - } - else - { - msg (D_HANDSHAKE, "VERIFY EKU ERROR"); - return FAILURE; /* Reject connection */ - } - } - - /* verify X509 name or username against --verify-x509-[user]name */ - if (opt->verify_x509_type != VERIFY_X509_NONE) - { - if ( (opt->verify_x509_type == VERIFY_X509_SUBJECT_DN - && strcmp (opt->verify_x509_name, subject) == 0) - || (opt->verify_x509_type == VERIFY_X509_SUBJECT_RDN - && strcmp (opt->verify_x509_name, common_name) == 0) - || (opt->verify_x509_type == VERIFY_X509_SUBJECT_RDN_PREFIX - && strncmp (opt->verify_x509_name, common_name, - strlen (opt->verify_x509_name)) == 0) ) - msg (D_HANDSHAKE, "VERIFY X509NAME OK: %s", subject); - else - { - msg (D_HANDSHAKE, "VERIFY X509NAME ERROR: %s, must be %s", - subject, opt->verify_x509_name); - return FAILURE; /* Reject connection */ - } - } - - return SUCCESS; + msg(D_HANDSHAKE, "VERIFY X509NAME OK: %s", subject); + } + else + { + msg(D_HANDSHAKE, "VERIFY X509NAME ERROR: %s, must be %s", + subject, opt->verify_x509_name); + return FAILURE; /* Reject connection */ + } + } + + return SUCCESS; } /* @@ -382,55 +426,59 @@ verify_peer_cert(const struct tls_options *opt, openvpn_x509_cert_t *peer_cert, */ static void verify_cert_set_env(struct env_set *es, openvpn_x509_cert_t *peer_cert, int cert_depth, - const char *subject, const char *common_name, - const struct x509_track *x509_track) + const char *subject, const char *common_name, + const struct x509_track *x509_track) { - char envname[64]; - char *serial = NULL; - struct gc_arena gc = gc_new (); + char envname[64]; + char *serial = NULL; + struct gc_arena gc = gc_new(); - /* Save X509 fields in environment */ - if (x509_track) - x509_setenv_track (x509_track, es, cert_depth, peer_cert); - else - x509_setenv (es, cert_depth, peer_cert); + /* Save X509 fields in environment */ + if (x509_track) + { + x509_setenv_track(x509_track, es, cert_depth, peer_cert); + } + else + { + x509_setenv(es, cert_depth, peer_cert); + } - /* export subject name string as environmental variable */ - openvpn_snprintf (envname, sizeof(envname), "tls_id_%d", cert_depth); - setenv_str (es, envname, subject); + /* export subject name string as environmental variable */ + openvpn_snprintf(envname, sizeof(envname), "tls_id_%d", cert_depth); + setenv_str(es, envname, subject); #if 0 - /* export common name string as environmental variable */ - openvpn_snprintf (envname, sizeof(envname), "tls_common_name_%d", cert_depth); - setenv_str (es, envname, common_name); + /* export common name string as environmental variable */ + openvpn_snprintf(envname, sizeof(envname), "tls_common_name_%d", cert_depth); + setenv_str(es, envname, common_name); #endif - /* export X509 cert fingerprints */ - { - struct buffer sha1 = x509_get_sha1_fingerprint(peer_cert, &gc); - struct buffer sha256 = x509_get_sha256_fingerprint(peer_cert, &gc); + /* export X509 cert fingerprints */ + { + struct buffer sha1 = x509_get_sha1_fingerprint(peer_cert, &gc); + struct buffer sha256 = x509_get_sha256_fingerprint(peer_cert, &gc); - openvpn_snprintf (envname, sizeof(envname), "tls_digest_%d", cert_depth); - setenv_str (es, envname, - format_hex_ex(BPTR(&sha1), BLEN(&sha1), 0, 1, ":", &gc)); + openvpn_snprintf(envname, sizeof(envname), "tls_digest_%d", cert_depth); + setenv_str(es, envname, + format_hex_ex(BPTR(&sha1), BLEN(&sha1), 0, 1, ":", &gc)); - openvpn_snprintf (envname, sizeof(envname), "tls_digest_sha256_%d", - cert_depth); - setenv_str (es, envname, - format_hex_ex(BPTR(&sha256), BLEN(&sha256), 0, 1, ":", &gc)); - } + openvpn_snprintf(envname, sizeof(envname), "tls_digest_sha256_%d", + cert_depth); + setenv_str(es, envname, + format_hex_ex(BPTR(&sha256), BLEN(&sha256), 0, 1, ":", &gc)); + } - /* export serial number as environmental variable */ - serial = backend_x509_get_serial(peer_cert, &gc); - openvpn_snprintf (envname, sizeof(envname), "tls_serial_%d", cert_depth); - setenv_str (es, envname, serial); + /* export serial number as environmental variable */ + serial = backend_x509_get_serial(peer_cert, &gc); + openvpn_snprintf(envname, sizeof(envname), "tls_serial_%d", cert_depth); + setenv_str(es, envname, serial); - /* export serial number in hex as environmental variable */ - serial = backend_x509_get_serial_hex(peer_cert, &gc); - openvpn_snprintf (envname, sizeof(envname), "tls_serial_hex_%d", cert_depth); - setenv_str (es, envname, serial); + /* export serial number in hex as environmental variable */ + serial = backend_x509_get_serial_hex(peer_cert, &gc); + openvpn_snprintf(envname, sizeof(envname), "tls_serial_hex_%d", cert_depth); + setenv_str(es, envname, serial); - gc_free(&gc); + gc_free(&gc); } /* @@ -438,59 +486,63 @@ verify_cert_set_env(struct env_set *es, openvpn_x509_cert_t *peer_cert, int cert */ static result_t verify_cert_call_plugin(const struct plugin_list *plugins, struct env_set *es, - int cert_depth, openvpn_x509_cert_t *cert, char *subject) + int cert_depth, openvpn_x509_cert_t *cert, char *subject) { - if (plugin_defined (plugins, OPENVPN_PLUGIN_TLS_VERIFY)) + if (plugin_defined(plugins, OPENVPN_PLUGIN_TLS_VERIFY)) { - int ret; - struct argv argv = argv_new (); + int ret; + struct argv argv = argv_new(); - argv_printf (&argv, "%d %s", cert_depth, subject); + argv_printf(&argv, "%d %s", cert_depth, subject); - ret = plugin_call_ssl (plugins, OPENVPN_PLUGIN_TLS_VERIFY, &argv, NULL, es, cert_depth, cert); + ret = plugin_call_ssl(plugins, OPENVPN_PLUGIN_TLS_VERIFY, &argv, NULL, es, cert_depth, cert); - argv_reset (&argv); + argv_reset(&argv); - if (ret == OPENVPN_PLUGIN_FUNC_SUCCESS) - { - msg (D_HANDSHAKE, "VERIFY PLUGIN OK: depth=%d, %s", - cert_depth, subject); - } - else - { - msg (D_HANDSHAKE, "VERIFY PLUGIN ERROR: depth=%d, %s", - cert_depth, subject); - return FAILURE; /* Reject connection */ - } + if (ret == OPENVPN_PLUGIN_FUNC_SUCCESS) + { + msg(D_HANDSHAKE, "VERIFY PLUGIN OK: depth=%d, %s", + cert_depth, subject); + } + else + { + msg(D_HANDSHAKE, "VERIFY PLUGIN ERROR: depth=%d, %s", + cert_depth, subject); + return FAILURE; /* Reject connection */ + } } - return SUCCESS; + return SUCCESS; } static const char * verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, struct gc_arena *gc) { - FILE *peercert_file; - const char *peercert_filename=""; + FILE *peercert_file; + const char *peercert_filename = ""; - if(!tmp_dir) - return NULL; + if (!tmp_dir) + { + return NULL; + } - /* create tmp file to store peer cert */ - peercert_filename = create_temp_file (tmp_dir, "pcf", gc); + /* create tmp file to store peer cert */ + peercert_filename = create_temp_file(tmp_dir, "pcf", gc); - /* write peer-cert in tmp-file */ - peercert_file = fopen(peercert_filename, "w+"); - if(!peercert_file) + /* write peer-cert in tmp-file */ + peercert_file = fopen(peercert_filename, "w+"); + if (!peercert_file) { - msg (M_ERR, "Failed to open temporary file : %s", peercert_filename); - return NULL; + msg(M_ERR, "Failed to open temporary file : %s", peercert_filename); + return NULL; } - if (SUCCESS != x509_write_pem(peercert_file, peercert)) - msg (M_ERR, "Error writing PEM file containing certificate"); + if (SUCCESS != x509_write_pem(peercert_file, peercert)) + { + msg(M_ERR, "Error writing PEM file containing certificate"); + } - fclose(peercert_file); - return peercert_filename; + fclose(peercert_file); + return peercert_filename; } @@ -499,48 +551,50 @@ verify_cert_export_cert(openvpn_x509_cert_t *peercert, const char *tmp_dir, stru */ static result_t verify_cert_call_command(const char *verify_command, struct env_set *es, - int cert_depth, openvpn_x509_cert_t *cert, char *subject, const char *verify_export_cert) + int cert_depth, openvpn_x509_cert_t *cert, char *subject, const char *verify_export_cert) { - const char *tmp_file = NULL; - int ret; - struct gc_arena gc = gc_new(); - struct argv argv = argv_new (); + const char *tmp_file = NULL; + int ret; + struct gc_arena gc = gc_new(); + struct argv argv = argv_new(); - setenv_str (es, "script_type", "tls-verify"); + setenv_str(es, "script_type", "tls-verify"); - if (verify_export_cert) + if (verify_export_cert) { - if ((tmp_file=verify_cert_export_cert(cert, verify_export_cert, &gc))) - { - setenv_str(es, "peer_cert", tmp_file); - } + if ((tmp_file = verify_cert_export_cert(cert, verify_export_cert, &gc))) + { + setenv_str(es, "peer_cert", tmp_file); + } } - argv_parse_cmd (&argv, verify_command); - argv_printf_cat (&argv, "%d %s", cert_depth, subject); + argv_parse_cmd(&argv, verify_command); + argv_printf_cat(&argv, "%d %s", cert_depth, subject); - argv_msg_prefix (D_TLS_DEBUG, &argv, "TLS: executing verify command"); - ret = openvpn_run_script (&argv, es, 0, "--tls-verify script"); + argv_msg_prefix(D_TLS_DEBUG, &argv, "TLS: executing verify command"); + ret = openvpn_run_script(&argv, es, 0, "--tls-verify script"); - if (verify_export_cert) + if (verify_export_cert) { - if (tmp_file) - platform_unlink(tmp_file); + if (tmp_file) + { + platform_unlink(tmp_file); + } } - gc_free(&gc); - argv_reset (&argv); + gc_free(&gc); + argv_reset(&argv); - if (ret) + if (ret) { - msg (D_HANDSHAKE, "VERIFY SCRIPT OK: depth=%d, %s", - cert_depth, subject); - return SUCCESS; + msg(D_HANDSHAKE, "VERIFY SCRIPT OK: depth=%d, %s", + cert_depth, subject); + return SUCCESS; } - msg (D_HANDSHAKE, "VERIFY SCRIPT ERROR: depth=%d, %s", - cert_depth, subject); - return FAILURE; /* Reject connection */ + msg(D_HANDSHAKE, "VERIFY SCRIPT ERROR: depth=%d, %s", + cert_depth, subject); + return FAILURE; /* Reject connection */ } /* @@ -549,167 +603,179 @@ verify_cert_call_command(const char *verify_command, struct env_set *es, static result_t verify_check_crl_dir(const char *crl_dir, openvpn_x509_cert_t *cert) { - result_t ret = FAILURE; - char fn[256]; - int fd = -1; - struct gc_arena gc = gc_new(); + result_t ret = FAILURE; + char fn[256]; + int fd = -1; + struct gc_arena gc = gc_new(); - char *serial = backend_x509_get_serial(cert, &gc); + char *serial = backend_x509_get_serial(cert, &gc); - if (!openvpn_snprintf(fn, sizeof(fn), "%s%c%s", crl_dir, OS_SPECIFIC_DIRSEP, serial)) + if (!openvpn_snprintf(fn, sizeof(fn), "%s%c%s", crl_dir, OS_SPECIFIC_DIRSEP, serial)) { - msg (D_HANDSHAKE, "VERIFY CRL: filename overflow"); - goto cleanup; + msg(D_HANDSHAKE, "VERIFY CRL: filename overflow"); + goto cleanup; } - fd = platform_open (fn, O_RDONLY, 0); - if (fd >= 0) + fd = platform_open(fn, O_RDONLY, 0); + if (fd >= 0) { - msg (D_HANDSHAKE, "VERIFY CRL: certificate serial number %s is revoked", serial); - goto cleanup; + msg(D_HANDSHAKE, "VERIFY CRL: certificate serial number %s is revoked", serial); + goto cleanup; } - ret = SUCCESS; + ret = SUCCESS; cleanup: - if (fd != -1) - close(fd); - gc_free(&gc); - return ret; + if (fd != -1) + { + close(fd); + } + gc_free(&gc); + return ret; } result_t verify_cert(struct tls_session *session, openvpn_x509_cert_t *cert, int cert_depth) { - result_t ret = FAILURE; - char *subject = NULL; - char common_name[TLS_USERNAME_LEN+1] = {0}; /* null-terminated */ - const struct tls_options *opt; - struct gc_arena gc = gc_new(); + result_t ret = FAILURE; + char *subject = NULL; + char common_name[TLS_USERNAME_LEN+1] = {0}; /* null-terminated */ + const struct tls_options *opt; + struct gc_arena gc = gc_new(); - opt = session->opt; - ASSERT (opt); + opt = session->opt; + ASSERT(opt); - session->verified = false; + session->verified = false; - /* get the X509 name */ - subject = x509_get_subject(cert, &gc); - if (!subject) + /* get the X509 name */ + subject = x509_get_subject(cert, &gc); + if (!subject) { - msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, could not extract X509 " - "subject string from certificate", cert_depth); - goto cleanup; + msg(D_TLS_ERRORS, "VERIFY ERROR: depth=%d, could not extract X509 " + "subject string from certificate", cert_depth); + goto cleanup; } - /* enforce character class restrictions in X509 name */ - string_mod_remap_name (subject, X509_NAME_CHAR_CLASS); - string_replace_leading (subject, '-', '_'); + /* enforce character class restrictions in X509 name */ + string_mod_remap_name(subject, X509_NAME_CHAR_CLASS); + string_replace_leading(subject, '-', '_'); - /* extract the username (default is CN) */ - if (SUCCESS != backend_x509_get_username (common_name, sizeof(common_name), - opt->x509_username_field, cert)) + /* extract the username (default is CN) */ + if (SUCCESS != backend_x509_get_username(common_name, sizeof(common_name), + opt->x509_username_field, cert)) { - if (!cert_depth) - { - msg (D_TLS_ERRORS, "VERIFY ERROR: could not extract %s from X509 " - "subject string ('%s') -- note that the username length is " - "limited to %d characters", - opt->x509_username_field, - subject, - TLS_USERNAME_LEN); - goto cleanup; - } + if (!cert_depth) + { + msg(D_TLS_ERRORS, "VERIFY ERROR: could not extract %s from X509 " + "subject string ('%s') -- note that the username length is " + "limited to %d characters", + opt->x509_username_field, + subject, + TLS_USERNAME_LEN); + goto cleanup; + } } - /* enforce character class restrictions in common name */ - string_mod_remap_name (common_name, COMMON_NAME_CHAR_CLASS); + /* enforce character class restrictions in common name */ + string_mod_remap_name(common_name, COMMON_NAME_CHAR_CLASS); - /* warn if cert chain is too deep */ - if (cert_depth >= MAX_CERT_DEPTH) + /* warn if cert chain is too deep */ + if (cert_depth >= MAX_CERT_DEPTH) { - msg (D_TLS_ERRORS, "TLS Error: Convoluted certificate chain detected with depth [%d] greater than %d", cert_depth, MAX_CERT_DEPTH); - goto cleanup; /* Reject connection */ + msg(D_TLS_ERRORS, "TLS Error: Convoluted certificate chain detected with depth [%d] greater than %d", cert_depth, MAX_CERT_DEPTH); + goto cleanup; /* Reject connection */ } - /* verify level 1 cert, i.e. the CA that signed our leaf cert */ - if (cert_depth == 1 && opt->verify_hash) + /* verify level 1 cert, i.e. the CA that signed our leaf cert */ + if (cert_depth == 1 && opt->verify_hash) { - struct buffer sha1_hash = x509_get_sha1_fingerprint(cert, &gc); - if (memcmp (BPTR (&sha1_hash), opt->verify_hash, BLEN(&sha1_hash))) - { - msg (D_TLS_ERRORS, "TLS Error: level-1 certificate hash verification failed"); - goto cleanup; - } + struct buffer sha1_hash = x509_get_sha1_fingerprint(cert, &gc); + if (memcmp(BPTR(&sha1_hash), opt->verify_hash, BLEN(&sha1_hash))) + { + msg(D_TLS_ERRORS, "TLS Error: level-1 certificate hash verification failed"); + goto cleanup; + } } - /* save common name in session object */ - if (cert_depth == 0) - set_common_name (session, common_name); + /* save common name in session object */ + if (cert_depth == 0) + { + set_common_name(session, common_name); + } - session->verify_maxlevel = max_int (session->verify_maxlevel, cert_depth); + session->verify_maxlevel = max_int(session->verify_maxlevel, cert_depth); - /* export certificate values to the environment */ - verify_cert_set_env(opt->es, cert, cert_depth, subject, common_name, - opt->x509_track); + /* export certificate values to the environment */ + verify_cert_set_env(opt->es, cert, cert_depth, subject, common_name, + opt->x509_track); - /* export current untrusted IP */ - setenv_untrusted (session); + /* export current untrusted IP */ + setenv_untrusted(session); - /* If this is the peer's own certificate, verify it */ - if (cert_depth == 0 && SUCCESS != verify_peer_cert(opt, cert, subject, common_name)) - goto cleanup; + /* If this is the peer's own certificate, verify it */ + if (cert_depth == 0 && SUCCESS != verify_peer_cert(opt, cert, subject, common_name)) + { + goto cleanup; + } - /* call --tls-verify plug-in(s), if registered */ - if (SUCCESS != verify_cert_call_plugin(opt->plugins, opt->es, cert_depth, cert, subject)) - goto cleanup; + /* call --tls-verify plug-in(s), if registered */ + if (SUCCESS != verify_cert_call_plugin(opt->plugins, opt->es, cert_depth, cert, subject)) + { + goto cleanup; + } - /* run --tls-verify script */ - if (opt->verify_command && SUCCESS != verify_cert_call_command(opt->verify_command, - opt->es, cert_depth, cert, subject, opt->verify_export_cert)) - goto cleanup; + /* run --tls-verify script */ + if (opt->verify_command && SUCCESS != verify_cert_call_command(opt->verify_command, + opt->es, cert_depth, cert, subject, opt->verify_export_cert)) + { + goto cleanup; + } - /* check peer cert against CRL */ - if (opt->crl_file) + /* check peer cert against CRL */ + if (opt->crl_file) { - if (opt->ssl_flags & SSLF_CRL_VERIFY_DIR) - { - if (SUCCESS != verify_check_crl_dir(opt->crl_file, cert)) - goto cleanup; - } - else - { - if (tls_verify_crl_missing (opt)) - { - msg (D_TLS_ERRORS, "VERIFY ERROR: CRL not loaded"); - goto cleanup; - } - } + if (opt->ssl_flags & SSLF_CRL_VERIFY_DIR) + { + if (SUCCESS != verify_check_crl_dir(opt->crl_file, cert)) + { + goto cleanup; + } + } + else + { + if (tls_verify_crl_missing(opt)) + { + msg(D_TLS_ERRORS, "VERIFY ERROR: CRL not loaded"); + goto cleanup; + } + } } - msg (D_HANDSHAKE, "VERIFY OK: depth=%d, %s", cert_depth, subject); - session->verified = true; - ret = SUCCESS; + msg(D_HANDSHAKE, "VERIFY OK: depth=%d, %s", cert_depth, subject); + session->verified = true; + ret = SUCCESS; cleanup: - if (ret != SUCCESS) + if (ret != SUCCESS) { - tls_clear_error(); /* always? */ - session->verified = false; /* double sure? */ + tls_clear_error(); /* always? */ + session->verified = false; /* double sure? */ } - gc_free(&gc); + gc_free(&gc); - return ret; + return ret; } /* *************************************************************************** - * Functions for the management of deferred authentication when using - * user/password authentication. - *************************************************************************** */ +* Functions for the management of deferred authentication when using +* user/password authentication. +*************************************************************************** */ #ifdef ENABLE_DEF_AUTH /* key_state_test_auth_control_file return values, - NOTE: acf_merge indexing depends on these values */ + * NOTE: acf_merge indexing depends on these values */ #define ACF_UNDEFINED 0 #define ACF_SUCCEEDED 1 #define ACF_DISABLED 2 @@ -718,27 +784,33 @@ cleanup: #ifdef MANAGEMENT_DEF_AUTH void -man_def_auth_set_client_reason (struct tls_multi *multi, const char *client_reason) +man_def_auth_set_client_reason(struct tls_multi *multi, const char *client_reason) { - if (multi->client_reason) + if (multi->client_reason) + { + free(multi->client_reason); + multi->client_reason = NULL; + } + if (client_reason && strlen(client_reason)) { - free (multi->client_reason); - multi->client_reason = NULL; + /* FIXME: Last alloc will never be freed */ + multi->client_reason = string_alloc(client_reason, NULL); } - if (client_reason && strlen (client_reason)) - /* FIXME: Last alloc will never be freed */ - multi->client_reason = string_alloc (client_reason, NULL); } static inline unsigned int -man_def_auth_test (const struct key_state *ks) +man_def_auth_test(const struct key_state *ks) { - if (management_enable_def_auth (management)) - return ks->mda_status; - else - return ACF_DISABLED; + if (management_enable_def_auth(management)) + { + return ks->mda_status; + } + else + { + return ACF_DISABLED; + } } -#endif +#endif /* ifdef MANAGEMENT_DEF_AUTH */ #ifdef PLUGIN_DEF_AUTH @@ -747,58 +819,63 @@ man_def_auth_test (const struct key_state *ks) */ void -key_state_rm_auth_control_file (struct key_state *ks) +key_state_rm_auth_control_file(struct key_state *ks) { - if (ks && ks->auth_control_file) + if (ks && ks->auth_control_file) { - platform_unlink (ks->auth_control_file); - free (ks->auth_control_file); - ks->auth_control_file = NULL; + platform_unlink(ks->auth_control_file); + free(ks->auth_control_file); + ks->auth_control_file = NULL; } } static void -key_state_gen_auth_control_file (struct key_state *ks, const struct tls_options *opt) +key_state_gen_auth_control_file(struct key_state *ks, const struct tls_options *opt) { - struct gc_arena gc = gc_new (); - const char *acf; + struct gc_arena gc = gc_new(); + const char *acf; - key_state_rm_auth_control_file (ks); - acf = create_temp_file (opt->tmp_dir, "acf", &gc); - if (acf) { - ks->auth_control_file = string_alloc (acf, NULL); - setenv_str (opt->es, "auth_control_file", ks->auth_control_file); - } /* FIXME: Should have better error handling? */ + key_state_rm_auth_control_file(ks); + acf = create_temp_file(opt->tmp_dir, "acf", &gc); + if (acf) + { + ks->auth_control_file = string_alloc(acf, NULL); + setenv_str(opt->es, "auth_control_file", ks->auth_control_file); + } /* FIXME: Should have better error handling? */ - gc_free (&gc); + gc_free(&gc); } static unsigned int -key_state_test_auth_control_file (struct key_state *ks) +key_state_test_auth_control_file(struct key_state *ks) { - if (ks && ks->auth_control_file) - { - unsigned int ret = ks->auth_control_status; - if (ret == ACF_UNDEFINED) - { - FILE *fp = fopen (ks->auth_control_file, "r"); - if (fp) - { - const int c = fgetc (fp); - if (c == '1') - ret = ACF_SUCCEEDED; - else if (c == '0') - ret = ACF_FAILED; - fclose (fp); - ks->auth_control_status = ret; - } - } - return ret; - } - return ACF_DISABLED; + if (ks && ks->auth_control_file) + { + unsigned int ret = ks->auth_control_status; + if (ret == ACF_UNDEFINED) + { + FILE *fp = fopen(ks->auth_control_file, "r"); + if (fp) + { + const int c = fgetc(fp); + if (c == '1') + { + ret = ACF_SUCCEEDED; + } + else if (c == '0') + { + ret = ACF_FAILED; + } + fclose(fp); + ks->auth_control_status = ret; + } + } + return ret; + } + return ACF_DISABLED; } -#endif +#endif /* ifdef PLUGIN_DEF_AUTH */ /* * Return current session authentication state. Return @@ -806,97 +883,110 @@ key_state_test_auth_control_file (struct key_state *ks) */ int -tls_authentication_status (struct tls_multi *multi, const int latency) +tls_authentication_status(struct tls_multi *multi, const int latency) { - bool deferred = false; - bool success = false; - bool active = false; + bool deferred = false; + bool success = false; + bool active = false; #ifdef ENABLE_DEF_AUTH - static const unsigned char acf_merge[] = - { - ACF_UNDEFINED, /* s1=ACF_UNDEFINED s2=ACF_UNDEFINED */ - ACF_UNDEFINED, /* s1=ACF_UNDEFINED s2=ACF_SUCCEEDED */ - ACF_UNDEFINED, /* s1=ACF_UNDEFINED s2=ACF_DISABLED */ - ACF_FAILED, /* s1=ACF_UNDEFINED s2=ACF_FAILED */ - ACF_UNDEFINED, /* s1=ACF_SUCCEEDED s2=ACF_UNDEFINED */ - ACF_SUCCEEDED, /* s1=ACF_SUCCEEDED s2=ACF_SUCCEEDED */ - ACF_SUCCEEDED, /* s1=ACF_SUCCEEDED s2=ACF_DISABLED */ - ACF_FAILED, /* s1=ACF_SUCCEEDED s2=ACF_FAILED */ - ACF_UNDEFINED, /* s1=ACF_DISABLED s2=ACF_UNDEFINED */ - ACF_SUCCEEDED, /* s1=ACF_DISABLED s2=ACF_SUCCEEDED */ - ACF_DISABLED, /* s1=ACF_DISABLED s2=ACF_DISABLED */ - ACF_FAILED, /* s1=ACF_DISABLED s2=ACF_FAILED */ - ACF_FAILED, /* s1=ACF_FAILED s2=ACF_UNDEFINED */ - ACF_FAILED, /* s1=ACF_FAILED s2=ACF_SUCCEEDED */ - ACF_FAILED, /* s1=ACF_FAILED s2=ACF_DISABLED */ - ACF_FAILED /* s1=ACF_FAILED s2=ACF_FAILED */ + static const unsigned char acf_merge[] = + { + ACF_UNDEFINED, /* s1=ACF_UNDEFINED s2=ACF_UNDEFINED */ + ACF_UNDEFINED, /* s1=ACF_UNDEFINED s2=ACF_SUCCEEDED */ + ACF_UNDEFINED, /* s1=ACF_UNDEFINED s2=ACF_DISABLED */ + ACF_FAILED, /* s1=ACF_UNDEFINED s2=ACF_FAILED */ + ACF_UNDEFINED, /* s1=ACF_SUCCEEDED s2=ACF_UNDEFINED */ + ACF_SUCCEEDED, /* s1=ACF_SUCCEEDED s2=ACF_SUCCEEDED */ + ACF_SUCCEEDED, /* s1=ACF_SUCCEEDED s2=ACF_DISABLED */ + ACF_FAILED, /* s1=ACF_SUCCEEDED s2=ACF_FAILED */ + ACF_UNDEFINED, /* s1=ACF_DISABLED s2=ACF_UNDEFINED */ + ACF_SUCCEEDED, /* s1=ACF_DISABLED s2=ACF_SUCCEEDED */ + ACF_DISABLED, /* s1=ACF_DISABLED s2=ACF_DISABLED */ + ACF_FAILED, /* s1=ACF_DISABLED s2=ACF_FAILED */ + ACF_FAILED, /* s1=ACF_FAILED s2=ACF_UNDEFINED */ + ACF_FAILED, /* s1=ACF_FAILED s2=ACF_SUCCEEDED */ + ACF_FAILED, /* s1=ACF_FAILED s2=ACF_DISABLED */ + ACF_FAILED /* s1=ACF_FAILED s2=ACF_FAILED */ }; #endif /* ENABLE_DEF_AUTH */ - if (multi) + if (multi) { - int i; + int i; #ifdef ENABLE_DEF_AUTH - if (latency && multi->tas_last && multi->tas_last + latency >= now) - return TLS_AUTHENTICATION_UNDEFINED; - multi->tas_last = now; + if (latency && multi->tas_last && multi->tas_last + latency >= now) + { + return TLS_AUTHENTICATION_UNDEFINED; + } + multi->tas_last = now; #endif /* ENABLE_DEF_AUTH */ - for (i = 0; i < KEY_SCAN_SIZE; ++i) - { - struct key_state *ks = multi->key_scan[i]; - if (DECRYPT_KEY_ENABLED (multi, ks)) - { - active = true; - if (ks->authenticated) - { + for (i = 0; i < KEY_SCAN_SIZE; ++i) + { + struct key_state *ks = multi->key_scan[i]; + if (DECRYPT_KEY_ENABLED(multi, ks)) + { + active = true; + if (ks->authenticated) + { #ifdef ENABLE_DEF_AUTH - unsigned int s1 = ACF_DISABLED; - unsigned int s2 = ACF_DISABLED; + unsigned int s1 = ACF_DISABLED; + unsigned int s2 = ACF_DISABLED; #ifdef PLUGIN_DEF_AUTH - s1 = key_state_test_auth_control_file (ks); + s1 = key_state_test_auth_control_file(ks); #endif /* PLUGIN_DEF_AUTH */ #ifdef MANAGEMENT_DEF_AUTH - s2 = man_def_auth_test (ks); + s2 = man_def_auth_test(ks); #endif /* MANAGEMENT_DEF_AUTH */ - ASSERT (s1 < 4 && s2 < 4); - switch (acf_merge[(s1<<2) + s2]) - { - case ACF_SUCCEEDED: - case ACF_DISABLED: - success = true; - ks->auth_deferred = false; - break; - case ACF_UNDEFINED: - if (now < ks->auth_deferred_expire) - deferred = true; - break; - case ACF_FAILED: - ks->authenticated = false; - break; - default: - ASSERT (0); - } + ASSERT(s1 < 4 && s2 < 4); + switch (acf_merge[(s1<<2) + s2]) + { + case ACF_SUCCEEDED: + case ACF_DISABLED: + success = true; + ks->auth_deferred = false; + break; + + case ACF_UNDEFINED: + if (now < ks->auth_deferred_expire) + { + deferred = true; + } + break; + + case ACF_FAILED: + ks->authenticated = false; + break; + + default: + ASSERT(0); + } #else /* !ENABLE_DEF_AUTH */ - success = true; + success = true; #endif /* ENABLE_DEF_AUTH */ - } - } - } + } + } + } } #if 0 - dmsg (D_TLS_ERRORS, "TAS: a=%d s=%d d=%d", active, success, deferred); + dmsg(D_TLS_ERRORS, "TAS: a=%d s=%d d=%d", active, success, deferred); #endif - if (success) - return TLS_AUTHENTICATION_SUCCEEDED; - else if (!active || deferred) - return TLS_AUTHENTICATION_DEFERRED; - else - return TLS_AUTHENTICATION_FAILED; + if (success) + { + return TLS_AUTHENTICATION_SUCCEEDED; + } + else if (!active || deferred) + { + return TLS_AUTHENTICATION_DEFERRED; + } + else + { + return TLS_AUTHENTICATION_FAILED; + } } #ifdef MANAGEMENT_DEF_AUTH @@ -905,26 +995,26 @@ tls_authentication_status (struct tls_multi *multi, const int latency) * to indicate auth failure/success. */ bool -tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth, const char *client_reason) +tls_authenticate_key(struct tls_multi *multi, const unsigned int mda_key_id, const bool auth, const char *client_reason) { - bool ret = false; - if (multi) - { - int i; - man_def_auth_set_client_reason (multi, client_reason); - for (i = 0; i < KEY_SCAN_SIZE; ++i) - { - struct key_state *ks = multi->key_scan[i]; - if (ks->mda_key_id == mda_key_id) - { - ks->mda_status = auth ? ACF_SUCCEEDED : ACF_FAILED; - ret = true; - } - } - } - return ret; + bool ret = false; + if (multi) + { + int i; + man_def_auth_set_client_reason(multi, client_reason); + for (i = 0; i < KEY_SCAN_SIZE; ++i) + { + struct key_state *ks = multi->key_scan[i]; + if (ks->mda_key_id == mda_key_id) + { + ks->mda_status = auth ? ACF_SUCCEEDED : ACF_FAILED; + ret = true; + } + } + } + return ret; } -#endif +#endif /* ifdef MANAGEMENT_DEF_AUTH */ /* **************************************************************************** @@ -941,124 +1031,135 @@ tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, co * Verify the user name and password using a script */ static bool -verify_user_pass_script (struct tls_session *session, const struct user_pass *up) +verify_user_pass_script(struct tls_session *session, const struct user_pass *up) { - struct gc_arena gc = gc_new (); - struct argv argv = argv_new (); - const char *tmp_file = ""; - bool ret = false; - - /* Is username defined? */ - if ((session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) || strlen (up->username)) - { - /* Set environmental variables prior to calling script */ - setenv_str (session->opt->es, "script_type", "user-pass-verify"); - - if (session->opt->auth_user_pass_verify_script_via_file) - { - struct status_output *so; - - tmp_file = create_temp_file (session->opt->tmp_dir, "up", &gc); - if( tmp_file ) { - so = status_open (tmp_file, 0, -1, NULL, STATUS_OUTPUT_WRITE); - status_printf (so, "%s", up->username); - status_printf (so, "%s", up->password); - if (!status_close (so)) - { - msg (D_TLS_ERRORS, "TLS Auth Error: could not write username/password to file: %s", - tmp_file); - goto done; - } - } else { - msg (D_TLS_ERRORS, "TLS Auth Error: could not create write " - "username/password to temp file"); - } - } - else - { - setenv_str (session->opt->es, "username", up->username); - setenv_str (session->opt->es, "password", up->password); - } - - /* setenv incoming cert common name for script */ - setenv_str (session->opt->es, "common_name", session->common_name); - - /* setenv client real IP address */ - setenv_untrusted (session); - - /* format command line */ - argv_parse_cmd (&argv, session->opt->auth_user_pass_verify_script); - argv_printf_cat (&argv, "%s", tmp_file); - - /* call command */ - ret = openvpn_run_script (&argv, session->opt->es, 0, - "--auth-user-pass-verify"); - - if (!session->opt->auth_user_pass_verify_script_via_file) - setenv_del (session->opt->es, "password"); - } - else - { - msg (D_TLS_ERRORS, "TLS Auth Error: peer provided a blank username"); - } - - done: - if (tmp_file && strlen (tmp_file) > 0) - platform_unlink (tmp_file); - - argv_reset (&argv); - gc_free (&gc); - return ret; + struct gc_arena gc = gc_new(); + struct argv argv = argv_new(); + const char *tmp_file = ""; + bool ret = false; + + /* Is username defined? */ + if ((session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) || strlen(up->username)) + { + /* Set environmental variables prior to calling script */ + setenv_str(session->opt->es, "script_type", "user-pass-verify"); + + if (session->opt->auth_user_pass_verify_script_via_file) + { + struct status_output *so; + + tmp_file = create_temp_file(session->opt->tmp_dir, "up", &gc); + if (tmp_file) + { + so = status_open(tmp_file, 0, -1, NULL, STATUS_OUTPUT_WRITE); + status_printf(so, "%s", up->username); + status_printf(so, "%s", up->password); + if (!status_close(so)) + { + msg(D_TLS_ERRORS, "TLS Auth Error: could not write username/password to file: %s", + tmp_file); + goto done; + } + } + else + { + msg(D_TLS_ERRORS, "TLS Auth Error: could not create write " + "username/password to temp file"); + } + } + else + { + setenv_str(session->opt->es, "username", up->username); + setenv_str(session->opt->es, "password", up->password); + } + + /* setenv incoming cert common name for script */ + setenv_str(session->opt->es, "common_name", session->common_name); + + /* setenv client real IP address */ + setenv_untrusted(session); + + /* format command line */ + argv_parse_cmd(&argv, session->opt->auth_user_pass_verify_script); + argv_printf_cat(&argv, "%s", tmp_file); + + /* call command */ + ret = openvpn_run_script(&argv, session->opt->es, 0, + "--auth-user-pass-verify"); + + if (!session->opt->auth_user_pass_verify_script_via_file) + { + setenv_del(session->opt->es, "password"); + } + } + else + { + msg(D_TLS_ERRORS, "TLS Auth Error: peer provided a blank username"); + } + +done: + if (tmp_file && strlen(tmp_file) > 0) + { + platform_unlink(tmp_file); + } + + argv_reset(&argv); + gc_free(&gc); + return ret; } /* * 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, const char *raw_username) { - int retval = OPENVPN_PLUGIN_FUNC_ERROR; + int retval = OPENVPN_PLUGIN_FUNC_ERROR; #ifdef PLUGIN_DEF_AUTH - struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ + struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ #endif - /* Is username defined? */ - if ((session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) || strlen (up->username)) + /* Is username defined? */ + 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 ? raw_username : up->username)); - setenv_str (session->opt->es, "password", up->password); + /* set username/password in private env space */ + 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 */ - setenv_str (session->opt->es, "common_name", session->common_name); + /* setenv incoming cert common name for script */ + setenv_str(session->opt->es, "common_name", session->common_name); - /* setenv client real IP address */ - setenv_untrusted (session); + /* setenv client real IP address */ + setenv_untrusted(session); #ifdef PLUGIN_DEF_AUTH - /* generate filename for deferred auth control file */ - key_state_gen_auth_control_file (ks, session->opt); + /* generate filename for deferred auth control file */ + key_state_gen_auth_control_file(ks, session->opt); #endif - /* call command */ - retval = plugin_call (session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY, NULL, NULL, session->opt->es); + /* call command */ + retval = plugin_call(session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY, NULL, NULL, session->opt->es); #ifdef PLUGIN_DEF_AUTH - /* purge auth control filename (and file itself) for non-deferred returns */ - if (retval != OPENVPN_PLUGIN_FUNC_DEFERRED) - key_state_rm_auth_control_file (ks); + /* purge auth control filename (and file itself) for non-deferred returns */ + if (retval != OPENVPN_PLUGIN_FUNC_DEFERRED) + { + key_state_rm_auth_control_file(ks); + } #endif - setenv_del (session->opt->es, "password"); - if (raw_username) - setenv_str (session->opt->es, "username", up->username); + setenv_del(session->opt->es, "password"); + if (raw_username) + { + setenv_str(session->opt->es, "username", up->username); + } } - else + else { - msg (D_TLS_ERRORS, "TLS Auth Error (verify_user_pass_plugin): peer provided a blank username"); + msg(D_TLS_ERRORS, "TLS Auth Error (verify_user_pass_plugin): peer provided a blank username"); } - return retval; + return retval; } @@ -1072,287 +1173,311 @@ 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, const char *raw_username) { - int retval = KMDA_ERROR; - struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ + int retval = KMDA_ERROR; + struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ - /* Is username defined? */ - if ((session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) || strlen (up->username)) + /* Is username defined? */ + 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 ? raw_username : up->username)); - setenv_str (session->opt->es, "password", up->password); + /* set username/password in private env space */ + 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 */ - setenv_str (session->opt->es, "common_name", session->common_name); + /* setenv incoming cert common name for script */ + setenv_str(session->opt->es, "common_name", session->common_name); - /* setenv client real IP address */ - setenv_untrusted (session); + /* setenv client real IP address */ + setenv_untrusted(session); - if (management) - management_notify_client_needing_auth (management, ks->mda_key_id, session->opt->mda_context, session->opt->es); + if (management) + { + 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); + setenv_del(session->opt->es, "password"); + if (raw_username) + { + setenv_str(session->opt->es, "username", up->username); + } - retval = KMDA_SUCCESS; + retval = KMDA_SUCCESS; } - else + else { - msg (D_TLS_ERRORS, "TLS Auth Error (verify_user_pass_management): peer provided a blank username"); + msg(D_TLS_ERRORS, "TLS Auth Error (verify_user_pass_management): peer provided a blank username"); } - return retval; + return retval; +} +#endif /* ifdef MANAGEMENT_DEF_AUTH */ + +/** + * Wipes the authentication token out of the memory, frees and cleans up related buffers and flags + * + * @param multi Pointer to a multi object holding the auth_token variables + */ +static void +wipe_auth_token(struct tls_multi *multi) +{ + secure_memzero(multi->auth_token, AUTH_TOKEN_SIZE); + free(multi->auth_token); + multi->auth_token = NULL; + multi->auth_token_sent = false; } -#endif + /* * Main username/password verification entry point */ void verify_user_pass(struct user_pass *up, struct tls_multi *multi, - struct tls_session *session) + struct tls_session *session) { - int s1 = OPENVPN_PLUGIN_FUNC_SUCCESS; - bool s2 = true; - struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ + int s1 = OPENVPN_PLUGIN_FUNC_SUCCESS; + bool s2 = true; + struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ - struct gc_arena gc = gc_new (); - char *raw_username = NULL; + struct gc_arena gc = gc_new(); + char *raw_username = NULL; #ifdef MANAGEMENT_DEF_AUTH - int man_def_auth = KMDA_UNDEF; + int man_def_auth = KMDA_UNDEF; - if (management_enable_def_auth (management)) - man_def_auth = KMDA_DEF; + if (management_enable_def_auth(management)) + { + 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)) + /* + * 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, '_'); + 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_remap_name (up->username, COMMON_NAME_CHAR_CLASS); - string_mod (up->password, CC_PRINT, CC_CRLF, '_'); - - /* If server is configured with --auth-gen-token and we have an - * authentication token for this client, this authentication - * round will be done internally using the token instead of - * calling any external authentication modules. - */ - if (session->opt->auth_token_generate && multi->auth_token_sent - && NULL != multi->auth_token) + /* enforce character class restrictions in username/password */ + string_mod_remap_name(up->username, COMMON_NAME_CHAR_CLASS); + string_mod(up->password, CC_PRINT, CC_CRLF, '_'); + + /* If server is configured with --auth-gen-token and we have an + * authentication token for this client, this authentication + * round will be done internally using the token instead of + * calling any external authentication modules. + */ + if (session->opt->auth_token_generate && multi->auth_token_sent + && NULL != multi->auth_token) { - unsigned int ssl_flags = session->opt->ssl_flags; + unsigned int ssl_flags = session->opt->ssl_flags; - /* Ensure that the username has not changed */ - if (!tls_lock_username(multi, up->username)) + /* Ensure that the username has not changed */ + if (!tls_lock_username(multi, up->username)) { - ks->authenticated = false; - goto done; + wipe_auth_token(multi); + ks->authenticated = false; + goto done; } - /* If auth-token lifetime has been enabled, - * ensure the token has not expired - */ - if (session->opt->auth_token_lifetime > 0 - && (multi->auth_token_tstamp + session->opt->auth_token_lifetime) < now) + /* If auth-token lifetime has been enabled, + * ensure the token has not expired + */ + if (session->opt->auth_token_lifetime > 0 + && (multi->auth_token_tstamp + session->opt->auth_token_lifetime) < now) { - msg (D_HANDSHAKE, "Auth-token for client expired\n"); - ks->authenticated = false; - goto done; + msg(D_HANDSHAKE, "Auth-token for client expired\n"); + wipe_auth_token(multi); + ks->authenticated = false; + goto done; } - /* The core authentication of the token itself */ - if (memcmp_constant_time(multi->auth_token, up->password, - strlen(multi->auth_token)) != 0) + /* The core authentication of the token itself */ + if (memcmp_constant_time(multi->auth_token, up->password, + strlen(multi->auth_token)) != 0) { - secure_memzero (multi->auth_token, AUTH_TOKEN_SIZE); - free (multi->auth_token); - multi->auth_token = NULL; - multi->auth_token_sent = false; - ks->authenticated = false; - tls_deauthenticate (multi); - - msg (D_TLS_ERRORS, "TLS Auth Error: Auth-token verification " - "failed for username '%s' %s", up->username, - (ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) ? "[CN SET]" : ""); + wipe_auth_token(multi); + ks->authenticated = false; + tls_deauthenticate(multi); + + msg(D_TLS_ERRORS, "TLS Auth Error: Auth-token verification " + "failed for username '%s' %s", up->username, + (ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) ? "[CN SET]" : ""); } - else + else { - ks->authenticated = true; - - if (ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) - set_common_name (session, up->username); - msg (D_HANDSHAKE, "TLS: Username/auth-token authentication " - "succeeded for username '%s' %s", - up->username, - (ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) ? "[CN SET]" : ""); + ks->authenticated = true; + + if (ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) + { + set_common_name(session, up->username); + } + msg(D_HANDSHAKE, "TLS: Username/auth-token authentication " + "succeeded for username '%s' %s", + up->username, + (ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) ? "[CN SET]" : ""); } - goto done; + goto done; } - /* call plugin(s) and/or script */ + /* 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); + if (man_def_auth == KMDA_DEF) + { + 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, raw_username); - if (session->opt->auth_user_pass_verify_script) - s2 = verify_user_pass_script (session, up); + if (plugin_defined(session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)) + { + s1 = verify_user_pass_plugin(session, up, raw_username); + } + if (session->opt->auth_user_pass_verify_script) + { + s2 = verify_user_pass_script(session, up); + } - /* check sizing of username if it will become our common name */ - if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen (up->username) > TLS_USERNAME_LEN) + /* check sizing of username if it will become our common name */ + if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen(up->username) > TLS_USERNAME_LEN) { - msg (D_TLS_ERRORS, "TLS Auth Error: --username-as-common name specified and username is longer than the maximum permitted Common Name length of %d characters", TLS_USERNAME_LEN); - s1 = OPENVPN_PLUGIN_FUNC_ERROR; + msg(D_TLS_ERRORS, "TLS Auth Error: --username-as-common name specified and username is longer than the maximum permitted Common Name length of %d characters", TLS_USERNAME_LEN); + s1 = OPENVPN_PLUGIN_FUNC_ERROR; } - /* auth succeeded? */ - if ((s1 == OPENVPN_PLUGIN_FUNC_SUCCESS + /* auth succeeded? */ + if ((s1 == OPENVPN_PLUGIN_FUNC_SUCCESS #ifdef PLUGIN_DEF_AUTH - || s1 == OPENVPN_PLUGIN_FUNC_DEFERRED + || s1 == OPENVPN_PLUGIN_FUNC_DEFERRED #endif - ) && s2 + ) && s2 #ifdef MANAGEMENT_DEF_AUTH - && man_def_auth != KMDA_ERROR + && man_def_auth != KMDA_ERROR #endif - && tls_lock_username (multi, up->username)) + && tls_lock_username(multi, up->username)) { - ks->authenticated = true; + ks->authenticated = true; #ifdef PLUGIN_DEF_AUTH - if (s1 == OPENVPN_PLUGIN_FUNC_DEFERRED) - ks->auth_deferred = true; + if (s1 == OPENVPN_PLUGIN_FUNC_DEFERRED) + { + ks->auth_deferred = true; + } #endif #ifdef MANAGEMENT_DEF_AUTH - if (man_def_auth != KMDA_UNDEF) - ks->auth_deferred = true; + if (man_def_auth != KMDA_UNDEF) + { + ks->auth_deferred = true; + } #endif - if ((session->opt->auth_token_generate) && (NULL == multi->auth_token)) - { - /* Server is configured with --auth-gen-token but no token has yet - * been generated for this client. Generate one and save it. - */ - uint8_t tok[AUTH_TOKEN_SIZE]; - - if (!rand_bytes(tok, AUTH_TOKEN_SIZE)) - { - msg( M_FATAL, "Failed to get enough randomness for " - "authentication token"); - } - - /* The token should be longer than the input when - * being base64 encoded - */ - if( openvpn_base64_encode(tok, AUTH_TOKEN_SIZE, - &multi->auth_token) < AUTH_TOKEN_SIZE) - { - msg(D_TLS_ERRORS, "BASE64 encoding of token failed. " - "No auth-token will be activated now"); - if (multi->auth_token) - { - secure_memzero (multi->auth_token, AUTH_TOKEN_SIZE); - free (multi->auth_token); - multi->auth_token = NULL; - } - } - else - { - multi->auth_token_tstamp = now; - dmsg (D_SHOW_KEYS, "Generated token for client: %s", - multi->auth_token); - } - } - - if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME)) - set_common_name (session, up->username); + if ((session->opt->auth_token_generate) && (NULL == multi->auth_token)) + { + /* Server is configured with --auth-gen-token but no token has yet + * been generated for this client. Generate one and save it. + */ + uint8_t tok[AUTH_TOKEN_SIZE]; + + if (!rand_bytes(tok, AUTH_TOKEN_SIZE)) + { + msg( M_FATAL, "Failed to get enough randomness for " + "authentication token"); + } + + /* The token should be longer than the input when + * being base64 encoded + */ + ASSERT(openvpn_base64_encode(tok, AUTH_TOKEN_SIZE, + &multi->auth_token) > AUTH_TOKEN_SIZE); + multi->auth_token_tstamp = now; + dmsg(D_SHOW_KEYS, "Generated token for client: %s", + multi->auth_token); + } + + if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME)) + { + set_common_name(session, up->username); + } + #ifdef ENABLE_DEF_AUTH - msg (D_HANDSHAKE, "TLS: Username/Password authentication %s for username '%s' %s", - ks->auth_deferred ? "deferred" : "succeeded", - up->username, - (session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) ? "[CN SET]" : ""); + msg(D_HANDSHAKE, "TLS: Username/Password authentication %s for username '%s' %s", + ks->auth_deferred ? "deferred" : "succeeded", + up->username, + (session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) ? "[CN SET]" : ""); #else - msg (D_HANDSHAKE, "TLS: Username/Password authentication %s for username '%s' %s", - "succeeded", - up->username, - (session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) ? "[CN SET]" : ""); + msg(D_HANDSHAKE, "TLS: Username/Password authentication %s for username '%s' %s", + "succeeded", + up->username, + (session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) ? "[CN SET]" : ""); #endif } - else + else { - msg (D_TLS_ERRORS, "TLS Auth Error: Auth Username/Password verification failed for peer"); + msg(D_TLS_ERRORS, "TLS Auth Error: Auth Username/Password verification failed for peer"); } - done: - gc_free (&gc); +done: + gc_free(&gc); } void verify_final_auth_checks(struct tls_multi *multi, struct tls_session *session) { - struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ + struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ - /* While it shouldn't really happen, don't allow the common name to be NULL */ - if (!session->common_name) - set_common_name (session, ""); + /* While it shouldn't really happen, don't allow the common name to be NULL */ + if (!session->common_name) + { + set_common_name(session, ""); + } - /* Don't allow the CN to change once it's been locked */ - if (ks->authenticated && multi->locked_cn) + /* Don't allow the CN to change once it's been locked */ + if (ks->authenticated && multi->locked_cn) { - const char *cn = session->common_name; - if (cn && strcmp (cn, multi->locked_cn)) - { - msg (D_TLS_ERRORS, "TLS Auth Error: TLS object CN attempted to change from '%s' to '%s' -- tunnel disabled", - multi->locked_cn, - cn); + const char *cn = session->common_name; + if (cn && strcmp(cn, multi->locked_cn)) + { + msg(D_TLS_ERRORS, "TLS Auth Error: TLS object CN attempted to change from '%s' to '%s' -- tunnel disabled", + multi->locked_cn, + cn); - /* change the common name back to its original value and disable the tunnel */ - set_common_name (session, multi->locked_cn); - tls_deauthenticate (multi); - } + /* change the common name back to its original value and disable the tunnel */ + set_common_name(session, multi->locked_cn); + tls_deauthenticate(multi); + } } - /* Don't allow the cert hashes to change once they have been locked */ - if (ks->authenticated && multi->locked_cert_hash_set) + /* Don't allow the cert hashes to change once they have been locked */ + if (ks->authenticated && multi->locked_cert_hash_set) { - const struct cert_hash_set *chs = session->cert_hash_set; - if (chs && !cert_hash_compare (chs, multi->locked_cert_hash_set)) - { - msg (D_TLS_ERRORS, "TLS Auth Error: TLS object CN=%s client-provided SSL certs unexpectedly changed during mid-session reauth", - session->common_name); + const struct cert_hash_set *chs = session->cert_hash_set; + if (chs && !cert_hash_compare(chs, multi->locked_cert_hash_set)) + { + msg(D_TLS_ERRORS, "TLS Auth Error: TLS object CN=%s client-provided SSL certs unexpectedly changed during mid-session reauth", + session->common_name); - /* disable the tunnel */ - tls_deauthenticate (multi); - } + /* disable the tunnel */ + tls_deauthenticate(multi); + } } - /* verify --client-config-dir based authentication */ - if (ks->authenticated && session->opt->client_config_dir_exclusive) + /* verify --client-config-dir based authentication */ + if (ks->authenticated && session->opt->client_config_dir_exclusive) { - struct gc_arena gc = gc_new (); + struct gc_arena gc = gc_new(); - const char *cn = session->common_name; - const char *path = gen_path (session->opt->client_config_dir_exclusive, cn, &gc); - if (!cn || !strcmp (cn, CCD_DEFAULT) || !test_file (path)) - { - ks->authenticated = false; - msg (D_TLS_ERRORS, "TLS Auth Error: --client-config-dir authentication failed for common name '%s' file='%s'", - session->common_name, - path ? path : "UNDEF"); - } + const char *cn = session->common_name; + const char *path = gen_path(session->opt->client_config_dir_exclusive, cn, &gc); + if (!cn || !strcmp(cn, CCD_DEFAULT) || !test_file(path)) + { + ks->authenticated = false; + msg(D_TLS_ERRORS, "TLS Auth Error: --client-config-dir authentication failed for common name '%s' file='%s'", + session->common_name, + path ? path : "UNDEF"); + } - gc_free (&gc); + gc_free(&gc); } } #endif /* ENABLE_CRYPTO */ |