Commit 053cd3d1d5f7d14881fb0b6c07f7d4d894dea372

Authored by Perry Werneck
1 parent 6021974d

Adding CRL download from LDAP (optional).

configure.ac
... ... @@ -472,9 +472,9 @@ else
472 472 LDAP_LIBS=
473 473 fi
474 474  
  475 +AC_SUBST(LDAP_CFLAGS)
475 476 AC_SUBST(LDAP_LIBS)
476 477  
477   -
478 478 dnl ---------------------------------------------------------------------------
479 479 dnl Directory config
480 480 dnl ---------------------------------------------------------------------------
... ...
src/include/config.h.in
... ... @@ -36,7 +36,6 @@
36 36 #undef PACKAGE_RELEASE
37 37  
38 38 #undef HAVE_GNUC_VISIBILITY
39   - #undef HAVE_LIBM
40 39 #undef HAVE_LIBINTL
41 40 #undef HAVE_GETADDRINFO
42 41 #undef HAVE_VASPRINTF
... ...
src/include/lib3270.h
... ... @@ -149,6 +149,7 @@
149 149 LIB3270_TOGGLE_ALTSCREEN, /**< @brief auto resize on altscreen */
150 150 LIB3270_TOGGLE_KEEP_ALIVE, /**< @brief Enable network keep-alive with SO_KEEPALIVE */
151 151 LIB3270_TOGGLE_NETWORK_TRACE, /**< @brief Enable network in/out trace */
  152 + LIB3270_TOGGLE_SSL_TRACE, /**< @brief Enable security traces */
152 153  
153 154 LIB3270_TOGGLE_COUNT
154 155  
... ...
src/include/toggle.h
... ... @@ -62,7 +62,7 @@
62 62 // #define INSERT LIB3270_TOGGLE_INSERT
63 63 #define KEYPAD LIB3270_TOGGLE_KEYPAD
64 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 67 #define LIB3270_TOGGLE_ID LIB3270_TOGGLE
68 68  
... ...
src/include/trace_dsc.h
... ... @@ -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 34 #if defined(X3270_TRACE)
36 35  
37   -// LIB3270_INTERNAL Boolean trace_skipping;
38   -
39 36 const char *rcba(H3270 *session, int baddr);
40 37  
41 38 void trace_ansi_disc(H3270 *hSession);
... ... @@ -43,23 +40,22 @@
43 40 void trace_ds(H3270 *hSession, const char *fmt, ...) LIB3270_GNUC_FORMAT(2, 3);
44 41 void trace_ds_nb(H3270 *hSession, const char *fmt, ...) LIB3270_GNUC_FORMAT(2, 3);
45 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 44 void trace_screen(H3270 *session);
47 45  
48   -// #define trace_event(...) lib3270_trace_event(&h3270,__VA_ARGS__)
49   -
50 46 #elif defined(__GNUC__)
51 47  
52 48 #define trace_ds(session, format, args...)
53 49 #define trace_dsn(session, format, args...)
  50 + #define trace_ssl(session, format, args...)
54 51 #define trace_ds_nb(session, format, args...)
55   -// #define trace_event(session, format, args...)
56 52  
57 53 #else
58 54  
59 55 #define trace_ds 0 &&
60 56 #define trace_ds_nb 0 &&
61 57 #define trace_dsn 0 &&
62   -// #define trace_event 0 &&
  58 + #define trace_ssl 0 &&
63 59 #define rcba 0 &&
64 60  
65 61 #endif
... ...
src/lib3270/Makefile.in
... ... @@ -94,13 +94,15 @@ CFLAGS= \
94 94 -g \
95 95 -I../include
96 96 -DBUILD_DATE=`date +%Y%m%d` \
97   - @LIBSSL_CFLAGS@
  97 + @LIBSSL_CFLAGS@ \
  98 + @LDAP_CFLAGS@
98 99  
99 100 LIBS= \
100 101 @LIBS@ \
101 102 @LIBSSL_LIBS@ \
102 103 @LIBICONV@ \
103   - @INTL_LIBS@
  104 + @INTL_LIBS@ \
  105 + @LDAP_LIBS@
104 106  
105 107 #---[ Debug Rules ]----------------------------------------------------------------------
106 108  
... ... @@ -325,7 +327,14 @@ $(BINDBG)/$(LIBNAME)@EXEEXT@: \
325 327  
326 328 @$(MKDIR) `dirname $@`
327 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 339 run: \
331 340 $(BINDBG)/$(LIBNAME)@EXEEXT@
... ...
src/lib3270/private.h
... ... @@ -605,6 +605,9 @@ struct _h3270
605 605 char host;
606 606 LIB3270_SSL_STATE state;
607 607 unsigned long error;
  608 +#ifdef SSL_ENABLE_CRL_CHECK
  609 + char * crl;
  610 +#endif // SSL_ENABLE_CRL_CHECK
608 611 SSL * con;
609 612 } ssl;
610 613 #endif // HAVE_LIBSSL
... ...
src/lib3270/session.c
... ... @@ -74,6 +74,14 @@ void lib3270_session_free(H3270 *h)
74 74  
75 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 85 // Release state change callbacks
78 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 320 hSession->unlock_delay_ms = 350; // 0.35s after last unlock
313 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 331 // CSD
316 332 for(f=0;f<4;f++)
317 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 84 if(ssl_ctx)
85 85 return 0;
86 86  
87   - trace_dsn(hSession,"Initializing SSL context.\n");
  87 + trace_ssl(hSession,"Initializing SSL context.\n");
88 88  
89 89 SSL_load_error_strings();
90 90 SSL_library_init();
... ... @@ -111,42 +111,42 @@ int ssl_ctx_init(H3270 *hSession, SSL_ERROR_MESSAGE * message)
111 111 //
112 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 150 #endif // SSL_ENABLE_CRL_CHECK
151 151  
152 152 return 0;
... ...
src/lib3270/ssl/linux/getcrl.c 0 → 100644
... ... @@ -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 125 /* Set up the TLS/SSL connection. */
126 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 130 ((SSL_ERROR_MESSAGE *) message)->title = N_( "Security error" );
131 131 ((SSL_ERROR_MESSAGE *) message)->text = N_( "SSL negotiation failed" );
... ... @@ -134,9 +134,9 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
134 134 return -1;
135 135 }
136 136  
137   - trace("%s: Running SSL_connect",__FUNCTION__);
  137 + trace_ssl(hSession, "%s","Running SSL_connect\n");
138 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 141 if (rv != 1)
142 142 {
... ... @@ -148,7 +148,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
148 148  
149 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 153 ((SSL_ERROR_MESSAGE *) message)->title = N_( "Security error" );
154 154 ((SSL_ERROR_MESSAGE *) message)->text = N_( "SSL Connect failed" );
... ... @@ -168,14 +168,14 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
168 168 peer = SSL_get_peer_certificate(hSession->ssl.con);
169 169  
170 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 173 break;
174 174  
175 175 case X509_V_ERR_UNABLE_TO_GET_CRL:
176 176  
177 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 180 ((SSL_ERROR_MESSAGE *) message)->title = _( "SSL error" );
181 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 184 return -1;
185 185  
186 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 189 ((SSL_ERROR_MESSAGE *) message)->title = _( "SSL error" );
190 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 192 return -1;
193 193  
194 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 196 ((SSL_ERROR_MESSAGE *) message)->title = _( "SSL error" );
197 197 ((SSL_ERROR_MESSAGE *) message)->text = _( "The CRL has expired." );
198 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 203 peer = SSL_get_peer_certificate(hSession->ssl.con);
204 204  
205 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 208 #ifdef SSL_ALLOW_SELF_SIGNED_CERT
209 209 break;
... ... @@ -220,7 +220,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
220 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 225 char buffer[4096];
226 226 int alg_bits = 0;
... ... @@ -228,7 +228,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
228 228  
229 229 trace_dsn(hSession,"TLS/SSL cipher description: %s",SSL_CIPHER_description((SSL_CIPHER *) cipher, buffer, 4095));
230 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 232 SSL_CIPHER_get_name(cipher),
233 233 SSL_CIPHER_get_version(cipher),
234 234 alg_bits);
... ... @@ -237,7 +237,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
237 237  
238 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 242 BIO * out = BIO_new(BIO_s_mem());
243 243 unsigned char * data;
... ... @@ -251,7 +251,7 @@ static int background_ssl_negotiation(H3270 *hSession, void *message)
251 251 text[n] ='\0';
252 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 256 free(text);
257 257 BIO_free(out);
... ...
src/lib3270/testprogram/testprogram.c
... ... @@ -17,7 +17,8 @@ int main(int numpar, char *param[])
17 17 h = lib3270_session_new("");
18 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 23 lib3270_set_url(h,url ? url : "tn3270://fandezhi.efglobe.com");
23 24 rc = lib3270_connect(h,120);
... ...
src/lib3270/toggles.c
... ... @@ -224,13 +224,19 @@ toggle_info[LIB3270_TOGGLE_COUNT] =
224 224 N_( "Trace network data flow" ),
225 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 235 LIB3270_EXPORT unsigned char lib3270_get_toggle(H3270 *session, LIB3270_TOGGLE ix)
230 236 {
231 237 CHECK_SESSION_HANDLE(session);
232 238  
233   - if(ix < 0 || ix >= N_TOGGLES)
  239 + if(ix < 0 || ix >= LIB3270_TOGGLE_COUNT)
234 240 return 0;
235 241  
236 242 return session->toggle[ix].value != 0;
... ... @@ -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 336 void initialize_toggles(H3270 *session)
331 337 {
... ... @@ -367,21 +373,21 @@ void shutdown_toggles(H3270 *session)
367 373  
368 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 377 return toggle_info[ix].label;
372 378 return "";
373 379 }
374 380  
375 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 384 return toggle_info[ix].description;
379 385 return "";
380 386 }
381 387  
382 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 391 return toggle_info[ix].name;
386 392 return "";
387 393 }
... ... @@ -391,7 +397,7 @@ LIB3270_EXPORT LIB3270_TOGGLE lib3270_get_toggle_id(const char *name)
391 397 if(name)
392 398 {
393 399 int f;
394   - for(f=0;f<N_TOGGLES;f++)
  400 + for(f=0;f<LIB3270_TOGGLE_COUNT;f++)
395 401 {
396 402 if(!strcasecmp(name,toggle_info[f].name))
397 403 return f;
... ...
src/lib3270/trace_ds.c
... ... @@ -160,7 +160,9 @@ void trace_ds_nb(H3270 *hSession, const char *fmt, ...)
160 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 166 void trace_dsn(H3270 *session, const char *fmt, ...)
165 167 {
166 168 va_list args;
... ... @@ -174,6 +176,24 @@ void trace_dsn(H3270 *session, const char *fmt, ...)
174 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 197 /* Write to the trace file. */
178 198 static void wtrace(H3270 *session, const char *fmt, ...)
179 199 {
... ...