summaryrefslogtreecommitdiff
path: root/src/openvpn/ssl_verify.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpn/ssl_verify.c')
-rw-r--r--src/openvpn/ssl_verify.c1789
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 */