summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ssl.c2
-rw-r--r--ssl_backend.h6
-rw-r--r--ssl_openssl.c76
-rw-r--r--ssl_verify.c14
-rw-r--r--ssl_verify_backend.h30
-rw-r--r--ssl_verify_openssl.c25
6 files changed, 97 insertions, 56 deletions
diff --git a/ssl.c b/ssl.c
index 407eba0..1607630 100644
--- a/ssl.c
+++ b/ssl.c
@@ -345,7 +345,7 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx)
#ifdef MANAGMENT_EXTERNAL_KEY
else if ((options->management_flags & MF_EXTERNAL_KEY) && options->cert_file)
{
- X509 *my_cert = NULL;
+ x509_cert_t *my_cert = NULL;
tls_ctx_load_cert_file(new_ctx, options->cert_file, options->cert_file_inline,
&my_cert);
tls_ctx_use_external_private_key(new_ctx, my_cert);
diff --git a/ssl_backend.h b/ssl_backend.h
index b0c9a6d..324fc33 100644
--- a/ssl_backend.h
+++ b/ssl_backend.h
@@ -173,6 +173,8 @@ void tls_ctx_load_cryptoapi(struct tls_root_ctx *ctx, const char *cryptoapi_cert
* Load certificate file into the given TLS context. If the given certificate
* file contains a certificate chain, load the whole chain.
*
+ * If the x509 parameter is not NULL, the certificate will be returned in it.
+ *
* @param ctx TLS context to use
* @param cert_file The file name to load the certificate from, or
* "[[INLINE]]" in the case of inline files.
@@ -186,7 +188,7 @@ void tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file,
#if ENABLE_INLINE_FILES
const char *cert_file_inline,
#endif
- X509 **x509
+ x509_cert_t **x509
);
/**
@@ -219,7 +221,7 @@ int tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file
* @return 1 if an error occurred, 0 if parsing was
* successful.
*/
-int tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, X509 *cert);
+int tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, x509_cert_t *cert);
#endif
diff --git a/ssl_openssl.c b/ssl_openssl.c
index ca3f01d..35f9b14 100644
--- a/ssl_openssl.c
+++ b/ssl_openssl.c
@@ -809,7 +809,41 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,
msg (M_SSLERR, "Cannot load CA certificate file %s (SSL_load_client_CA_file)", ca_file);
SSL_CTX_set_client_CA_list (ctx->ctx, cert_names);
}
+}
+
+void
+tls_ctx_load_extra_certs (struct tls_root_ctx *ctx, const char *extra_certs_file
+#if ENABLE_INLINE_FILES
+ , const char *extra_certs_file_inline
+#endif
+ )
+{
+ BIO *bio;
+ X509 *cert;
+#if ENABLE_INLINE_FILES
+ if (!strcmp (extra_certs_file, INLINE_FILE_TAG) && extra_certs_file_inline)
+ {
+ bio = BIO_new_mem_buf ((char *)extra_certs_file_inline, -1);
+ }
+ else
+#endif
+ {
+ bio = BIO_new(BIO_s_file());
+ if (BIO_read_filename(bio, extra_certs_file) <= 0)
+ msg (M_SSLERR, "Cannot load extra-certs file: %s", extra_certs_file);
+ }
+ for (;;)
+ {
+ cert = NULL;
+ if (!PEM_read_bio_X509 (bio, &cert, 0, NULL)) /* takes ownership of cert */
+ break;
+ if (!cert)
+ msg (M_SSLERR, "Error reading extra-certs certificate");
+ if (SSL_CTX_add_extra_chain_cert(ctx->ctx, cert) != 1)
+ msg (M_SSLERR, "Error adding extra-certs certificate");
+ }
+ BIO_free (bio);
}
/* **************************************
@@ -1099,11 +1133,9 @@ key_state_write_plaintext_const (struct key_state_ssl *ks_ssl, const uint8_t *da
int ret = 0;
perf_push (PERF_BIO_WRITE_PLAINTEXT);
-#ifdef USE_OPENSSL
ASSERT (NULL != ks_ssl);
ret = bio_write (ks_ssl->ssl_bio, data, len, "tls_write_plaintext_const");
-#endif /* USE_OPENSSL */
perf_pop ();
return ret;
@@ -1116,11 +1148,9 @@ key_state_read_ciphertext (struct key_state_ssl *ks_ssl, struct buffer *buf,
int ret = 0;
perf_push (PERF_BIO_READ_CIPHERTEXT);
-#ifdef USE_OPENSSL
ASSERT (NULL != ks_ssl);
ret = bio_read (ks_ssl->ct_out, buf, maxlen, "tls_read_ciphertext");
-#endif /* USE_OPENSSL */
perf_pop ();
return ret;
@@ -1132,12 +1162,10 @@ key_state_write_ciphertext (struct key_state_ssl *ks_ssl, struct buffer *buf)
int ret = 0;
perf_push (PERF_BIO_WRITE_CIPHERTEXT);
-#ifdef USE_OPENSSL
ASSERT (NULL != ks_ssl);
ret = bio_write (ks_ssl->ct_in, BPTR(buf), BLEN(buf), "tls_write_ciphertext");
bio_write_post (ret, buf);
-#endif /* USE_OPENSSL */
perf_pop ();
return ret;
@@ -1150,11 +1178,9 @@ key_state_read_plaintext (struct key_state_ssl *ks_ssl, struct buffer *buf,
int ret = 0;
perf_push (PERF_BIO_READ_PLAINTEXT);
-#ifdef USE_OPENSSL
ASSERT (NULL != ks_ssl);
ret = bio_read (ks_ssl->ssl_bio, buf, maxlen, "tls_read_plaintext");
-#endif /* USE_OPENSSL */
perf_pop ();
return ret;
@@ -1210,40 +1236,6 @@ print_details (struct key_state_ssl * ks_ssl, const char *prefix)
}
void
-tls_ctx_load_extra_certs (struct tls_root_ctx *ctx, const char *extra_certs_file
-#if ENABLE_INLINE_FILES
- , const char *extra_certs_file_inline
-#endif
- )
-{
- BIO *bio;
- X509 *cert;
-#if ENABLE_INLINE_FILES
- if (!strcmp (extra_certs_file, INLINE_FILE_TAG) && extra_certs_file_inline)
- {
- bio = BIO_new_mem_buf ((char *)extra_certs_file_inline, -1);
- }
- else
-#endif
- {
- bio = BIO_new(BIO_s_file());
- if (BIO_read_filename(bio, extra_certs_file) <= 0)
- msg (M_SSLERR, "Cannot load extra-certs file: %s", extra_certs_file);
- }
- for (;;)
- {
- cert = NULL;
- if (!PEM_read_bio_X509 (bio, &cert, 0, NULL)) /* takes ownership of cert */
- break;
- if (!cert)
- msg (M_SSLERR, "Error reading extra-certs certificate");
- if (SSL_CTX_add_extra_chain_cert(ctx->ctx, cert) != 1)
- msg (M_SSLERR, "Error adding extra-certs certificate");
- }
- BIO_free (bio);
-}
-
-void
show_available_tls_ciphers ()
{
SSL_CTX *ctx;
diff --git a/ssl_verify.c b/ssl_verify.c
index 804abe7..ac5c03b 100644
--- a/ssl_verify.c
+++ b/ssl_verify.c
@@ -433,9 +433,12 @@ verify_cert_set_env(struct env_set *es, x509_cert_t *peer_cert, int cert_depth,
/* export X509 cert SHA1 fingerprint */
{
struct gc_arena gc = gc_new ();
+ unsigned char *sha1_hash = x509_get_sha1_hash(peer_cert);
+
openvpn_snprintf (envname, sizeof(envname), "tls_digest_%d", cert_depth);
- setenv_str (es, envname,
- format_hex_ex(peer_cert->sha1_hash, SHA_DIGEST_LENGTH, 0, 1, ":", &gc));
+ setenv_str (es, envname, format_hex_ex(sha1_hash, SHA_DIGEST_LENGTH, 0, 1,
+ ":", &gc));
+ x509_free_sha1_hash(sha1_hash);
gc_free(&gc);
}
#endif
@@ -536,7 +539,7 @@ verify_cert_call_command(const char *verify_command, struct env_set *es,
* check peer cert against CRL directory
*/
static bool
-verify_check_crl_dir(const char *crl_dir, X509 *cert)
+verify_check_crl_dir(const char *crl_dir, x509_cert_t *cert)
{
char fn[256];
int fd;
@@ -615,11 +618,14 @@ verify_cert(struct tls_session *session, x509_cert_t *cert, int cert_depth)
/* 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))
+ unsigned char *sha1_hash = x509_get_sha1_hash(cert);
+ if (memcmp (sha1_hash, opt->verify_hash, SHA_DIGEST_LENGTH))
{
msg (D_TLS_ERRORS, "TLS Error: level-1 certificate hash verification failed");
+ x509_free_sha1_hash(sha1_hash);
goto err;
}
+ x509_free_sha1_hash(sha1_hash);
}
/* save common name in session object */
diff --git a/ssl_verify_backend.h b/ssl_verify_backend.h
index cab847d..f3773b3 100644
--- a/ssl_verify_backend.h
+++ b/ssl_verify_backend.h
@@ -73,7 +73,7 @@ void cert_hash_remember (struct tls_session *session, const int cert_depth,
*/
/*
- * Retrieve certificate's subject name, and place it in **subject.
+ * Retrieve certificate's subject name.
*
* The returned string must be freed with \c verify_free_subject()
*
@@ -84,12 +84,30 @@ void cert_hash_remember (struct tls_session *session, const int cert_depth,
char *x509_get_subject (x509_cert_t *cert);
/*
- * Free a subjectnumber string as returned by \c verify_get_subject()
+ * Free a subject string as returned by \c verify_get_subject()
*
* @param subject The subject to be freed.
*/
void x509_free_subject (char *subject);
+/* Retrieve the certificate's SHA1 hash.
+ *
+ * The returned string must be freed with \c verify_free_sha1_hash()
+ *
+ * @param cert Certificate to retrieve the hash from.
+ *
+ * @return a string containing the SHA1 hash of the certificate
+ */
+
+unsigned char *x509_get_sha1_hash (x509_cert_t *cert);
+
+/*
+ * Free a hash as returned by \c verify_get_hash()
+ *
+ * @param hash The subject to be freed.
+ */
+void x509_free_sha1_hash (unsigned char *hash);
+
/*
* Retrieve the certificate's username from the specified field.
*
@@ -126,7 +144,9 @@ char *x509_get_serial (x509_cert_t *cert);
void x509_free_serial (char *serial);
/*
- * TODO: document
+ * Save X509 fields to environment, using the naming convention:
+ *
+ * X509_{cert_depth}_{name}={value}
*
* @param xt
* @param es Environment set to save variables in
@@ -160,6 +180,8 @@ void x509_setenv (struct env_set *es, int cert_depth, x509_cert_t *cert);
*/
bool x509_verify_ns_cert_type(const x509_cert_t *cert, const int usage);
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L || USE_POLARSSL
+
/*
* Verify X.509 key usage extension field.
*
@@ -188,6 +210,8 @@ bool x509_verify_cert_ku (x509_cert_t *x509, const unsigned * const expected_ku,
*/
bool x509_verify_cert_eku (x509_cert_t *x509, const char * const expected_oid);
+#endif
+
/*
* Store the given certificate in pem format in a temporary file in tmp_dir
*
diff --git a/ssl_verify_openssl.c b/ssl_verify_openssl.c
index f6d27b1..1d32255 100644
--- a/ssl_verify_openssl.c
+++ b/ssl_verify_openssl.c
@@ -37,6 +37,7 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
{
struct tls_session *session;
SSL *ssl;
+ unsigned char *sha1_hash = NULL;
/* get the tls_session pointer */
ssl = X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
@@ -44,14 +45,15 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
session = (struct tls_session *) SSL_get_ex_data (ssl, mydata_index);
ASSERT (session);
- cert_hash_remember (session, ctx->error_depth, ctx->current_cert->sha1_hash);
+ sha1_hash = x509_get_sha1_hash(ctx->current_cert);
+ cert_hash_remember (session, ctx->error_depth, sha1_hash);
+ x509_free_sha1_hash(sha1_hash);
/* did peer present cert which was signed by our root cert? */
if (!preverify_ok)
{
/* get the X509 name */
- char *subject = X509_NAME_oneline (
- X509_get_subject_name (ctx->current_cert), NULL, 0);
+ char *subject = x509_get_serial(ctx->current_cert);
if (subject)
{
@@ -60,7 +62,7 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
ctx->error_depth,
X509_verify_cert_error_string (ctx->error),
subject);
- free (subject);
+ x509_free_subject(subject);
}
ERR_clear_error();
@@ -222,6 +224,21 @@ x509_free_serial (char *serial)
OPENSSL_free(serial);
}
+unsigned char *
+x509_get_sha1_hash (X509 *cert)
+{
+ char *hash = malloc(SHA_DIGEST_LENGTH);
+ memcpy(hash, cert->sha1_hash, SHA_DIGEST_LENGTH);
+ return cert->sha1_hash;
+}
+
+void
+x509_free_sha1_hash (unsigned char *hash)
+{
+ if (hash)
+ free(hash);
+}
+
char *
x509_get_subject (X509 *cert)
{