Commit 3b32273a30de961f011393174f3a3e221d70d087

Authored by Perry Werneck
1 parent 3b563b02

Refactoring CRL download engine.

@@ -314,10 +314,16 @@ @@ -314,10 +314,16 @@
314 <Unit filename="src/network_modules/openssl/context.c"> 314 <Unit filename="src/network_modules/openssl/context.c">
315 <Option compilerVar="CC" /> 315 <Option compilerVar="CC" />
316 </Unit> 316 </Unit>
  317 + <Unit filename="src/network_modules/openssl/crl.c">
  318 + <Option compilerVar="CC" />
  319 + </Unit>
317 <Unit filename="src/network_modules/openssl/main.c"> 320 <Unit filename="src/network_modules/openssl/main.c">
318 <Option compilerVar="CC" /> 321 <Option compilerVar="CC" />
319 </Unit> 322 </Unit>
320 <Unit filename="src/network_modules/openssl/private.h" /> 323 <Unit filename="src/network_modules/openssl/private.h" />
  324 + <Unit filename="src/network_modules/openssl/start.c">
  325 + <Option compilerVar="CC" />
  326 + </Unit>
321 <Unit filename="src/network_modules/openssl/states.c"> 327 <Unit filename="src/network_modules/openssl/states.c">
322 <Option compilerVar="CC" /> 328 <Option compilerVar="CC" />
323 </Unit> 329 </Unit>
src/core/session.c
@@ -260,18 +260,6 @@ static void nop_int(H3270 GNUC_UNUSED(*session), int GNUC_UNUSED(width)) @@ -260,18 +260,6 @@ static void nop_int(H3270 GNUC_UNUSED(*session), int GNUC_UNUSED(width))
260 return; 260 return;
261 } 261 }
262 262
263 -#ifdef HAVE_LIBSSL  
264 -static void set_peer_certificate(const X509 GNUC_UNUSED(*cert))  
265 -{  
266 -  
267 -}  
268 -#else  
269 -static void set_peer_certificate(const void GNUC_UNUSED(*cert))  
270 -{  
271 -  
272 -}  
273 -#endif // HAVE_LIBSSL  
274 -  
275 static void default_update_luname(H3270 GNUC_UNUSED(*session), const char GNUC_UNUSED(*name)) 263 static void default_update_luname(H3270 GNUC_UNUSED(*session), const char GNUC_UNUSED(*name))
276 { 264 {
277 } 265 }
@@ -307,7 +295,6 @@ void lib3270_reset_callbacks(H3270 *hSession) @@ -307,7 +295,6 @@ void lib3270_reset_callbacks(H3270 *hSession)
307 hSession->cbk.print = print; 295 hSession->cbk.print = print;
308 hSession->cbk.save = save; 296 hSession->cbk.save = save;
309 hSession->cbk.load = load; 297 hSession->cbk.load = load;
310 - hSession->cbk.set_peer_certificate = set_peer_certificate;  
311 hSession->cbk.update_luname = default_update_luname; 298 hSession->cbk.update_luname = default_update_luname;
312 hSession->cbk.update_url = default_update_url; 299 hSession->cbk.update_url = default_update_url;
313 300
src/include/internals.h
@@ -860,3 +860,5 @@ LIB3270_INTERNAL void set_ssl_state(H3270 *session, LIB3270_SSL_STATE state); @@ -860,3 +860,5 @@ LIB3270_INTERNAL void set_ssl_state(H3270 *session, LIB3270_SSL_STATE state);
860 LIB3270_INTERNAL int lib3270_start_tls(H3270 *hSession); 860 LIB3270_INTERNAL int lib3270_start_tls(H3270 *hSession);
861 861
862 862
  863 + /// @brief Load file using URL.
  864 + LIB3270_INTERNAL char * lib3270_url_get(H3270 *hSession, const char *url, LIB3270_POPUP **popup);
src/include/lib3270/session.h
@@ -80,12 +80,6 @@ @@ -80,12 +80,6 @@
80 80
81 int (*popup)(H3270 *hSession, const LIB3270_POPUP *popup, unsigned char wait); 81 int (*popup)(H3270 *hSession, const LIB3270_POPUP *popup, unsigned char wait);
82 82
83 -#ifdef HAVE_LIBSSL  
84 - void (*set_peer_certificate)(const X509 *cert);  
85 -#else  
86 - void (*set_peer_certificate)(const void *cert);  
87 -#endif // HAVE_LIBSSL  
88 -  
89 }; 83 };
90 84
91 /** 85 /**
src/network_modules/openssl/crl.c 0 → 100644
@@ -0,0 +1,93 @@ @@ -0,0 +1,93 @@
  1 +/*
  2 + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
  3 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
  4 + * aplicativos mainframe. Registro no INPI sob o nome G3270.
  5 + *
  6 + * Copyright (C) <2008> <Banco do Brasil S.A.>
  7 + *
  8 + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
  9 + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
  10 + * Free Software Foundation.
  11 + *
  12 + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
  13 + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
  14 + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
  15 + * obter mais detalhes.
  16 + *
  17 + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
  18 + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
  19 + * St, Fifth Floor, Boston, MA 02110-1301 USA
  20 + *
  21 + * Este programa está nomeado como - e possui - linhas de código.
  22 + *
  23 + * Contatos:
  24 + *
  25 + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
  26 + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
  27 + *
  28 + */
  29 +
  30 +/// @brief Get CRL infro from X509 cert.
  31 +///
  32 +/// References:
  33 +///
  34 +/// http://www.zedwood.com/article/cpp-check-crl-for-revocation
  35 +
  36 +
  37 +#include "private.h"
  38 +
  39 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  40 +
  41 +LIB3270_STRING_ARRAY * lib3270_openssl_get_crls_from_peer(H3270 *hSession, X509 *cert) {
  42 +
  43 + //
  44 + // Get Distribution points.
  45 + //
  46 + lib3270_autoptr(CRL_DIST_POINTS) dist_points = (CRL_DIST_POINTS *) X509_get_ext_d2i(cert, NID_crl_distribution_points, NULL, NULL);
  47 +
  48 + if(!dist_points) {
  49 + trace_ssl(hSession,"The host certificate doesn't have CRL distribution points\n");
  50 + return NULL;
  51 + }
  52 +
  53 + LIB3270_STRING_ARRAY * uris = lib3270_string_array_new();
  54 +
  55 + size_t ix;
  56 + for(ix = 0; ix < (size_t) sk_DIST_POINT_num(dist_points); ix++) {
  57 +
  58 + DIST_POINT *dp = sk_DIST_POINT_value(dist_points, ix);
  59 +
  60 + if(!dp->distpoint || dp->distpoint->type != 0)
  61 + continue;
  62 +
  63 + GENERAL_NAMES *gens = dp->distpoint->name.fullname;
  64 +
  65 + size_t i;
  66 + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
  67 + int gtype;
  68 + GENERAL_NAME *gen = sk_GENERAL_NAME_value(gens, i);
  69 + ASN1_STRING *uri = GENERAL_NAME_get0_value(gen, &gtype);
  70 +
  71 + if(uri && gtype == GEN_URI)
  72 + {
  73 + int length = ASN1_STRING_length(uri);
  74 +
  75 +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) // OpenSSL 1.1.0+
  76 + const unsigned char * data = ASN1_STRING_get0_data(uri);
  77 +#else
  78 + const unsigned char * data = ASN1_STRING_data(uri);
  79 +#endif // OpenSSL 1.1.0+
  80 +
  81 + if(data && length > 0)
  82 + lib3270_string_array_append_with_length(uris,(char *) data, (size_t) length);
  83 +
  84 + }
  85 +
  86 + }
  87 +
  88 + }
  89 +
  90 + return uris;
  91 +
  92 +}
  93 +
src/network_modules/openssl/main.c
@@ -178,87 +178,6 @@ static int openssl_network_connect(H3270 *hSession, LIB3270_NETWORK_STATE *state @@ -178,87 +178,6 @@ static int openssl_network_connect(H3270 *hSession, LIB3270_NETWORK_STATE *state
178 178
179 } 179 }
180 180
181 -static int openssl_network_start_tls(H3270 *hSession, LIB3270_NETWORK_STATE *state) {  
182 -  
183 - SSL_CTX * ctx_context = (SSL_CTX *) lib3270_openssl_get_context(state,state);  
184 - if(!ctx_context)  
185 - return -1;  
186 -  
187 - LIB3270_NET_CONTEXT * context = hSession->network.context;  
188 -  
189 - debug("%s",__FUNCTION__);  
190 -  
191 - set_ssl_state(hSession,LIB3270_SSL_NEGOTIATING);  
192 - context->con = SSL_new(ctx_context);  
193 - if(context->con == NULL)  
194 - {  
195 - static const LIB3270_POPUP popup = {  
196 - .type = LIB3270_NOTIFY_SECURE,  
197 - .summary = N_( "Cant create a new SSL structure for current connection." )  
198 - };  
199 -  
200 - state->popup = &popup;  
201 - return -1;  
202 - }  
203 -  
204 - SSL_set_ex_data(context->con,lib3270_openssl_get_ex_index(hSession),(char *) hSession);  
205 -// SSL_set_verify(context->con, SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);  
206 - SSL_set_verify(context->con, 0, NULL);  
207 -  
208 - if(SSL_set_fd(context->con, context->sock) != 1)  
209 - {  
210 - trace_ssl(hSession,"%s","SSL_set_fd failed!\n");  
211 -  
212 - static const LIB3270_NETWORK_POPUP popup = {  
213 - .summary = N_( "SSL negotiation failed" ),  
214 - .body = N_( "Cant set the file descriptor for the input/output facility for the TLS/SSL (encrypted) side of ssl." )  
215 - };  
216 -  
217 - state->popup = &popup;  
218 - return -1;  
219 -  
220 - }  
221 -  
222 - trace_ssl(hSession, "%s","Running SSL_connect\n");  
223 - int rv = SSL_connect(context->con);  
224 - trace_ssl(hSession, "SSL_connect exits with rc=%d\n",rv);  
225 -  
226 - if (rv != 1)  
227 - {  
228 - int code = SSL_get_error(context->con,rv);  
229 -  
230 - if(code == SSL_ERROR_SYSCALL && hSession->ssl.error)  
231 - code = hSession->ssl.error;  
232 -  
233 - state->error_message = ERR_lib_error_string(code);  
234 -  
235 - trace_ssl(hSession,"SSL_connect failed: %s\n",ERR_reason_error_string(code));  
236 -  
237 - static const LIB3270_POPUP popup = {  
238 - .type = LIB3270_NOTIFY_ERROR,  
239 - .summary = N_( "SSL Connect failed" ),  
240 - };  
241 -  
242 - state->popup = &popup;  
243 - return -1;  
244 -  
245 - }  
246 -  
247 - //  
248 - // Connection succeeded, do we need to download the CRL?  
249 - //  
250 - if(lib3270_ssl_get_crl_download(hSession)) {  
251 -  
252 -  
253 - } else {  
254 -  
255 - trace_ssl(hSession,"CRL download is disabled\n");  
256 -  
257 - }  
258 -  
259 - return 0;  
260 -}  
261 -  
262 void lib3270_set_openssl_network_module(H3270 *hSession) { 181 void lib3270_set_openssl_network_module(H3270 *hSession) {
263 182
264 static const LIB3270_NET_MODULE module = { 183 static const LIB3270_NET_MODULE module = {
src/network_modules/openssl/private.h
@@ -44,12 +44,14 @@ @@ -44,12 +44,14 @@
44 #include <lib3270.h> 44 #include <lib3270.h>
45 #include <lib3270/log.h> 45 #include <lib3270/log.h>
46 #include <lib3270/popup.h> 46 #include <lib3270/popup.h>
  47 + #include <array.h>
47 #include <internals.h> 48 #include <internals.h>
48 #include <networking.h> 49 #include <networking.h>
49 #include <trace_dsc.h> 50 #include <trace_dsc.h>
50 51
51 #include <openssl/ssl.h> 52 #include <openssl/ssl.h>
52 #include <openssl/x509.h> 53 #include <openssl/x509.h>
  54 + #include <openssl/err.h>
53 55
54 struct _lib3270_network_popup { 56 struct _lib3270_network_popup {
55 LIB3270_POPUP_HEAD 57 LIB3270_POPUP_HEAD
@@ -80,9 +82,27 @@ @@ -80,9 +82,27 @@
80 82
81 }; 83 };
82 84
  85 + /// @brief X509 auto-cleanup.
  86 + static inline void lib3270_autoptr_cleanup_X509(X509 **ptr) {
  87 + if(*ptr)
  88 + X509_free(*ptr);
  89 + *ptr = NULL;
  90 + }
  91 +
  92 + /// @brief Dist points auto-cleanup.
  93 + static inline void lib3270_autoptr_cleanup_CRL_DIST_POINTS(CRL_DIST_POINTS **ptr)
  94 + {
  95 + if(*ptr)
  96 + CRL_DIST_POINTS_free(*ptr);
  97 + *ptr = NULL;
  98 + }
  99 +
83 LIB3270_INTERNAL SSL_CTX * lib3270_openssl_get_context(H3270 *hSession, LIB3270_NETWORK_STATE *state); 100 LIB3270_INTERNAL SSL_CTX * lib3270_openssl_get_context(H3270 *hSession, LIB3270_NETWORK_STATE *state);
84 LIB3270_INTERNAL int lib3270_openssl_get_ex_index(H3270 *hSession); 101 LIB3270_INTERNAL int lib3270_openssl_get_ex_index(H3270 *hSession);
85 LIB3270_INTERNAL const LIB3270_NETWORK_POPUP * lib3270_openssl_get_popup_from_error_code(long id); 102 LIB3270_INTERNAL const LIB3270_NETWORK_POPUP * lib3270_openssl_get_popup_from_error_code(long id);
86 103
  104 + LIB3270_INTERNAL int openssl_network_start_tls(H3270 *hSession, LIB3270_NETWORK_STATE *state);
  105 +
  106 + LIB3270_INTERNAL LIB3270_STRING_ARRAY * lib3270_openssl_get_crls_from_peer(H3270 *hSession, X509 *cert);
87 107
88 #endif // !LIB3270_OPENSSL_MODULE_PRIVATE_H_INCLUDED 108 #endif // !LIB3270_OPENSSL_MODULE_PRIVATE_H_INCLUDED
src/network_modules/openssl/start.c 0 → 100644
@@ -0,0 +1,183 @@ @@ -0,0 +1,183 @@
  1 +/*
  2 + * "Software PW3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
  3 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
  4 + * aplicativos mainframe. Registro no INPI sob o nome G3270.
  5 + *
  6 + * Copyright (C) <2008> <Banco do Brasil S.A.>
  7 + *
  8 + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
  9 + * os termos da GPL v.2 - Licença Pública Geral ', conforme publicado pela
  10 + * Free Software Foundation.
  11 + *
  12 + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
  13 + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
  14 + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
  15 + * obter mais detalhes.
  16 + *
  17 + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
  18 + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
  19 + * St, Fifth Floor, Boston, MA 02110-1301 USA
  20 + *
  21 + * Este programa está nomeado como openssl.c e possui - linhas de código.
  22 + *
  23 + * Contatos:
  24 + *
  25 + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
  26 + * erico.mendonca@gmail.com (Erico Mascarenhas de Mendonça)
  27 + *
  28 + */
  29 +
  30 + /**
  31 + * @brief Negotiate OpenSSL session.
  32 + *
  33 + */
  34 +
  35 + #include "private.h"
  36 + #include <lib3270/properties.h>
  37 +
  38 + int openssl_network_start_tls(H3270 *hSession, LIB3270_NETWORK_STATE *state) {
  39 +
  40 + SSL_CTX * ctx_context = (SSL_CTX *) lib3270_openssl_get_context(hSession,state);
  41 + if(!ctx_context)
  42 + return -1;
  43 +
  44 + LIB3270_NET_CONTEXT * context = hSession->network.context;
  45 +
  46 + debug("%s",__FUNCTION__);
  47 +
  48 + set_ssl_state(hSession,LIB3270_SSL_NEGOTIATING);
  49 + context->con = SSL_new(ctx_context);
  50 + if(context->con == NULL)
  51 + {
  52 + static const LIB3270_NETWORK_POPUP popup = {
  53 + .type = LIB3270_NOTIFY_SECURE,
  54 + .summary = N_( "Cant create a new SSL structure for current connection." )
  55 + };
  56 +
  57 + state->popup = &popup;
  58 + return -1;
  59 + }
  60 +
  61 + SSL_set_ex_data(context->con,lib3270_openssl_get_ex_index(hSession),(char *) hSession);
  62 +// SSL_set_verify(context->con, SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
  63 + SSL_set_verify(context->con, 0, NULL);
  64 +
  65 + if(SSL_set_fd(context->con, context->sock) != 1)
  66 + {
  67 + trace_ssl(hSession,"%s","SSL_set_fd failed!\n");
  68 +
  69 + static const LIB3270_NETWORK_POPUP popup = {
  70 + .summary = N_( "SSL negotiation failed" ),
  71 + .body = N_( "Cant set the file descriptor for the input/output facility for the TLS/SSL (encrypted) side of ssl." )
  72 + };
  73 +
  74 + state->popup = &popup;
  75 + return -1;
  76 +
  77 + }
  78 +
  79 + trace_ssl(hSession, "%s","Running SSL_connect\n");
  80 + int rv = SSL_connect(context->con);
  81 + trace_ssl(hSession, "SSL_connect exits with rc=%d\n",rv);
  82 +
  83 + if (rv != 1)
  84 + {
  85 + int code = SSL_get_error(context->con,rv);
  86 +
  87 + if(code == SSL_ERROR_SYSCALL && hSession->ssl.error)
  88 + code = hSession->ssl.error;
  89 +
  90 + state->error_message = ERR_lib_error_string(code);
  91 +
  92 + trace_ssl(hSession,"SSL_connect failed: %s\n",ERR_reason_error_string(code));
  93 +
  94 + static const LIB3270_NETWORK_POPUP popup = {
  95 + .summary = N_( "SSL Connect failed" ),
  96 + };
  97 +
  98 + state->popup = &popup;
  99 + return -1;
  100 +
  101 + }
  102 +
  103 + // Get peer certificate, notify application before validation.
  104 + lib3270_autoptr(X509) peer = SSL_get_peer_certificate(context->con);
  105 +
  106 + if(peer) {
  107 +
  108 + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE))
  109 + {
  110 + BIO * out = BIO_new(BIO_s_mem());
  111 + unsigned char * data;
  112 + unsigned char * text;
  113 + int n;
  114 +
  115 + X509_print(out,peer);
  116 +
  117 + n = BIO_get_mem_data(out, &data);
  118 + text = (unsigned char *) malloc (n+1);
  119 + text[n] ='\0';
  120 + memcpy(text,data,n);
  121 +
  122 + trace_ssl(hSession,"TLS/SSL peer certificate:\n%s\n",text);
  123 +
  124 + free(text);
  125 + BIO_free(out);
  126 +
  127 + }
  128 +
  129 + }
  130 +
  131 + // Do we really need to download a new CRL?
  132 + if(lib3270_ssl_get_crl_download(hSession) && SSL_get_verify_result(context->con) == X509_V_ERR_UNABLE_TO_GET_CRL) {
  133 +
  134 + trace_ssl(hSession,"CRL Validation has failed, requesting download\n");
  135 +
  136 + lib3270_autoptr(char) crl_text = NULL;
  137 + if(context->crl.url) {
  138 +
  139 + // There's a pre-defined URL, use it.
  140 + const LIB3270_POPUP * popup = NULL;
  141 + crl_text = lib3270_url_get(hSession, context->crl.url,&popup);
  142 +
  143 + if(popup) {
  144 + state->popup = popup;
  145 + trace_ssl(hSession,"Error downloading CRL from %s: %s\n",context->crl.url,popup->summary);
  146 + }
  147 +
  148 +#ifndef DEBUG
  149 + #error TODO: Import crl_text;
  150 +#endif // DEBUG
  151 +
  152 + } else if(peer) {
  153 +
  154 + // There's no pre-defined URL, get them from peer.
  155 + lib3270_autoptr(LIB3270_STRING_ARRAY) uris = lib3270_openssl_get_crls_from_peer(hSession, peer);
  156 +
  157 + if(uris) {
  158 +
  159 + size_t ix;
  160 + for(ix = 0; ix < uris->length; ix++) {
  161 +
  162 + LIB3270_POPUP * popup = NULL;
  163 + crl_text = lib3270_url_get(hSession, uris->str[ix], &popup);
  164 +
  165 + if(popup) {
  166 + trace_ssl(hSession,"Error downloading CRL from %s: %s\n",uris[ix],popup->summary);
  167 + }
  168 +
  169 +#ifndef DEBUG
  170 + #error TODO: Import crl_text;
  171 +#endif // DEBUG
  172 +
  173 + }
  174 + }
  175 +
  176 + }
  177 +
  178 + }
  179 +
  180 +
  181 +
  182 + return 0;
  183 +}