Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(448)

Unified Diff: c/sslutils.c

Issue 2842333002: Updated netty-tcnative to version 2.0.0.Final (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « c/sslnetwork.c ('k') | c/stdlib.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: c/sslutils.c
diff --git a/c/sslutils.c b/c/sslutils.c
index f49f0bdd7f4dc1d352b570d537775e3e0c6209af..a3801040c3b6f9299c2246fdaadb89ba3dd2eaf3 100644
--- a/c/sslutils.c
+++ b/c/sslutils.c
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2016 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
@@ -14,40 +29,104 @@
* limitations under the License.
*/
-/** SSL Utilities
- *
- * @author Mladen Turk
- * @version $Id: sslutils.c 1658728 2015-02-10 14:45:19Z kkolinko $
- */
-
#include "tcn.h"
-#ifdef HAVE_OPENSSL
-#include "apr_poll.h"
#include "ssl_private.h"
-#ifdef WIN32
-extern int WIN32_SSL_password_prompt(tcn_pass_cb_t *data);
-#endif
-
-#ifdef HAVE_OPENSSL_OCSP
-#include <openssl/bio.h>
-#include <openssl/ocsp.h>
-/* defines with the values as seen by the asn1parse -dump openssl command */
-#define ASN1_SEQUENCE 0x30
-#define ASN1_OID 0x06
-#define ASN1_STRING 0x86
-#pragma message("Using OCSP")
-static int ssl_verify_OCSP(int ok, X509_STORE_CTX *ctx);
-static int ssl_ocsp_request(X509 *cert, X509 *issuer);
-#endif
-
/* _________________________________________________________________
**
** Additional High-Level Functions for OpenSSL
** _________________________________________________________________
*/
+
+/*
+ * Adapted from OpenSSL:
+ * http://osxr.org/openssl/source/ssl/ssl_locl.h#0291
+ */
+/* Bits for algorithm_mkey (key exchange algorithm) */
+#define SSL_kRSA 0x00000001L /* RSA key exchange */
+#define SSL_kDHr 0x00000002L /* DH cert, RSA CA cert */ /* no such ciphersuites supported! */
+#define SSL_kDHd 0x00000004L /* DH cert, DSA CA cert */ /* no such ciphersuite supported! */
+#define SSL_kEDH 0x00000008L /* tmp DH key no DH cert */
+#define SSL_kKRB5 0x00000010L /* Kerberos5 key exchange */
+#define SSL_kECDHr 0x00000020L /* ECDH cert, RSA CA cert */
+#define SSL_kECDHe 0x00000040L /* ECDH cert, ECDSA CA cert */
+#define SSL_kEECDH 0x00000080L /* ephemeral ECDH */
+#define SSL_kPSK 0x00000100L /* PSK */
+#define SSL_kGOST 0x00000200L /* GOST key exchange */
+#define SSL_kSRP 0x00000400L /* SRP */
+
+/* Bits for algorithm_auth (server authentication) */
+#define SSL_aRSA 0x00000001L /* RSA auth */
+#define SSL_aDSS 0x00000002L /* DSS auth */
+#define SSL_aNULL 0x00000004L /* no auth (i.e. use ADH or AECDH) */
+#define SSL_aDH 0x00000008L /* Fixed DH auth (kDHd or kDHr) */ /* no such ciphersuites supported! */
+#define SSL_aECDH 0x00000010L /* Fixed ECDH auth (kECDHe or kECDHr) */
+#define SSL_aKRB5 0x00000020L /* KRB5 auth */
+#define SSL_aECDSA 0x00000040L /* ECDSA auth*/
+#define SSL_aPSK 0x00000080L /* PSK auth */
+#define SSL_aGOST94 0x00000100L /* GOST R 34.10-94 signature auth */
+#define SSL_aGOST01 0x00000200L /* GOST R 34.10-2001 signature auth */
+
+const char* TCN_UNKNOWN_AUTH_METHOD = "UNKNOWN";
+
+/* OpenSSL end */
+
+/*
+ * Adapted from Android:
+ * https://android.googlesource.com/platform/external/openssl/+/master/patches/0003-jsse.patch
+ */
+const char* SSL_cipher_authentication_method(const SSL_CIPHER* cipher){
+#ifndef OPENSSL_IS_BORINGSSL
+ switch (cipher->algorithm_mkey)
+ {
+ case SSL_kRSA:
+ return SSL_TXT_RSA;
+ case SSL_kDHr:
+ return SSL_TXT_DH "_" SSL_TXT_RSA;
+
+ case SSL_kDHd:
+ return SSL_TXT_DH "_" SSL_TXT_DSS;
+ case SSL_kEDH:
+ switch (cipher->algorithm_auth)
+ {
+ case SSL_aDSS:
+ return "DHE_" SSL_TXT_DSS;
+ case SSL_aRSA:
+ return "DHE_" SSL_TXT_RSA;
+ case SSL_aNULL:
+ return SSL_TXT_DH "_anon";
+ default:
+ return TCN_UNKNOWN_AUTH_METHOD;
+ }
+ case SSL_kKRB5:
+ return SSL_TXT_KRB5;
+ case SSL_kECDHr:
+ return SSL_TXT_ECDH "_" SSL_TXT_RSA;
+ case SSL_kECDHe:
+ return SSL_TXT_ECDH "_" SSL_TXT_ECDSA;
+ case SSL_kEECDH:
+ switch (cipher->algorithm_auth)
+ {
+ case SSL_aECDSA:
+ return "ECDHE_" SSL_TXT_ECDSA;
+ case SSL_aRSA:
+ return "ECDHE_" SSL_TXT_RSA;
+ case SSL_aNULL:
+ return SSL_TXT_ECDH "_anon";
+ default:
+ return TCN_UNKNOWN_AUTH_METHOD;
+ }
+ default:
+ return TCN_UNKNOWN_AUTH_METHOD;
+ }
+#else
+ return SSL_CIPHER_get_kx_name(cipher);
+#endif
+
+}
+
/* we initialize this index at startup time
* and never write to it at request time,
* so this static is thread safe.
@@ -56,30 +135,25 @@ static int ssl_ocsp_request(X509 *cert, X509 *issuer);
*/
static int SSL_app_data2_idx = -1;
static int SSL_app_data3_idx = -1;
-void SSL_init_app_data2_3_idx(void)
+static int SSL_app_data4_idx = -1;
+void SSL_init_app_data_idx()
{
int i;
- if (SSL_app_data2_idx > -1) {
- return;
+ if (SSL_app_data2_idx == -1) {
+ /* we _do_ need to call this two times */
+ for (i = 0; i <= 1; i++) {
+ SSL_app_data2_idx = SSL_get_ex_new_index(0, "tcn_ssl_ctxt_t*", NULL, NULL, NULL);
+ }
}
- /* we _do_ need to call this two times */
- for (i = 0; i <= 1; i++) {
- SSL_app_data2_idx =
- SSL_get_ex_new_index(0,
- "Second Application Data for SSL",
- NULL, NULL, NULL);
+ if (SSL_app_data3_idx == -1) {
+ SSL_app_data3_idx = SSL_get_ex_new_index(0, "int* handshakeCount", NULL, NULL, NULL);
}
- if (SSL_app_data3_idx > -1) {
- return;
+ if (SSL_app_data4_idx == -1) {
+ SSL_app_data4_idx = SSL_get_ex_new_index(0, "tcn_ssl_verify_config_t*", NULL, NULL, NULL);
}
-
- SSL_app_data3_idx =
- SSL_get_ex_new_index(0,
- "Third Application Data for SSL",
- NULL, NULL, NULL);
}
void *SSL_get_app_data2(SSL *ssl)
@@ -103,80 +177,36 @@ void SSL_set_app_data3(SSL *ssl, void *arg)
SSL_set_ex_data(ssl, SSL_app_data3_idx, arg);
}
-/* Simple echo password prompting */
-int SSL_password_prompt(tcn_pass_cb_t *data)
+void *SSL_get_app_data4(SSL *ssl)
{
- int rv = 0;
- data->password[0] = '\0';
- if (data->cb.obj) {
- JNIEnv *e;
- jobject o;
- jstring prompt;
- tcn_get_java_env(&e);
- prompt = AJP_TO_JSTRING(data->prompt);
- if ((o = (*e)->CallObjectMethod(e, data->cb.obj,
- data->cb.mid[0], prompt))) {
- TCN_ALLOC_CSTRING(o);
- if (J2S(o)) {
- strncpy(data->password, J2S(o), SSL_MAX_PASSWORD_LEN);
- data->password[SSL_MAX_PASSWORD_LEN-1] = '\0';
- rv = (int)strlen(data->password);
- }
- TCN_FREE_CSTRING(o);
- }
- }
- else {
-#ifdef WIN32
- rv = WIN32_SSL_password_prompt(data);
-#elif !defined(OPENSSL_IS_BORINGSSL)
- EVP_read_pw_string(data->password, SSL_MAX_PASSWORD_LEN,
- data->prompt, 0);
-#endif
- rv = (int)strlen(data->password);
- }
- if (rv > 0) {
- /* Remove LF char if present */
- char *r = strchr(data->password, '\n');
- if (r) {
- *r = '\0';
- rv--;
- }
-#ifdef WIN32
- if ((r = strchr(data->password, '\r'))) {
- *r = '\0';
- rv--;
- }
-#endif
- }
- return rv;
+ return SSL_get_ex_data(ssl, SSL_app_data4_idx);
+}
+
+void SSL_set_app_data4(SSL *ssl, void *arg)
+{
+ SSL_set_ex_data(ssl, SSL_app_data4_idx, arg);
}
int SSL_password_callback(char *buf, int bufsiz, int verify,
void *cb)
{
- tcn_pass_cb_t *cb_data = (tcn_pass_cb_t *)cb;
+ char *password = (char *) cb;
- if (buf == NULL)
+ if (buf == NULL || password == NULL)
return 0;
*buf = '\0';
- if (cb_data == NULL)
- cb_data = &tcn_password_callback;
- if (!cb_data->prompt)
- cb_data->prompt = SSL_DEFAULT_PASS_PROMPT;
- if (cb_data->password[0]) {
+
+ if (password[0]) {
/* Return already obtained password */
- strncpy(buf, cb_data->password, bufsiz);
- buf[bufsiz - 1] = '\0';
- return (int)strlen(buf);
- }
- else {
- if (SSL_password_prompt(cb_data) > 0)
- strncpy(buf, cb_data->password, bufsiz);
+ strncpy(buf, password, bufsiz);
}
+
buf[bufsiz - 1] = '\0';
return (int)strlen(buf);
}
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(OPENSSL_USE_DEPRECATED) || defined(LIBRESSL_VERSION_NUMBER)
+
static unsigned char dh0512_p[]={
0xD9,0xBA,0xBF,0xFD,0x69,0x38,0xC9,0x51,0x2D,0x19,0x37,0x39,
0xD7,0x7D,0x7E,0x3E,0x25,0x58,0x55,0x94,0x90,0x60,0x93,0x7A,
@@ -273,9 +303,7 @@ static unsigned char dhxxx2_g[]={
static DH *get_dh(int idx)
{
-#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(OPENSSL_USE_DEPRECATED)
DH *dh;
-
if ((dh = DH_new()) == NULL)
return NULL;
switch (idx) {
@@ -299,10 +327,14 @@ static DH *get_dh(int idx)
}
else
return dh;
+ return NULL;
+}
#else
+static DH *get_dh(int idx)
+{
return NULL;
-#endif
}
+#endif
DH *SSL_dh_get_tmp_param(int key_len)
{
@@ -321,88 +353,6 @@ DH *SSL_dh_get_tmp_param(int key_len)
return dh;
}
-DH *SSL_dh_get_param_from_file(const char *file)
-{
- DH *dh = NULL;
- BIO *bio;
-
- if ((bio = BIO_new_file(file, "r")) == NULL)
- return NULL;
- dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
- BIO_free(bio);
- return dh;
-}
-
-/*
- * Handle out temporary RSA private keys on demand
- *
- * The background of this as the TLSv1 standard explains it:
- *
- * | D.1. Temporary RSA keys
- * |
- * | US Export restrictions limit RSA keys used for encryption to 512
- * | bits, but do not place any limit on lengths of RSA keys used for
- * | signing operations. Certificates often need to be larger than 512
- * | bits, since 512-bit RSA keys are not secure enough for high-value
- * | transactions or for applications requiring long-term security. Some
- * | certificates are also designated signing-only, in which case they
- * | cannot be used for key exchange.
- * |
- * | When the public key in the certificate cannot be used for encryption,
- * | the server signs a temporary RSA key, which is then exchanged. In
- * | exportable applications, the temporary RSA key should be the maximum
- * | allowable length (i.e., 512 bits). Because 512-bit RSA keys are
- * | relatively insecure, they should be changed often. For typical
- * | electronic commerce applications, it is suggested that keys be
- * | changed daily or every 500 transactions, and more often if possible.
- * | Note that while it is acceptable to use the same temporary key for
- * | multiple transactions, it must be signed each time it is used.
- * |
- * | RSA key generation is a time-consuming process. In many cases, a
- * | low-priority process can be assigned the task of key generation.
- * | Whenever a new key is completed, the existing temporary key can be
- * | replaced with the new one.
- *
- * XXX: base on comment above, if thread support is enabled,
- * we should spawn a low-priority thread to generate new keys
- * on the fly.
- *
- * So we generated 512 and 1024 bit temporary keys on startup
- * which we now just hand out on demand....
- */
-
-RSA *SSL_callback_tmp_RSA(SSL *ssl, int export, int keylen)
-{
- int idx;
-
- /* doesn't matter if export flag is on,
- * we won't be asked for keylen > 512 in that case.
- * if we are asked for a keylen > 1024, it is too expensive
- * to generate on the fly.
- */
-
- switch (keylen) {
- case 512:
- idx = SSL_TMP_KEY_RSA_512;
- break;
- case 2048:
- idx = SSL_TMP_KEY_RSA_2048;
- if (SSL_temp_keys[idx] == NULL)
- idx = SSL_TMP_KEY_RSA_1024;
- break;
- case 4096:
- idx = SSL_TMP_KEY_RSA_4096;
- if (SSL_temp_keys[idx] == NULL)
- idx = SSL_TMP_KEY_RSA_2048;
- break;
- case 1024:
- default:
- idx = SSL_TMP_KEY_RSA_1024;
- break;
- }
- return (RSA *)SSL_temp_keys[idx];
-}
-
/*
* Hand out the already generated DH parameters...
*/
@@ -427,13 +377,32 @@ DH *SSL_callback_tmp_DH(SSL *ssl, int export, int keylen)
return (DH *)SSL_temp_keys[idx];
}
+DH *SSL_callback_tmp_DH_512(SSL *ssl, int export, int keylen)
+{
+ return (DH *)SSL_temp_keys[SSL_TMP_KEY_DH_512];
+}
+
+DH *SSL_callback_tmp_DH_1024(SSL *ssl, int export, int keylen)
+{
+ return (DH *)SSL_temp_keys[SSL_TMP_KEY_DH_1024];
+}
+
+DH *SSL_callback_tmp_DH_2048(SSL *ssl, int export, int keylen)
+{
+ return (DH *)SSL_temp_keys[SSL_TMP_KEY_DH_2048];
+}
+
+DH *SSL_callback_tmp_DH_4096(SSL *ssl, int export, int keylen)
+{
+ return (DH *)SSL_temp_keys[SSL_TMP_KEY_DH_4096];
+}
+
/*
* Read a file that optionally contains the server certificate in PEM
* format, possibly followed by a sequence of CA certificates that
* should be sent to the peer in the SSL Certificate message.
*/
-int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, const char *file,
- int skipfirst)
+int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, const char *file, bool skipfirst)
{
BIO *bio;
int n;
@@ -449,8 +418,7 @@ int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, const char *file,
return n;
}
-int SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO *bio,
- int skipfirst)
+static int SSL_CTX_setup_certs(SSL_CTX *ctx, BIO *bio, bool skipfirst, bool ca)
{
X509 *x509;
unsigned long err;
@@ -464,307 +432,169 @@ int SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO *bio,
X509_free(x509);
}
- /* free a perhaps already configured extra chain */
- SSL_CTX_clear_extra_chain_certs(ctx);
-
- /* create new extra chain by loading the certs */
n = 0;
- while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
- if (SSL_CTX_add_extra_chain_cert(ctx, x509) != 1) {
+ if (ca) {
+ while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
+ if (SSL_CTX_add_client_CA(ctx, x509) != 1) {
+ X509_free(x509);
+ return -1;
+ }
+ // SSL_CTX_add_client_CA does not take ownership of the x509. It just calls X509_get_subject_name
+ // and make a duplicate of this value. So we should always free the x509 after this call.
+ // See https://github.com/netty/netty/issues/6249.
X509_free(x509);
- return -1;
+ n++;
+ }
+ } else {
+ /* free a perhaps already configured extra chain */
+ SSL_CTX_clear_extra_chain_certs(ctx);
+
+ /* create new extra chain by loading the certs */
+ while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
+ // SSL_CTX_add_extra_chain_cert transfers ownership of the x509 certificate if the method succeeds.
+ if (SSL_CTX_add_extra_chain_cert(ctx, x509) != 1) {
+ X509_free(x509);
+ return -1;
+ }
+ n++;
}
- n++;
}
+
/* Make sure that only the error is just an EOF */
if ((err = ERR_peek_error()) > 0) {
if (!( ERR_GET_LIB(err) == ERR_LIB_PEM
&& ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
return -1;
}
- while (ERR_get_error() > 0) ;
+ ERR_clear_error();
}
return n;
}
-static int ssl_X509_STORE_lookup(X509_STORE *store, int yype,
- X509_NAME *name, X509_OBJECT *obj)
+int SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO *bio, bool skipfirst)
{
- X509_STORE_CTX ctx;
- int rc;
-
- X509_STORE_CTX_init(&ctx, store, NULL, NULL);
- rc = X509_STORE_get_by_subject(&ctx, yype, name, obj);
- X509_STORE_CTX_cleanup(&ctx);
- return rc;
+ return SSL_CTX_setup_certs(ctx, bio, skipfirst, false);
}
-static int ssl_verify_CRL(int ok, X509_STORE_CTX *ctx, tcn_ssl_ctxt_t *c)
-{
- X509_OBJECT obj;
- X509_NAME *subject, *issuer;
- X509 *cert;
- X509_CRL *crl;
- EVP_PKEY *pubkey;
- int i, n, rc;
-
- /*
- * Determine certificate ingredients in advance
- */
- cert = X509_STORE_CTX_get_current_cert(ctx);
- subject = X509_get_subject_name(cert);
- issuer = X509_get_issuer_name(cert);
-
- /*
- * OpenSSL provides the general mechanism to deal with CRLs but does not
- * use them automatically when verifying certificates, so we do it
- * explicitly here. We will check the CRL for the currently checked
- * certificate, if there is such a CRL in the store.
- *
- * We come through this procedure for each certificate in the certificate
- * chain, starting with the root-CA's certificate. At each step we've to
- * both verify the signature on the CRL (to make sure it's a valid CRL)
- * and it's revocation list (to make sure the current certificate isn't
- * revoked). But because to check the signature on the CRL we need the
- * public key of the issuing CA certificate (which was already processed
- * one round before), we've a little problem. But we can both solve it and
- * at the same time optimize the processing by using the following
- * verification scheme (idea and code snippets borrowed from the GLOBUS
- * project):
- *
- * 1. We'll check the signature of a CRL in each step when we find a CRL
- * through the _subject_ name of the current certificate. This CRL
- * itself will be needed the first time in the next round, of course.
- * But we do the signature processing one round before this where the
- * public key of the CA is available.
- *
- * 2. We'll check the revocation list of a CRL in each step when
- * we find a CRL through the _issuer_ name of the current certificate.
- * This CRLs signature was then already verified one round before.
- *
- * This verification scheme allows a CA to revoke its own certificate as
- * well, of course.
- */
-
- /*
- * Try to retrieve a CRL corresponding to the _subject_ of
- * the current certificate in order to verify it's integrity.
- */
- memset((char *)&obj, 0, sizeof(obj));
- rc = ssl_X509_STORE_lookup(c->crl,
- X509_LU_CRL, subject, &obj);
- crl = obj.data.crl;
-
- if ((rc > 0) && crl) {
- /*
- * Log information about CRL
- * (A little bit complicated because of ASN.1 and BIOs...)
- */
- /*
- * Verify the signature on this CRL
- */
- pubkey = X509_get_pubkey(cert);
- rc = X509_CRL_verify(crl, pubkey);
- /* Only refcounted in OpenSSL */
- if (pubkey)
- EVP_PKEY_free(pubkey);
- if (rc <= 0) {
- /* TODO: Log Invalid signature on CRL */
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE);
- X509_OBJECT_free_contents(&obj);
- return 0;
- }
- /*
- * Check date of CRL to make sure it's not expired
- */
- i = X509_cmp_current_time(X509_CRL_get_nextUpdate(crl));
+int SSL_CTX_use_client_CA_bio(SSL_CTX *ctx, BIO *bio)
+{
+ return SSL_CTX_setup_certs(ctx, bio, false, true);
+}
- if (i == 0) {
- /* TODO: Log Found CRL has invalid nextUpdate field */
+int SSL_use_certificate_chain_bio(SSL *ssl, BIO *bio, bool skipfirst)
+{
+#if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
+ // Only supported on openssl 1.0.2+
+ return -1;
+#else
+ X509 *x509;
+ unsigned long err;
+ int n;
- X509_STORE_CTX_set_error(ctx,
- X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
- X509_OBJECT_free_contents(&obj);
- return 0;
+ /* optionally skip a leading server certificate */
+ if (skipfirst) {
+ if ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) {
+ return -1;
}
+ X509_free(x509);
+ }
- if (i < 0) {
- /* TODO: Log Found CRL is expired */
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_HAS_EXPIRED);
- X509_OBJECT_free_contents(&obj);
+ /* create new extra chain by loading the certs */
+ n = 0;
- return 0;
+ while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
+ if (SSL_add0_chain_cert(ssl, x509) != 1) {
+ X509_free(x509);
+ return -1;
}
-
- X509_OBJECT_free_contents(&obj);
+ n++;
}
-
- /*
- * Try to retrieve a CRL corresponding to the _issuer_ of
- * the current certificate in order to check for revocation.
- */
- memset((char *)&obj, 0, sizeof(obj));
- rc = ssl_X509_STORE_lookup(c->crl,
- X509_LU_CRL, issuer, &obj);
-
- crl = obj.data.crl;
- if ((rc > 0) && crl) {
- /*
- * Check if the current certificate is revoked by this CRL
- */
- n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
-
- for (i = 0; i < n; i++) {
- X509_REVOKED *revoked =
- sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
-
- ASN1_INTEGER *sn = revoked->serialNumber;
-
- if (!ASN1_INTEGER_cmp(sn, X509_get_serialNumber(cert))) {
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED);
- X509_OBJECT_free_contents(&obj);
-
- return 0;
- }
+ /* Make sure that only the error is just an EOF */
+ if ((err = ERR_peek_error()) > 0) {
+ if (!( ERR_GET_LIB(err) == ERR_LIB_PEM
+ && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
+ return -1;
}
-
- X509_OBJECT_free_contents(&obj);
+ ERR_clear_error();
}
-
- return ok;
+ return n;
+#endif
}
-/*
- * This OpenSSL callback function is called when OpenSSL
- * does client authentication and verifies the certificate chain.
- */
-
-
-int SSL_callback_SSL_verify(int ok, X509_STORE_CTX *ctx)
+X509 *load_pem_cert_bio(const char *password, const BIO *bio)
{
- /* Get Apache context back through OpenSSL context */
- SSL *ssl = X509_STORE_CTX_get_ex_data(ctx,
- SSL_get_ex_data_X509_STORE_CTX_idx());
- tcn_ssl_ctxt_t *c = SSL_get_app_data2(ssl);
-
- /* Get verify ingredients */
- int errnum = X509_STORE_CTX_get_error(ctx);
- int errdepth = X509_STORE_CTX_get_error_depth(ctx);
- int verify = c->verify_mode;
- int depth = c->verify_depth;
- int skip_crl = 0;
-
- if (verify == SSL_CVERIFY_UNSET ||
- verify == SSL_CVERIFY_NONE)
- return 1;
-
- if (SSL_VERIFY_ERROR_IS_OPTIONAL(errnum) &&
- (verify == SSL_CVERIFY_OPTIONAL_NO_CA)) {
- ok = 1;
- SSL_set_verify_result(ssl, X509_V_OK);
- }
-
-#ifdef HAVE_OPENSSL_OCSP
- /* First perform OCSP validation if possible */
- if (ok) {
- /* If there was an optional verification error, it's not
- * possible to perform OCSP validation since the issuer may be
- * missing/untrusted. Fail in that case.
- */
- if (SSL_VERIFY_ERROR_IS_OPTIONAL(errnum)) {
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION);
- errnum = X509_V_ERR_APPLICATION_VERIFICATION;
- ok = 0;
- }
- else {
- int ocsp_response = ssl_verify_OCSP(ok, ctx);
- if (ocsp_response == OCSP_STATUS_OK) {
- skip_crl = 1; /* we know it is valid we skip crl evaluation */
- }
- else if (ocsp_response == OCSP_STATUS_REVOKED) {
- ok = 0 ;
- errnum = X509_STORE_CTX_get_error(ctx);
- }
- else if (ocsp_response == OCSP_STATUS_UNKNOWN) {
- /* TODO: do nothing for time being, continue with CRL */
- ;
- }
- }
- }
-#endif
- /*
- * Additionally perform CRL-based revocation checks
- */
- if (ok && c->crl && !skip_crl) {
- if (!(ok = ssl_verify_CRL(ok, ctx, c))) {
- errnum = X509_STORE_CTX_get_error(ctx);
- /* TODO: Log something */
- }
- }
- /*
- * If we already know it's not ok, log the real reason
- */
- if (!ok) {
- // Just in case that sslnetwork stuff was used, which is not true for netty but it can't harm to still
- // guard against it.
- tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)SSL_get_app_data(ssl);
-
- /* TODO: Some logging
- * Certificate Verification: Error
- */
- if (con != NULL && con->peer) {
- X509_free(con->peer);
- con->peer = NULL;
- }
+ X509 *cert = PEM_read_bio_X509_AUX((BIO*) bio, NULL,
+ (pem_password_cb *)SSL_password_callback,
+ (void *)password);
+ if (cert == NULL &&
+ (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE)) {
+ ERR_clear_error();
+ BIO_ctrl((BIO*) bio, BIO_CTRL_RESET, 0, NULL);
+ cert = d2i_X509_bio((BIO*) bio, NULL);
}
- if (errdepth > depth) {
- /* TODO: Some logging
- * Certificate Verification: Certificate Chain too long
- */
- ok = 0;
- }
- return ok;
+ return cert;
}
-/*
- * This callback function is executed while OpenSSL processes the SSL
- * handshake and does SSL record layer stuff. It's used to trap
- * client-initiated renegotiations, and for dumping everything to the
- * log.
- */
-void SSL_callback_handshake(const SSL *ssl, int where, int rc)
+EVP_PKEY *load_pem_key_bio(const char *password, const BIO *bio)
{
- tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)SSL_get_app_data(ssl);
-
- /* Retrieve the conn_rec and the associated SSLConnRec. */
- if (con == NULL) {
- return;
- }
+ EVP_PKEY *key = PEM_read_bio_PrivateKey((BIO*) bio, NULL,
+ (pem_password_cb *)SSL_password_callback,
+ (void *)password);
+ BIO_ctrl((BIO*) bio, BIO_CTRL_RESET, 0, NULL);
+ return key;
+}
- /* If the reneg state is to reject renegotiations, check the SSL
- * state machine and move to ABORT if a Client Hello is being
- * read. */
- if ((where & SSL_CB_ACCEPT_LOOP) && con->reneg_state == RENEG_REJECT) {
- int state = SSL_get_state(ssl);
+int tcn_EVP_PKEY_up_ref(EVP_PKEY* pkey) {
+#if defined(OPENSSL_IS_BORINGSSL)
+ // Workaround for https://bugs.chromium.org/p/boringssl/issues/detail?id=89#
+ EVP_PKEY_up_ref(pkey);
+ return 1;
+#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ return CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+#else
+ return EVP_PKEY_up_ref(pkey);
+#endif
+}
- if (state == SSL3_ST_SR_CLNT_HELLO_A
-#ifndef OPENSSL_IS_BORINGSSL
- || state == SSL23_ST_SR_CLNT_HELLO_A
+int tcn_X509_up_ref(X509* cert) {
+#if defined(OPENSSL_IS_BORINGSSL)
+ // Workaround for https://bugs.chromium.org/p/boringssl/issues/detail?id=89#
+ X509_up_ref(cert);
+ return 1;
+#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ return CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509);
+#else
+ return X509_up_ref(cert);
#endif
- ) {
- con->reneg_state = RENEG_ABORT;
- /* XXX: rejecting client initiated renegotiation
- */
- }
- }
- /* If the first handshake is complete, change state to reject any
- * subsequent client-initated renegotiation. */
- else if ((where & SSL_CB_HANDSHAKE_DONE) && con->reneg_state == RENEG_INIT) {
- con->reneg_state = RENEG_REJECT;
+}
+
+int tcn_set_verify_config(tcn_ssl_verify_config_t* c, jint tcn_mode, jint depth) {
+ if (depth >= 0) {
+ c->verify_depth = depth;
}
+ switch (tcn_mode) {
+ case SSL_CVERIFY_IGNORED:
+ switch (c->verify_mode) {
+ case SSL_CVERIFY_NONE:
+ return SSL_VERIFY_NONE;
+ case SSL_CVERIFY_OPTIONAL:
+ return SSL_VERIFY_PEER;
+ default:
+ return (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
+ }
+ case SSL_CVERIFY_NONE:
+ c->verify_mode = SSL_CVERIFY_NONE;
+ return SSL_VERIFY_NONE;
+ case SSL_CVERIFY_OPTIONAL:
+ c->verify_mode = SSL_CVERIFY_OPTIONAL;
+ return SSL_VERIFY_PEER;
+ default:
+ c->verify_mode = SSL_CVERIFY_REQUIRED;
+ return SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+ }
}
int SSL_callback_next_protos(SSL *ssl, const unsigned char **data,
@@ -848,513 +678,3 @@ int SSL_callback_alpn_select_proto(SSL* ssl, const unsigned char **out, unsigned
tcn_ssl_ctxt_t *ssl_ctxt = arg;
return select_next_proto(ssl, out, outlen, in, inlen, ssl_ctxt->alpn_proto_data, ssl_ctxt->alpn_proto_len, ssl_ctxt->alpn_selector_failure_behavior);
}
-
-#ifdef HAVE_OPENSSL_OCSP
-
-/* Function that is used to do the OCSP verification */
-static int ssl_verify_OCSP(int ok, X509_STORE_CTX *ctx)
-{
- X509 *cert, *issuer;
- int r = OCSP_STATUS_UNKNOWN;
-
- cert = X509_STORE_CTX_get_current_cert(ctx);
- /* if we can't get the issuer, we cannot perform OCSP verification */
- if (X509_STORE_CTX_get1_issuer(&issuer, ctx, cert) == 1 ) {
- r = ssl_ocsp_request(cert, issuer);
- if (r == OCSP_STATUS_REVOKED) {
- /* we set the error if we know that it is revoked */
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED);
- }
- else {
- /* else we return unknown, so that we can continue with the crl */
- r = OCSP_STATUS_UNKNOWN;
- }
- X509_free(issuer); /* It appears that we should free issuer since
- * X509_STORE_CTX_get1_issuer() calls X509_OBJECT_up_ref_count()
- * on the issuer object (unline X509_STORE_CTX_get_current_cert()
- * that just returns the pointer
- */
- }
- return r;
-}
-
-
-/* Helps with error handling or realloc */
-static void *apr_xrealloc(void *buf, size_t oldlen, size_t len, apr_pool_t *p)
-{
- void *newp = apr_palloc(p, len);
-
- if(newp)
- memcpy(newp, buf, oldlen);
- return newp;
-}
-
-/* parses the ocsp url and updates the ocsp_urls and nocsp_urls variables
- returns 0 on success, 1 on failure */
-static int parse_ocsp_url(unsigned char *asn1, char ***ocsp_urls,
- int *nocsp_urls, apr_pool_t *p)
-{
- char **new_ocsp_urls, *ocsp_url;
- int len, err = 0, new_nocsp_urls;
-
- if (*asn1 == ASN1_STRING) {
- len = *++asn1;
- asn1++;
- new_nocsp_urls = *nocsp_urls+1;
- if ((new_ocsp_urls = apr_xrealloc(*ocsp_urls,*nocsp_urls, new_nocsp_urls, p)) == NULL)
- err = 1;
- if (!err) {
- *ocsp_urls = new_ocsp_urls;
- *nocsp_urls = new_nocsp_urls;
- *(*ocsp_urls + *nocsp_urls) = NULL;
- if ((ocsp_url = apr_palloc(p, len + 1)) == NULL) {
- err = 1;
- }
- else {
- memcpy(ocsp_url, asn1, len);
- ocsp_url[len] = '\0';
- *(*ocsp_urls + *nocsp_urls - 1) = ocsp_url;
- }
- }
- }
- return err;
-
-}
-
-/* parses the ANS1 OID and if it is an OCSP OID then calls the parse_ocsp_url function */
-static int parse_ASN1_OID(unsigned char *asn1, char ***ocsp_urls, int *nocsp_urls, apr_pool_t *p)
-{
- int len, err = 0 ;
- const unsigned char OCSP_OID[] = {0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01};
-
- len = *++asn1;
- asn1++;
- if (memcmp(asn1, OCSP_OID, len) == 0) {
- asn1+=len;
- err = parse_ocsp_url(asn1, ocsp_urls, nocsp_urls, p);
- }
- return err;
-}
-
-
-/* Parses an ASN1 Sequence. It is a recursive function, since if it finds a sequence
- within the sequence it calls recursively itself. This function stops when it finds
- the end of the ASN1 sequence (marked by '\0'), so if there are other sequences within
- the same sequence the while loop parses the sequences */
-
-/* This algo was developed with AIA in mind so it was tested only with this extension */
-static int parse_ASN1_Sequence(unsigned char *asn1, char ***ocsp_urls,
- int *nocsp_urls, apr_pool_t *p)
-{
- int len = 0 , err = 0;
-
- while (!err && *asn1 != '\0') {
- switch(*asn1) {
- case ASN1_SEQUENCE:
- len = *++asn1;
- asn1++;
- err = parse_ASN1_Sequence(asn1, ocsp_urls, nocsp_urls, p);
- break;
- case ASN1_OID:
- err = parse_ASN1_OID(asn1,ocsp_urls,nocsp_urls, p);
- return 0;
- break;
- default:
- err = 1; /* we shouldn't have any errors */
- break;
- }
- asn1+=len;
- }
- return err;
-}
-
-/* the main function that gets the ASN1 encoding string and returns
- a pointer to a NULL terminated "array" of char *, that contains
- the ocsp_urls */
-static char **decode_OCSP_url(ASN1_OCTET_STRING *os, apr_pool_t *p)
-{
- char **response = NULL;
- unsigned char *ocsp_urls;
- int len, numofresponses = 0 ;
-
- len = ASN1_STRING_length(os);
-
- ocsp_urls = apr_palloc(p, len + 1);
- memcpy(ocsp_urls,os->data, len);
- ocsp_urls[len] = '\0';
-
- if ((response = apr_pcalloc(p, sizeof(char *))) == NULL)
- return NULL;
- if (parse_ASN1_Sequence(ocsp_urls, &response, &numofresponses, p))
- response = NULL;
- return response;
-}
-
-
-/* stolen from openssl ocsp command */
-static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
- STACK_OF(OCSP_CERTID) *ids)
-{
- OCSP_CERTID *id;
-
- if (!issuer)
- return 0;
- if (!*req)
- *req = OCSP_REQUEST_new();
- if (!*req)
- return 0;
- id = OCSP_cert_to_id(NULL, cert, issuer);
- if (!id || !sk_OCSP_CERTID_push(ids, id))
- return 0;
- if (!OCSP_request_add0_id(*req, id))
- return 0;
- else
- return 1;
-}
-
-
-/* Creates the APR socket and connect to the hostname. Returns the
- socket or NULL if there is an error.
-*/
-static apr_socket_t *make_socket(char *hostname, int port, apr_pool_t *mp)
-{
- apr_sockaddr_t *sa_in;
- apr_status_t status;
- apr_socket_t *sock = NULL;
-
-
- status = apr_sockaddr_info_get(&sa_in, hostname, APR_INET, port, 0, mp);
-
- if (status == APR_SUCCESS)
- status = apr_socket_create(&sock, sa_in->family, SOCK_STREAM, APR_PROTO_TCP, mp);
- if (status == APR_SUCCESS)
- status = apr_socket_connect(sock, sa_in);
-
- if (status == APR_SUCCESS)
- return sock;
- return NULL;
-}
-
-
-/* Creates the request in a memory BIO in order to send it to the OCSP server.
- Most parts of this function are taken from mod_ssl support for OCSP (with some
- minor modifications
-*/
-static BIO *serialize_request(OCSP_REQUEST *req, char *host, int port, char *path)
-{
- BIO *bio;
- int len;
-
- len = i2d_OCSP_REQUEST(req, NULL);
-
- bio = BIO_new(BIO_s_mem());
-
- BIO_printf(bio, "POST %s HTTP/1.0\r\n"
- "Host: %s:%d\r\n"
- "Content-Type: application/ocsp-request\r\n"
- "Content-Length: %d\r\n"
- "\r\n",
- path, host, port, len);
-
- if (i2d_OCSP_REQUEST_bio(bio, req) != 1) {
- BIO_free(bio);
- return NULL;
- }
-
- return bio;
-}
-
-
-/* Send the OCSP request to the OCSP server. Taken from mod_ssl OCSP support */
-static int ocsp_send_req(apr_socket_t *sock, BIO *req)
-{
- int len;
- char buf[TCN_BUFFER_SZ];
- apr_status_t rv;
- int ok = 1;
-
- while ((len = BIO_read(req, buf, sizeof buf)) > 0) {
- char *wbuf = buf;
- apr_size_t remain = len;
-
- do {
- apr_size_t wlen = remain;
- rv = apr_socket_send(sock, wbuf, &wlen);
- wbuf += remain;
- remain -= wlen;
- } while (rv == APR_SUCCESS && remain > 0);
-
- if (rv != APR_SUCCESS) {
- apr_socket_close(sock);
- ok = 0;
- }
- }
-
- return ok;
-}
-
-
-
-/* Parses the buffer from the response and extracts the OCSP response.
- Taken from openssl library */
-static OCSP_RESPONSE *parse_ocsp_resp(char *buf, int len)
-{
- BIO *mem = NULL;
- char tmpbuf[1024];
- OCSP_RESPONSE *resp = NULL;
- char *p, *q, *r;
- int retcode;
-
- mem = BIO_new(BIO_s_mem());
- if(mem == NULL)
- return NULL;
-
- BIO_write(mem, buf, len); /* write the buffer to the bio */
- if (BIO_gets(mem, tmpbuf, 512) <= 0) {
- OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
- goto err;
- }
- /* Parse the HTTP response. This will look like this:
- * "HTTP/1.0 200 OK". We need to obtain the numeric code and
- * (optional) informational message.
- */
-
- /* Skip to first white space (passed protocol info) */
- for (p = tmpbuf; *p && !apr_isspace(*p); p++)
- continue;
- if (!*p) {
- goto err;
- }
- /* Skip past white space to start of response code */
- while (apr_isspace(*p))
- p++;
- if (!*p) {
- goto err;
- }
- /* Find end of response code: first whitespace after start of code */
- for (q = p; *q && !apr_isspace(*q); q++)
- continue;
- if (!*q) {
- goto err;
- }
- /* Set end of response code and start of message */
- *q++ = 0;
- /* Attempt to parse numeric code */
- retcode = strtoul(p, &r, 10);
- if (*r)
- goto err;
- /* Skip over any leading white space in message */
- while (apr_isspace(*q))
- q++;
- if (*q) {
- /* Finally zap any trailing white space in message (include CRLF) */
- /* We know q has a non white space character so this is OK */
- for(r = q + strlen(q) - 1; apr_isspace(*r); r--) *r = 0;
- }
- if (retcode != 200) {
- goto err;
- }
- /* Find blank line marking beginning of content */
- while (BIO_gets(mem, tmpbuf, 512) > 0) {
- for (p = tmpbuf; apr_isspace(*p); p++)
- continue;
- if (!*p)
- break;
- }
- if (*p) {
- goto err;
- }
- if (!(resp = d2i_OCSP_RESPONSE_bio(mem, NULL))) {
- goto err;
- }
-err:
- BIO_free(mem);
- return resp;
-}
-
-
-/* Reads the respnse from the APR socket to a buffer, and parses the buffer to
- return the OCSP response */
-#define ADDLEN 512
-static OCSP_RESPONSE *ocsp_get_resp(apr_socket_t *sock)
-{
- int buflen;
- apr_size_t totalread = 0;
- apr_size_t readlen;
- char *buf, tmpbuf[ADDLEN];
- apr_status_t rv = APR_SUCCESS;
- apr_pool_t *p;
- OCSP_RESPONSE *resp;
-
- apr_pool_create(&p, NULL);
- buflen = ADDLEN;
- buf = apr_palloc(p, buflen);
- if (buf == NULL) {
- apr_pool_destroy(p);
- return NULL;
- }
-
- while (rv == APR_SUCCESS ) {
- readlen = sizeof(tmpbuf);
- rv = apr_socket_recv(sock, tmpbuf, &readlen);
- if (rv == APR_SUCCESS) { /* if we have read something .. we can put it in the buffer*/
- if ((totalread + readlen) >= buflen) {
- buf = apr_xrealloc(buf, buflen, buflen + ADDLEN, p);
- if (buf == NULL) {
- apr_pool_destroy(p);
- return NULL;
- }
- buflen += ADDLEN; /* if needed we enlarge the buffer */
- }
- memcpy(buf + totalread, tmpbuf, readlen); /* the copy to the buffer */
- totalread += readlen; /* update the total bytes read */
- }
- else {
- if (rv == APR_EOF && readlen == 0)
- ; /* EOF, normal situation */
- else if (readlen == 0) {
- /* Not success, and readlen == 0 .. some error */
- apr_pool_destroy(p);
- return NULL;
- }
- }
- }
-
- resp = parse_ocsp_resp(buf, buflen);
- apr_pool_destroy(p);
- return resp;
-}
-
-/* Creates and OCSP request and returns the OCSP_RESPONSE */
-static OCSP_RESPONSE *get_ocsp_response(X509 *cert, X509 *issuer, char *url)
-{
- OCSP_RESPONSE *ocsp_resp = NULL;
- OCSP_REQUEST *ocsp_req = NULL;
- BIO *bio_req;
- char *hostname, *path, *c_port;
- int port, use_ssl;
- STACK_OF(OCSP_CERTID) *ids = NULL;
- int ok = 0;
- apr_socket_t *apr_sock = NULL;
- apr_pool_t *mp;
-
- apr_pool_create(&mp, NULL);
- ids = sk_OCSP_CERTID_new_null();
-
- /* problem parsing the URL */
- if (OCSP_parse_url(url,&hostname, &c_port, &path, &use_ssl) == 0 ) {
- sk_OCSP_CERTID_free(ids);
- return NULL;
- }
-
- /* Create the OCSP request */
- if (sscanf(c_port, "%d", &port) != 1)
- goto end;
- ocsp_req = OCSP_REQUEST_new();
- if (ocsp_req == NULL)
- return NULL;
- if (add_ocsp_cert(&ocsp_req,cert,issuer,ids) == 0 )
- goto free_req;
-
- /* create the BIO with the request to send */
- bio_req = serialize_request(ocsp_req, hostname, port, path);
- if (bio_req == NULL) {
- goto free_req;
- }
-
- apr_sock = make_socket(hostname, port, mp);
- if (apr_sock == NULL) {
- ocsp_resp = NULL;
- goto free_bio;
- }
-
- ok = ocsp_send_req(apr_sock, bio_req);
- if (ok)
- ocsp_resp = ocsp_get_resp(apr_sock);
-
-free_bio:
- BIO_free(bio_req);
-
-free_req:
- if(apr_sock && ok) /* if ok == 0 we have already closed the socket */
- apr_socket_close(apr_sock);
-
- apr_pool_destroy(mp);
-
- sk_OCSP_CERTID_free(ids);
- OCSP_REQUEST_free(ocsp_req);
-
-end:
- return ocsp_resp;
-}
-
-/* Process the OCSP_RESPONSE and returns the corresponding
- answert according to the status.
-*/
-static int process_ocsp_response(OCSP_RESPONSE *ocsp_resp)
-{
- int r, o = V_OCSP_CERTSTATUS_UNKNOWN, i;
- OCSP_BASICRESP *bs;
- OCSP_SINGLERESP *ss;
-
- r = OCSP_response_status(ocsp_resp);
-
- if (r != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
- OCSP_RESPONSE_free(ocsp_resp);
- return OCSP_STATUS_UNKNOWN;
- }
- bs = OCSP_response_get1_basic(ocsp_resp);
-
- ss = OCSP_resp_get0(bs,0); /* we know we have only 1 request */
-
- i = OCSP_single_get0_status(ss, NULL, NULL, NULL, NULL);
- if (i == V_OCSP_CERTSTATUS_GOOD)
- o = OCSP_STATUS_OK;
- else if (i == V_OCSP_CERTSTATUS_REVOKED)
- o = OCSP_STATUS_REVOKED;
- else if (i == V_OCSP_CERTSTATUS_UNKNOWN)
- o = OCSP_STATUS_UNKNOWN;
-
- /* we clean up */
- OCSP_RESPONSE_free(ocsp_resp);
- return o;
-}
-
-static int ssl_ocsp_request(X509 *cert, X509 *issuer)
-{
- char **ocsp_urls = NULL;
- int nid;
- X509_EXTENSION *ext;
- ASN1_OCTET_STRING *os;
- apr_pool_t *p;
-
- apr_pool_create(&p, NULL);
-
- /* Get the proper extension */
- nid = X509_get_ext_by_NID(cert,NID_info_access,-1);
- if (nid >= 0 ) {
- ext = X509_get_ext(cert,nid);
- os = X509_EXTENSION_get_data(ext);
-
- ocsp_urls = decode_OCSP_url(os, p);
- }
-
- /* if we find the extensions and we can parse it check
- the ocsp status. Otherwise, return OCSP_STATUS_UNKNOWN */
- if (ocsp_urls != NULL) {
- OCSP_RESPONSE *resp;
- /* for the time being just check for the fist response .. a better
- approach is to iterate for all the possible ocsp urls */
- resp = get_ocsp_response(cert, issuer, ocsp_urls[0]);
-
- if (resp != NULL) {
- apr_pool_destroy(p);
- return process_ocsp_response(resp);
- }
- }
- apr_pool_destroy(p);
- return OCSP_STATUS_UNKNOWN;
-}
-
-#endif /* HAS_OCSP_ENABLED */
-#endif /* HAVE_OPENSSL */
« no previous file with comments | « c/sslnetwork.c ('k') | c/stdlib.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698