From 2e323b27473104cce3d849662b7b440fd6a32ce8 Mon Sep 17 00:00:00 2001 From: Perry Werneck Date: Fri, 2 Aug 2019 10:18:44 -0300 Subject: [PATCH] Splitting CRL download methods. --- .gitignore | 1 + lib3270.cbp | 11 +++++++++++ src/ssl/linux/curl.c | 324 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ssl/linux/getcrl.c | 484 +++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/ssl/linux/ldap.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ssl/linux/private.h | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ssl/windows/curl.c | 381 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ssl/windows/getcrl.c | 349 ++++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/ssl/windows/private.h | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 1078 insertions(+), 826 deletions(-) create mode 100644 src/ssl/linux/curl.c create mode 100644 src/ssl/linux/ldap.c create mode 100644 src/ssl/linux/private.h create mode 100644 src/ssl/windows/curl.c create mode 100644 src/ssl/windows/private.h diff --git a/.gitignore b/.gitignore index 5386f78..ff9b350 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ scripts vgcore.* doxygen/html *.crl +*.sh src/include/lib3270/actions.h doxygen/doxyfile win32-configure* diff --git a/lib3270.cbp b/lib3270.cbp index 7d298f9..1dcead6 100644 --- a/lib3270.cbp +++ b/lib3270.cbp @@ -266,18 +266,29 @@ + + + + + + + + diff --git a/src/ssl/linux/curl.c b/src/ssl/linux/curl.c new file mode 100644 index 0000000..93ac9e1 --- /dev/null +++ b/src/ssl/linux/curl.c @@ -0,0 +1,324 @@ +/* + * "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) + * + * + * References: + * + * http://www.openssl.org/docs/ssl/ + * https://stackoverflow.com/questions/4389954/does-openssl-automatically-handle-crls-certificate-revocation-lists-now + * + */ + +#include + +#if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK) && defined(HAVE_LIBCURL) + +#include "private.h" +#include + +#define CRL_DATA_LENGTH 2048 + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +static inline void lib3270_autoptr_cleanup_CURL(CURL **ptr) +{ + debug("%s(%p)",__FUNCTION__,*ptr); + if(*ptr) + curl_easy_cleanup(*ptr); + *ptr = NULL; +} + +typedef struct _curldata +{ + size_t length; + H3270 * hSession; + SSL_ERROR_MESSAGE * message; + char errbuf[CURL_ERROR_SIZE]; + struct { + size_t length; + unsigned char * contents; + } data; +} CURLDATA; + +static inline void lib3270_autoptr_cleanup_CURLDATA(CURLDATA **ptr) +{ + debug("%s(%p)",__FUNCTION__,*ptr); + if(*ptr) + { + CURLDATA *cdata = *ptr; + + if(cdata->data.contents) { + lib3270_free(cdata->data.contents); + cdata->data.contents = NULL; + } + lib3270_free(cdata); + } + *ptr = NULL; +} + +static inline void lib3270_autoptr_cleanup_BIO(BIO **ptr) +{ + debug("%s(%p)",__FUNCTION__,*ptr); + if(*ptr) + BIO_free_all(*ptr); + *ptr = NULL; +} + +static size_t internal_curl_write_callback(void *contents, size_t size, size_t nmemb, void *userp) +{ + CURLDATA * data = (CURLDATA *) userp; + + debug("%s",__FUNCTION__); + + size_t realsize = size * nmemb; + + debug("%s size=%d data->length=%d crldatalength=%d",__FUNCTION__,(int) size, (int) data->length, CRL_DATA_LENGTH); + + if((realsize + data->length) > data->data.length) + { + data->data.length += (CRL_DATA_LENGTH + realsize); + data->data.contents = lib3270_realloc(data->data.contents,data->data.length); + memset(&(data->data.contents[data->length]),0,data->data.length-data->length); + } + + debug("%s",__FUNCTION__); + + if(lib3270_get_toggle(data->hSession,LIB3270_TOGGLE_SSL_TRACE)) + { + lib3270_trace_data( + data->hSession, + "Received", + (const char *) contents, + realsize + ); + } + + debug("%s",__FUNCTION__); + + memcpy(&(data->data.contents[data->length]),contents,realsize); + data->length += realsize; + + debug("%s",__FUNCTION__); + + return realsize; +} + +static int internal_curl_trace_callback(CURL GNUC_UNUSED(*handle), curl_infotype type, char *data, size_t size, void *userp) +{ + const char * text = NULL; + + switch (type) { + case CURLINFO_TEXT: + lib3270_write_log(((CURLDATA *) userp)->hSession,"curl","%s",data); + return 0; + + case CURLINFO_HEADER_OUT: + text = "=> Send header"; + break; + + case CURLINFO_DATA_OUT: + text = "=> Send data"; + break; + + case CURLINFO_SSL_DATA_OUT: + text = "=> Send SSL data"; + break; + + case CURLINFO_HEADER_IN: + text = "<= Recv header"; + break; + + case CURLINFO_DATA_IN: + text = "<= Recv data"; + break; + + case CURLINFO_SSL_DATA_IN: + text = "<= Recv SSL data"; + break; + + default: + return 0; + + } + + lib3270_trace_data( + ((CURLDATA *) userp)->hSession, + text, + data, + size + ); + + return 0; +} + +LIB3270_INTERNAL X509_CRL * get_crl_using_curl(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl) +{ + X509_CRL * x509_crl = NULL; + + // Use CURL to download the CRL + lib3270_autoptr(CURLDATA) crl_data = lib3270_malloc(sizeof(CURLDATA)); + lib3270_autoptr(CURL) hCurl = curl_easy_init(); + + memset(crl_data,0,sizeof(CURLDATA)); + crl_data->message = message; + crl_data->hSession = hSession; + crl_data->data.length = CRL_DATA_LENGTH; + crl_data->data.contents = lib3270_malloc(crl_data->data.length); + + if(!hCurl) + { + message->title = _( "Security error" ); + message->text = _( "Error loading certificate revocation list" ); + message->description = _( "Can't initialize curl operation" ); + return NULL; + } + + CURLcode res; + + curl_easy_setopt(hCurl, CURLOPT_URL, consturl); + curl_easy_setopt(hCurl, CURLOPT_FOLLOWLOCATION, 1L); + + curl_easy_setopt(hCurl, CURLOPT_ERRORBUFFER, crl_data->errbuf); + + curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, internal_curl_write_callback); + curl_easy_setopt(hCurl, CURLOPT_WRITEDATA, (void *) crl_data); + + curl_easy_setopt(hCurl, CURLOPT_USERNAME, ""); + + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) + { + curl_easy_setopt(hCurl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(hCurl, CURLOPT_DEBUGFUNCTION, internal_curl_trace_callback); + curl_easy_setopt(hCurl, CURLOPT_DEBUGDATA, (void *) crl_data); + } + + res = curl_easy_perform(hCurl); + + if(res != CURLE_OK) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + + if(crl_data->errbuf[0]) + { + message->text = curl_easy_strerror(res); + message->description = crl_data->errbuf; + } + else + { + message->text = _( "Error loading certificate revocation list" ); + message->description = curl_easy_strerror(res); + } + + lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->description); + errno = EINVAL; + return NULL; + + } + + char *ct = NULL; + res = curl_easy_getinfo(hCurl, CURLINFO_CONTENT_TYPE, &ct); + if(res != CURLE_OK) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Error loading certificate revocation list" ); + message->description = curl_easy_strerror(res); + lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->description); + errno = EINVAL; + return NULL; + } + + if(lib3270_get_toggle(crl_data->hSession,LIB3270_TOGGLE_SSL_TRACE)) + lib3270_trace_data(crl_data->hSession,"CRL Data",(const char *) crl_data->data.contents, (unsigned int) crl_data->length); + + if(ct) + { + const unsigned char * data = crl_data->data.contents; + + + if(strcasecmp(ct,"application/pkix-crl") == 0) + { + // CRL File, convert it + if(!d2i_X509_CRL(&x509_crl, &data, crl_data->length)) + { + message->error = hSession->ssl.error = ERR_get_error(); + message->title = _( "Security error" ); + message->text = _( "Can't decode certificate revocation list" ); + lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->text); + return NULL; + } + } + else + { + message->error = hSession->ssl.error = ERR_get_error(); + message->title = _( "Security error" ); + message->text = _( "Got an invalid certificate revocation list from server" ); + lib3270_write_log(hSession,"ssl","%s: content-type unexpected: \"%s\"",consturl, ct); + errno = EINVAL; + return NULL; + } + } + else if(strncasecmp(consturl,"ldap://",7) == 0) + { + // It's an LDAP query, assumes a base64 data. + char * data = strstr((char *) crl_data->data.contents,":: "); + if(!data) + { + message->error = hSession->ssl.error = ERR_get_error(); + message->title = _( "Security error" ); + message->text = _( "Got a bad formatted certificate revocation list from LDAP server" ); + lib3270_write_log(hSession,"ssl","%s: invalid format:\n%s\n",consturl, crl_data->data.contents); + errno = EINVAL; + return NULL; + } + data += 3; + + lib3270_autoptr(BIO) bio = BIO_new_mem_buf(data,-1); + + BIO * b64 = BIO_new(BIO_f_base64()); + bio = BIO_push(b64, bio); + + BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); + + if(!d2i_X509_CRL_bio(bio, &x509_crl)) + { + message->error = hSession->ssl.error = ERR_get_error(); + message->title = _( "Security error" ); + message->text = _( "Can't decode certificate revocation list got from LDAP server" ); + lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->text); + errno = EINVAL; + return NULL; + } + + } + + return x509_crl; + +} + +#endif // HAVE_LIBSSL && SSL_ENABLE_CRL_CHECK && HAVE_LIBCURL diff --git a/src/ssl/linux/getcrl.c b/src/ssl/linux/getcrl.c index c76c8ec..27df0f4 100644 --- a/src/ssl/linux/getcrl.c +++ b/src/ssl/linux/getcrl.c @@ -33,33 +33,10 @@ * */ -#define CRL_DATA_LENGTH 2048 - -#include +#include "private.h" #if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK) -#include -#include -#include -#include - -#ifdef HAVE_LDAP - #define LDAP_DEPRECATED 1 - #include -#endif // HAVE_LDAP - -#ifdef HAVE_LIBCURL - #include -#endif // HAVE_LIBCURL - -#include -#include -#include -#include -#include -#include - /*--[ Implement ]------------------------------------------------------------------------------------*/ static inline void lib3270_autoptr_cleanup_FILE(FILE **file) @@ -68,176 +45,6 @@ static inline void lib3270_autoptr_cleanup_FILE(FILE **file) fclose(*file); } -#ifdef HAVE_LDAP -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; -} - -#endif // HAVE_LDAP - -#ifdef HAVE_LIBCURL -static inline void lib3270_autoptr_cleanup_CURL(CURL **ptr) -{ - debug("%s(%p)",__FUNCTION__,*ptr); - if(*ptr) - curl_easy_cleanup(*ptr); - *ptr = NULL; -} - -typedef struct _curldata -{ - size_t length; - H3270 * hSession; - SSL_ERROR_MESSAGE * message; - char errbuf[CURL_ERROR_SIZE]; - struct { - size_t length; - unsigned char * contents; - } data; -} CURLDATA; - -static inline void lib3270_autoptr_cleanup_CURLDATA(CURLDATA **ptr) -{ - debug("%s(%p)",__FUNCTION__,*ptr); - if(*ptr) - { - CURLDATA *cdata = *ptr; - - if(cdata->data.contents) { - lib3270_free(cdata->data.contents); - cdata->data.contents = NULL; - } - lib3270_free(cdata); - } - *ptr = NULL; -} - -static inline void lib3270_autoptr_cleanup_BIO(BIO **ptr) -{ - debug("%s(%p)",__FUNCTION__,*ptr); - if(*ptr) - BIO_free_all(*ptr); - *ptr = NULL; -} - -static size_t internal_curl_write_callback(void *contents, size_t size, size_t nmemb, void *userp) -{ - CURLDATA * data = (CURLDATA *) userp; - - debug("%s",__FUNCTION__); - - size_t realsize = size * nmemb; - - debug("%s size=%d data->length=%d crldatalength=%d",__FUNCTION__,(int) size, (int) data->length, CRL_DATA_LENGTH); - - if((realsize + data->length) > data->data.length) - { - data->data.length += (CRL_DATA_LENGTH + realsize); - data->data.contents = lib3270_realloc(data->data.contents,data->data.length); - memset(&(data->data.contents[data->length]),0,data->data.length-data->length); - } - - debug("%s",__FUNCTION__); - - if(lib3270_get_toggle(data->hSession,LIB3270_TOGGLE_SSL_TRACE)) - { - lib3270_trace_data( - data->hSession, - "Received", - (const char *) contents, - realsize - ); - } - - debug("%s",__FUNCTION__); - - memcpy(&(data->data.contents[data->length]),contents,realsize); - data->length += realsize; - - debug("%s",__FUNCTION__); - - return realsize; -} - -static int internal_curl_trace_callback(CURL GNUC_UNUSED(*handle), curl_infotype type, char *data, size_t size, void *userp) -{ - const char * text = NULL; - - switch (type) { - case CURLINFO_TEXT: - lib3270_write_log(((CURLDATA *) userp)->hSession,"curl","%s",data); - return 0; - - case CURLINFO_HEADER_OUT: - text = "=> Send header"; - break; - - case CURLINFO_DATA_OUT: - text = "=> Send data"; - break; - - case CURLINFO_SSL_DATA_OUT: - text = "=> Send SSL data"; - break; - - case CURLINFO_HEADER_IN: - text = "<= Recv header"; - break; - - case CURLINFO_DATA_IN: - text = "<= Recv data"; - break; - - case CURLINFO_SSL_DATA_IN: - text = "<= Recv SSL data"; - break; - - default: - return 0; - - } - - lib3270_trace_data( - ((CURLDATA *) userp)->hSession, - text, - data, - size - ); - - return 0; -} - -#endif // HAVE_LIBCURL - - LIB3270_INTERNAL X509_CRL * lib3270_get_crl(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl) { X509_CRL * x509_crl = NULL; @@ -288,148 +95,7 @@ LIB3270_INTERNAL X509_CRL * lib3270_get_crl(H3270 *hSession, SSL_ERROR_MESSAGE * #ifdef HAVE_LDAP else if(strncasecmp(consturl,"ldap://",7) == 0 && strlen(consturl) > 8) { - int rc; - lib3270_autoptr(char) url = strdup(consturl); - char * base = strchr(url+7,'/'); - char * attrs[] = { NULL, NULL }; - - if(!base) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "No DN of the entry at which to start the search on the URL" ); - message->description = _( "The URL argument should be in the format ldap://[HOST]/[DN]?attribute" ); - return errno = EINVAL; - } - - *(base++) = 0; - attrs[0] = strchr(base,'?'); - - if(!base) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "No LDAP attribute on the URL" ); - message->description = _( "The URL argument should be in the format ldap://[HOST]/[DN]?attribute" ); - return errno = EINVAL; - } - - *(attrs[0]++) = 0; - - debug("host: \"%s\"",url); - debug("Base: \"%s\"",base); - debug("Attr: \"%s\"",attrs[0]); - - // Do LDAP Query - LDAP __attribute__ ((__cleanup__(lib3270_autoptr_cleanup_LDAP))) *ld = NULL; - BerElement __attribute__ ((__cleanup__(lib3270_autoptr_cleanup_BerElement))) * ber = NULL; - - rc = ldap_initialize(&ld, url); - if(rc != LDAP_SUCCESS) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Can't initialize LDAP" ); - message->description = ldap_err2string(rc); - lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); - return -1; - } - - unsigned long version = LDAP_VERSION3; - rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,(void *) &version); - if(rc != LDAP_SUCCESS) { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Can't set LDAP version" ); - message->description = ldap_err2string(rc); - lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); - return NULL; - } - - rc = ldap_simple_bind_s(ld, "", ""); - if(rc != LDAP_SUCCESS) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Can't bind to LDAP server" ); - message->description = ldap_err2string(rc); - lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); - return -1; - } - - 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) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Can't search LDAP server" ); - message->description = ldap_err2string(rc); - lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); - return NULL; - } - - char __attribute__ ((__cleanup__(lib3270_autoptr_cleanup_LDAPPTR))) *attr = ldap_first_attribute(ld, results, &ber); - if(!attr) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Can't get LDAP attribute" ); - message->description = _("Search did not produce any attributes."); - lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); - errno = ENOENT; - return NULL; - } - - struct berval ** value = ldap_get_values_len(ld, results, attr); - if(!value) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Can't get LDAP attribute" ); - message->description = _("Search did not produce any values."); - lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); - errno = ENOENT; - return NULL; - } - - if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) - { - lib3270_trace_data( - hSession, - "CRL Data received from LDAP server", - (const char *) value[0]->bv_val, - value[0]->bv_len - ); - } - - // Precisa salvar uma cópia porque d2i_X509_CRL modifica o ponteiro. - const unsigned char *crl_data = (const unsigned char *) value[0]->bv_val; - - if(!d2i_X509_CRL(&x509_crl, &crl_data, value[0]->bv_len)) - { - message->error = hSession->ssl.error = ERR_get_error(); - message->title = _( "Security error" ); - message->text = _( "Can't decode CRL" ); - lib3270_write_log(hSession,"ssl","%s: %s",url, message->text); - ldap_value_free_len(value); - return NULL; - } - - ldap_value_free_len(value); + return get_crl_using_ldap(hSession, message, consturl); } #endif // HAVE_LDAP @@ -437,151 +103,7 @@ LIB3270_INTERNAL X509_CRL * lib3270_get_crl(H3270 *hSession, SSL_ERROR_MESSAGE * { #ifdef HAVE_LIBCURL - // Use CURL to download the CRL - lib3270_autoptr(CURLDATA) crl_data = lib3270_malloc(sizeof(CURLDATA)); - lib3270_autoptr(CURL) hCurl = curl_easy_init(); - - memset(crl_data,0,sizeof(CURLDATA)); - crl_data->message = message; - crl_data->hSession = hSession; - crl_data->data.length = CRL_DATA_LENGTH; - crl_data->data.contents = lib3270_malloc(crl_data->data.length); - - if(hCurl) - { - CURLcode res; - - curl_easy_setopt(hCurl, CURLOPT_URL, consturl); - curl_easy_setopt(hCurl, CURLOPT_FOLLOWLOCATION, 1L); - - curl_easy_setopt(hCurl, CURLOPT_ERRORBUFFER, crl_data->errbuf); - - curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, internal_curl_write_callback); - curl_easy_setopt(hCurl, CURLOPT_WRITEDATA, (void *) crl_data); - - curl_easy_setopt(hCurl, CURLOPT_USERNAME, ""); - - if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) - { - curl_easy_setopt(hCurl, CURLOPT_VERBOSE, 1L); - curl_easy_setopt(hCurl, CURLOPT_DEBUGFUNCTION, internal_curl_trace_callback); - curl_easy_setopt(hCurl, CURLOPT_DEBUGDATA, (void *) crl_data); - } - - res = curl_easy_perform(hCurl); - - if(res != CURLE_OK) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - - if(crl_data->errbuf[0]) - { - message->text = curl_easy_strerror(res); - message->description = crl_data->errbuf; - } - else - { - message->text = _( "Error loading CRL" ); - message->description = curl_easy_strerror(res); - } - - lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->description); - errno = EINVAL; - return NULL; - - } - - char *ct = NULL; - res = curl_easy_getinfo(hCurl, CURLINFO_CONTENT_TYPE, &ct); - if(res != CURLE_OK) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Error loading CRL" ); - message->description = curl_easy_strerror(res); - lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->description); - errno = EINVAL; - return NULL; - } - - if(lib3270_get_toggle(crl_data->hSession,LIB3270_TOGGLE_SSL_TRACE)) - lib3270_trace_data(crl_data->hSession,"CRL Data",(const char *) crl_data->data.contents, (unsigned int) crl_data->length); - - if(ct) - { - const unsigned char * data = crl_data->data.contents; - - - if(strcasecmp(ct,"application/pkix-crl") == 0) - { - // CRL File, convert it - if(!d2i_X509_CRL(&x509_crl, &data, crl_data->length)) - { - message->error = hSession->ssl.error = ERR_get_error(); - message->title = _( "Security error" ); - message->text = _( "Can't decode CRL" ); - lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->text); - return NULL; - } - } - else - { - message->error = hSession->ssl.error = ERR_get_error(); - message->title = _( "Security error" ); - message->text = _( "Got an invalid CRL from server" ); - lib3270_write_log(hSession,"ssl","%s: content-type unexpected: \"%s\"",consturl, ct); - errno = EINVAL; - return NULL; - } - } - else if(strncasecmp(consturl,"ldap://",7) == 0) - { - // It's an LDAP query, assumes a base64 data. - char * data = strstr((char *) crl_data->data.contents,":: "); - if(!data) - { - message->error = hSession->ssl.error = ERR_get_error(); - message->title = _( "Security error" ); - message->text = _( "Got a bad formatted CRL from LDAP server" ); - lib3270_write_log(hSession,"ssl","%s: invalid format:\n%s\n",consturl, crl_data->data.contents); - errno = EINVAL; - return NULL; - } - data += 3; - -#ifdef DEBUG - { - FILE *out = fopen("linux_base64.crl","w"); - if(out) - { - fwrite(data,strlen(data),1,out); - fclose(out); - } - - } -#endif - - lib3270_autoptr(BIO) bio = BIO_new_mem_buf(data,-1); - - BIO * b64 = BIO_new(BIO_f_base64()); - bio = BIO_push(b64, bio); - - BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); - - if(!d2i_X509_CRL_bio(bio, &x509_crl)) - { - message->error = hSession->ssl.error = ERR_get_error(); - message->title = _( "Security error" ); - message->text = _( "Can't decode CRL got from LDAP server" ); - lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->text); - errno = EINVAL; - return NULL; - } - - } - - } + return get_crl_using_curl(hSession, message, consturl); #else // Can't get CRL. diff --git a/src/ssl/linux/ldap.c b/src/ssl/linux/ldap.c new file mode 100644 index 0000000..3f0683b --- /dev/null +++ b/src/ssl/linux/ldap.c @@ -0,0 +1,228 @@ +/* + * "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) + * + * + * References: + * + * http://www.openssl.org/docs/ssl/ + * https://stackoverflow.com/questions/4389954/does-openssl-automatically-handle-crls-certificate-revocation-lists-now + * + */ + +#include + +#if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK) && defined(HAVE_LDAP) + +#define LDAP_DEPRECATED 1 +#include + +/*--[ 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; +} + +LIB3270_INTERNAL X509_CRL * get_crl_using_ldap(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl) +{ + X509_CRL * x509_crl = NULL; + + int rc; + lib3270_autoptr(char) url = strdup(consturl); + char * base = strchr(url+7,'/'); + char * attrs[] = { NULL, NULL }; + + if(!base) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "No DN of the entry at which to start the search on the URL" ); + message->description = _( "The URL argument should be in the format ldap://[HOST]/[DN]?attribute" ); + return errno = EINVAL; + } + + *(base++) = 0; + attrs[0] = strchr(base,'?'); + + if(!base) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "No LDAP attribute on the URL" ); + message->description = _( "The URL argument should be in the format ldap://[HOST]/[DN]?attribute" ); + return errno = EINVAL; + } + + *(attrs[0]++) = 0; + + debug("host: \"%s\"",url); + debug("Base: \"%s\"",base); + debug("Attr: \"%s\"",attrs[0]); + + // Do LDAP Query + LDAP __attribute__ ((__cleanup__(lib3270_autoptr_cleanup_LDAP))) *ld = NULL; + BerElement __attribute__ ((__cleanup__(lib3270_autoptr_cleanup_BerElement))) * ber = NULL; + + rc = ldap_initialize(&ld, url); + if(rc != LDAP_SUCCESS) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't initialize LDAP" ); + message->description = ldap_err2string(rc); + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); + return -1; + } + + unsigned long version = LDAP_VERSION3; + rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,(void *) &version); + if(rc != LDAP_SUCCESS) { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't set LDAP version" ); + message->description = ldap_err2string(rc); + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); + return NULL; + } + + rc = ldap_simple_bind_s(ld, "", ""); + if(rc != LDAP_SUCCESS) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't bind to LDAP server" ); + message->description = ldap_err2string(rc); + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); + return -1; + } + + 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) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't search LDAP server" ); + message->description = ldap_err2string(rc); + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); + return NULL; + } + + char __attribute__ ((__cleanup__(lib3270_autoptr_cleanup_LDAPPTR))) *attr = ldap_first_attribute(ld, results, &ber); + if(!attr) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't get LDAP attribute" ); + message->description = _("Search did not produce any attributes."); + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); + errno = ENOENT; + return NULL; + } + + struct berval ** value = ldap_get_values_len(ld, results, attr); + if(!value) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't get LDAP attribute" ); + message->description = _("Search did not produce any values."); + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description); + errno = ENOENT; + return NULL; + } + + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) + { + lib3270_trace_data( + hSession, + "CRL Data received from LDAP server", + (const char *) value[0]->bv_val, + value[0]->bv_len + ); + } + + // Precisa salvar uma cópia porque d2i_X509_CRL modifica o ponteiro. + const unsigned char *crl_data = (const unsigned char *) value[0]->bv_val; + + if(!d2i_X509_CRL(&x509_crl, &crl_data, value[0]->bv_len)) + { + message->error = hSession->ssl.error = ERR_get_error(); + message->title = _( "Security error" ); + message->text = _( "Can't decode certificate revocation list" ); + lib3270_write_log(hSession,"ssl","%s: %s",url, message->text); + ldap_value_free_len(value); + return NULL; + } + + ldap_value_free_len(value); + + return x509_crl; + +} + +#endif // HAVE_LIBSSL && SSL_ENABLE_CRL_CHECK && HAVE_LDAP diff --git a/src/ssl/linux/private.h b/src/ssl/linux/private.h new file mode 100644 index 0000000..3f1726b --- /dev/null +++ b/src/ssl/linux/private.h @@ -0,0 +1,63 @@ +/* + * "Software G3270, 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 ', 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 private.h e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas de Mendonça) + * + */ + +#ifndef LIB3270_LINUX_SSL_PRIVATE_H_INCLUDED + + #define LIB3270_LINUX_SSL_PRIVATE_H_INCLUDED + + #include + + #include + #include + #include + #include + + #include + #include + #include + #include + #include + #include + + #ifdef HAVE_LDAP + + /// @brief Use libldap to get CRL. + LIB3270_INTERNAL X509_CRL * get_crl_using_ldap(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl); + + #endif // HAVE_LDAP + + #ifdef HAVE_LIBCURL + + /// @brief Use libcurl to get CRL. + LIB3270_INTERNAL X509_CRL * get_crl_using_curl(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl); + + #endif // HAVE_LIBCURL + + +#endif // !LIB3270_LINUX_SSL_PRIVATE_H_INCLUDED diff --git a/src/ssl/windows/curl.c b/src/ssl/windows/curl.c new file mode 100644 index 0000000..7ab0017 --- /dev/null +++ b/src/ssl/windows/curl.c @@ -0,0 +1,381 @@ +/* + * "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) + * + * References: + * + * http://www.openssl.org/docs/ssl/ + * https://stackoverflow.com/questions/4389954/does-openssl-automatically-handle-crls-certificate-revocation-lists-now + * + */ + +#include + +#if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK) && defined(HAVE_LIBCURL) + +#include "private.h" +#include + +#define CRL_DATA_LENGTH 2048 + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +static inline void lib3270_autoptr_cleanup_CURL(CURL **ptr) +{ + debug("%s(%p)",__FUNCTION__,*ptr); + if(*ptr) + curl_easy_cleanup(*ptr); + *ptr = NULL; +} + +typedef struct _curldata +{ + size_t length; + H3270 * hSession; + SSL_ERROR_MESSAGE * message; + char errbuf[CURL_ERROR_SIZE]; + struct { + size_t length; + unsigned char * contents; + } data; +} CURLDATA; + +static inline void lib3270_autoptr_cleanup_CURLDATA(CURLDATA **ptr) +{ + debug("%s(%p)",__FUNCTION__,*ptr); + if(*ptr) + { + CURLDATA *cdata = *ptr; + + if(cdata->data.contents) { + lib3270_free(cdata->data.contents); + cdata->data.contents = NULL; + } + lib3270_free(cdata); + } + *ptr = NULL; +} + +static inline void lib3270_autoptr_cleanup_BIO(BIO **ptr) +{ + debug("%s(%p)",__FUNCTION__,*ptr); + if(*ptr) + BIO_free_all(*ptr); + *ptr = NULL; +} + +static size_t internal_curl_write_callback(void *contents, size_t size, size_t nmemb, void *userp) +{ + CURLDATA * data = (CURLDATA *) userp; + + size_t realsize = size * nmemb; + size_t ix; + + debug("Received %u bytes (datablock is %p)", (unsigned int) realsize, data); + + unsigned char *ptr = (unsigned char *) contents; + + if(lib3270_get_toggle(data->hSession,LIB3270_TOGGLE_SSL_TRACE)) + lib3270_trace_data(data->hSession,"curl_write:",(const char *) contents, realsize); + + if((realsize + data->length) > data->data.length) + { + data->data.length += (CRL_DATA_LENGTH + realsize); + data->data.contents = lib3270_realloc(data->data.contents,data->data.length); + + for(ix = data->length; ix < data->data.length; ix++) + { + data->data.contents[ix] = 0; + } + + } + + for(ix = 0; ix < realsize; ix++) + { + data->data.contents[data->length++] = *(ptr++); + } + + return realsize; +} + +static int internal_curl_trace_callback(CURL GNUC_UNUSED(*handle), curl_infotype type, char *data, size_t size, void *userp) +{ + const char * text = NULL; + + switch (type) { + case CURLINFO_TEXT: + lib3270_write_log(((CURLDATA *) userp)->hSession,"curl","%s",data); + return 0; + + case CURLINFO_HEADER_OUT: + text = "=> Send header"; + break; + + case CURLINFO_DATA_OUT: + text = "=> Send data"; + break; + + case CURLINFO_SSL_DATA_OUT: + text = "=> Send SSL data"; + break; + + case CURLINFO_HEADER_IN: + text = "<= Recv header"; + break; + + case CURLINFO_DATA_IN: + text = "<= Recv data"; + break; + + case CURLINFO_SSL_DATA_IN: + text = "<= Recv SSL data"; + break; + + default: + return 0; + + } + + lib3270_trace_data( + ((CURLDATA *) userp)->hSession, + text, + data, + size + ); + + return 0; +} + +X509_CRL * get_crl_using_curl(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl) +{ + X509_CRL * x509_crl = NULL; + + lib3270_autoptr(CURLDATA) crl_data = lib3270_malloc(sizeof(CURLDATA)); + lib3270_autoptr(CURL) hCurl = curl_easy_init(); + + memset(crl_data,0,sizeof(CURLDATA)); + crl_data->message = message; + crl_data->hSession = hSession; + crl_data->data.length = CRL_DATA_LENGTH; + crl_data->data.contents = lib3270_malloc(crl_data->data.length); + + if(!hCurl) + { + message->title = _( "Security error" ); + message->text = _( "Error loading certificate revocation list" ); + message->description = _( "Can't initialize curl operation" ); + return NULL; + } + + CURLcode res; + + curl_easy_setopt(hCurl, CURLOPT_URL, consturl); + curl_easy_setopt(hCurl, CURLOPT_FOLLOWLOCATION, 1L); + + curl_easy_setopt(hCurl, CURLOPT_ERRORBUFFER, crl_data->errbuf); + + curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, internal_curl_write_callback); + curl_easy_setopt(hCurl, CURLOPT_WRITEDATA, (void *) crl_data); + + curl_easy_setopt(hCurl, CURLOPT_USERNAME, ""); + + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) + { + curl_easy_setopt(hCurl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(hCurl, CURLOPT_DEBUGFUNCTION, internal_curl_trace_callback); + curl_easy_setopt(hCurl, CURLOPT_DEBUGDATA, (void *) crl_data); + } + + res = curl_easy_perform(hCurl); + + if(res != CURLE_OK) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + + if(crl_data->errbuf[0]) + { + message->text = curl_easy_strerror(res); + message->description = crl_data->errbuf; + } + else + { + message->text = _( "Error loading certificate revocation list" ); + message->description = curl_easy_strerror(res); + } + + lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->description); + errno = EINVAL; + return NULL; + + } + + char *ct = NULL; + res = curl_easy_getinfo(hCurl, CURLINFO_CONTENT_TYPE, &ct); + if(res != CURLE_OK) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Error loading certificate revocation list" ); + message->description = curl_easy_strerror(res); + lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->description); + errno = EINVAL; + return NULL; + } + + if(lib3270_get_toggle(crl_data->hSession,LIB3270_TOGGLE_SSL_TRACE)) + lib3270_trace_data(crl_data->hSession,"CRL Data",(const char *) crl_data->data.contents, (unsigned int) crl_data->length); + + if(ct) + { + const unsigned char * data = crl_data->data.contents; + + if(strcasecmp(ct,"application/pkix-crl") == 0) + { + // CRL File, convert it + if(!d2i_X509_CRL(&x509_crl, &data, crl_data->length)) + { + message->error = hSession->ssl.error = ERR_get_error(); + message->title = _( "Security error" ); + message->text = _( "Can't decode certificate revocation list" ); + lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->text); + return NULL; + } + } + else + { + message->error = hSession->ssl.error = ERR_get_error(); + message->title = _( "Security error" ); + message->text = _( "Got an invalid certificate revocation list from server" ); + lib3270_write_log(hSession,"ssl","%s: content-type unexpected: \"%s\"",consturl, ct); + errno = EINVAL; + return NULL; + } + } + else if(strncasecmp(consturl,"ldap://",7) == 0) + { + // + // curl's LDAP query on windows returns diferently. Working with it. + // +#ifdef DEBUG + { + FILE *out = fopen("downloaded.crl","w"); + if(out) + { + fwrite(crl_data->data.contents,crl_data->length,1,out); + fclose(out); + } + + } +#endif + + char * attr = strchr(consturl,'?'); + if(!attr) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "No attribute in LDAP search URL" ); + errno = ENOENT; + return NULL; + } + + attr++; + + lib3270_autoptr(char) text = lib3270_strdup_printf("No mime-type, extracting \"%s\" directly from LDAP response\n",attr); + trace_ssl(crl_data->hSession, text); + + lib3270_autoptr(char) key = lib3270_strdup_printf("%s: ",attr); + + +// char *ptr = strcasestr((char *) crl_data->data.contents, key); + + size_t ix; + unsigned char *from = NULL; + size_t keylength = strlen(key); + for(ix = 0; ix < (crl_data->length - keylength); ix++) + { + if(!strncasecmp( (char *) (crl_data->data.contents+ix),key,keylength)) + { + from = crl_data->data.contents+ix; + break; + } + } + + debug("strstr(%s): %p", key, from); + + if(!from) + { + message->error = hSession->ssl.error = 0; + message->title = _( "Security error" ); + message->text = _( "Can't find certificate revocation list in LDAP response" ); + errno = ENOENT; + return NULL; + } + + from += strlen(key); + size_t length = crl_data->length - (from - crl_data->data.contents); + + static const char terminator[] = { 0x0a, 0x0a, 0x09 }; + unsigned char *to = from+length; + + for(ix = 0; ix < (length - sizeof(terminator)); ix++) + { + if(!memcmp(from+ix,terminator,sizeof(terminator))) + { + to = from+ix; + break; + } + } + + length = to - from; + + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) + { + lib3270_trace_data( + hSession, + "CRL Data received from LDAP server", + (const char *) from, + length + ); + } + + if(!d2i_X509_CRL(&x509_crl, (const unsigned char **) &from, length)) + { + message->error = hSession->ssl.error = ERR_get_error(); + message->title = _( "Security error" ); + message->text = _( "Can't decode certificate revocation list got from LDAP Search" ); + lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->text); + errno = EINVAL; + return NULL; + } + + } + + return x509_crl; + +} + +#endif // defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK) && defined(HAVE_LIBCURL) diff --git a/src/ssl/windows/getcrl.c b/src/ssl/windows/getcrl.c index 5aaf292..c98b3e7 100644 --- a/src/ssl/windows/getcrl.c +++ b/src/ssl/windows/getcrl.c @@ -33,31 +33,15 @@ * */ -#define CRL_DATA_LENGTH 2048 - #include -#include -#include -#include - #if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK) -#include -#include -#include -#include +#include "private.h" -#ifdef HAVE_LIBCURL - #include -#endif // HAVE_LIBCURL +#define CRL_DATA_LENGTH 2048 -#include -#include -#include -#include -#include -#include +// #include /*--[ Implement ]------------------------------------------------------------------------------------*/ @@ -67,136 +51,6 @@ static inline void lib3270_autoptr_cleanup_FILE(FILE **file) fclose(*file); } -#ifdef HAVE_LIBCURL -static inline void lib3270_autoptr_cleanup_CURL(CURL **ptr) -{ - debug("%s(%p)",__FUNCTION__,*ptr); - if(*ptr) - curl_easy_cleanup(*ptr); - *ptr = NULL; -} - -typedef struct _curldata -{ - size_t length; - H3270 * hSession; - SSL_ERROR_MESSAGE * message; - char errbuf[CURL_ERROR_SIZE]; - struct { - size_t length; - unsigned char * contents; - } data; -} CURLDATA; - -static inline void lib3270_autoptr_cleanup_CURLDATA(CURLDATA **ptr) -{ - debug("%s(%p)",__FUNCTION__,*ptr); - if(*ptr) - { - CURLDATA *cdata = *ptr; - - if(cdata->data.contents) { - lib3270_free(cdata->data.contents); - cdata->data.contents = NULL; - } - lib3270_free(cdata); - } - *ptr = NULL; -} - -static inline void lib3270_autoptr_cleanup_BIO(BIO **ptr) -{ - debug("%s(%p)",__FUNCTION__,*ptr); - if(*ptr) - BIO_free_all(*ptr); - *ptr = NULL; -} - -static size_t internal_curl_write_callback(void *contents, size_t size, size_t nmemb, void *userp) -{ - CURLDATA * data = (CURLDATA *) userp; - - size_t realsize = size * nmemb; - size_t ix; - - debug("Received %u bytes (datablock is %p)", (unsigned int) realsize, data); - - unsigned char *ptr = (unsigned char *) contents; - - if(lib3270_get_toggle(data->hSession,LIB3270_TOGGLE_SSL_TRACE)) - lib3270_trace_data(data->hSession,"curl_write:",(const char *) contents, realsize); - - if((realsize + data->length) > data->data.length) - { - data->data.length += (CRL_DATA_LENGTH + realsize); - data->data.contents = lib3270_realloc(data->data.contents,data->data.length); - - for(ix = data->length; ix < data->data.length; ix++) - { - data->data.contents[ix] = 0; - } - - } - - for(ix = 0; ix < realsize; ix++) - { - data->data.contents[data->length++] = *(ptr++); - } - - return realsize; -} - -static int internal_curl_trace_callback(CURL GNUC_UNUSED(*handle), curl_infotype type, char *data, size_t size, void *userp) -{ - const char * text = NULL; - - switch (type) { - case CURLINFO_TEXT: - lib3270_write_log(((CURLDATA *) userp)->hSession,"curl","%s",data); - return 0; - - case CURLINFO_HEADER_OUT: - text = "=> Send header"; - break; - - case CURLINFO_DATA_OUT: - text = "=> Send data"; - break; - - case CURLINFO_SSL_DATA_OUT: - text = "=> Send SSL data"; - break; - - case CURLINFO_HEADER_IN: - text = "<= Recv header"; - break; - - case CURLINFO_DATA_IN: - text = "<= Recv data"; - break; - - case CURLINFO_SSL_DATA_IN: - text = "<= Recv SSL data"; - break; - - default: - return 0; - - } - - lib3270_trace_data( - ((CURLDATA *) userp)->hSession, - text, - data, - size - ); - - return 0; -} - -#endif // HAVE_LIBCURL - - LIB3270_INTERNAL X509_CRL * lib3270_get_crl(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl) { X509_CRL * x509_crl = NULL; @@ -248,202 +102,7 @@ LIB3270_INTERNAL X509_CRL * lib3270_get_crl(H3270 *hSession, SSL_ERROR_MESSAGE * { #ifdef HAVE_LIBCURL - // Use CURL to download the CRL - lib3270_autoptr(CURLDATA) crl_data = lib3270_malloc(sizeof(CURLDATA)); - lib3270_autoptr(CURL) hCurl = curl_easy_init(); - - memset(crl_data,0,sizeof(CURLDATA)); - crl_data->message = message; - crl_data->hSession = hSession; - crl_data->data.length = CRL_DATA_LENGTH; - crl_data->data.contents = lib3270_malloc(crl_data->data.length); - - if(hCurl) - { - CURLcode res; - - curl_easy_setopt(hCurl, CURLOPT_URL, consturl); - curl_easy_setopt(hCurl, CURLOPT_FOLLOWLOCATION, 1L); - - curl_easy_setopt(hCurl, CURLOPT_ERRORBUFFER, crl_data->errbuf); - - curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, internal_curl_write_callback); - curl_easy_setopt(hCurl, CURLOPT_WRITEDATA, (void *) crl_data); - - curl_easy_setopt(hCurl, CURLOPT_USERNAME, ""); - - if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) - { - curl_easy_setopt(hCurl, CURLOPT_VERBOSE, 1L); - curl_easy_setopt(hCurl, CURLOPT_DEBUGFUNCTION, internal_curl_trace_callback); - curl_easy_setopt(hCurl, CURLOPT_DEBUGDATA, (void *) crl_data); - } - - res = curl_easy_perform(hCurl); - - if(res != CURLE_OK) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - - if(crl_data->errbuf[0]) - { - message->text = curl_easy_strerror(res); - message->description = crl_data->errbuf; - } - else - { - message->text = _( "Error loading CRL" ); - message->description = curl_easy_strerror(res); - } - - lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->description); - errno = EINVAL; - return NULL; - - } - - char *ct = NULL; - res = curl_easy_getinfo(hCurl, CURLINFO_CONTENT_TYPE, &ct); - if(res != CURLE_OK) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Error loading CRL" ); - message->description = curl_easy_strerror(res); - lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->description); - errno = EINVAL; - return NULL; - } - - if(lib3270_get_toggle(crl_data->hSession,LIB3270_TOGGLE_SSL_TRACE)) - lib3270_trace_data(crl_data->hSession,"CRL Data",(const char *) crl_data->data.contents, (unsigned int) crl_data->length); - - if(ct) - { - const unsigned char * data = crl_data->data.contents; - - if(strcasecmp(ct,"application/pkix-crl") == 0) - { - // CRL File, convert it - if(!d2i_X509_CRL(&x509_crl, &data, crl_data->length)) - { - message->error = hSession->ssl.error = ERR_get_error(); - message->title = _( "Security error" ); - message->text = _( "Can't decode CRL" ); - lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->text); - return NULL; - } - } - else - { - message->error = hSession->ssl.error = ERR_get_error(); - message->title = _( "Security error" ); - message->text = _( "Got an invalid CRL from server" ); - lib3270_write_log(hSession,"ssl","%s: content-type unexpected: \"%s\"",consturl, ct); - errno = EINVAL; - return NULL; - } - } - else if(strncasecmp(consturl,"ldap://",7) == 0) - { - // - // curl's LDAP query on windows returns diferently. Working with it. - // -#ifdef DEBUG - { - FILE *out = fopen("downloaded.crl","w"); - if(out) - { - fwrite(crl_data->data.contents,crl_data->length,1,out); - fclose(out); - } - - } -#endif - - char * attr = strchr(consturl,'?'); - if(!attr) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "No attribute in LDAP search URL" ); - errno = ENOENT; - return NULL; - } - - attr++; - - lib3270_autoptr(char) text = lib3270_strdup_printf("No mime-type, extracting \"%s\" directly from LDAP response\n",attr); - trace_ssl(crl_data->hSession, text); - - lib3270_autoptr(char) key = lib3270_strdup_printf("%s: ",attr); - - -// char *ptr = strcasestr((char *) crl_data->data.contents, key); - - size_t ix; - unsigned char *from = NULL; - size_t keylength = strlen(key); - for(ix = 0; ix < (crl_data->length - keylength); ix++) - { - if(!strncasecmp( (char *) (crl_data->data.contents+ix),key,keylength)) - { - from = crl_data->data.contents+ix; - break; - } - } - - debug("strstr(%s): %p", key, from); - - if(!from) - { - message->error = hSession->ssl.error = 0; - message->title = _( "Security error" ); - message->text = _( "Can't find attribute in LDAP response" ); - errno = ENOENT; - return NULL; - } - - from += strlen(key); - size_t length = crl_data->length - (from - crl_data->data.contents); - - static const char terminator[] = { 0x0a, 0x0a, 0x09 }; - unsigned char *to = from+length; - - for(ix = 0; ix < (length - sizeof(terminator)); ix++) - { - if(!memcmp(from+ix,terminator,sizeof(terminator))) - { - to = from+ix; - break; - } - } - - length = to - from; - - if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE)) - { - lib3270_trace_data( - hSession, - "CRL Data received from LDAP server", - (const char *) from, - length - ); - } - - if(!d2i_X509_CRL(&x509_crl, (const unsigned char **) &from, length)) - { - message->error = hSession->ssl.error = ERR_get_error(); - message->title = _( "Security error" ); - message->text = _( "Can't decode CRL got from LDAP Search" ); - lib3270_write_log(hSession,"ssl","%s: %s",consturl, message->text); - errno = EINVAL; - return NULL; - } - - } - } + return get_crl_using_curl(hSession, message, consturl); #else // Can't get CRL. diff --git a/src/ssl/windows/private.h b/src/ssl/windows/private.h new file mode 100644 index 0000000..abc9d71 --- /dev/null +++ b/src/ssl/windows/private.h @@ -0,0 +1,63 @@ +/* + * "Software G3270, 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 ', 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 private.h e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas de Mendonça) + * + */ + +#ifndef LIB3270_WIN32_SSL_PRIVATE_H_INCLUDED + + #define LIB3270_WIN32_SSL_PRIVATE_H_INCLUDED + + #include + + #include + #include + + #include + #include + #include + #include + + #include + #include + #include + #include + #include + #include + + #ifdef HAVE_LIBCURL + + #include + + /// @brief Use libcurl to get CRL. + LIB3270_INTERNAL X509_CRL * get_crl_using_curl(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl); + + #endif // HAVE_LIBCURL + + // LIB3270_INTERNAL X509_CRL * get_crl_using_winldap(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl); + + +#endif // !LIB3270_WIN32_SSL_PRIVATE_H_INCLUDED -- libgit2 0.21.2