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