diff --git a/src/ssl/crl.c b/src/ssl/crl.c index 2ae8282..920a3e5 100644 --- a/src/ssl/crl.c +++ b/src/ssl/crl.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "crl.h" @@ -141,4 +142,126 @@ int lib3270_crl_new_from_url(H3270 *hSession, void *ssl_error, const char *url) } +/// @brief Load CRL from X509 certificate. +int lib3270_crl_new_from_x509(H3270 *hSession, void *ssl_error, X509 *cert) +{ + // References: + // + // http://www.zedwood.com/article/cpp-check-crl-for-revocation + // + lib3270_autoptr(CRL_DIST_POINTS) dist_points = (CRL_DIST_POINTS *) X509_get_ext_d2i(cert, NID_crl_distribution_points, NULL, NULL); + + if(!dist_points) + { + ((SSL_ERROR_MESSAGE *) ssl_error)->title = _( "Security error" ); + ((SSL_ERROR_MESSAGE *) ssl_error)->text = _( "Can't verify." ); + ((SSL_ERROR_MESSAGE *) ssl_error)->description = _( "The host certificate doesn't have CRL distribution points" ); + return EACCES; + } + + if(lib3270_crl_new_from_dist_points(hSession, ssl_error, dist_points)) + return EACCES; + + return 0; +} + +int lib3270_crl_new_from_dist_points(H3270 *hSession, void *ssl_error, CRL_DIST_POINTS * dist_points) +{ + // + // Reference: + // + // https://nougat.cablelabs.com/DLNA-RUI/openssl/commit/57912ed329f870b237f2fd9f2de8dec3477d1729 + // + size_t ix; + int i, gtype; + + lib3270_autoptr(LIB3270_STRING_ARRAY) uris = lib3270_string_array_new(); + + for(ix = 0; ix < (size_t) sk_DIST_POINT_num(dist_points); ix++) { + + DIST_POINT *dp = sk_DIST_POINT_value(dist_points, ix); + + if(!dp->distpoint || dp->distpoint->type != 0) + continue; + + GENERAL_NAMES *gens = dp->distpoint->name.fullname; + + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) + { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(gens, i); + ASN1_STRING *uri = GENERAL_NAME_get0_value(gen, >ype); + if(uri) + { +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) // OpenSSL 1.1.0+ + const unsigned char * data = ASN1_STRING_get0_data(uri); +#else + const unsigned char * data = ASN1_STRING_data(uri); // ASN1_STRING_get0_data(uri); +#endif // OpenSSL 1.1.0+ + if(data) + { + lib3270_string_array_append(uris,(char *) data); + } + } + + } + + } + +#ifdef DEBUG + { + for(ix = 0; ix < uris->length; ix++) + { + debug("%u: %s", (unsigned int) ix, uris->str[ix]); + } + } +#endif // DEBUG + + if(hSession->ssl.crl.url) + { + // Check if the current URL is still valid. + for(ix = 0; ix < uris->length; ix++) + { + if(!strcmp(hSession->ssl.crl.url,uris->str[ix])) + { + trace_ssl(hSession,"Keeping CRL from %s\n",hSession->ssl.crl.url); + return 0; + } + } + + trace_ssl(hSession,"Discarding invalid CRL from %s\n",hSession->ssl.crl.url); + + // The URL is invalid or not to this cert, remove it! + lib3270_free(hSession->ssl.crl.url); + hSession->ssl.crl.url = NULL; + } + + if(hSession->ssl.crl.prefer && *hSession->ssl.crl.prefer) + { + size_t length = strlen(hSession->ssl.crl.prefer); + + for(ix = 0; ix < uris->length; ix++) + { + if(!strncmp(uris->str[ix],hSession->ssl.crl.prefer,length)) + { + trace_ssl(hSession,"Trying preferred URL %s\n",uris->str[ix]); + if(lib3270_crl_new_from_url(hSession, ssl_error, uris->str[ix]) == 0) + return 0; + } + + } + + } + + // Can't load, try all of them. + for(ix = 0; ix < uris->length; ix++) + { + trace_ssl(hSession,"Trying CRL from %s\n",uris->str[ix]); + if(lib3270_crl_new_from_url(hSession, ssl_error, uris->str[ix]) == 0) + return 0; + } + + return -1; + +} + #endif // SSL_ENABLE_CRL_CHECK && HAVE_LIBSSL diff --git a/src/ssl/crl.h b/src/ssl/crl.h index 8f1761c..5c9d12b 100644 --- a/src/ssl/crl.h +++ b/src/ssl/crl.h @@ -49,10 +49,32 @@ /// @brief Load CRL from URL. LIB3270_INTERNAL int lib3270_crl_new_from_url(H3270 *hSession, void *ssl_error, const char *url); + /// @brief Load CRL from X509 certificate. + LIB3270_INTERNAL int lib3270_crl_new_from_x509(H3270 *hSession, void *ssl_error, X509 *cert); + + /// @brief Load CRL from distribution points. + LIB3270_INTERNAL int lib3270_crl_new_from_dist_points(H3270 *hSession, void *ssl_error, CRL_DIST_POINTS * dist_points); LIB3270_INTERNAL X509_CRL * lib3270_download_crl(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *url); -// LIB3270_INTERNAL int lib3270_get_crl_from_url(H3270 *hSession, void *ssl_error, const char *url); -// LIB3270_INTERNAL int lib3270_get_crl_from_dist_points(H3270 *hSession, CRL_DIST_POINTS * dist_points, void *ssl_error); + + /** + * @brief X509 auto-cleanup. + */ + static inline void lib3270_autoptr_cleanup_X509(X509 **ptr) + { + if(*ptr) + X509_free(*ptr); + } + + /** + * @brief Dist points auto-cleanup. + */ + static inline void lib3270_autoptr_cleanup_CRL_DIST_POINTS(CRL_DIST_POINTS **ptr) + { + if(*ptr) + CRL_DIST_POINTS_free(*ptr); + } + #endif // SSL_ENABLE_CRL_CHECK && HAVE_LIBSSL diff --git a/src/ssl/negotiate.c b/src/ssl/negotiate.c index 0d22bac..d392a47 100644 --- a/src/ssl/negotiate.c +++ b/src/ssl/negotiate.c @@ -42,7 +42,6 @@ #include #include #include - #include #ifndef SSL_ST_OK #define SSL_ST_OK 3 @@ -77,24 +76,6 @@ */ SSL_CTX * ssl_ctx = NULL; - /** - * @brief X509 auto-cleanup. - */ -static inline void lib3270_autoptr_cleanup_X509(X509 **ptr) -{ - if(*ptr) - X509_free(*ptr); -} - - /** - * @brief Dist points auto-cleanup. - */ -static inline void lib3270_autoptr_cleanup_CRL_DIST_POINTS(CRL_DIST_POINTS **ptr) -{ - if(*ptr) - CRL_DIST_POINTS_free(*ptr); -} - /** * @brief Initialize openssl session. * @@ -135,7 +116,7 @@ static int background_ssl_init(H3270 *hSession, void *message) return 0; } -#if !defined(SSL_CRL_URL) && defined(SSL_ENABLE_CRL_CHECK) +#if defined(SSL_ENABLE_CRL_CHECK) int x509_store_ctx_error_callback(int ok, X509_STORE_CTX GNUC_UNUSED(*ctx)) { debug("%s(%d)",__FUNCTION__,ok); @@ -154,26 +135,7 @@ int x509_store_ctx_error_callback(int ok, X509_STORE_CTX GNUC_UNUSED(*ctx)) */ return ok; } -#endif // !SSL_CRL_URL && SSL_ENABLE_CRL_CHECK - -static int x509_store_ctx_error_callback(int ok, X509_STORE_CTX GNUC_UNUSED(*ctx)) -{ - debug("%s(%d)",__FUNCTION__,ok); - -/* - 55 { - 56 if (!ok) { - 57 Category::getInstance("OpenSSL").error( - 58 "path validation failure at depth(%d): %s", - 59 X509_STORE_CTX_get_error_depth(ctx), - 60 X509_verify_cert_error_string(X509_STORE_CTX_get_error(ctx)) - 61 ); - 62 } - 63 return ok; - 64 } -*/ - return ok; -} +#endif // SSL_ENABLE_CRL_CHECK static int background_ssl_negotiation(H3270 *hSession, void *message) { @@ -199,6 +161,14 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) return -1; } +#ifdef SSL_CRL_URL + + // Load CRL from pre-defined URL + if(lib3270_crl_new_from_url(hSession, message, SSL_CRL_URL)) + return EACCES; + +#endif // SSL_CRL_URL + trace_ssl(hSession, "%s","Running SSL_connect\n"); rv = SSL_connect(hSession->ssl.con); trace_ssl(hSession, "SSL_connect exits with rc=%d\n",rv); @@ -254,13 +224,15 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) hSession->cbk.set_peer_certificate(peer); -#ifdef SSL_CRL_URL +#ifdef SSL_ENABLE_CRL_CHECK - // Load CRL from pre-defined URL - if(lib3270_crl_new_from_url(hSession, message, SSL_CRL_URL)) - return EACCES; + if(!hSession->ssl.crl.cert) + { + if(lib3270_crl_new_from_x509(hSession, message, peer)) + return EACCES; + } -#endif // SSL_CRL_URL +#endif // SSL_ENABLE_CRL_CHECK } @@ -272,10 +244,6 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) // // No default CRL, try to download from the peer // - // References: - // - // http://www.zedwood.com/article/cpp-check-crl-for-revocation - // lib3270_autoptr(CRL_DIST_POINTS) dist_points = (CRL_DIST_POINTS *) X509_get_ext_d2i(peer, NID_crl_distribution_points, NULL, NULL); if(!dist_points) @@ -317,8 +285,9 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) } */ - if(SSL_get_verify_result(hSession->ssl.con) == X509_V_ERR_UNABLE_TO_GET_CRL && hSession->ssl.crl.cert) + if(SSL_get_verify_result(hSession->ssl.con) == X509_V_ERR_UNABLE_TO_GET_CRL && hSession->ssl.crl.cert && peer) { + // // Verify CRL // // References: @@ -334,30 +303,17 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) X509_STORE_CTX_set_verify_cb(csc, x509_store_ctx_error_callback); X509_STORE_CTX_init(csc, SSL_CTX_get_cert_store(ssl_ctx), peer, NULL); -/* -#ifdef SSL_ENABLE_CRL_CHECK - // Enable CRL check - X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new(); - X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK); - X509_STORE_CTX_set0_param(csc, param); -#endif // SSL_ENABLE_CRL_CHECK -*/ - if(X509_verify_cert(csc) != 1) rv = X509_STORE_CTX_get_error(csc); else rv = X509_V_OK; - debug("CRL Check response was %d", rv); + trace_ssl(hSession, "X509_verify_cert error code was %d", rv); SSL_set_verify_result(hSession->ssl.con, rv); X509_STORE_CTX_free(csc); -#ifdef SSL_ENABLE_CRL_CHECK -// X509_VERIFY_PARAM_free(param); -#endif // SSL_ENABLE_CRL_CHECK - } // Check validation state. @@ -393,14 +349,14 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) set_ssl_state(hSession,LIB3270_SSL_NEGOTIATED); - #ifdef SSL_ENABLE_SELF_SIGNED_CERT_CHECK +#ifdef SSL_ENABLE_SELF_SIGNED_CERT_CHECK ((SSL_ERROR_MESSAGE *) message)->title = _( "Security error" ); ((SSL_ERROR_MESSAGE *) message)->text = _( "The SSL certificate for this host is not trusted." ); ((SSL_ERROR_MESSAGE *) message)->description = _( "The security certificate presented by this host was not issued by a trusted certificate authority." ); return EACCES; - #else +#else break; - #endif // SSL_ENABLE_SELF_SIGNED_CERT_CHECK +#endif // SSL_ENABLE_SELF_SIGNED_CERT_CHECK default: trace_ssl(hSession,"TLS/SSL verify result was %d (%s)\n", rv, msg->description); -- libgit2 0.21.2