diff --git a/lib3270.cbp b/lib3270.cbp
index 8654ef3..4a98eb5 100644
--- a/lib3270.cbp
+++ b/lib3270.cbp
@@ -314,10 +314,16 @@
+
+
+
+
+
+
diff --git a/src/core/session.c b/src/core/session.c
index 5304134..f4d4ebf 100644
--- a/src/core/session.c
+++ b/src/core/session.c
@@ -260,18 +260,6 @@ static void nop_int(H3270 GNUC_UNUSED(*session), int GNUC_UNUSED(width))
return;
}
-#ifdef HAVE_LIBSSL
-static void set_peer_certificate(const X509 GNUC_UNUSED(*cert))
-{
-
-}
-#else
-static void set_peer_certificate(const void GNUC_UNUSED(*cert))
-{
-
-}
-#endif // HAVE_LIBSSL
-
static void default_update_luname(H3270 GNUC_UNUSED(*session), const char GNUC_UNUSED(*name))
{
}
@@ -307,7 +295,6 @@ void lib3270_reset_callbacks(H3270 *hSession)
hSession->cbk.print = print;
hSession->cbk.save = save;
hSession->cbk.load = load;
- hSession->cbk.set_peer_certificate = set_peer_certificate;
hSession->cbk.update_luname = default_update_luname;
hSession->cbk.update_url = default_update_url;
diff --git a/src/include/internals.h b/src/include/internals.h
index 5cb2d26..43c798f 100644
--- a/src/include/internals.h
+++ b/src/include/internals.h
@@ -860,3 +860,5 @@ LIB3270_INTERNAL void set_ssl_state(H3270 *session, LIB3270_SSL_STATE state);
LIB3270_INTERNAL int lib3270_start_tls(H3270 *hSession);
+ /// @brief Load file using URL.
+ LIB3270_INTERNAL char * lib3270_url_get(H3270 *hSession, const char *url, LIB3270_POPUP **popup);
diff --git a/src/include/lib3270/session.h b/src/include/lib3270/session.h
index 9399ad7..073fb9b 100644
--- a/src/include/lib3270/session.h
+++ b/src/include/lib3270/session.h
@@ -80,12 +80,6 @@
int (*popup)(H3270 *hSession, const LIB3270_POPUP *popup, unsigned char wait);
-#ifdef HAVE_LIBSSL
- void (*set_peer_certificate)(const X509 *cert);
-#else
- void (*set_peer_certificate)(const void *cert);
-#endif // HAVE_LIBSSL
-
};
/**
diff --git a/src/network_modules/openssl/crl.c b/src/network_modules/openssl/crl.c
new file mode 100644
index 0000000..f9d07a7
--- /dev/null
+++ b/src/network_modules/openssl/crl.c
@@ -0,0 +1,93 @@
+/*
+ * "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)
+ *
+ */
+
+/// @brief Get CRL infro from X509 cert.
+///
+/// References:
+///
+/// http://www.zedwood.com/article/cpp-check-crl-for-revocation
+
+
+#include "private.h"
+
+/*--[ Implement ]------------------------------------------------------------------------------------*/
+
+LIB3270_STRING_ARRAY * lib3270_openssl_get_crls_from_peer(H3270 *hSession, X509 *cert) {
+
+ //
+ // Get Distribution points.
+ //
+ lib3270_autoptr(CRL_DIST_POINTS) dist_points = (CRL_DIST_POINTS *) X509_get_ext_d2i(cert, NID_crl_distribution_points, NULL, NULL);
+
+ if(!dist_points) {
+ trace_ssl(hSession,"The host certificate doesn't have CRL distribution points\n");
+ return NULL;
+ }
+
+ LIB3270_STRING_ARRAY * uris = lib3270_string_array_new();
+
+ size_t ix;
+ 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;
+
+ size_t i;
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ int gtype;
+ GENERAL_NAME *gen = sk_GENERAL_NAME_value(gens, i);
+ ASN1_STRING *uri = GENERAL_NAME_get0_value(gen, >ype);
+
+ if(uri && gtype == GEN_URI)
+ {
+ int length = ASN1_STRING_length(uri);
+
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) // OpenSSL 1.1.0+
+ const unsigned char * data = ASN1_STRING_get0_data(uri);
+#else
+ const unsigned char * data = ASN1_STRING_data(uri);
+#endif // OpenSSL 1.1.0+
+
+ if(data && length > 0)
+ lib3270_string_array_append_with_length(uris,(char *) data, (size_t) length);
+
+ }
+
+ }
+
+ }
+
+ return uris;
+
+}
+
diff --git a/src/network_modules/openssl/main.c b/src/network_modules/openssl/main.c
index d6be2ad..aae6113 100644
--- a/src/network_modules/openssl/main.c
+++ b/src/network_modules/openssl/main.c
@@ -178,87 +178,6 @@ static int openssl_network_connect(H3270 *hSession, LIB3270_NETWORK_STATE *state
}
-static int openssl_network_start_tls(H3270 *hSession, LIB3270_NETWORK_STATE *state) {
-
- SSL_CTX * ctx_context = (SSL_CTX *) lib3270_openssl_get_context(state,state);
- if(!ctx_context)
- return -1;
-
- LIB3270_NET_CONTEXT * context = hSession->network.context;
-
- debug("%s",__FUNCTION__);
-
- set_ssl_state(hSession,LIB3270_SSL_NEGOTIATING);
- context->con = SSL_new(ctx_context);
- if(context->con == NULL)
- {
- static const LIB3270_POPUP popup = {
- .type = LIB3270_NOTIFY_SECURE,
- .summary = N_( "Cant create a new SSL structure for current connection." )
- };
-
- state->popup = &popup;
- return -1;
- }
-
- SSL_set_ex_data(context->con,lib3270_openssl_get_ex_index(hSession),(char *) hSession);
-// SSL_set_verify(context->con, SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
- SSL_set_verify(context->con, 0, NULL);
-
- if(SSL_set_fd(context->con, context->sock) != 1)
- {
- trace_ssl(hSession,"%s","SSL_set_fd failed!\n");
-
- static const LIB3270_NETWORK_POPUP popup = {
- .summary = N_( "SSL negotiation failed" ),
- .body = N_( "Cant set the file descriptor for the input/output facility for the TLS/SSL (encrypted) side of ssl." )
- };
-
- state->popup = &popup;
- return -1;
-
- }
-
- trace_ssl(hSession, "%s","Running SSL_connect\n");
- int rv = SSL_connect(context->con);
- trace_ssl(hSession, "SSL_connect exits with rc=%d\n",rv);
-
- if (rv != 1)
- {
- int code = SSL_get_error(context->con,rv);
-
- if(code == SSL_ERROR_SYSCALL && hSession->ssl.error)
- code = hSession->ssl.error;
-
- state->error_message = ERR_lib_error_string(code);
-
- trace_ssl(hSession,"SSL_connect failed: %s\n",ERR_reason_error_string(code));
-
- static const LIB3270_POPUP popup = {
- .type = LIB3270_NOTIFY_ERROR,
- .summary = N_( "SSL Connect failed" ),
- };
-
- state->popup = &popup;
- return -1;
-
- }
-
- //
- // Connection succeeded, do we need to download the CRL?
- //
- if(lib3270_ssl_get_crl_download(hSession)) {
-
-
- } else {
-
- trace_ssl(hSession,"CRL download is disabled\n");
-
- }
-
- return 0;
-}
-
void lib3270_set_openssl_network_module(H3270 *hSession) {
static const LIB3270_NET_MODULE module = {
diff --git a/src/network_modules/openssl/private.h b/src/network_modules/openssl/private.h
index 9985073..86c6f24 100644
--- a/src/network_modules/openssl/private.h
+++ b/src/network_modules/openssl/private.h
@@ -44,12 +44,14 @@
#include
#include
#include
+ #include
#include
#include
#include
#include
#include
+ #include
struct _lib3270_network_popup {
LIB3270_POPUP_HEAD
@@ -80,9 +82,27 @@
};
+ /// @brief X509 auto-cleanup.
+ static inline void lib3270_autoptr_cleanup_X509(X509 **ptr) {
+ if(*ptr)
+ X509_free(*ptr);
+ *ptr = NULL;
+ }
+
+ /// @brief Dist points auto-cleanup.
+ static inline void lib3270_autoptr_cleanup_CRL_DIST_POINTS(CRL_DIST_POINTS **ptr)
+ {
+ if(*ptr)
+ CRL_DIST_POINTS_free(*ptr);
+ *ptr = NULL;
+ }
+
LIB3270_INTERNAL SSL_CTX * lib3270_openssl_get_context(H3270 *hSession, LIB3270_NETWORK_STATE *state);
LIB3270_INTERNAL int lib3270_openssl_get_ex_index(H3270 *hSession);
LIB3270_INTERNAL const LIB3270_NETWORK_POPUP * lib3270_openssl_get_popup_from_error_code(long id);
+ LIB3270_INTERNAL int openssl_network_start_tls(H3270 *hSession, LIB3270_NETWORK_STATE *state);
+
+ LIB3270_INTERNAL LIB3270_STRING_ARRAY * lib3270_openssl_get_crls_from_peer(H3270 *hSession, X509 *cert);
#endif // !LIB3270_OPENSSL_MODULE_PRIVATE_H_INCLUDED
diff --git a/src/network_modules/openssl/start.c b/src/network_modules/openssl/start.c
new file mode 100644
index 0000000..fd8de89
--- /dev/null
+++ b/src/network_modules/openssl/start.c
@@ -0,0 +1,183 @@
+/*
+ * "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 ', 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 openssl.c 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)
+ *
+ */
+
+ /**
+ * @brief Negotiate OpenSSL session.
+ *
+ */
+
+ #include "private.h"
+ #include
+
+ int openssl_network_start_tls(H3270 *hSession, LIB3270_NETWORK_STATE *state) {
+
+ SSL_CTX * ctx_context = (SSL_CTX *) lib3270_openssl_get_context(hSession,state);
+ if(!ctx_context)
+ return -1;
+
+ LIB3270_NET_CONTEXT * context = hSession->network.context;
+
+ debug("%s",__FUNCTION__);
+
+ set_ssl_state(hSession,LIB3270_SSL_NEGOTIATING);
+ context->con = SSL_new(ctx_context);
+ if(context->con == NULL)
+ {
+ static const LIB3270_NETWORK_POPUP popup = {
+ .type = LIB3270_NOTIFY_SECURE,
+ .summary = N_( "Cant create a new SSL structure for current connection." )
+ };
+
+ state->popup = &popup;
+ return -1;
+ }
+
+ SSL_set_ex_data(context->con,lib3270_openssl_get_ex_index(hSession),(char *) hSession);
+// SSL_set_verify(context->con, SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
+ SSL_set_verify(context->con, 0, NULL);
+
+ if(SSL_set_fd(context->con, context->sock) != 1)
+ {
+ trace_ssl(hSession,"%s","SSL_set_fd failed!\n");
+
+ static const LIB3270_NETWORK_POPUP popup = {
+ .summary = N_( "SSL negotiation failed" ),
+ .body = N_( "Cant set the file descriptor for the input/output facility for the TLS/SSL (encrypted) side of ssl." )
+ };
+
+ state->popup = &popup;
+ return -1;
+
+ }
+
+ trace_ssl(hSession, "%s","Running SSL_connect\n");
+ int rv = SSL_connect(context->con);
+ trace_ssl(hSession, "SSL_connect exits with rc=%d\n",rv);
+
+ if (rv != 1)
+ {
+ int code = SSL_get_error(context->con,rv);
+
+ if(code == SSL_ERROR_SYSCALL && hSession->ssl.error)
+ code = hSession->ssl.error;
+
+ state->error_message = ERR_lib_error_string(code);
+
+ trace_ssl(hSession,"SSL_connect failed: %s\n",ERR_reason_error_string(code));
+
+ static const LIB3270_NETWORK_POPUP popup = {
+ .summary = N_( "SSL Connect failed" ),
+ };
+
+ state->popup = &popup;
+ return -1;
+
+ }
+
+ // Get peer certificate, notify application before validation.
+ lib3270_autoptr(X509) peer = SSL_get_peer_certificate(context->con);
+
+ if(peer) {
+
+ if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE))
+ {
+ BIO * out = BIO_new(BIO_s_mem());
+ unsigned char * data;
+ unsigned char * text;
+ int n;
+
+ X509_print(out,peer);
+
+ n = BIO_get_mem_data(out, &data);
+ text = (unsigned char *) malloc (n+1);
+ text[n] ='\0';
+ memcpy(text,data,n);
+
+ trace_ssl(hSession,"TLS/SSL peer certificate:\n%s\n",text);
+
+ free(text);
+ BIO_free(out);
+
+ }
+
+ }
+
+ // Do we really need to download a new CRL?
+ if(lib3270_ssl_get_crl_download(hSession) && SSL_get_verify_result(context->con) == X509_V_ERR_UNABLE_TO_GET_CRL) {
+
+ trace_ssl(hSession,"CRL Validation has failed, requesting download\n");
+
+ lib3270_autoptr(char) crl_text = NULL;
+ if(context->crl.url) {
+
+ // There's a pre-defined URL, use it.
+ const LIB3270_POPUP * popup = NULL;
+ crl_text = lib3270_url_get(hSession, context->crl.url,&popup);
+
+ if(popup) {
+ state->popup = popup;
+ trace_ssl(hSession,"Error downloading CRL from %s: %s\n",context->crl.url,popup->summary);
+ }
+
+#ifndef DEBUG
+ #error TODO: Import crl_text;
+#endif // DEBUG
+
+ } else if(peer) {
+
+ // There's no pre-defined URL, get them from peer.
+ lib3270_autoptr(LIB3270_STRING_ARRAY) uris = lib3270_openssl_get_crls_from_peer(hSession, peer);
+
+ if(uris) {
+
+ size_t ix;
+ for(ix = 0; ix < uris->length; ix++) {
+
+ LIB3270_POPUP * popup = NULL;
+ crl_text = lib3270_url_get(hSession, uris->str[ix], &popup);
+
+ if(popup) {
+ trace_ssl(hSession,"Error downloading CRL from %s: %s\n",uris[ix],popup->summary);
+ }
+
+#ifndef DEBUG
+ #error TODO: Import crl_text;
+#endif // DEBUG
+
+ }
+ }
+
+ }
+
+ }
+
+
+
+ return 0;
+}
--
libgit2 0.21.2