Commit f3c2e2799eec8539531dcfe7cfcd8277317f168f

Authored by perry.werneck@gmail.com
1 parent d9eeb3b7

Separando funções SSL do módulo telnet para facilitar a manutenção

connect.c
... ... @@ -82,7 +82,7 @@ static void net_connected(H3270 *hSession)
82 82 _( "Network error" ),
83 83 _( "Unable to get connection state." ),
84 84 #ifdef _WIN32
85   - _( "Winsock Error %d"), WSAGetLastError()
  85 + "%s", lib3270_win32_strerror(WSAGetLastError()));
86 86 #else
87 87 _( "%s" ), strerror(errno)
88 88 #endif // _WIN32
... ... @@ -167,16 +167,6 @@ static void net_connected(H3270 *hSession)
167 167 }
168 168 #endif /*]*/
169 169  
170   - static void set_ssl_state(H3270 *hSession, LIB3270_SSL_STATE state)
171   - {
172   - if(state == hSession->secure)
173   - return;
174   -
175   - trace_dsn(hSession,"SSL state changes to %d\n",(int) state);
176   -
177   - hSession->update_ssl(hSession,hSession->secure = state);
178   - }
179   -
180 170 LIB3270_EXPORT int lib3270_connect_host(H3270 *hSession, const char *hostname, const char *srvc)
181 171 {
182 172 int s;
... ... @@ -303,8 +293,7 @@ static void net_connected(H3270 *hSession)
303 293 LIB3270_NOTIFY_ERROR,
304 294 _( "Connection error" ),
305 295 _( "ioctlsocket(FIONBIO) failed." ),
306   - "%s", lib3270_win32_strerror(GetLastError()));
307   -
  296 + "%s", lib3270_win32_strerror(WSAGetLastError()));
308 297 SOCK_CLOSE(hSession);
309 298 }
310 299 else if(connect(hSession->sock, rp->ai_addr, rp->ai_addrlen))
... ... @@ -316,7 +305,7 @@ static void net_connected(H3270 *hSession)
316 305 LIB3270_NOTIFY_ERROR,
317 306 _( "Connection error" ),
318 307 _( "Can't connect to host." ),
319   - "%s", lib3270_win32_strerror(GetLastError()));
  308 + "%s", lib3270_win32_strerror(err));
320 309 SOCK_CLOSE(hSession);
321 310 }
322 311 }
... ... @@ -390,3 +379,56 @@ static void net_connected(H3270 *hSession)
390 379  
391 380 }
392 381  
  382 +int non_blocking(H3270 *hSession, Boolean on)
  383 +{
  384 +#ifdef WIN32
  385 + WSASetLastError(0);
  386 + u_long iMode= on ? 1 : 0;
  387 +
  388 + if(ioctlsocket(hSession->sock,FIONBIO,&iMode))
  389 + {
  390 + lib3270_popup_dialog( hSession,
  391 + LIB3270_NOTIFY_ERROR,
  392 + _( "Connection error" ),
  393 + _( "ioctlsocket(FIONBIO) failed." ),
  394 + "%s", lib3270_win32_strerror(GetLastError()));
  395 + }
  396 +#else
  397 +
  398 + int f;
  399 +
  400 + if ((f = fcntl(hSession->sock, F_GETFL, 0)) == -1)
  401 + {
  402 + lib3270_popup_dialog( hSession,
  403 + LIB3270_NOTIFY_ERROR,
  404 + _( "Socket error" ),
  405 + _( "fcntl() error when getting socket state." ),
  406 + _( "%s" ), strerror(errno)
  407 + );
  408 +
  409 + return -1;
  410 + }
  411 +
  412 + if (on)
  413 + f |= O_NDELAY;
  414 + else
  415 + f &= ~O_NDELAY;
  416 +
  417 + if (fcntl(hSession->sock, F_SETFL, f) < 0)
  418 + {
  419 + lib3270_popup_dialog( hSession,
  420 + LIB3270_NOTIFY_ERROR,
  421 + _( "Socket error" ),
  422 + on ? _( "Can't set socket to blocking mode." ) : _( "Can't set socket to non blocking mode" ),
  423 + _( "%s" ), strerror(errno)
  424 + );
  425 + return -1;
  426 + }
  427 +
  428 +#endif
  429 +
  430 + trace("Socket %d is %s",hSession->sock, on ? "non-blocking" : "blocking");
  431 +
  432 + return 0;
  433 +}
  434 +
... ...
globals.h
... ... @@ -137,18 +137,6 @@ enum iaction {
137 137 IA_IDLE
138 138 };
139 139  
140   -// LIB3270_INTERNAL int COLS;
141   -// LIB3270_INTERNAL int ROWS;
142   -
143   -// LIB3270_INTERNAL H3270 h3270;
144   -
145   -/*
146   -#if defined(X3270_DISPLAY)
147   - LIB3270_INTERNAL Atom a_3270, a_registry, a_encoding;
148   - LIB3270_INTERNAL XtAppContext appcontext;
149   -#endif
150   -*/
151   -
152 140 // Version strings
153 141 LIB3270_INTERNAL const char * build;
154 142 LIB3270_INTERNAL const char * app_defaults_version;
... ... @@ -157,99 +145,15 @@ LIB3270_INTERNAL const char * build_rpq_timestamp;
157 145 LIB3270_INTERNAL const char * build_rpq_version;
158 146 LIB3270_INTERNAL const char * build_rpq_revision;
159 147  
160   -// LIB3270_INTERNAL int children;
161   -
162 148 #if defined(X3270_DBCS) /*[*/
163 149 LIB3270_INTERNAL Boolean dbcs;
164 150 #endif /*]*/
165 151  
166   -// #if defined(X3270_FT) /*[*/
167   -// LIB3270_INTERNAL int dft_buffersize;
168   -// #endif /*]*/
169   -
170   -// LIB3270_INTERNAL char *efontname;
171   -// LIB3270_INTERNAL Boolean ever_3270;
172   -// LIB3270_INTERNAL Boolean exiting;
173   -
174   -/*
175   -#if defined(X3270_DISPLAY)
176   - LIB3270_INTERNAL Boolean *extended_3270font;
177   - LIB3270_INTERNAL Font *fid;
178   - LIB3270_INTERNAL Boolean *font_8bit;
179   -#endif
180   -*/
181   -
182   -// LIB3270_INTERNAL Boolean flipped;
183   -// LIB3270_INTERNAL char *full_current_host;
184   -// LIB3270_INTERNAL char *full_efontname;
185 152  
186 153 #if defined(X3270_DBCS) /*[*/
187 154 LIB3270_INTERNAL char *full_efontname_dbcs;
188 155 #endif /*]*/
189 156  
190   -//LIB3270_INTERNAL char *funky_font;
191   -//LIB3270_INTERNAL char *hostname;
192   -
193   -#if defined(X3270_DBCS) /*[*/
194   -// LIB3270_INTERNAL char *local_encoding;
195   -
196   - #if defined(X3270_DISPLAY) /*[*/
197   -// LIB3270_INTERNAL char *locale_name;
198   - #endif /*]*/
199   -
200   -#endif /*]*/
201   -
202   -/*
203   -#if defined(LOCAL_PROCESS)
204   - LIB3270_INTERNAL Boolean local_process;
205   -#endif
206   -*/
207   -
208   -// LIB3270_INTERNAL int maxCOLS;
209   -// LIB3270_INTERNAL int maxROWS;
210   -// LIB3270_INTERNAL char *model_name;
211   -// LIB3270_INTERNAL int model_num;
212   -// LIB3270_INTERNAL Boolean no_login_host;
213   -// LIB3270_INTERNAL Boolean non_tn3270e_host;
214   -// LIB3270_INTERNAL int ov_cols, ov_rows;
215   -// LIB3270_INTERNAL Boolean passthru_host;
216   -// extern const char *programname;
217   -// LIB3270_INTERNAL char *qualified_host;
218   -// LIB3270_INTERNAL char *reconnect_host;
219   -// LIB3270_INTERNAL int screen_depth;
220   -// LIB3270_INTERNAL Boolean scroll_initted;
221   -
222   -//#if defined(HAVE_LIBSSL) /*[*/
223   -// LIB3270_INTERNAL Boolean secure_connection;
224   -//#endif /*]*/
225   -
226   -// LIB3270_INTERNAL Boolean shifted;
227   -// LIB3270_INTERNAL Boolean ssl_host;
228   -// LIB3270_INTERNAL Boolean *standard_font;
229   -// LIB3270_INTERNAL Boolean std_ds_host;
230   -// LIB3270_INTERNAL char *termtype;
231   -// LIB3270_INTERNAL Widget toplevel;
232   -// LIB3270_INTERNAL Boolean visible_control;
233   -// LIB3270_INTERNAL int *xtra_width;
234   -
235   -/*
236   -#if defined(X3270_DISPLAY)
237   - LIB3270_INTERNAL Atom a_delete_me;
238   - LIB3270_INTERNAL Atom a_save_yourself;
239   - LIB3270_INTERNAL Atom a_state;
240   - LIB3270_INTERNAL Display *display;
241   - LIB3270_INTERNAL Pixmap gray;
242   - LIB3270_INTERNAL Pixel keypadbg_pixel;
243   - LIB3270_INTERNAL XrmDatabase rdb;
244   - LIB3270_INTERNAL Window root_window;
245   - LIB3270_INTERNAL char *user_title;
246   - LIB3270_INTERNAL unsigned char xk_selector;
247   -#endif
248   -*/
249   -
250   -/* Connection state */
251   -// LIB3270_INTERNAL enum ft_state ft_state;
252   -
253 157  
254 158 /* keyboard modifer bitmap */
255 159 #define ShiftKeyDown 0x01
... ... @@ -263,19 +167,7 @@ struct toggle_name {
263 167 };
264 168  
265 169  
266   -/* translation lists */ /*
267   -struct trans_list {
268   - char *name;
269   - char *pathname;
270   - Boolean is_temp;
271   - Boolean from_server;
272   - struct trans_list *next;
273   -};
274   -LIB3270_INTERNAL struct trans_list *trans_list;
275   -*/
276   -
277 170 /* input key type */
278   -// enum keytype { KT_STD, KT_GE };
279 171  
280 172 /* Naming convention for private actions. */
281 173 #define PA_PFX "PA-"
... ... @@ -341,8 +233,6 @@ LIB3270_INTERNAL void key_ACharacter(H3270 *hSession, unsigned char c, enum keyt
341 233 LIB3270_INTERNAL void lib3270_initialize(void);
342 234 LIB3270_INTERNAL int cursor_move(H3270 *session, int baddr);
343 235  
344   -// LIB3270_INTERNAL void add_input_calls(H3270 *, void (*)(H3270 *), void (*)(H3270 *));
345   -
346 236 LIB3270_INTERNAL void toggle_rectselect(H3270 *session, struct lib3270_toggle *t, LIB3270_TOGGLE_TYPE tt);
347 237 LIB3270_INTERNAL void remove_input_calls(H3270 *session);
348 238  
... ... @@ -358,3 +248,23 @@ LIB3270_INTERNAL void lib3270_sock_disconnect(H3270 *hSession);
358 248 #endif // DEBUG
359 249  
360 250 LIB3270_EXPORT int lib3270_connect_host(H3270 *hSession, const char *hostname, const char *srvc);
  251 +
  252 +LIB3270_INTERNAL int non_blocking(H3270 *session, Boolean on);
  253 +
  254 +#if defined(HAVE_LIBSSL) /*[*/
  255 +
  256 + LIB3270_INTERNAL void ssl_init(H3270 *session);
  257 + LIB3270_INTERNAL int ssl_negotiate(H3270 *hSession);
  258 + LIB3270_INTERNAL void set_ssl_state(H3270 *session, LIB3270_SSL_STATE state);
  259 +
  260 +
  261 + #if OPENSSL_VERSION_NUMBER >= 0x00907000L /*[*/
  262 + #define INFO_CONST const
  263 + #else /*][*/
  264 + #define INFO_CONST
  265 + #endif /*]*/
  266 +
  267 + LIB3270_INTERNAL void ssl_info_callback(INFO_CONST SSL *s, int where, int ret);
  268 +
  269 +#endif /*]*/
  270 +
... ...
lib3270.cbp
... ... @@ -189,6 +189,7 @@
189 189 </Unit>
190 190 <Unit filename="sfc.h" />
191 191 <Unit filename="shlobj_missing.h" />
  192 + <Unit filename="sources.mak" />
192 193 <Unit filename="state.c">
193 194 <Option compilerVar="CC" />
194 195 </Unit>
... ...
sources.mak
... ... @@ -28,7 +28,7 @@
28 28 TERMINAL_SOURCES = bounds.c ctlr.c util.c toggles.c screen.c selection.c kybd.c telnet.c \
29 29 host.c sf.c ansi.c resolver.c charset.c \
30 30 version.c session.c state.c html.c trace_ds.c see.c \
31   - paste.c
  31 + paste.c ssl.c
32 32  
33 33 # tables.c utf8.c
34 34  
... ...
ssl.c 0 → 100644
... ... @@ -0,0 +1,356 @@
  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 ssl.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 Mendonça)
  27 + * licinio@bb.com.br (Licínio Luis Branco)
  28 + * kraucer@bb.com.br (Kraucer Fernandes Mazuco)
  29 + *
  30 + */
  31 +
  32 +
  33 +#include <lib3270/config.h>
  34 +#if defined(HAVE_LIBSSL)
  35 + #include <openssl/ssl.h>
  36 + #include <openssl/err.h>
  37 +#endif
  38 +
  39 +#include "globals.h"
  40 +#include <errno.h>
  41 +#include <lib3270/internals.h>
  42 +#include <lib3270/trace.h>
  43 +#include "trace_dsc.h"
  44 +
  45 +static int ssl_3270_ex_index = -1; /**< Index of h3270 handle in SSL session */
  46 +
  47 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  48 +
  49 +#if defined(HAVE_LIBSSL)
  50 +int ssl_negotiate(H3270 *hSession)
  51 +{
  52 + int rv;
  53 +
  54 + trace("%s",__FUNCTION__);
  55 +
  56 + set_ssl_state(hSession,LIB3270_SSL_NEGOTIATING);
  57 + non_blocking(hSession,False);
  58 +
  59 + /* Initialize the SSL library. */
  60 + ssl_init(hSession);
  61 + if(hSession->ssl_con == NULL)
  62 + {
  63 + /* Failed. */
  64 + popup_an_error(hSession,_( "SSL init failed!"));
  65 + lib3270_disconnect(hSession);
  66 + return -1;
  67 + }
  68 +
  69 + /* Set up the TLS/SSL connection. */
  70 + if(SSL_set_fd(hSession->ssl_con, hSession->sock) != 1)
  71 + {
  72 + trace_dsn(hSession,"SSL_set_fd failed!\n");
  73 + #warning Show a better popup here
  74 + // popup_an_error(hSession,_( "SSL_set_fd failed!"));
  75 + lib32070_disconnect(hSession);
  76 + return -1;
  77 + }
  78 +
  79 + trace("%s: Running SSL_connect",__FUNCTION__);
  80 + rv = SSL_connect(hSession->ssl_con);
  81 + trace("%s: SSL_connect exits with rc=%d",__FUNCTION__,rv);
  82 +
  83 + if (rv != 1)
  84 + {
  85 + int ssl_error = SSL_get_error(hSession->ssl_con,rv);
  86 +
  87 + if(ssl_error == SSL_ERROR_SYSCALL)
  88 + {
  89 + if(!hSession->ssl_error)
  90 + {
  91 + trace_dsn(hSession,"SSL_connect failed (ssl_error=%lu)\n",hSession->ssl_error);
  92 + popup_an_error(hSession,_( "SSL connect failed!"));
  93 + }
  94 + else
  95 + {
  96 + trace_dsn(hSession,"SSL_connect failed: %s %s\n",
  97 + ERR_lib_error_string(hSession->ssl_error),
  98 + ERR_reason_error_string(hSession->ssl_error));
  99 + popup_an_error(hSession,"%s",_( ERR_reason_error_string(hSession->ssl_error) ));
  100 + }
  101 +
  102 + }
  103 + else
  104 + {
  105 + trace_dsn(hSession,"SSL_connect failed (ssl_error=%d errno=%d)\n",ssl_error,errno);
  106 + popup_an_error(hSession,_( "SSL connect failed!"));
  107 + }
  108 +
  109 + lib3270_disconnect(hSession);
  110 + return -1;
  111 + }
  112 +
  113 + /* Success. */
  114 + if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_DS_TRACE))
  115 + {
  116 + char buffer[4096];
  117 + int alg_bits = 0;
  118 + const SSL_CIPHER * cipher = SSL_get_current_cipher(hSession->ssl_con);
  119 + X509 * peer = SSL_get_peer_certificate(hSession->ssl_con);
  120 +
  121 + trace_dsn(hSession,"TLS/SSL negotiated connection complete. Connection is now secure.\n");
  122 +
  123 + trace_dsn(hSession,"TLS/SSL cipher description: %s",SSL_CIPHER_description((SSL_CIPHER *) cipher, buffer, 4095));
  124 + SSL_CIPHER_get_bits(cipher, &alg_bits);
  125 + trace_dsn(hSession,"%s version %s with %d bits verify=%ld\n",
  126 + SSL_CIPHER_get_name(cipher),
  127 + SSL_CIPHER_get_version(cipher),
  128 + alg_bits,
  129 + SSL_get_verify_result(hSession->ssl_con));
  130 +
  131 + if(peer)
  132 + {
  133 + BIO * out = BIO_new(BIO_s_mem());
  134 + unsigned char * data;
  135 + unsigned char * text;
  136 + int n;
  137 +
  138 + X509_print(out,peer);
  139 +
  140 + n = BIO_get_mem_data(out, &data);
  141 + text = (unsigned char *) malloc (n+1);
  142 + text[n] ='\0';
  143 + memcpy(text,data,n);
  144 +
  145 + trace_dsn(hSession,"TLS/SSL peer certificate:\n%s\n",text);
  146 +
  147 + free(text);
  148 + BIO_free(out);
  149 + X509_free(peer);
  150 +
  151 + }
  152 + }
  153 +
  154 + if(!SSL_get_verify_result(hSession->ssl_con))
  155 + set_ssl_state(hSession,LIB3270_SSL_SECURE);
  156 +
  157 + /* Tell the world that we are (still) connected, now in secure mode. */
  158 + lib3270_set_connected(hSession);
  159 + return 0;
  160 +}
  161 +#endif // HAVE_LIBSSL
  162 +
  163 +#if defined(HAVE_LIBSSL) /*[*/
  164 +
  165 +/* Initialize the OpenSSL library. */
  166 +void ssl_init(H3270 *session)
  167 +{
  168 + static SSL_CTX *ssl_ctx = NULL;
  169 +
  170 + session->ssl_error = 0;
  171 + set_ssl_state(session,LIB3270_SSL_UNDEFINED);
  172 +
  173 + if(ssl_ctx == NULL)
  174 + {
  175 + lib3270_write_log(session,"SSL","%s","Initializing SSL context");
  176 + SSL_load_error_strings();
  177 + SSL_library_init();
  178 + ssl_ctx = SSL_CTX_new(SSLv23_method());
  179 + if(ssl_ctx == NULL)
  180 + {
  181 + popup_an_error(session,"SSL_CTX_new failed");
  182 + session->ssl_host = False;
  183 + return;
  184 + }
  185 + SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL);
  186 + SSL_CTX_set_info_callback(ssl_ctx, ssl_info_callback);
  187 + SSL_CTX_set_default_verify_paths(ssl_ctx);
  188 +
  189 +#if defined(_WIN32)
  190 + {
  191 + HKEY hKey = 0;
  192 +
  193 + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\" PACKAGE_NAME,0,KEY_QUERY_VALUE,&hKey) == ERROR_SUCCESS)
  194 + {
  195 + char data[4096];
  196 + unsigned long datalen = sizeof(data); // data field length(in), data returned length(out)
  197 + unsigned long datatype; // #defined in winnt.h (predefined types 0-11)
  198 +
  199 + if(RegQueryValueExA(hKey,"datadir",NULL,&datatype,(LPBYTE) data,&datalen) == ERROR_SUCCESS)
  200 + {
  201 + strncat(data,"\\certs",4095);
  202 +
  203 + trace("Loading certs from \"%s\"",data);
  204 + SSL_CTX_load_verify_locations(ssl_ctx,NULL,data);
  205 + }
  206 + RegCloseKey(hKey);
  207 + }
  208 +
  209 +
  210 + }
  211 +
  212 +#endif // _WIN32
  213 +
  214 + ssl_3270_ex_index = SSL_get_ex_new_index(0,NULL,NULL,NULL,NULL);
  215 +
  216 +
  217 + }
  218 +
  219 + if(session->ssl_con)
  220 + SSL_free(session->ssl_con);
  221 +
  222 + session->ssl_con = SSL_new(ssl_ctx);
  223 + if(session->ssl_con == NULL)
  224 + {
  225 + popup_an_error(session,"SSL_new failed");
  226 + session->ssl_host = False;
  227 + return;
  228 + }
  229 +
  230 + SSL_set_ex_data(session->ssl_con,ssl_3270_ex_index,(char *) session);
  231 +
  232 +// SSL_set_verify(session->ssl_con, SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
  233 + SSL_set_verify(session->ssl_con, 0, NULL);
  234 +
  235 +}
  236 +
  237 +/* Callback for tracing protocol negotiation. */
  238 +void ssl_info_callback(INFO_CONST SSL *s, int where, int ret)
  239 +{
  240 +// H3270 *hSession = lib3270_get_default_session_handle(); // TODO: Find a better way!
  241 + H3270 *hSession = (H3270 *) SSL_get_ex_data(s,ssl_3270_ex_index);
  242 +
  243 +#ifdef DEBUG
  244 + trace("%s: hsession=%p, session=%p",__FUNCTION__,hSession,lib3270_get_default_session_handle());
  245 + if(hSession != lib3270_get_default_session_handle())
  246 + exit(-1);
  247 +#endif // DEBUG
  248 +
  249 + switch(where)
  250 + {
  251 + case SSL_CB_CONNECT_LOOP:
  252 + trace_dsn(hSession,"SSL_connect: %s %s\n",SSL_state_string(s), SSL_state_string_long(s));
  253 + break;
  254 +
  255 + case SSL_CB_CONNECT_EXIT:
  256 +
  257 + trace_dsn(hSession,"%s: SSL_CB_CONNECT_EXIT\n",__FUNCTION__);
  258 +
  259 + if (ret == 0)
  260 + {
  261 + trace_dsn(hSession,"SSL_connect: failed in %s\n",SSL_state_string_long(s));
  262 + }
  263 + else if (ret < 0)
  264 + {
  265 + unsigned long e = ERR_get_error();
  266 + char err_buf[1024];
  267 +
  268 + if(e != 0)
  269 + {
  270 + hSession->ssl_error = e;
  271 + (void) ERR_error_string_n(e, err_buf, 1023);
  272 + }
  273 +#if defined(_WIN32)
  274 + else if (GetLastError() != 0)
  275 + {
  276 + strncpy(err_buf,lib3270_win32_strerror(GetLastError()),1023);
  277 + }
  278 +#else
  279 + else if (errno != 0)
  280 + {
  281 + strncpy(err_buf, strerror(errno),1023);
  282 + }
  283 +#endif
  284 + else
  285 + {
  286 + err_buf[0] = '\0';
  287 + }
  288 +
  289 + trace_dsn(hSession,"SSL Connect error %d\nMessage: %s\nState: %s\nAlert: %s\n",
  290 + ret,
  291 + err_buf,
  292 + SSL_state_string_long(s),
  293 + SSL_alert_type_string_long(ret)
  294 + );
  295 +
  296 + }
  297 +
  298 +
  299 + default:
  300 + trace_dsn(hSession,"SSL Current state is \"%s\"\n",SSL_state_string_long(s));
  301 + }
  302 +
  303 +// trace("%s: state=%04x where=%04x ret=%d",__FUNCTION__,SSL_state(s),where,ret);
  304 +
  305 +#ifdef DEBUG
  306 + if(where & SSL_CB_EXIT)
  307 + {
  308 + trace("%s: SSL_CB_EXIT ret=%d\n",__FUNCTION__,ret);
  309 + }
  310 +#endif
  311 +
  312 + if(where & SSL_CB_ALERT)
  313 + trace_dsn(hSession,"SSL ALERT: %s\n",SSL_alert_type_string_long(ret));
  314 +
  315 + if(where & SSL_CB_HANDSHAKE_DONE)
  316 + {
  317 + trace_dsn(hSession,"%s: SSL_CB_HANDSHAKE_DONE state=%04x\n",__FUNCTION__,SSL_state(s));
  318 + if(SSL_state(s) == 0x03)
  319 + set_ssl_state(hSession,LIB3270_SSL_NEGOTIATED);
  320 + else
  321 + set_ssl_state(hSession,LIB3270_SSL_UNSECURE);
  322 + }
  323 +}
  324 +
  325 +#endif /*]*/
  326 +
  327 +LIB3270_EXPORT LIB3270_SSL_STATE lib3270_get_secure(H3270 *session)
  328 +{
  329 + CHECK_SESSION_HANDLE(session);
  330 + return session->secure;
  331 +}
  332 +
  333 +LIB3270_EXPORT int lib3270_is_secure(H3270 *hSession)
  334 +{
  335 + return lib3270_get_secure(hSession) == LIB3270_SSL_SECURE;
  336 +}
  337 +
  338 +LIB3270_EXPORT long lib3270_get_SSL_verify_result(H3270 *hSession)
  339 +{
  340 + CHECK_SESSION_HANDLE(hSession);
  341 +#if defined(HAVE_LIBSSL)
  342 + if(hSession->ssl_con)
  343 + return SSL_get_verify_result(hSession->ssl_con);
  344 +#endif // HAVE_LIBSSL
  345 + return -1;
  346 +}
  347 +
  348 +void set_ssl_state(H3270 *session, LIB3270_SSL_STATE state)
  349 +{
  350 + if(state == session->secure)
  351 + return;
  352 +
  353 + trace_dsn(session,"SSL state changes to %d\n",(int) state);
  354 +
  355 + session->update_ssl(session,session->secure = state);
  356 +}
... ...
telnet.c
... ... @@ -46,10 +46,6 @@
46 46 #endif // !ANDROID
47 47  
48 48 #include <lib3270/config.h>
49   -#if defined(HAVE_LIBSSL)
50   - #include <openssl/ssl.h>
51   - #include <openssl/err.h>
52   -#endif
53 49  
54 50 #include "globals.h"
55 51 #include <errno.h>
... ... @@ -136,8 +132,9 @@ static void net_rawout(H3270 *session, unsigned const char *buf, size_t len);
136 132 static void check_in3270(H3270 *session);
137 133 static void store3270in(H3270 *hSession, unsigned char c);
138 134 static void check_linemode(H3270 *hSession, Boolean init);
139   -static int non_blocking(H3270 *session, Boolean on);
140 135 static int net_connected(H3270 *session);
  136 +static void continue_tls(H3270 *hSession, unsigned char *sbbuf, int len);
  137 +
141 138 #if defined(X3270_TN3270E) /*[*/
142 139 static int tn3270e_negotiate(H3270 *hSession);
143 140 #endif /*]*/
... ... @@ -239,22 +236,6 @@ static const char *trsp_flag[2] = { &quot;POSITIVE-RESPONSE&quot;, &quot;NEGATIVE-RESPONSE&quot; };
239 236 #define XMIT_ROWS hSession->maxROWS
240 237 #define XMIT_COLS hSession->maxCOLS
241 238  
242   -#if defined(HAVE_LIBSSL) /*[*/
243   -
244   - static void ssl_init(H3270 *session);
245   -
246   - #if OPENSSL_VERSION_NUMBER >= 0x00907000L /*[*/
247   - #define INFO_CONST const
248   - #else /*][*/
249   - #define INFO_CONST
250   - #endif /*]*/
251   -
252   - static void ssl_info_callback(INFO_CONST SSL *s, int where, int ret);
253   - static void continue_tls(H3270 *hSession, unsigned char *sbbuf, int len);
254   -
255   - static int ssl_3270_ex_index = -1; /**< Index of h3270 handle in SSL session */
256   -
257   -#endif /*]*/
258 239  
259 240 #if defined(_WIN32) /*[*/
260 241 #define socket_errno() WSAGetLastError()
... ... @@ -285,16 +266,6 @@ static const char *trsp_flag[2] = { &quot;POSITIVE-RESPONSE&quot;, &quot;NEGATIVE-RESPONSE&quot; };
285 266  
286 267 /*--[ Implement ]------------------------------------------------------------------------------------*/
287 268  
288   -static void set_ssl_state(H3270 *session, LIB3270_SSL_STATE state)
289   -{
290   - if(state == session->secure)
291   - return;
292   -
293   - trace_dsn(session,"SSL state changes to %d\n",(int) state);
294   -
295   - session->update_ssl(session,session->secure = state);
296   -}
297   -
298 269 #if defined(_WIN32) /*[*/
299 270 void sockstart(H3270 *session)
300 271 {
... ... @@ -801,121 +772,6 @@ static void setup_lus(H3270 *hSession)
801 772 hSession->try_lu = *hSession->curr_lu;
802 773 }
803 774  
804   -#if defined(HAVE_LIBSSL)
805   -static int ssl_negotiate(H3270 *hSession)
806   -{
807   - int rv;
808   -
809   - trace("%s",__FUNCTION__);
810   -
811   - set_ssl_state(hSession,LIB3270_SSL_NEGOTIATING);
812   - non_blocking(hSession,False);
813   -
814   - /* Initialize the SSL library. */
815   - ssl_init(hSession);
816   - if(hSession->ssl_con == NULL)
817   - {
818   - /* Failed. */
819   - popup_an_error(hSession,_( "SSL init failed!"));
820   - net_disconnect(hSession);
821   - return -1;
822   - }
823   -
824   - /* Set up the TLS/SSL connection. */
825   - if(SSL_set_fd(hSession->ssl_con, hSession->sock) != 1)
826   - {
827   - trace_dsn(hSession,"SSL_set_fd failed!\n");
828   - popup_an_error(hSession,_( "SSL_set_fd failed!"));
829   - net_disconnect(hSession);
830   - return -1;
831   - }
832   -
833   - trace("%s: Running SSL_connect",__FUNCTION__);
834   - rv = SSL_connect(hSession->ssl_con);
835   - trace("%s: SSL_connect exits with rc=%d",__FUNCTION__,rv);
836   -
837   - if (rv != 1)
838   - {
839   - int ssl_error = SSL_get_error(hSession->ssl_con,rv);
840   -
841   - if(ssl_error == SSL_ERROR_SYSCALL)
842   - {
843   - if(!hSession->ssl_error)
844   - {
845   - trace_dsn(hSession,"SSL_connect failed (ssl_error=%lu)\n",hSession->ssl_error);
846   - popup_an_error(hSession,_( "SSL connect failed!"));
847   - }
848   - else
849   - {
850   - trace_dsn(hSession,"SSL_connect failed: %s %s\n",
851   - ERR_lib_error_string(hSession->ssl_error),
852   - ERR_reason_error_string(hSession->ssl_error));
853   - popup_an_error(hSession,"%s",_( ERR_reason_error_string(hSession->ssl_error) ));
854   - }
855   -
856   - }
857   - else
858   - {
859   - trace_dsn(hSession,"SSL_connect failed (ssl_error=%d errno=%d)\n",ssl_error,errno);
860   - popup_an_error(hSession,_( "SSL connect failed!"));
861   - }
862   -
863   - net_disconnect(hSession);
864   - return -1;
865   - }
866   -
867   - non_blocking(hSession,True);
868   -
869   - /* Success. */
870   - if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_DS_TRACE))
871   - {
872   - char buffer[4096];
873   - int alg_bits = 0;
874   - const SSL_CIPHER * cipher = SSL_get_current_cipher(hSession->ssl_con);
875   - X509 * peer = SSL_get_peer_certificate(hSession->ssl_con);
876   -
877   - trace_dsn(hSession,"TLS/SSL negotiated connection complete. Connection is now secure.\n");
878   -
879   - trace_dsn(hSession,"TLS/SSL cipher description: %s",SSL_CIPHER_description((SSL_CIPHER *) cipher, buffer, 4095));
880   - SSL_CIPHER_get_bits(cipher, &alg_bits);
881   - trace_dsn(hSession,"%s version %s with %d bits verify=%ld\n",
882   - SSL_CIPHER_get_name(cipher),
883   - SSL_CIPHER_get_version(cipher),
884   - alg_bits,
885   - SSL_get_verify_result(hSession->ssl_con));
886   -
887   - if(peer)
888   - {
889   - BIO * out = BIO_new(BIO_s_mem());
890   - unsigned char * data;
891   - unsigned char * text;
892   - int n;
893   -
894   - X509_print(out,peer);
895   -
896   - n = BIO_get_mem_data(out, &data);
897   - text = (unsigned char *) malloc (n+1);
898   - text[n] ='\0';
899   - memcpy(text,data,n);
900   -
901   - trace_dsn(hSession,"TLS/SSL peer certificate:\n%s\n",text);
902   -
903   - free(text);
904   - BIO_free(out);
905   - X509_free(peer);
906   -
907   - }
908   - }
909   -
910   - if(!SSL_get_verify_result(hSession->ssl_con))
911   - set_ssl_state(hSession,LIB3270_SSL_SECURE);
912   -
913   - /* Tell the world that we are (still) connected, now in secure mode. */
914   - lib3270_set_connected(hSession);
915   - return 0;
916   -}
917   -#endif // HAVE_LIBSSL
918   -
919 775 static int net_connected(H3270 *hSession)
920 776 {
921 777 if(hSession->proxy_type > 0)
... ... @@ -1627,6 +1483,29 @@ static int telnet_fsm(H3270 *hSession, unsigned char c)
1627 1483 return 0;
1628 1484 }
1629 1485  
  1486 +/**
  1487 + * Process a STARTTLS subnegotiation.
  1488 + */
  1489 +static void continue_tls(H3270 *hSession, unsigned char *sbbuf, int len)
  1490 +{
  1491 + /* Whatever happens, we're not expecting another SB STARTTLS. */
  1492 + hSession->need_tls_follows = 0;
  1493 +
  1494 + /* Make sure the option is FOLLOWS. */
  1495 + if (len < 2 || sbbuf[1] != TLS_FOLLOWS)
  1496 + {
  1497 + /* Trace the junk. */
  1498 + trace_dsn(hSession,"%s ? %s\n", opt(TELOPT_STARTTLS), cmd(SE));
  1499 + popup_an_error(hSession,_( "TLS negotiation failure"));
  1500 + net_disconnect(hSession);
  1501 + return;
  1502 + }
  1503 +
  1504 + /* Trace what we got. */
  1505 + trace_dsn(hSession,"%s FOLLOWS %s\n", opt(TELOPT_STARTTLS), cmd(SE));
  1506 + ssl_negotiate(hSession);
  1507 +}
  1508 +
1630 1509 #if defined(X3270_TN3270E) /*[*/
1631 1510 /* Send a TN3270E terminal type request. */
1632 1511 static void tn3270e_request(H3270 *hSession)
... ... @@ -3127,237 +3006,6 @@ parse_ctlchar(char *s)
3127 3006 }
3128 3007 #endif /*]*/
3129 3008  
3130   -/*
3131   - * Set blocking/non-blocking mode on the socket. On error, pops up an error
3132   - * message, but does not close the socket.
3133   - */
3134   -static int non_blocking(H3270 *session, Boolean on)
3135   -{
3136   -# if defined(FIONBIO)
3137   -
3138   - int i = on ? 1 : 0;
3139   -
3140   - if (SOCK_IOCTL(session->sock, FIONBIO, (int *) &i) < 0)
3141   - {
3142   - popup_a_sockerr(session,N_( "Error in ioctl(%s) when setting no blocking mode" ), "FIONBIO");
3143   - return -1;
3144   - }
3145   -
3146   -#else
3147   -
3148   - int f;
3149   -
3150   - if ((f = fcntl(session->sock, F_GETFL, 0)) == -1)
3151   - {
3152   - popup_an_errno(session,errno, _( "Error in fcntl(%s) when setting non blocking mode" ), "F_GETFL" );
3153   - return -1;
3154   - }
3155   -
3156   - if (on)
3157   - f |= O_NDELAY;
3158   - else
3159   - f &= ~O_NDELAY;
3160   -
3161   - if (fcntl(session->sock, F_SETFL, f) < 0)
3162   - {
3163   - popup_an_errno(session,errno, _( "Error in fcntl(%s) when setting non blocking mode" ), "F_SETFL");
3164   - return -1;
3165   - }
3166   -
3167   -#endif // FIONBIO
3168   -
3169   - trace("Socket %d is %s",session->sock, on ? "non-blocking" : "blocking");
3170   -
3171   - return 0;
3172   -}
3173   -
3174   -#if defined(HAVE_LIBSSL) /*[*/
3175   -
3176   -/* Initialize the OpenSSL library. */
3177   -static void ssl_init(H3270 *session)
3178   -{
3179   - static SSL_CTX *ssl_ctx = NULL;
3180   -
3181   - session->ssl_error = 0;
3182   - set_ssl_state(session,LIB3270_SSL_UNDEFINED);
3183   -
3184   - if(ssl_ctx == NULL)
3185   - {
3186   - lib3270_write_log(session,"SSL","%s","Initializing SSL context");
3187   - SSL_load_error_strings();
3188   - SSL_library_init();
3189   - ssl_ctx = SSL_CTX_new(SSLv23_method());
3190   - if(ssl_ctx == NULL)
3191   - {
3192   - popup_an_error(session,"SSL_CTX_new failed");
3193   - session->ssl_host = False;
3194   - return;
3195   - }
3196   - SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL);
3197   - SSL_CTX_set_info_callback(ssl_ctx, ssl_info_callback);
3198   - SSL_CTX_set_default_verify_paths(ssl_ctx);
3199   -
3200   -#if defined(_WIN32)
3201   - {
3202   - HKEY hKey = 0;
3203   -
3204   - if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\" PACKAGE_NAME,0,KEY_QUERY_VALUE,&hKey) == ERROR_SUCCESS)
3205   - {
3206   - char data[4096];
3207   - unsigned long datalen = sizeof(data); // data field length(in), data returned length(out)
3208   - unsigned long datatype; // #defined in winnt.h (predefined types 0-11)
3209   -
3210   - if(RegQueryValueExA(hKey,"datadir",NULL,&datatype,(LPBYTE) data,&datalen) == ERROR_SUCCESS)
3211   - {
3212   - strncat(data,"\\certs",4095);
3213   -
3214   - trace("Loading certs from \"%s\"",data);
3215   - SSL_CTX_load_verify_locations(ssl_ctx,NULL,data);
3216   - }
3217   - RegCloseKey(hKey);
3218   - }
3219   -
3220   -
3221   - }
3222   -
3223   -#endif // _WIN32
3224   -
3225   - ssl_3270_ex_index = SSL_get_ex_new_index(0,NULL,NULL,NULL,NULL);
3226   -
3227   -
3228   - }
3229   -
3230   - if(session->ssl_con)
3231   - SSL_free(session->ssl_con);
3232   -
3233   - session->ssl_con = SSL_new(ssl_ctx);
3234   - if(session->ssl_con == NULL)
3235   - {
3236   - popup_an_error(session,"SSL_new failed");
3237   - session->ssl_host = False;
3238   - return;
3239   - }
3240   -
3241   - SSL_set_ex_data(session->ssl_con,ssl_3270_ex_index,(char *) session);
3242   -
3243   -// SSL_set_verify(session->ssl_con, SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
3244   - SSL_set_verify(session->ssl_con, 0, NULL);
3245   -
3246   -}
3247   -
3248   -/* Callback for tracing protocol negotiation. */
3249   -static void ssl_info_callback(INFO_CONST SSL *s, int where, int ret)
3250   -{
3251   -// H3270 *hSession = lib3270_get_default_session_handle(); // TODO: Find a better way!
3252   - H3270 *hSession = (H3270 *) SSL_get_ex_data(s,ssl_3270_ex_index);
3253   -
3254   -#ifdef DEBUG
3255   - trace("%s: hsession=%p, session=%p",__FUNCTION__,hSession,lib3270_get_default_session_handle());
3256   - if(hSession != lib3270_get_default_session_handle())
3257   - exit(-1);
3258   -#endif // DEBUG
3259   -
3260   - switch(where)
3261   - {
3262   - case SSL_CB_CONNECT_LOOP:
3263   - trace_dsn(hSession,"SSL_connect: %s %s\n",SSL_state_string(s), SSL_state_string_long(s));
3264   - break;
3265   -
3266   - case SSL_CB_CONNECT_EXIT:
3267   -
3268   - trace_dsn(hSession,"%s: SSL_CB_CONNECT_EXIT\n",__FUNCTION__);
3269   -
3270   - if (ret == 0)
3271   - {
3272   - trace_dsn(hSession,"SSL_connect: failed in %s\n",SSL_state_string_long(s));
3273   - }
3274   - else if (ret < 0)
3275   - {
3276   - unsigned long e = ERR_get_error();
3277   - char err_buf[1024];
3278   -
3279   - if(e != 0)
3280   - {
3281   - hSession->ssl_error = e;
3282   - (void) ERR_error_string_n(e, err_buf, 1023);
3283   - }
3284   -#if defined(_WIN32)
3285   - else if (GetLastError() != 0)
3286   - {
3287   - strncpy(err_buf,lib3270_win32_strerror(GetLastError()),1023);
3288   - }
3289   -#else
3290   - else if (errno != 0)
3291   - {
3292   - strncpy(err_buf, strerror(errno),1023);
3293   - }
3294   -#endif
3295   - else
3296   - {
3297   - err_buf[0] = '\0';
3298   - }
3299   -
3300   - trace_dsn(hSession,"SSL Connect error %d\nMessage: %s\nState: %s\nAlert: %s\n",
3301   - ret,
3302   - err_buf,
3303   - SSL_state_string_long(s),
3304   - SSL_alert_type_string_long(ret)
3305   - );
3306   -
3307   - }
3308   -
3309   -
3310   - default:
3311   - trace_dsn(hSession,"SSL Current state is \"%s\"\n",SSL_state_string_long(s));
3312   - }
3313   -
3314   -// trace("%s: state=%04x where=%04x ret=%d",__FUNCTION__,SSL_state(s),where,ret);
3315   -
3316   -#ifdef DEBUG
3317   - if(where & SSL_CB_EXIT)
3318   - {
3319   - trace("%s: SSL_CB_EXIT ret=%d\n",__FUNCTION__,ret);
3320   - }
3321   -#endif
3322   -
3323   - if(where & SSL_CB_ALERT)
3324   - trace_dsn(hSession,"SSL ALERT: %s\n",SSL_alert_type_string_long(ret));
3325   -
3326   - if(where & SSL_CB_HANDSHAKE_DONE)
3327   - {
3328   - trace_dsn(hSession,"%s: SSL_CB_HANDSHAKE_DONE state=%04x\n",__FUNCTION__,SSL_state(s));
3329   - if(SSL_state(s) == 0x03)
3330   - set_ssl_state(hSession,LIB3270_SSL_NEGOTIATED);
3331   - else
3332   - set_ssl_state(hSession,LIB3270_SSL_UNSECURE);
3333   - }
3334   -}
3335   -
3336   -/**
3337   - * Process a STARTTLS subnegotiation.
3338   - */
3339   -static void continue_tls(H3270 *hSession, unsigned char *sbbuf, int len)
3340   -{
3341   - /* Whatever happens, we're not expecting another SB STARTTLS. */
3342   - hSession->need_tls_follows = 0;
3343   -
3344   - /* Make sure the option is FOLLOWS. */
3345   - if (len < 2 || sbbuf[1] != TLS_FOLLOWS)
3346   - {
3347   - /* Trace the junk. */
3348   - trace_dsn(hSession,"%s ? %s\n", opt(TELOPT_STARTTLS), cmd(SE));
3349   - popup_an_error(hSession,_( "TLS negotiation failure"));
3350   - net_disconnect(hSession);
3351   - return;
3352   - }
3353   -
3354   - /* Trace what we got. */
3355   - trace_dsn(hSession,"%s FOLLOWS %s\n", opt(TELOPT_STARTTLS), cmd(SE));
3356   - ssl_negotiate(hSession);
3357   -}
3358   -
3359   -#endif /*]*/
3360   -
3361 3009 /* Return the local address for the socket. */
3362 3010 int net_getsockname(const H3270 *session, void *buf, int *len)
3363 3011 {
... ... @@ -3365,24 +3013,3 @@ int net_getsockname(const H3270 *session, void *buf, int *len)
3365 3013 return -1;
3366 3014 return getsockname(session->sock, buf, (socklen_t *)(void *)len);
3367 3015 }
3368   -
3369   -LIB3270_EXPORT LIB3270_SSL_STATE lib3270_get_secure(H3270 *session)
3370   -{
3371   - CHECK_SESSION_HANDLE(session);
3372   - return session->secure;
3373   -}
3374   -
3375   -LIB3270_EXPORT int lib3270_is_secure(H3270 *hSession)
3376   -{
3377   - return lib3270_get_secure(hSession) == LIB3270_SSL_SECURE;
3378   -}
3379   -
3380   -LIB3270_EXPORT long lib3270_get_SSL_verify_result(H3270 *hSession)
3381   -{
3382   - CHECK_SESSION_HANDLE(hSession);
3383   -#if defined(HAVE_LIBSSL)
3384   - if(hSession->ssl_con)
3385   - return SSL_get_verify_result(hSession->ssl_con);
3386   -#endif // HAVE_LIBSSL
3387   - return -1;
3388   -}
... ...
testprogram.c
... ... @@ -22,7 +22,7 @@ static void * mainloop(void *dunno)
22 22 int main(int numpar, char *param[])
23 23 {
24 24 H3270 * h;
25   - char line[4096];
  25 +// char line[4096];
26 26 // pthread_t thread;
27 27  
28 28 lib3270_initialize();
... ... @@ -30,10 +30,13 @@ int main(int numpar, char *param[])
30 30 session = h = lib3270_session_new("");
31 31 printf("3270 session %p created\n]",h);
32 32  
  33 + lib3270_set_toggle(session,LIB3270_TOGGLE_DS_TRACE,1);
  34 +
33 35 // pthread_create(&thread, NULL, mainloop, NULL);
34 36 // pthread_detach(thread);
35 37  
36   - lib3270_connect_host(h, "fandezhi.efglobe.com", "telnet");
  38 + lib3270_connect_host(h, "$HOST3270", "8023");
  39 +// lib3270_connect_host(h, "fandezhi.efglobe.com", "telnet");
37 40 // lib3270_connect_host(h, "127.0.0.1", "9090");
38 41  
39 42 mainloop(0);
... ...