summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ssl.c130
-rw-r--r--ssl.h7
-rw-r--r--ssl_verify.c125
-rw-r--r--ssl_verify.h13
4 files changed, 119 insertions, 156 deletions
diff --git a/ssl.c b/ssl.c
index 2858a24..516ed1a 100644
--- a/ssl.c
+++ b/ssl.c
@@ -296,136 +296,6 @@ ssl_put_auth_challenge (const char *cr_str)
#endif
-static void
-setenv_untrusted (struct tls_session *session)
-{
- setenv_link_socket_actual (session->opt->es, "untrusted", &session->untrusted_addr, SA_IP_PORT);
-}
-
-static void
-string_mod_sslname (char *str, const unsigned int restrictive_flags, const unsigned int ssl_flags)
-{
- if (ssl_flags & SSLF_NO_NAME_REMAPPING)
- string_mod (str, CC_PRINT, CC_CRLF, '_');
- else
- string_mod (str, restrictive_flags, 0, '_');
-}
-
-int
-verify_cert(struct tls_session *session, x509_cert_t *cert, int cert_depth)
-{
- char *subject = NULL;
- char common_name[TLS_USERNAME_LEN] = {0};
- const struct tls_options *opt;
-
- opt = session->opt;
- ASSERT (opt);
-
- session->verified = false;
-
- /* get the X509 name */
- subject = verify_get_subject(cert);
- if (!subject)
- {
- msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, could not extract X509 "
- "subject string from certificate", cert_depth);
- goto err;
- }
-
- /* enforce character class restrictions in X509 name */
- string_mod_sslname (subject, X509_NAME_CHAR_CLASS, opt->ssl_flags);
- string_replace_leading (subject, '-', '_');
-
- /* extract the username (default is CN) */
- if (verify_get_username (common_name, TLS_USERNAME_LEN, 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 err;
- }
- }
-
- /* enforce character class restrictions in common name */
- string_mod_sslname (common_name, COMMON_NAME_CHAR_CLASS, opt->ssl_flags);
-
- /* 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 err; /* Reject connection */
- }
-
- /* verify level 1 cert, i.e. the CA that signed our leaf cert */
- if (cert_depth == 1 && opt->verify_hash)
- {
- if (memcmp (cert->sha1_hash, opt->verify_hash, SHA_DIGEST_LENGTH))
- {
- msg (D_TLS_ERRORS, "TLS Error: level-1 certificate hash verification failed");
- goto err;
- }
- }
-
- /* 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);
-
- /* 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);
-
- /* If this is the peer's own certificate, verify it */
- if (cert_depth == 0 && verify_peer_cert(opt, cert, subject, common_name))
- goto err;
-
- /* call --tls-verify plug-in(s), if registered */
- if (verify_cert_call_plugin(opt->plugins, opt->es, cert_depth, cert, subject))
- goto err;
-
- /* run --tls-verify script */
- if (opt->verify_command && verify_cert_call_command(opt->verify_command, opt->es,
- cert_depth, cert, subject, opt->verify_export_cert))
- goto err;
-
- /* check peer cert against CRL */
- if (opt->crl_file)
- {
- if (opt->ssl_flags & SSLF_CRL_VERIFY_DIR)
- {
- if (verify_check_crl_dir(opt->crl_file, cert))
- goto err;
- }
- else
- {
- if (verify_check_crl(opt->crl_file, cert, subject))
- goto err;
- }
- }
-
- msg (D_HANDSHAKE, "VERIFY OK: depth=%d, %s", cert_depth, subject);
- session->verified = true;
-
- done:
- verify_free_subject (subject);
- return (session->verified == true) ? 1 : 0;
-
- err:
- tls_clear_error();
- session->verified = false;
- goto done;
-}
-
-/** @} name Function for authenticating a new connection from a remote OpenVPN peer */
-
/*
* Initialize SSL context.
* All files are in PEM format.
diff --git a/ssl.h b/ssl.h
index 3bad848..417cac9 100644
--- a/ssl.h
+++ b/ssl.h
@@ -118,13 +118,6 @@
* Buffer sizes (also see mtu.h).
*/
-/* Maximum length of the username in cert */
-#define TLS_USERNAME_LEN 64
-
-/* Legal characters in an X509 or common name */
-#define X509_NAME_CHAR_CLASS (CC_ALNUM|CC_UNDERBAR|CC_DASH|CC_DOT|CC_AT|CC_COLON|CC_SLASH|CC_EQUAL)
-#define COMMON_NAME_CHAR_CLASS (CC_ALNUM|CC_UNDERBAR|CC_DASH|CC_DOT|CC_AT|CC_SLASH)
-
/* Maximum length of OCC options string passed as part of auth handshake */
#define TLS_OPTIONS_LEN 512
diff --git a/ssl_verify.c b/ssl_verify.c
index 2609c1d..e82e5c0 100644
--- a/ssl_verify.c
+++ b/ssl_verify.c
@@ -82,7 +82,7 @@ tls_deauthenticate (struct tls_multi *multi)
/*
* Set the given session's common_name
*/
-void
+static void
set_common_name (struct tls_session *session, const char *common_name)
{
if (session->common_name)
@@ -331,7 +331,7 @@ print_nsCertType (int type)
* @param subject the peer's extracted subject name
* @param subject the peer's extracted common name
*/
-int
+static int
verify_peer_cert(const struct tls_options *opt, x509_cert_t *peer_cert,
const char *subject, const char *common_name)
{
@@ -404,7 +404,7 @@ verify_peer_cert(const struct tls_options *opt, x509_cert_t *peer_cert,
* Export the subject, common_name, and raw certificate fields to the
* environment for later verification by scripts and plugins.
*/
-void
+static void
verify_cert_set_env(struct env_set *es, x509_cert_t *peer_cert, int cert_depth,
const char *subject, const char *common_name,
const struct x509_track *x509_track)
@@ -453,7 +453,7 @@ verify_cert_set_env(struct env_set *es, x509_cert_t *peer_cert, int cert_depth,
/*
* call --tls-verify plug-in(s)
*/
-int
+static int
verify_cert_call_plugin(const struct plugin_list *plugins, struct env_set *es,
int cert_depth, x509_cert_t *cert, char *subject)
{
@@ -486,7 +486,7 @@ verify_cert_call_plugin(const struct plugin_list *plugins, struct env_set *es,
/*
* run --tls-verify script
*/
-int
+static int
verify_cert_call_command(const char *verify_command, struct env_set *es,
int cert_depth, x509_cert_t *cert, char *subject, const char *verify_export_cert)
{
@@ -535,7 +535,7 @@ verify_cert_call_command(const char *verify_command, struct env_set *es,
/*
* check peer cert against CRL directory
*/
-bool
+static bool
verify_check_crl_dir(const char *crl_dir, X509 *cert)
{
char fn[256];
@@ -562,6 +562,119 @@ verify_check_crl_dir(const char *crl_dir, X509 *cert)
return false;
}
+int
+verify_cert(struct tls_session *session, x509_cert_t *cert, int cert_depth)
+{
+ char *subject = NULL;
+ char common_name[TLS_USERNAME_LEN] = {0};
+ const struct tls_options *opt;
+
+ opt = session->opt;
+ ASSERT (opt);
+
+ session->verified = false;
+
+ /* get the X509 name */
+ subject = verify_get_subject(cert);
+ if (!subject)
+ {
+ msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, could not extract X509 "
+ "subject string from certificate", cert_depth);
+ goto err;
+ }
+
+ /* enforce character class restrictions in X509 name */
+ string_mod_sslname (subject, X509_NAME_CHAR_CLASS, opt->ssl_flags);
+ string_replace_leading (subject, '-', '_');
+
+ /* extract the username (default is CN) */
+ if (verify_get_username (common_name, TLS_USERNAME_LEN, 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 err;
+ }
+ }
+
+ /* enforce character class restrictions in common name */
+ string_mod_sslname (common_name, COMMON_NAME_CHAR_CLASS, opt->ssl_flags);
+
+ /* 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 err; /* Reject connection */
+ }
+
+ /* verify level 1 cert, i.e. the CA that signed our leaf cert */
+ if (cert_depth == 1 && opt->verify_hash)
+ {
+ if (memcmp (cert->sha1_hash, opt->verify_hash, SHA_DIGEST_LENGTH))
+ {
+ msg (D_TLS_ERRORS, "TLS Error: level-1 certificate hash verification failed");
+ goto err;
+ }
+ }
+
+ /* 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);
+
+ /* 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);
+
+ /* If this is the peer's own certificate, verify it */
+ if (cert_depth == 0 && verify_peer_cert(opt, cert, subject, common_name))
+ goto err;
+
+ /* call --tls-verify plug-in(s), if registered */
+ if (verify_cert_call_plugin(opt->plugins, opt->es, cert_depth, cert, subject))
+ goto err;
+
+ /* run --tls-verify script */
+ if (opt->verify_command && verify_cert_call_command(opt->verify_command, opt->es,
+ cert_depth, cert, subject, opt->verify_export_cert))
+ goto err;
+
+ /* check peer cert against CRL */
+ if (opt->crl_file)
+ {
+ if (opt->ssl_flags & SSLF_CRL_VERIFY_DIR)
+ {
+ if (verify_check_crl_dir(opt->crl_file, cert))
+ goto err;
+ }
+ else
+ {
+ if (verify_check_crl(opt->crl_file, cert, subject))
+ goto err;
+ }
+ }
+
+ msg (D_HANDSHAKE, "VERIFY OK: depth=%d, %s", cert_depth, subject);
+ session->verified = true;
+
+ done:
+ verify_free_subject (subject);
+ return (session->verified == true) ? 1 : 0;
+
+ err:
+ tls_clear_error();
+ session->verified = false;
+ goto done;
+}
+
/* ***************************************************************************
* Functions for the management of deferred authentication when using
* user/password authentication.
diff --git a/ssl_verify.h b/ssl_verify.h
index 7e53513..87d401a 100644
--- a/ssl_verify.h
+++ b/ssl_verify.h
@@ -242,18 +242,5 @@ tls_client_reason (struct tls_multi *multi)
#endif
}
-/* TEMP */
-int verify_peer_cert(const struct tls_options *opt, x509_cert_t *peer_cert,
- const char *subject, const char *common_name);
-void
-verify_cert_set_env(struct env_set *es, x509_cert_t *peer_cert, int cert_depth,
- const char *subject, const char *common_name,
- const struct x509_track *x509_track);
-int verify_cert_call_plugin(const struct plugin_list *plugins, struct env_set *es,
- int cert_depth, x509_cert_t *cert, char *subject);
-int verify_cert_call_command(const char *verify_command, struct env_set *es,
- int cert_depth, x509_cert_t *cert, char *subject, const char *verify_export_cert);
-bool verify_check_crl_dir(const char *crl_dir, X509 *cert);
-
#endif /* SSL_VERIFY_H_ */