Commit 053cd3d1d5f7d14881fb0b6c07f7d4d894dea372

Authored by Perry Werneck
1 parent 6021974d

Adding CRL download from LDAP (optional).

@@ -472,9 +472,9 @@ else @@ -472,9 +472,9 @@ else
472 LDAP_LIBS= 472 LDAP_LIBS=
473 fi 473 fi
474 474
  475 +AC_SUBST(LDAP_CFLAGS)
475 AC_SUBST(LDAP_LIBS) 476 AC_SUBST(LDAP_LIBS)
476 477
477 -  
478 dnl --------------------------------------------------------------------------- 478 dnl ---------------------------------------------------------------------------
479 dnl Directory config 479 dnl Directory config
480 dnl --------------------------------------------------------------------------- 480 dnl ---------------------------------------------------------------------------
src/include/config.h.in
@@ -36,7 +36,6 @@ @@ -36,7 +36,6 @@
36 #undef PACKAGE_RELEASE 36 #undef PACKAGE_RELEASE
37 37
38 #undef HAVE_GNUC_VISIBILITY 38 #undef HAVE_GNUC_VISIBILITY
39 - #undef HAVE_LIBM  
40 #undef HAVE_LIBINTL 39 #undef HAVE_LIBINTL
41 #undef HAVE_GETADDRINFO 40 #undef HAVE_GETADDRINFO
42 #undef HAVE_VASPRINTF 41 #undef HAVE_VASPRINTF
src/include/lib3270.h
@@ -149,6 +149,7 @@ @@ -149,6 +149,7 @@
149 LIB3270_TOGGLE_ALTSCREEN, /**< @brief auto resize on altscreen */ 149 LIB3270_TOGGLE_ALTSCREEN, /**< @brief auto resize on altscreen */
150 LIB3270_TOGGLE_KEEP_ALIVE, /**< @brief Enable network keep-alive with SO_KEEPALIVE */ 150 LIB3270_TOGGLE_KEEP_ALIVE, /**< @brief Enable network keep-alive with SO_KEEPALIVE */
151 LIB3270_TOGGLE_NETWORK_TRACE, /**< @brief Enable network in/out trace */ 151 LIB3270_TOGGLE_NETWORK_TRACE, /**< @brief Enable network in/out trace */
  152 + LIB3270_TOGGLE_SSL_TRACE, /**< @brief Enable security traces */
152 153
153 LIB3270_TOGGLE_COUNT 154 LIB3270_TOGGLE_COUNT
154 155
src/include/toggle.h
@@ -62,7 +62,7 @@ @@ -62,7 +62,7 @@
62 // #define INSERT LIB3270_TOGGLE_INSERT 62 // #define INSERT LIB3270_TOGGLE_INSERT
63 #define KEYPAD LIB3270_TOGGLE_KEYPAD 63 #define KEYPAD LIB3270_TOGGLE_KEYPAD
64 #define SMART_PASTE LIB3270_TOGGLE_SMART_PASTE 64 #define SMART_PASTE LIB3270_TOGGLE_SMART_PASTE
65 - #define N_TOGGLES LIB3270_TOGGLE_COUNT 65 +// #define N_TOGGLES LIB3270_TOGGLE_COUNT
66 66
67 #define LIB3270_TOGGLE_ID LIB3270_TOGGLE 67 #define LIB3270_TOGGLE_ID LIB3270_TOGGLE
68 68
src/include/trace_dsc.h
@@ -27,15 +27,12 @@ @@ -27,15 +27,12 @@
27 * 27 *
28 */ 28 */
29 29
30 -/*  
31 - * trace_dsc.h  
32 - * Global declarations for trace_ds.c. 30 +/**
  31 + * @brief Global declarations for trace_ds.c.
33 */ 32 */
34 33
35 #if defined(X3270_TRACE) 34 #if defined(X3270_TRACE)
36 35
37 -// LIB3270_INTERNAL Boolean trace_skipping;  
38 -  
39 const char *rcba(H3270 *session, int baddr); 36 const char *rcba(H3270 *session, int baddr);
40 37
41 void trace_ansi_disc(H3270 *hSession); 38 void trace_ansi_disc(H3270 *hSession);
@@ -43,23 +40,22 @@ @@ -43,23 +40,22 @@
43 void trace_ds(H3270 *hSession, const char *fmt, ...) LIB3270_GNUC_FORMAT(2, 3); 40 void trace_ds(H3270 *hSession, const char *fmt, ...) LIB3270_GNUC_FORMAT(2, 3);
44 void trace_ds_nb(H3270 *hSession, const char *fmt, ...) LIB3270_GNUC_FORMAT(2, 3); 41 void trace_ds_nb(H3270 *hSession, const char *fmt, ...) LIB3270_GNUC_FORMAT(2, 3);
45 void trace_dsn(H3270 *hSession, const char *fmt, ...) LIB3270_GNUC_FORMAT(2, 3); 42 void trace_dsn(H3270 *hSession, const char *fmt, ...) LIB3270_GNUC_FORMAT(2, 3);
  43 + void trace_ssl(H3270 *hSession, const char *fmt, ...) LIB3270_GNUC_FORMAT(2, 3);
46 void trace_screen(H3270 *session); 44 void trace_screen(H3270 *session);
47 45
48 -// #define trace_event(...) lib3270_trace_event(&h3270,__VA_ARGS__)  
49 -  
50 #elif defined(__GNUC__) 46 #elif defined(__GNUC__)
51 47
52 #define trace_ds(session, format, args...) 48 #define trace_ds(session, format, args...)
53 #define trace_dsn(session, format, args...) 49 #define trace_dsn(session, format, args...)
  50 + #define trace_ssl(session, format, args...)
54 #define trace_ds_nb(session, format, args...) 51 #define trace_ds_nb(session, format, args...)
55 -// #define trace_event(session, format, args...)  
56 52
57 #else 53 #else
58 54
59 #define trace_ds 0 && 55 #define trace_ds 0 &&
60 #define trace_ds_nb 0 && 56 #define trace_ds_nb 0 &&
61 #define trace_dsn 0 && 57 #define trace_dsn 0 &&
62 -// #define trace_event 0 && 58 + #define trace_ssl 0 &&
63 #define rcba 0 && 59 #define rcba 0 &&
64 60
65 #endif 61 #endif
src/lib3270/Makefile.in
@@ -94,13 +94,15 @@ CFLAGS= \ @@ -94,13 +94,15 @@ CFLAGS= \
94 -g \ 94 -g \
95 -I../include 95 -I../include
96 -DBUILD_DATE=`date +%Y%m%d` \ 96 -DBUILD_DATE=`date +%Y%m%d` \
97 - @LIBSSL_CFLAGS@ 97 + @LIBSSL_CFLAGS@ \
  98 + @LDAP_CFLAGS@
98 99
99 LIBS= \ 100 LIBS= \
100 @LIBS@ \ 101 @LIBS@ \
101 @LIBSSL_LIBS@ \ 102 @LIBSSL_LIBS@ \
102 @LIBICONV@ \ 103 @LIBICONV@ \
103 - @INTL_LIBS@ 104 + @INTL_LIBS@ \
  105 + @LDAP_LIBS@
104 106
105 #---[ Debug Rules ]---------------------------------------------------------------------- 107 #---[ Debug Rules ]----------------------------------------------------------------------
106 108
@@ -325,7 +327,14 @@ $(BINDBG)/$(LIBNAME)@EXEEXT@: \ @@ -325,7 +327,14 @@ $(BINDBG)/$(LIBNAME)@EXEEXT@: \
325 327
326 @$(MKDIR) `dirname $@` 328 @$(MKDIR) `dirname $@`
327 @echo $< ... 329 @echo $< ...
328 - @$(LD) -o $@ $^ $(LDFLAGS) $(LIBS) 330 + @$(LD) \
  331 + -Wl,--rpath,$(BINDBG) \
  332 + -o $@ \
  333 + $(foreach SRC, $(basename $(TEST_SOURCES)), $(OBJDBG)/$(SRC).o) \
  334 + $(LDFLAGS) \
  335 + $(LIBS) \
  336 + -L$(BINDBG) \
  337 + -l@LIB3270_NAME@
329 338
330 run: \ 339 run: \
331 $(BINDBG)/$(LIBNAME)@EXEEXT@ 340 $(BINDBG)/$(LIBNAME)@EXEEXT@
src/lib3270/private.h
@@ -605,6 +605,9 @@ struct _h3270 @@ -605,6 +605,9 @@ struct _h3270
605 char host; 605 char host;
606 LIB3270_SSL_STATE state; 606 LIB3270_SSL_STATE state;
607 unsigned long error; 607 unsigned long error;
  608 +#ifdef SSL_ENABLE_CRL_CHECK
  609 + char * crl;
  610 +#endif // SSL_ENABLE_CRL_CHECK
608 SSL * con; 611 SSL * con;
609 } ssl; 612 } ssl;
610 #endif // HAVE_LIBSSL 613 #endif // HAVE_LIBSSL
src/lib3270/session.c
@@ -74,6 +74,14 @@ void lib3270_session_free(H3270 *h) @@ -74,6 +74,14 @@ void lib3270_session_free(H3270 *h)
74 74
75 shutdown_toggles(h); 75 shutdown_toggles(h);
76 76
  77 +#ifdef SSL_ENABLE_CRL_CHECK
  78 + if(h->ssl.crl)
  79 + {
  80 + free(h->ssl.crl);
  81 + h->ssl.crl = NULL;
  82 + }
  83 +#endif // SSL_ENABLE_CRL_CHECK
  84 +
77 // Release state change callbacks 85 // Release state change callbacks
78 for(f=0;f<LIB3270_STATE_USER;f++) 86 for(f=0;f<LIB3270_STATE_USER;f++)
79 { 87 {
@@ -312,6 +320,14 @@ static void lib3270_session_init(H3270 *hSession, const char *model, const char @@ -312,6 +320,14 @@ static void lib3270_session_init(H3270 *hSession, const char *model, const char
312 hSession->unlock_delay_ms = 350; // 0.35s after last unlock 320 hSession->unlock_delay_ms = 350; // 0.35s after last unlock
313 hSession->pointer = (unsigned short) LIB3270_POINTER_LOCKED; 321 hSession->pointer = (unsigned short) LIB3270_POINTER_LOCKED;
314 322
  323 +#ifdef SSL_ENABLE_CRL_CHECK
  324 + char *env = getenv("LIB3270_DEFAULT_CRL");
  325 + if(env)
  326 + {
  327 + hSession->ssl.crl = strdup(env);
  328 + }
  329 +#endif // SSL_ENABLE_CRL_CHECK
  330 +
315 // CSD 331 // CSD
316 for(f=0;f<4;f++) 332 for(f=0;f<4;f++)
317 hSession->csd[f] = hSession->saved_csd[f] = LIB3270_ANSI_CSD_US; 333 hSession->csd[f] = hSession->saved_csd[f] = LIB3270_ANSI_CSD_US;
src/lib3270/ssl/ctx_init.c
@@ -84,7 +84,7 @@ int ssl_ctx_init(H3270 *hSession, SSL_ERROR_MESSAGE * message) @@ -84,7 +84,7 @@ int ssl_ctx_init(H3270 *hSession, SSL_ERROR_MESSAGE * message)
84 if(ssl_ctx) 84 if(ssl_ctx)
85 return 0; 85 return 0;
86 86
87 - trace_dsn(hSession,"Initializing SSL context.\n"); 87 + trace_ssl(hSession,"Initializing SSL context.\n");
88 88
89 SSL_load_error_strings(); 89 SSL_load_error_strings();
90 SSL_library_init(); 90 SSL_library_init();
@@ -111,42 +111,42 @@ int ssl_ctx_init(H3270 *hSession, SSL_ERROR_MESSAGE * message) @@ -111,42 +111,42 @@ int ssl_ctx_init(H3270 *hSession, SSL_ERROR_MESSAGE * message)
111 // 111 //
112 // https://stackoverflow.com/questions/10510850/how-to-verify-the-certificate-for-the-ongoing-ssl-session 112 // https://stackoverflow.com/questions/10510850/how-to-verify-the-certificate-for-the-ongoing-ssl-session
113 // 113 //
114 - lib3270_autoptr(X509_CRL) crl = lib3270_get_X509_CRL(hSession,message); 114 + if(hSession->ssl.crl)
  115 + {
  116 + lib3270_autoptr(X509_CRL) crl = lib3270_get_X509_CRL(hSession,message);
115 117
116 - if(!crl)  
117 - return -1; 118 + if(!crl)
  119 + return -1;
118 120
119 -// const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl);  
120 -// X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl); 121 + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE))
  122 + {
  123 + BIO * out = BIO_new(BIO_s_mem());
  124 + unsigned char * data;
  125 + unsigned char * text;
  126 + int n;
121 127
122 - if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_DS_TRACE))  
123 - {  
124 - BIO * out = BIO_new(BIO_s_mem());  
125 - unsigned char * data;  
126 - unsigned char * text;  
127 - int n; 128 + X509_CRL_print(out,crl);
128 129
129 - X509_CRL_print(out,crl); 130 + n = BIO_get_mem_data(out, &data);
  131 + text = (unsigned char *) malloc (n+1);
  132 + text[n] ='\0';
  133 + memcpy(text,data,n);
130 134
131 - n = BIO_get_mem_data(out, &data);  
132 - text = (unsigned char *) malloc (n+1);  
133 - text[n] ='\0';  
134 - memcpy(text,data,n); 135 + trace_ssl(hSession,"\n%s\n",text);
135 136
136 - trace_dsn(hSession,"\n%s\n",text); 137 + free(text);
  138 + BIO_free(out);
137 139
138 - free(text);  
139 - BIO_free(out); 140 + }
140 141
141 - }  
142 -  
143 - X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);  
144 - X509_STORE_add_crl(store, crl);  
145 - X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new();  
146 - X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);  
147 - X509_STORE_set1_param(store, param);  
148 - X509_VERIFY_PARAM_free(param); 142 + X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
  143 + X509_STORE_add_crl(store, crl);
  144 + X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new();
  145 + X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
  146 + X509_STORE_set1_param(store, param);
  147 + X509_VERIFY_PARAM_free(param);
149 148
  149 + }
150 #endif // SSL_ENABLE_CRL_CHECK 150 #endif // SSL_ENABLE_CRL_CHECK
151 151
152 return 0; 152 return 0;
src/lib3270/ssl/linux/getcrl.c 0 → 100644
@@ -0,0 +1,298 @@ @@ -0,0 +1,298 @@
  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 + * References:
  30 + *
  31 + * http://www.openssl.org/docs/ssl/
  32 + * https://stackoverflow.com/questions/4389954/does-openssl-automatically-handle-crls-certificate-revocation-lists-now
  33 + *
  34 + */
  35 +
  36 +#include <config.h>
  37 +#if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK)
  38 +
  39 +#include <openssl/ssl.h>
  40 +#include <openssl/err.h>
  41 +#include <openssl/x509_vfy.h>
  42 +#include <openssl/x509.h>
  43 +
  44 +#ifdef HAVE_LDAP
  45 + #define LDAP_DEPRECATED 1
  46 + #include <ldap.h>
  47 +#endif // HAVE_LDAP
  48 +
  49 +#include "../../private.h"
  50 +#include <errno.h>
  51 +#include <lib3270.h>
  52 +
  53 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  54 +
  55 +static inline void lib3270_autoptr_cleanup_FILE(FILE **file)
  56 +{
  57 + if(*file)
  58 + fclose(*file);
  59 +}
  60 +
  61 +#ifdef HAVE_LDAP
  62 +static inline void lib3270_autoptr_cleanup_LDAPMessage(LDAPMessage **message)
  63 +{
  64 + debug("%s(%p)",__FUNCTION__,*message);
  65 + if(message)
  66 + ldap_msgfree(*message);
  67 + *message = NULL;
  68 +}
  69 +
  70 +static inline void lib3270_autoptr_cleanup_LDAP(LDAP **ld)
  71 +{
  72 + debug("%s(%p)",__FUNCTION__,*ld);
  73 + if(*ld)
  74 + ldap_unbind_ext(*ld, NULL, NULL);
  75 + *ld = NULL;
  76 +}
  77 +
  78 +static inline void lib3270_autoptr_cleanup_BerElement(BerElement **ber)
  79 +{
  80 + debug("%s(%p)",__FUNCTION__,*ber);
  81 + if(*ber)
  82 + ber_free(*ber, 0);
  83 + *ber = NULL;
  84 +}
  85 +
  86 +static inline void lib3270_autoptr_cleanup_LDAPPTR(char **ptr)
  87 +{
  88 + debug("%s(%p)",__FUNCTION__,*ptr);
  89 + if(*ptr)
  90 + ldap_memfree(*ptr);
  91 + *ptr = NULL;
  92 +}
  93 +
  94 +#endif // HAVE_LDAP
  95 +
  96 +X509_CRL * lib3270_get_X509_CRL(H3270 *hSession, SSL_ERROR_MESSAGE * message)
  97 +{
  98 + X509_CRL * crl = NULL;
  99 +
  100 + if(strncasecmp(hSession->ssl.crl,"file://",7) == 0)
  101 + {
  102 + lib3270_autoptr(FILE) hCRL = fopen(hSession->ssl.crl+7,"r");
  103 +
  104 + if(!hCRL)
  105 + {
  106 + // Can't open CRL File.
  107 + message->error = hSession->ssl.error = 0;
  108 + message->title = N_( "Security error" );
  109 + message->text = N_( "Can't open CRL File" );
  110 + message->description = strerror(errno);
  111 + lib3270_write_log(hSession,"ssl","Can't open %s: %s",hSession->ssl.crl,message->description);
  112 + return NULL;
  113 +
  114 + }
  115 +
  116 + lib3270_write_log(hSession,"ssl","Loading CRL from %s",hSession->ssl.crl+7);
  117 + d2i_X509_CRL_fp(hCRL, &crl);
  118 +
  119 + }
  120 +#ifdef HAVE_LDAP
  121 + else if(strncasecmp(hSession->ssl.crl,"ldap",4) == 0)
  122 + {
  123 + int rc;
  124 + lib3270_autoptr(char) url = strdup(hSession->ssl.crl);
  125 +
  126 + char * attrs[] = { NULL, NULL };
  127 + char * base = NULL;
  128 +
  129 + const struct _args
  130 + {
  131 + const char * name;
  132 + char ** value;
  133 + }
  134 + args[] =
  135 + {
  136 + { "attr", &attrs[0] },
  137 + { "base", &base }
  138 + };
  139 +
  140 + // Get arguments
  141 + size_t arg;
  142 + char * ptr = strchr(url,'?');
  143 + while(ptr)
  144 + {
  145 + *(ptr++) = 0;
  146 + char *value = strchr(ptr,'=');
  147 + if(!value)
  148 + {
  149 + message->error = hSession->ssl.error = 0;
  150 + message->title = N_( "Security error" );
  151 + message->text = N_( "Invalid argument format" );
  152 + message->description = "The URL argument should be in the format name=value";
  153 + return NULL;
  154 + }
  155 +
  156 + *(value++) = 0;
  157 +
  158 + debug("%s=%s",ptr,value);
  159 +
  160 + for(arg = 0; arg < (sizeof(args)/sizeof(args[0])); arg++)
  161 + {
  162 + if(!strcasecmp(ptr,args[arg].name))
  163 + {
  164 + *args[arg].value = value;
  165 + debug("%s=\"%s\"",args[arg].name,*args[arg].value);
  166 + }
  167 + }
  168 +
  169 + ptr = strchr(value,'&');
  170 + }
  171 +
  172 + // Do we get all the required arguments?
  173 + for(arg = 0; arg < (sizeof(args)/sizeof(args[0])); arg++)
  174 + {
  175 + if(!*args[arg].value)
  176 + {
  177 + message->error = hSession->ssl.error = 0;
  178 + message->title = N_( "Security error" );
  179 + message->text = N_( "Can't set LDAP query" );
  180 + message->description = N_("Insuficient arguments");
  181 + lib3270_write_log(hSession,"ssl","%s: Required argument \"%s\" is missing",url, args[arg].name);
  182 + return NULL;
  183 + }
  184 + }
  185 +
  186 + // Do LDAP Query
  187 + LDAP __attribute__ ((__cleanup__(lib3270_autoptr_cleanup_LDAP))) *ld = NULL;
  188 + BerElement __attribute__ ((__cleanup__(lib3270_autoptr_cleanup_BerElement))) * ber = NULL;
  189 +
  190 + rc = ldap_initialize(&ld, url);
  191 + if(rc != LDAP_SUCCESS)
  192 + {
  193 + message->error = hSession->ssl.error = 0;
  194 + message->title = N_( "Security error" );
  195 + message->text = N_( "Can't initialize LDAP" );
  196 + message->description = ldap_err2string(rc);
  197 + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description);
  198 + return NULL;
  199 + }
  200 +
  201 + unsigned long version = LDAP_VERSION3;
  202 + rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,(void *) &version);
  203 + if(rc != LDAP_SUCCESS) {
  204 + message->error = hSession->ssl.error = 0;
  205 + message->title = N_( "Security error" );
  206 + message->text = N_( "Can't set LDAP version" );
  207 + message->description = ldap_err2string(rc);
  208 + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description);
  209 + return NULL;
  210 + }
  211 +
  212 + rc = ldap_simple_bind_s(ld, "", "");
  213 + if(rc != LDAP_SUCCESS)
  214 + {
  215 + message->error = hSession->ssl.error = 0;
  216 + message->title = N_( "Security error" );
  217 + message->text = N_( "Can't bind to LDAP server" );
  218 + message->description = ldap_err2string(rc);
  219 + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description);
  220 + return NULL;
  221 + }
  222 +
  223 + lib3270_autoptr(LDAPMessage) results = NULL;
  224 + rc = ldap_search_ext_s(
  225 + ld, // Specifies the LDAP pointer returned by a previous call to ldap_init(), ldap_ssl_init(), or ldap_open().
  226 + base, // Specifies the DN of the entry at which to start the search.
  227 + LDAP_SCOPE_BASE, // Specifies the scope of the search.
  228 + NULL, // Specifies a string representation of the filter to apply in the search.
  229 + (char **) &attrs, // Specifies a null-terminated array of character string attribute types to return from entries that match filter.
  230 + 0, // Should be set to 1 to request attribute types only. Set to 0 to request both attributes types and attribute values.
  231 + NULL,
  232 + NULL,
  233 + NULL,
  234 + 0,
  235 + &results
  236 + );
  237 +
  238 + if(rc != LDAP_SUCCESS)
  239 + {
  240 + message->error = hSession->ssl.error = 0;
  241 + message->title = N_( "Security error" );
  242 + message->text = N_( "Can't search LDAP server" );
  243 + message->description = ldap_err2string(rc);
  244 + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description);
  245 + return NULL;
  246 + }
  247 +
  248 + char __attribute__ ((__cleanup__(lib3270_autoptr_cleanup_LDAPPTR))) *attr = ldap_first_attribute(ld, results, &ber);
  249 + if(!attr)
  250 + {
  251 + message->error = hSession->ssl.error = 0;
  252 + message->title = N_( "Security error" );
  253 + message->text = N_( "Can't get LDAP attribute" );
  254 + message->description = N_("Search did not produce any attributes.");
  255 + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description);
  256 + return NULL;
  257 + }
  258 +
  259 + struct berval ** value = ldap_get_values_len(ld, results, attr);
  260 + if(!value)
  261 + {
  262 + message->error = hSession->ssl.error = 0;
  263 + message->title = N_( "Security error" );
  264 + message->text = N_( "Can't get LDAP attribute" );
  265 + message->description = N_("Search did not produce any values.");
  266 + lib3270_write_log(hSession,"ssl","%s: %s",url, message->description);
  267 + return NULL;
  268 + }
  269 +
  270 + debug("CRL Length=%d",(int) value[0]->bv_len);
  271 +
  272 + if(!d2i_X509_CRL(&crl, (const unsigned char **) &value[0]->bv_val, value[0]->bv_len))
  273 + {
  274 + message->error = hSession->ssl.error = ERR_get_error();
  275 + message->title = N_( "Security error" );
  276 + message->text = N_( "Can't get CRL from LDAP Search" );
  277 + lib3270_write_log(hSession,"ssl","%s: %s",url, message->text);
  278 + }
  279 +
  280 + // ldap_value_free_len(value);
  281 +
  282 + }
  283 +#endif // HAVE_LDAP
  284 + else
  285 + {
  286 + message->error = hSession->ssl.error = 0;
  287 + message->title = N_( "Security error" );
  288 + message->text = N_( "Unexpected or invalid CRL URL" );
  289 + message->description = N_("The URL scheme is unknown");
  290 + lib3270_write_log(hSession,"ssl","%s: %s",hSession->ssl.crl, message->description);
  291 + return NULL;
  292 + }
  293 +
  294 + return crl;
  295 +
  296 +}
  297 +
  298 +#endif // HAVE_LIBSSL && SSL_ENABLE_CRL_CHECK
src/lib3270/ssl/negotiate.c
@@ -125,7 +125,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) @@ -125,7 +125,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
125 /* Set up the TLS/SSL connection. */ 125 /* Set up the TLS/SSL connection. */
126 if(SSL_set_fd(hSession->ssl.con, hSession->sock) != 1) 126 if(SSL_set_fd(hSession->ssl.con, hSession->sock) != 1)
127 { 127 {
128 - trace_dsn(hSession,"%s","SSL_set_fd failed!\n"); 128 + trace_ssl(hSession,"%s","SSL_set_fd failed!\n");
129 129
130 ((SSL_ERROR_MESSAGE *) message)->title = N_( "Security error" ); 130 ((SSL_ERROR_MESSAGE *) message)->title = N_( "Security error" );
131 ((SSL_ERROR_MESSAGE *) message)->text = N_( "SSL negotiation failed" ); 131 ((SSL_ERROR_MESSAGE *) message)->text = N_( "SSL negotiation failed" );
@@ -134,9 +134,9 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) @@ -134,9 +134,9 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
134 return -1; 134 return -1;
135 } 135 }
136 136
137 - trace("%s: Running SSL_connect",__FUNCTION__); 137 + trace_ssl(hSession, "%s","Running SSL_connect\n");
138 rv = SSL_connect(hSession->ssl.con); 138 rv = SSL_connect(hSession->ssl.con);
139 - trace("%s: SSL_connect exits with rc=%d",__FUNCTION__,rv); 139 + trace_ssl(hSession, "SSL_connect exits with rc=%d\n",rv);
140 140
141 if (rv != 1) 141 if (rv != 1)
142 { 142 {
@@ -148,7 +148,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) @@ -148,7 +148,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
148 148
149 msg = ERR_lib_error_string(((SSL_ERROR_MESSAGE *) message)->error); 149 msg = ERR_lib_error_string(((SSL_ERROR_MESSAGE *) message)->error);
150 150
151 - trace_dsn(hSession,"SSL_connect failed: %s %s\n",msg,ERR_reason_error_string(hSession->ssl.error)); 151 + trace_ssl(hSession,"SSL_connect failed: %s %s\n",msg,ERR_reason_error_string(hSession->ssl.error));
152 152
153 ((SSL_ERROR_MESSAGE *) message)->title = N_( "Security error" ); 153 ((SSL_ERROR_MESSAGE *) message)->title = N_( "Security error" );
154 ((SSL_ERROR_MESSAGE *) message)->text = N_( "SSL Connect failed" ); 154 ((SSL_ERROR_MESSAGE *) message)->text = N_( "SSL Connect failed" );
@@ -168,14 +168,14 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) @@ -168,14 +168,14 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
168 peer = SSL_get_peer_certificate(hSession->ssl.con); 168 peer = SSL_get_peer_certificate(hSession->ssl.con);
169 169
170 debug("TLS/SSL negotiated connection complete. Peer certificate %s presented.", peer ? "was" : "was not"); 170 debug("TLS/SSL negotiated connection complete. Peer certificate %s presented.", peer ? "was" : "was not");
171 - trace_dsn(hSession,"TLS/SSL negotiated connection complete. Peer certificate %s presented.\n", peer ? "was" : "was not"); 171 + trace_ssl(hSession,"TLS/SSL negotiated connection complete. Peer certificate %s presented.\n", peer ? "was" : "was not");
172 172
173 break; 173 break;
174 174
175 case X509_V_ERR_UNABLE_TO_GET_CRL: 175 case X509_V_ERR_UNABLE_TO_GET_CRL:
176 176
177 debug("%s","The CRL of a certificate could not be found." ); 177 debug("%s","The CRL of a certificate could not be found." );
178 - trace_dsn(hSession,"%s","The CRL of a certificate could not be found.\n" ); 178 + trace_ssl(hSession,"%s","The CRL of a certificate could not be found.\n" );
179 179
180 ((SSL_ERROR_MESSAGE *) message)->title = _( "SSL error" ); 180 ((SSL_ERROR_MESSAGE *) message)->title = _( "SSL error" );
181 ((SSL_ERROR_MESSAGE *) message)->text = _( "Unable to get certificate CRL." ); 181 ((SSL_ERROR_MESSAGE *) message)->text = _( "Unable to get certificate CRL." );
@@ -184,7 +184,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) @@ -184,7 +184,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
184 return -1; 184 return -1;
185 185
186 case X509_V_ERR_CRL_NOT_YET_VALID: 186 case X509_V_ERR_CRL_NOT_YET_VALID:
187 - trace_dsn(hSession,"%s","The CRL of a certificate is not yet valid.\n" ); 187 + trace_ssl(hSession,"%s","The CRL of a certificate is not yet valid.\n" );
188 188
189 ((SSL_ERROR_MESSAGE *) message)->title = _( "SSL error" ); 189 ((SSL_ERROR_MESSAGE *) message)->title = _( "SSL error" );
190 ((SSL_ERROR_MESSAGE *) message)->text = _( "The CRL is not yet valid." ); 190 ((SSL_ERROR_MESSAGE *) message)->text = _( "The CRL is not yet valid." );
@@ -192,7 +192,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) @@ -192,7 +192,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
192 return -1; 192 return -1;
193 193
194 case X509_V_ERR_CRL_HAS_EXPIRED: 194 case X509_V_ERR_CRL_HAS_EXPIRED:
195 - trace_dsn(hSession,"%s","The CRL of a certificate has expired.\n" ); 195 + trace_ssl(hSession,"%s","The CRL of a certificate has expired.\n" );
196 ((SSL_ERROR_MESSAGE *) message)->title = _( "SSL error" ); 196 ((SSL_ERROR_MESSAGE *) message)->title = _( "SSL error" );
197 ((SSL_ERROR_MESSAGE *) message)->text = _( "The CRL has expired." ); 197 ((SSL_ERROR_MESSAGE *) message)->text = _( "The CRL has expired." );
198 ((SSL_ERROR_MESSAGE *) message)->description = _( "The Certificate revocation list (CRL) has expired." ); 198 ((SSL_ERROR_MESSAGE *) message)->description = _( "The Certificate revocation list (CRL) has expired." );
@@ -203,7 +203,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) @@ -203,7 +203,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
203 peer = SSL_get_peer_certificate(hSession->ssl.con); 203 peer = SSL_get_peer_certificate(hSession->ssl.con);
204 204
205 debug("%s","TLS/SSL negotiated connection complete with self signed certificate in certificate chain" ); 205 debug("%s","TLS/SSL negotiated connection complete with self signed certificate in certificate chain" );
206 - trace_dsn(hSession,"%s","TLS/SSL negotiated connection complete with self signed certificate in certificate chain\n" ); 206 + trace_ssl(hSession,"%s","TLS/SSL negotiated connection complete with self signed certificate in certificate chain\n" );
207 207
208 #ifdef SSL_ALLOW_SELF_SIGNED_CERT 208 #ifdef SSL_ALLOW_SELF_SIGNED_CERT
209 break; 209 break;
@@ -220,7 +220,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) @@ -220,7 +220,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
220 trace_dsn(hSession,"Unexpected or invalid TLS/SSL verify result %d\n",rv); 220 trace_dsn(hSession,"Unexpected or invalid TLS/SSL verify result %d\n",rv);
221 } 221 }
222 222
223 - if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_DS_TRACE)) 223 + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE))
224 { 224 {
225 char buffer[4096]; 225 char buffer[4096];
226 int alg_bits = 0; 226 int alg_bits = 0;
@@ -228,7 +228,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) @@ -228,7 +228,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
228 228
229 trace_dsn(hSession,"TLS/SSL cipher description: %s",SSL_CIPHER_description((SSL_CIPHER *) cipher, buffer, 4095)); 229 trace_dsn(hSession,"TLS/SSL cipher description: %s",SSL_CIPHER_description((SSL_CIPHER *) cipher, buffer, 4095));
230 SSL_CIPHER_get_bits(cipher, &alg_bits); 230 SSL_CIPHER_get_bits(cipher, &alg_bits);
231 - trace_dsn(hSession,"%s version %s with %d bits\n", 231 + trace_ssl(hSession,"%s version %s with %d bits\n",
232 SSL_CIPHER_get_name(cipher), 232 SSL_CIPHER_get_name(cipher),
233 SSL_CIPHER_get_version(cipher), 233 SSL_CIPHER_get_version(cipher),
234 alg_bits); 234 alg_bits);
@@ -237,7 +237,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) @@ -237,7 +237,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
237 237
238 if(peer) 238 if(peer)
239 { 239 {
240 - if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_DS_TRACE)) 240 + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_SSL_TRACE))
241 { 241 {
242 BIO * out = BIO_new(BIO_s_mem()); 242 BIO * out = BIO_new(BIO_s_mem());
243 unsigned char * data; 243 unsigned char * data;
@@ -251,7 +251,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message) @@ -251,7 +251,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
251 text[n] ='\0'; 251 text[n] ='\0';
252 memcpy(text,data,n); 252 memcpy(text,data,n);
253 253
254 - trace_dsn(hSession,"TLS/SSL peer certificate:\n%s\n",text); 254 + trace_ssl(hSession,"TLS/SSL peer certificate:\n%s\n",text);
255 255
256 free(text); 256 free(text);
257 BIO_free(out); 257 BIO_free(out);
src/lib3270/testprogram/testprogram.c
@@ -17,7 +17,8 @@ int main(int numpar, char *param[]) @@ -17,7 +17,8 @@ int main(int numpar, char *param[])
17 h = lib3270_session_new(""); 17 h = lib3270_session_new("");
18 printf("3270 session %p created\n]",h); 18 printf("3270 session %p created\n]",h);
19 19
20 - lib3270_set_toggle(h,LIB3270_TOGGLE_DS_TRACE,1); 20 +// lib3270_set_toggle(h,LIB3270_TOGGLE_DS_TRACE,1);
  21 + lib3270_set_toggle(h,LIB3270_TOGGLE_SSL_TRACE,1);
21 22
22 lib3270_set_url(h,url ? url : "tn3270://fandezhi.efglobe.com"); 23 lib3270_set_url(h,url ? url : "tn3270://fandezhi.efglobe.com");
23 rc = lib3270_connect(h,120); 24 rc = lib3270_connect(h,120);
src/lib3270/toggles.c
@@ -224,13 +224,19 @@ toggle_info[LIB3270_TOGGLE_COUNT] = @@ -224,13 +224,19 @@ toggle_info[LIB3270_TOGGLE_COUNT] =
224 N_( "Trace network data flow" ), 224 N_( "Trace network data flow" ),
225 N_( "Enable network in/out trace" ) 225 N_( "Enable network in/out trace" )
226 }, 226 },
  227 + {
  228 + "ssltrace",
  229 + False,
  230 + N_( "Trace SSL negotiation" ),
  231 + N_( "Enable SSL messages trace" )
  232 + },
227 }; 233 };
228 234
229 LIB3270_EXPORT unsigned char lib3270_get_toggle(H3270 *session, LIB3270_TOGGLE ix) 235 LIB3270_EXPORT unsigned char lib3270_get_toggle(H3270 *session, LIB3270_TOGGLE ix)
230 { 236 {
231 CHECK_SESSION_HANDLE(session); 237 CHECK_SESSION_HANDLE(session);
232 238
233 - if(ix < 0 || ix >= N_TOGGLES) 239 + if(ix < 0 || ix >= LIB3270_TOGGLE_COUNT)
234 return 0; 240 return 0;
235 241
236 return session->toggle[ix].value != 0; 242 return session->toggle[ix].value != 0;
@@ -324,8 +330,8 @@ static void toggle_keepalive(H3270 *session, struct lib3270_toggle *t unused, LI @@ -324,8 +330,8 @@ static void toggle_keepalive(H3270 *session, struct lib3270_toggle *t unused, LI
324 } 330 }
325 } 331 }
326 332
327 -/*  
328 - * Called from system initialization code to handle initial toggle settings. 333 +/**
  334 + * @brief Called from system initialization code to handle initial toggle settings.
329 */ 335 */
330 void initialize_toggles(H3270 *session) 336 void initialize_toggles(H3270 *session)
331 { 337 {
@@ -367,21 +373,21 @@ void shutdown_toggles(H3270 *session) @@ -367,21 +373,21 @@ void shutdown_toggles(H3270 *session)
367 373
368 LIB3270_EXPORT const char * lib3270_get_toggle_label(LIB3270_TOGGLE_ID ix) 374 LIB3270_EXPORT const char * lib3270_get_toggle_label(LIB3270_TOGGLE_ID ix)
369 { 375 {
370 - if(ix < N_TOGGLES) 376 + if(ix < LIB3270_TOGGLE_COUNT)
371 return toggle_info[ix].label; 377 return toggle_info[ix].label;
372 return ""; 378 return "";
373 } 379 }
374 380
375 LIB3270_EXPORT const char * lib3270_get_toggle_description(LIB3270_TOGGLE_ID ix) 381 LIB3270_EXPORT const char * lib3270_get_toggle_description(LIB3270_TOGGLE_ID ix)
376 { 382 {
377 - if(ix < N_TOGGLES) 383 + if(ix < LIB3270_TOGGLE_COUNT)
378 return toggle_info[ix].description; 384 return toggle_info[ix].description;
379 return ""; 385 return "";
380 } 386 }
381 387
382 LIB3270_EXPORT const char * lib3270_get_toggle_name(LIB3270_TOGGLE_ID ix) 388 LIB3270_EXPORT const char * lib3270_get_toggle_name(LIB3270_TOGGLE_ID ix)
383 { 389 {
384 - if(ix < N_TOGGLES) 390 + if(ix < LIB3270_TOGGLE_COUNT)
385 return toggle_info[ix].name; 391 return toggle_info[ix].name;
386 return ""; 392 return "";
387 } 393 }
@@ -391,7 +397,7 @@ LIB3270_EXPORT LIB3270_TOGGLE lib3270_get_toggle_id(const char *name) @@ -391,7 +397,7 @@ LIB3270_EXPORT LIB3270_TOGGLE lib3270_get_toggle_id(const char *name)
391 if(name) 397 if(name)
392 { 398 {
393 int f; 399 int f;
394 - for(f=0;f<N_TOGGLES;f++) 400 + for(f=0;f<LIB3270_TOGGLE_COUNT;f++)
395 { 401 {
396 if(!strcasecmp(name,toggle_info[f].name)) 402 if(!strcasecmp(name,toggle_info[f].name))
397 return f; 403 return f;
src/lib3270/trace_ds.c
@@ -160,7 +160,9 @@ void trace_ds_nb(H3270 *hSession, const char *fmt, ...) @@ -160,7 +160,9 @@ void trace_ds_nb(H3270 *hSession, const char *fmt, ...)
160 lib3270_free(text); 160 lib3270_free(text);
161 } 161 }
162 162
163 -/* Conditional data stream trace, without line splitting. */ 163 +/**
  164 + * @brief Conditional data stream trace, without line splitting.
  165 + */
164 void trace_dsn(H3270 *session, const char *fmt, ...) 166 void trace_dsn(H3270 *session, const char *fmt, ...)
165 { 167 {
166 va_list args; 168 va_list args;
@@ -174,6 +176,24 @@ void trace_dsn(H3270 *session, const char *fmt, ...) @@ -174,6 +176,24 @@ void trace_dsn(H3270 *session, const char *fmt, ...)
174 va_end(args); 176 va_end(args);
175 } 177 }
176 178
  179 +/**
  180 + * @brief Conditional ssl stream trace, without line splitting.
  181 + */
  182 +void trace_ssl(H3270 *session, const char *fmt, ...)
  183 +{
  184 + va_list args;
  185 +
  186 + debug("******************* %d",(int) lib3270_get_toggle(session,LIB3270_TOGGLE_SSL_TRACE));
  187 + if (!lib3270_get_toggle(session,LIB3270_TOGGLE_SSL_TRACE))
  188 + return;
  189 +
  190 + /* print out message */
  191 + va_start(args, fmt);
  192 + session->trace.handler(session,session->trace.userdata,fmt, args);
  193 + va_end(args);
  194 +}
  195 +
  196 +
177 /* Write to the trace file. */ 197 /* Write to the trace file. */
178 static void wtrace(H3270 *session, const char *fmt, ...) 198 static void wtrace(H3270 *session, const char *fmt, ...)
179 { 199 {