From 5edf578010d0a319a5362cc6743e228f7300d787 Mon Sep 17 00:00:00 2001 From: Perry Werneck Date: Tue, 15 Oct 2019 15:11:58 -0300 Subject: [PATCH] Still refactoring the CRL download methods. --- lib3270.cbp | 3 +++ src/core/connect.c | 34 ++-------------------------------- src/core/properties/string.c | 7 +++++++ src/core/session.c | 6 ++++++ src/include/lib3270-internals.h | 10 +++++++--- src/include/lib3270.h | 4 +++- src/ssl/crl.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ssl/linux/getcrl.c | 2 -- src/ssl/linux/ldap.c | 2 +- src/ssl/negotiate.c | 100 +++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------- src/ssl/properties.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/ssl/windows/getcrl.c | 2 -- src/testprogram/testprogram.c | 1 + 13 files changed, 304 insertions(+), 100 deletions(-) create mode 100644 src/ssl/crl.c diff --git a/lib3270.cbp b/lib3270.cbp index a2a962a..a99e29a 100644 --- a/lib3270.cbp +++ b/lib3270.cbp @@ -301,6 +301,9 @@ + + diff --git a/src/core/connect.c b/src/core/connect.c index a7b04f8..40d3745 100644 --- a/src/core/connect.c +++ b/src/core/connect.c @@ -55,7 +55,6 @@ } -#ifdef SSL_ENABLE_CRL_CHECK static int background_ssl_crl_get(H3270 *hSession, void *ssl_error) { if(ssl_ctx_init(hSession, (SSL_ERROR_MESSAGE *) ssl_error)) { @@ -105,39 +104,11 @@ static int background_ssl_crl_get(H3270 *hSession, void *ssl_error) // // https://stackoverflow.com/questions/10510850/how-to-verify-the-certificate-for-the-ongoing-ssl-session // - trace_ssl(hSession,"Getting CRL from %s\n",lib3270_get_crl_url(hSession)); - - hSession->ssl.crl.cert = lib3270_get_crl(hSession,(SSL_ERROR_MESSAGE *) ssl_error,lib3270_get_crl_url(hSession)); - if(hSession->ssl.crl.cert) - { - // Got CRL, add it to ssl store - if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) - { - lib3270_autoptr(char) text = lib3270_get_ssl_crl_text(hSession); - - if(text) - trace_ssl(hSession,"\n%s\n",text); - - } - - // Add CRL in the store. - X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx); - if(X509_STORE_add_crl(store, hSession->ssl.crl.cert)) - { - trace_ssl(hSession,"CRL was added to cert store\n"); - } - else - { - trace_ssl(hSession,"CRL was not added to cert store\n"); - } - - - } - - return 0; + return lib3270_get_crl_from_url(hSession, ssl_error, lib3270_get_crl_url(hSession)); } +#ifdef SSL_ENABLE_CRL_CHECK static int notify_crl_error(H3270 *hSession, int rc, const SSL_ERROR_MESSAGE *message) { lib3270_write_log( @@ -181,7 +152,6 @@ static int notify_crl_error(H3270 *hSession, int rc, const SSL_ERROR_MESSAGE *me return 0; } - #endif // SSL_ENABLE_CRL_CHECK int lib3270_reconnect(H3270 *hSession, int seconds) diff --git a/src/core/properties/string.c b/src/core/properties/string.c index 7802b27..d46d3d9 100644 --- a/src/core/properties/string.c +++ b/src/core/properties/string.c @@ -136,6 +136,13 @@ }, { + .name = "crlprefer", // Property name. + .description = N_( "Prefered protocol for CRL" ), // Property description. + .get = lib3270_get_crl_prefered_protocol, // Get value. + .set = lib3270_set_crl_prefered_protocol, // Set value. + }, + + { .name = "default_host", // Property name. .description = N_( "Default host URL" ), // Property description. .get = lib3270_get_default_host, // Get value. diff --git a/src/core/session.c b/src/core/session.c index a46a0aa..aa0d6be 100644 --- a/src/core/session.c +++ b/src/core/session.c @@ -82,6 +82,12 @@ void lib3270_session_free(H3270 *h) h->ssl.crl.url = NULL; } + if(h->ssl.crl.prefer) + { + free(h->ssl.crl.prefer); + h->ssl.crl.prefer = NULL; + } + if(h->ssl.crl.cert) { X509_CRL_free(h->ssl.crl.cert); diff --git a/src/include/lib3270-internals.h b/src/include/lib3270-internals.h index e430be1..90bd6ae 100644 --- a/src/include/lib3270-internals.h +++ b/src/include/lib3270-internals.h @@ -41,6 +41,8 @@ #if defined(HAVE_LIBSSL) #include + #include + #endif // HAVE_LIBSSL #if defined(X3270_TN3270E) && !defined(X3270_ANSI) /*[*/ @@ -693,8 +695,9 @@ struct _h3270 #ifdef SSL_ENABLE_CRL_CHECK struct { - char * url; - X509_CRL * cert; + char * prefer; ///< @brief Prefered protocol for CRL. + char * url; ///< @brief URL for CRL download. + X509_CRL * cert; ///< @brief Loaded CRL (can be null). } crl; #endif // SSL_ENABLE_CRL_CHECK SSL * con; @@ -848,6 +851,8 @@ LIB3270_INTERNAL int non_blocking(H3270 *session, Boolean on); #ifdef SSL_ENABLE_CRL_CHECK LIB3270_INTERNAL X509_CRL * lib3270_get_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); #endif // SSL_ENABLE_CRL_CHECK #endif @@ -862,4 +867,3 @@ LIB3270_INTERNAL int non_blocking(H3270 *session, Boolean on); LIB3270_INTERNAL char * lib3270_get_user_name(); - diff --git a/src/include/lib3270.h b/src/include/lib3270.h index 01b2e26..49f7788 100644 --- a/src/include/lib3270.h +++ b/src/include/lib3270.h @@ -490,9 +490,11 @@ * */ LIB3270_EXPORT int lib3270_set_crl_url(H3270 *hSession, const char *crl); - LIB3270_EXPORT const char * lib3270_get_crl_url(const H3270 *hSession); + LIB3270_EXPORT int lib3270_set_crl_prefered_protocol(H3270 *hSession, const char *protocol); + LIB3270_EXPORT const char * lib3270_get_crl_prefered_protocol(H3270 *hSession); + /** * @brief Get hostname for the connect/reconnect operations. * diff --git a/src/ssl/crl.c b/src/ssl/crl.c new file mode 100644 index 0000000..5281056 --- /dev/null +++ b/src/ssl/crl.c @@ -0,0 +1,184 @@ +/* + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a + * aplicativos mainframe. Registro no INPI sob o nome G3270. + * + * Copyright (C) <2008> + * + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela + * Free Software Foundation. + * + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para + * obter mais detalhes. + * + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Este programa está nomeado como - e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) + * + */ + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_LIBSSL + #include + #include +#endif // HAVE_LIBSSL + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +#ifdef SSL_ENABLE_CRL_CHECK +int lib3270_get_crl_from_url(H3270 *hSession, void *ssl_error, const char *url) +{ + + if(!(url && *url)) + return -1; + + // Invalidate current certificate. + if(hSession->ssl.crl.cert) + { + trace_ssl(hSession,"%s\n","Discarding current CRL"); + X509_CRL_free(hSession->ssl.crl.cert); + hSession->ssl.crl.cert = NULL; + } + + // + // Get the new CRL + // + // https://stackoverflow.com/questions/10510850/how-to-verify-the-certificate-for-the-ongoing-ssl-session + // + trace_ssl(hSession,"Getting new CRL from %s\n",url); + + hSession->ssl.crl.cert = lib3270_get_crl(hSession,(SSL_ERROR_MESSAGE *) ssl_error,url); + + if(hSession->ssl.crl.cert) + { + // Got CRL, add it to ssl store + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) + { + lib3270_autoptr(char) text = lib3270_get_ssl_crl_text(hSession); + + if(text) + trace_ssl(hSession,"\n%s\n",text); + + } + + // Add CRL in the store. + X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx); + if(X509_STORE_add_crl(store, hSession->ssl.crl.cert)) + { + trace_ssl(hSession,"CRL was added to context cert store\n"); + } + else + { + trace_ssl(hSession,"CRL was not added to context cert store\n"); + } + + return 0; + } + + return -1; + +} +#endif // SSL_ENABLE_CRL_CHECK + +#if !defined(SSL_DEFAULT_CRL_URL) && defined(SSL_ENABLE_CRL_CHECK) +int lib3270_get_crl_from_dist_points(H3270 *hSession, CRL_DIST_POINTS * dist_points, void *ssl_error) +{ + size_t ix; + int i, gtype; + lib3270_autoptr(LIB3270_STRING_ARRAY) uris = lib3270_string_array_new(); + + // https://nougat.cablelabs.com/DLNA-RUI/openssl/commit/57912ed329f870b237f2fd9f2de8dec3477d1729 + + 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) + { + const unsigned char * data = ASN1_STRING_get0_data(uri); + 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 we already have the URL. + if(!strcmp(hSession->ssl.crl.url,uris->str[ix])) + { + trace_ssl(hSession,"Keeping CRL from %s\n",hSession->ssl.crl.url); + return 0; + } + + // 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_get_crl_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_get_crl_from_url(hSession, ssl_error, uris->str[ix]) == 0) + return 0; + } + + return -1; +} +#endif // !SSL_DEFAULT_CRL_URL && SSL_ENABLE_CRL_CHECK diff --git a/src/ssl/linux/getcrl.c b/src/ssl/linux/getcrl.c index 27df0f4..ed201be 100644 --- a/src/ssl/linux/getcrl.c +++ b/src/ssl/linux/getcrl.c @@ -59,8 +59,6 @@ LIB3270_INTERNAL X509_CRL * lib3270_get_crl(H3270 *hSession, SSL_ERROR_MESSAGE * return NULL; } - trace_ssl(hSession, "Getting CRL from \"%s\"\n",consturl); - if(strncasecmp(consturl,"file://",7) == 0) { lib3270_autoptr(FILE) hCRL = fopen(consturl+7,"r"); diff --git a/src/ssl/linux/ldap.c b/src/ssl/linux/ldap.c index 789ab0f..2c32958 100644 --- a/src/ssl/linux/ldap.c +++ b/src/ssl/linux/ldap.c @@ -88,7 +88,7 @@ LIB3270_INTERNAL X509_CRL * get_crl_using_ldap(H3270 *hSession, SSL_ERROR_MESSAG X509_CRL * x509_crl = NULL; int rc; - lib3270_autoptr(char) url = strdup(consturl); + lib3270_autoptr(char) url = lib3270_unescape(consturl); char * base = strchr(url+7,'/'); char * attrs[] = { NULL, NULL }; diff --git a/src/ssl/negotiate.c b/src/ssl/negotiate.c index c31b359..1e4bdee 100644 --- a/src/ssl/negotiate.c +++ b/src/ssl/negotiate.c @@ -134,67 +134,27 @@ static int background_ssl_init(H3270 *hSession, void *message) } #if !defined(SSL_DEFAULT_CRL_URL) && defined(SSL_ENABLE_CRL_CHECK) - -static int getCRLFromDistPoints(H3270 *hSession, CRL_DIST_POINTS * dist_points, SSL_ERROR_MESSAGE *message) +int x509_store_ctx_error_callback(int ok, X509_STORE_CTX *ctx) { - int ix, i, gtype; - lib3270_autoptr(LIB3270_STRING_ARRAY) uris = lib3270_string_array_new(); - - // https://nougat.cablelabs.com/DLNA-RUI/openssl/commit/57912ed329f870b237f2fd9f2de8dec3477d1729 - - for(ix = 0; ix < 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; + debug("%s(%d)",__FUNCTION__,ok); - 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) - { - const unsigned char * data = ASN1_STRING_get0_data(uri); - 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 we already have the URL. - - - // The URL is invalid or not to this cert, remove it! - lib3270_free(hSession->ssl.crl.url); - hSession->ssl.crl.url = NULL; - } - */ - - - return 0; +/* + 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_DEFAULT_CRL_URL && SSL_ENABLE_CRL_CHECK + static int background_ssl_negotiation(H3270 *hSession, void *message) { int rv; @@ -225,7 +185,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) if (rv != 1) { - const char * msg = ""; + const char * msg = ""; ((SSL_ERROR_MESSAGE *) message)->error = SSL_get_error(hSession->ssl.con,rv); if(((SSL_ERROR_MESSAGE *) message)->error == SSL_ERROR_SYSCALL && hSession->ssl.error) @@ -292,16 +252,38 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) return EACCES; } - if(getCRLFromDistPoints(hSession, dist_points, (SSL_ERROR_MESSAGE *) message)) + if(lib3270_get_crl_from_dist_points(hSession, dist_points, (SSL_ERROR_MESSAGE *) message)) return EACCES; + // Got CRL, verify it! + // Reference: https://stackoverflow.com/questions/10510850/how-to-verify-the-certificate-for-the-ongoing-ssl-session + X509_STORE_CTX *csc = X509_STORE_CTX_new(); + + 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); + + if(X509_verify_cert(csc) != 1) + rv = X509_STORE_CTX_get_error(csc); + else + rv = X509_V_OK; + + X509_STORE_CTX_free(csc); + +#else + // No CRL download, use the standard verification. + rv = SSL_get_verify_result(hSession->ssl.con); + #endif // !SSL_DEFAULT_CRL_URL && SSL_ENABLE_CRL_CHECK } + else + { + rv = SSL_get_verify_result(hSession->ssl.con); + } // Validate certificate. - rv = SSL_get_verify_result(hSession->ssl.con); debug("SSL Verify result was %d", rv); const struct ssl_status_msg * msg = ssl_get_status_from_error_code((long) rv); diff --git a/src/ssl/properties.c b/src/ssl/properties.c index 3f88e9f..80e9b63 100644 --- a/src/ssl/properties.c +++ b/src/ssl/properties.c @@ -174,3 +174,52 @@ LIB3270_EXPORT char * lib3270_get_ssl_peer_certificate_text(const H3270 *hSessio } #pragma GCC diagnostic pop + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunused-parameter" + const char * lib3270_get_crl_prefered_protocol(H3270 *hSession) + { +#ifdef SSL_ENABLE_CRL_CHECK + if(hSession->ssl.crl.prefer) + return hSession->ssl.crl.prefer; +#endif + errno = ENODATA; + return ""; + } + #pragma GCC diagnostic pop + + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunused-parameter" + int lib3270_set_crl_prefered_protocol(H3270 *hSession, const char *protocol) + { + + FAIL_IF_ONLINE(hSession); + +#ifdef SSL_ENABLE_CRL_CHECK + + if(hSession->ssl.crl.prefer) + { + free(hSession->ssl.crl.prefer); + hSession->ssl.crl.prefer = NULL; + } + + if(hSession->ssl.crl.prefer) + { + X509_CRL_free(hSession->ssl.crl.prefer); + hSession->ssl.crl.prefer = NULL; + } + + if(protocol) + { + hSession->ssl.crl.prefer = strdup(protocol); + } + + return 0; + +#else + + return errno = ENOTSUP; + +#endif // SSL_ENABLE_CRL_CHECK + + } + #pragma GCC diagnostic pop diff --git a/src/ssl/windows/getcrl.c b/src/ssl/windows/getcrl.c index 891834d..d9a0907 100644 --- a/src/ssl/windows/getcrl.c +++ b/src/ssl/windows/getcrl.c @@ -65,8 +65,6 @@ LIB3270_INTERNAL X509_CRL * lib3270_get_crl(H3270 *hSession, SSL_ERROR_MESSAGE * return NULL; } - trace_ssl(hSession, "Getting CRL from \"%s\"\n",consturl); - if(strncasecmp(consturl,"file://",7) == 0) { lib3270_autoptr(FILE) hCRL = fopen(consturl+7,"r"); diff --git a/src/testprogram/testprogram.c b/src/testprogram/testprogram.c index 52a20b2..99aa745 100644 --- a/src/testprogram/testprogram.c +++ b/src/testprogram/testprogram.c @@ -43,6 +43,7 @@ int main(int argc, char *argv[]) printf("3270 session %p created\n]",h); + lib3270_set_crl_prefered_protocol(h,"ldap"); lib3270_set_url(h,NULL); int long_index =0; -- libgit2 0.21.2