From a81e00e1497f1052589281acf85f3fa2d262399a Mon Sep 17 00:00:00 2001 From: Perry Werneck Date: Thu, 6 Aug 2020 14:49:24 -0300 Subject: [PATCH] Reactivating CRL download from LDAP server. --- lib3270.cbp | 3 +++ src/core/linux/ldap.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/linux/private.h | 4 ++++ src/core/popup.c | 2 +- src/include/internals.h | 13 ++++++++++++- src/include/networking.h | 1 + src/network_modules/openssl/start.c | 72 ++++++++++++++++++++++++++++++++++++++++++------------------------------ 7 files changed, 243 insertions(+), 32 deletions(-) create mode 100644 src/core/linux/ldap.c diff --git a/lib3270.cbp b/lib3270.cbp index bde1d60..5a3de9c 100644 --- a/lib3270.cbp +++ b/lib3270.cbp @@ -134,6 +134,9 @@ + + diff --git a/src/core/linux/ldap.c b/src/core/linux/ldap.c new file mode 100644 index 0000000..306b221 --- /dev/null +++ b/src/core/linux/ldap.c @@ -0,0 +1,180 @@ +/* + * "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 + +#if defined(HAVE_LDAP) && defined HAVE_LIBSSL + +#include +#include +#include +#include +#include +#include + +#define LDAP_DEPRECATED 1 +#include + +typedef char LDAPPTR; + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +static inline void lib3270_autoptr_cleanup_LDAPMessage(LDAPMessage **message) +{ + debug("%s(%p)",__FUNCTION__,*message); + if(message) + ldap_msgfree(*message); + *message = NULL; +} + +static inline void lib3270_autoptr_cleanup_LDAP(LDAP **ld) +{ + debug("%s(%p)",__FUNCTION__,*ld); + if(*ld) + ldap_unbind_ext(*ld, NULL, NULL); + *ld = NULL; +} + +static inline void lib3270_autoptr_cleanup_BerElement(BerElement **ber) +{ + debug("%s(%p)",__FUNCTION__,*ber); + if(*ber) + ber_free(*ber, 0); + *ber = NULL; +} + +static inline void lib3270_autoptr_cleanup_LDAPPTR(char **ptr) +{ + debug("%s(%p)",__FUNCTION__,*ptr); + if(*ptr) + ldap_memfree(*ptr); + *ptr = NULL; +} + +X509_CRL * lib3270_crl_get_using_ldap(H3270 *hSession, const char *url, const char **error) { + + // Get attributes + char * attrs[] = { NULL, NULL }; + char * base = strchr(url+7,'/'); + if(!base) { + *error = _( "The URL argument should be in the format ldap://[HOST]/[DN]?attribute" ); + errno = EINVAL; + return NULL; + } + + *(base++) = 0; + attrs[0] = strchr(base,'?'); + + if(!base) { + *error = _( "The URL argument should be in the format ldap://[HOST]/[DN]?attribute" ); + errno = EINVAL; + return NULL; + } + + *(attrs[0]++) = 0; + + debug("host: \"%s\"",url); + debug("Base: \"%s\"",base); + debug("Attr: \"%s\"",attrs[0]); + + // Do LDAP Query + lib3270_autoptr(LDAP) ld = NULL; + lib3270_autoptr(BerElement) ber = NULL; + + int rc = ldap_initialize(&ld, url); + if(rc != LDAP_SUCCESS) { + *error = ldap_err2string(rc); + return NULL; + } + + unsigned long version = LDAP_VERSION3; + rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,(void *) &version); + if(rc != LDAP_SUCCESS) { + *error = ldap_err2string(rc); + return NULL; + } + + rc = ldap_simple_bind_s(ld, "", ""); + if(rc != LDAP_SUCCESS) { + *error = ldap_err2string(rc); + return NULL; + } + + lib3270_autoptr(LDAPMessage) results = NULL; + rc = ldap_search_ext_s( + ld, // Specifies the LDAP pointer returned by a previous call to ldap_init(), ldap_ssl_init(), or ldap_open(). + base, // Specifies the DN of the entry at which to start the search. + LDAP_SCOPE_BASE, // Specifies the scope of the search. + NULL, // Specifies a string representation of the filter to apply in the search. + (char **) &attrs, // Specifies a null-terminated array of character string attribute types to return from entries that match filter. + 0, // Should be set to 1 to request attribute types only. Set to 0 to request both attributes types and attribute values. + NULL, + NULL, + NULL, + 0, + &results + ); + + if(rc != LDAP_SUCCESS) { + *error = ldap_err2string(rc); + return NULL; + } + + lib3270_autoptr(LDAPPTR) attr = ldap_first_attribute(ld, results, &ber); + if(!attr) { + *error = _("LDAP search did not produce any attributes."); + errno = ENOENT; + return NULL; + } + + // + // Load CRL + // + struct berval ** value = ldap_get_values_len(ld, results, attr); + if(!value) { + *error =_("LDAP search did not produce any values."); + errno = ENOENT; + return NULL; + } + + X509_CRL * crl = NULL; + + const unsigned char *crl_data = (const unsigned char *) value[0]->bv_val; + + if(!d2i_X509_CRL(&crl, &crl_data, value[0]->bv_len)) { + *error = _( "Can't decode certificate revocation list" ); + } + + ldap_value_free_len(value); + + return crl; + +} + +#endif // HAVE_LDAP diff --git a/src/core/linux/private.h b/src/core/linux/private.h index 9820807..079a675 100644 --- a/src/core/linux/private.h +++ b/src/core/linux/private.h @@ -41,4 +41,8 @@ LIB3270_INTERNAL char * lib3270_url_get_using_curl(H3270 *hSession, const char *u, const char **error); #endif // HAVE_LIBCURL + #if defined(HAVE_LDAP) + LIB3270_INTERNAL char * lib3270_url_get_using_ldap(H3270 *hSession, const char *u, const char **error); + #endif // HAVE_LDAP + #endif // !PRIVATE_H_INCLUDED diff --git a/src/core/popup.c b/src/core/popup.c index 5380080..db75fe4 100644 --- a/src/core/popup.c +++ b/src/core/popup.c @@ -45,7 +45,7 @@ LIB3270_EXPORT int lib3270_popup(H3270 *hSession, const LIB3270_POPUP *popup, un return hSession->cbk.popup(hSession,popup,wait); } -LIB3270_EXPORT int lib3270_popup_translated(H3270 *hSession, const LIB3270_POPUP *popup, unsigned char wait) { +int lib3270_popup_translated(H3270 *hSession, const LIB3270_POPUP *popup, unsigned char wait) { LIB3270_POPUP translated = *popup; diff --git a/src/include/internals.h b/src/include/internals.h index ae51e79..a9b1118 100644 --- a/src/include/internals.h +++ b/src/include/internals.h @@ -888,5 +888,16 @@ LIB3270_INTERNAL void set_ssl_state(H3270 *session, LIB3270_SSL_STATE state); * @retval ECANCELED Operation was canceled. * @retval ENOTSUP No popup handler available. */ - LIB3270_EXPORT int lib3270_popup_translated(H3270 *hSession, const LIB3270_POPUP *popup, unsigned char wait); + LIB3270_INTERNAL int lib3270_popup_translated(H3270 *hSession, const LIB3270_POPUP *popup, unsigned char wait); +#if defined(HAVE_LDAP) && defined (HAVE_LIBSSL) + /** + * @brief Download X509 CRL using LDAP backend. + * + * @param hSession tn3270 session handle. + * @param url URL for Ldap access. + * @param error pointer to error message. + * + */ + LIB3270_INTERNAL X509_CRL * lib3270_crl_get_using_ldap(H3270 *hSession, const char *url, const char **error); +#endif // HAVE_LDAP diff --git a/src/include/networking.h b/src/include/networking.h index a85b646..1407838 100644 --- a/src/include/networking.h +++ b/src/include/networking.h @@ -224,5 +224,6 @@ LIB3270_INTERNAL int lib3270_activate_ssl_network_module(H3270 *hSession, int sock); + #endif // LIB3270_NETWORKING_H_INCLUDED diff --git a/src/network_modules/openssl/start.c b/src/network_modules/openssl/start.c index 5e91535..62906c2 100644 --- a/src/network_modules/openssl/start.c +++ b/src/network_modules/openssl/start.c @@ -35,13 +35,30 @@ #include "private.h" #include - static int import_crl(H3270 *hSession, SSL_CTX * ssl_ctx, LIB3270_NET_CONTEXT * context, const char *crl) { + static int import_crl(H3270 *hSession, SSL_CTX * ssl_ctx, LIB3270_NET_CONTEXT * context, const char *url) { X509_CRL * x509_crl = NULL; - // Import CRL - { - lib3270_autoptr(BIO) bio = BIO_new_mem_buf(crl,-1); + const char *error_message = NULL; + if(strncasecmp(url,"ldap",4) == 0) { + + // Download using LDAP +#ifdef HAVE_LDAP + + x509_crl = lib3270_crl_get_using_ldap(hSession, url, &error_message); + +#else + + *error_message = _("No LDAP support"); + +#endif // HAVE_LDAP + + } else { + + // Download with URL + lib3270_autoptr(char) crl_text = lib3270_url_get(hSession, url, &error_message); + + lib3270_autoptr(BIO) bio = BIO_new_mem_buf(crl_text,-1); BIO * b64 = BIO_new(BIO_f_base64()); bio = BIO_push(b64, bio); @@ -49,15 +66,21 @@ BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); if(!d2i_X509_CRL_bio(bio, &x509_crl)) { - trace_ssl(hSession,"Can't decode CRL data:\n%s\n",crl); - return -1; + trace_ssl(hSession,"Can't decode CRL data:\n%s\n",crl_text); + error_message = _("Can't decode CRL data"); } - lib3270_openssl_crl_free(context); - context->crl.cert = x509_crl; - } + if(error_message) + trace_ssl(hSession,"Error downloading CRL from %s: %s\n",url,error_message); + + if(!x509_crl) + return -1; + + lib3270_openssl_crl_free(context); + context->crl.cert = x509_crl; + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) { lib3270_autoptr(BIO) bio = BIO_new(BIO_s_mem()); @@ -88,7 +111,7 @@ } - static void download_crl(H3270 *hSession, SSL_CTX * ctx_context, LIB3270_NET_CONTEXT * context, X509 *peer) { + static void download_crl_from_peer(H3270 *hSession, SSL_CTX * ctx_context, LIB3270_NET_CONTEXT * context, X509 *peer) { debug("%s peer=%p",__FUNCTION__,(void *) peer); @@ -102,8 +125,6 @@ } size_t ix; - const char * error_message = NULL; - lib3270_autoptr(char) crl_text = NULL; const char *prefer = lib3270_crl_get_preferred_protocol(hSession); if(!prefer) { @@ -111,12 +132,7 @@ // No preferred protocol, try all uris. for(ix = 0; ix < uris->length; ix++) { - debug("Trying %s",uris->str[ix]); - crl_text = lib3270_url_get(hSession, uris->str[ix], &error_message); - - if(error_message) { - trace_ssl(hSession,"Error downloading CRL from %s: %s\n",uris->str[ix],error_message); - } else if(!import_crl(hSession, ctx_context, context, crl_text)) { + if(!import_crl(hSession,ctx_context,context,uris->str[ix])) { trace_ssl(hSession,"Got CRL from %s\n",uris->str[ix]); return; } @@ -137,11 +153,7 @@ continue; debug("Trying %s",uris->str[ix]); - crl_text = lib3270_url_get(hSession, uris->str[ix], &error_message); - - if(error_message) { - trace_ssl(hSession,"Error downloading CRL from %s: %s\n",uris->str[ix],error_message); - } else if(!import_crl(hSession, ctx_context, context, crl_text)) { + if(!import_crl(hSession,ctx_context,context,uris->str[ix])) { trace_ssl(hSession,"Got CRL from %s\n",uris->str[ix]); return; } @@ -154,12 +166,7 @@ if(!strncasecmp(prefer,uris->str[ix],length)) continue; - debug("Trying %s",uris->str[ix]); - crl_text = lib3270_url_get(hSession, uris->str[ix], &error_message); - - if(error_message) { - trace_ssl(hSession,"Error downloading CRL from %s: %s\n",uris->str[ix],error_message); - } else if(!import_crl(hSession, ctx_context, context, crl_text)) { + if(!import_crl(hSession,ctx_context,context,uris->str[ix])) { trace_ssl(hSession,"Got CRL from %s\n",uris->str[ix]); return; } @@ -265,8 +272,13 @@ if(lib3270_ssl_get_crl_download(hSession) && SSL_get_verify_result(context->con) == X509_V_ERR_UNABLE_TO_GET_CRL) { // CRL download is enabled and verification has failed; look for CRL file. + trace_ssl(hSession,"CRL Validation has failed, requesting CRL download\n"); - download_crl(hSession, ctx_context, context, peer); + if(context->crl.url) { + import_crl(hSession, ctx_context,context,context->crl.url); + } else { + download_crl_from_peer(hSession, ctx_context, context, peer); + } } -- libgit2 0.21.2