diff --git a/connect.c b/connect.c
index d892886..a6c8aba 100644
--- a/connect.c
+++ b/connect.c
@@ -82,7 +82,7 @@ static void net_connected(H3270 *hSession)
_( "Network error" ),
_( "Unable to get connection state." ),
#ifdef _WIN32
- _( "Winsock Error %d"), WSAGetLastError()
+ "%s", lib3270_win32_strerror(WSAGetLastError()));
#else
_( "%s" ), strerror(errno)
#endif // _WIN32
@@ -167,16 +167,6 @@ static void net_connected(H3270 *hSession)
}
#endif /*]*/
- static void set_ssl_state(H3270 *hSession, LIB3270_SSL_STATE state)
- {
- if(state == hSession->secure)
- return;
-
- trace_dsn(hSession,"SSL state changes to %d\n",(int) state);
-
- hSession->update_ssl(hSession,hSession->secure = state);
- }
-
LIB3270_EXPORT int lib3270_connect_host(H3270 *hSession, const char *hostname, const char *srvc)
{
int s;
@@ -303,8 +293,7 @@ static void net_connected(H3270 *hSession)
LIB3270_NOTIFY_ERROR,
_( "Connection error" ),
_( "ioctlsocket(FIONBIO) failed." ),
- "%s", lib3270_win32_strerror(GetLastError()));
-
+ "%s", lib3270_win32_strerror(WSAGetLastError()));
SOCK_CLOSE(hSession);
}
else if(connect(hSession->sock, rp->ai_addr, rp->ai_addrlen))
@@ -316,7 +305,7 @@ static void net_connected(H3270 *hSession)
LIB3270_NOTIFY_ERROR,
_( "Connection error" ),
_( "Can't connect to host." ),
- "%s", lib3270_win32_strerror(GetLastError()));
+ "%s", lib3270_win32_strerror(err));
SOCK_CLOSE(hSession);
}
}
@@ -390,3 +379,56 @@ static void net_connected(H3270 *hSession)
}
+int non_blocking(H3270 *hSession, Boolean on)
+{
+#ifdef WIN32
+ WSASetLastError(0);
+ u_long iMode= on ? 1 : 0;
+
+ if(ioctlsocket(hSession->sock,FIONBIO,&iMode))
+ {
+ lib3270_popup_dialog( hSession,
+ LIB3270_NOTIFY_ERROR,
+ _( "Connection error" ),
+ _( "ioctlsocket(FIONBIO) failed." ),
+ "%s", lib3270_win32_strerror(GetLastError()));
+ }
+#else
+
+ int f;
+
+ if ((f = fcntl(hSession->sock, F_GETFL, 0)) == -1)
+ {
+ lib3270_popup_dialog( hSession,
+ LIB3270_NOTIFY_ERROR,
+ _( "Socket error" ),
+ _( "fcntl() error when getting socket state." ),
+ _( "%s" ), strerror(errno)
+ );
+
+ return -1;
+ }
+
+ if (on)
+ f |= O_NDELAY;
+ else
+ f &= ~O_NDELAY;
+
+ if (fcntl(hSession->sock, F_SETFL, f) < 0)
+ {
+ lib3270_popup_dialog( hSession,
+ LIB3270_NOTIFY_ERROR,
+ _( "Socket error" ),
+ on ? _( "Can't set socket to blocking mode." ) : _( "Can't set socket to non blocking mode" ),
+ _( "%s" ), strerror(errno)
+ );
+ return -1;
+ }
+
+#endif
+
+ trace("Socket %d is %s",hSession->sock, on ? "non-blocking" : "blocking");
+
+ return 0;
+}
+
diff --git a/globals.h b/globals.h
index 6a0cedb..6a0605a 100644
--- a/globals.h
+++ b/globals.h
@@ -137,18 +137,6 @@ enum iaction {
IA_IDLE
};
-// LIB3270_INTERNAL int COLS;
-// LIB3270_INTERNAL int ROWS;
-
-// LIB3270_INTERNAL H3270 h3270;
-
-/*
-#if defined(X3270_DISPLAY)
- LIB3270_INTERNAL Atom a_3270, a_registry, a_encoding;
- LIB3270_INTERNAL XtAppContext appcontext;
-#endif
-*/
-
// Version strings
LIB3270_INTERNAL const char * build;
LIB3270_INTERNAL const char * app_defaults_version;
@@ -157,99 +145,15 @@ LIB3270_INTERNAL const char * build_rpq_timestamp;
LIB3270_INTERNAL const char * build_rpq_version;
LIB3270_INTERNAL const char * build_rpq_revision;
-// LIB3270_INTERNAL int children;
-
#if defined(X3270_DBCS) /*[*/
LIB3270_INTERNAL Boolean dbcs;
#endif /*]*/
-// #if defined(X3270_FT) /*[*/
-// LIB3270_INTERNAL int dft_buffersize;
-// #endif /*]*/
-
-// LIB3270_INTERNAL char *efontname;
-// LIB3270_INTERNAL Boolean ever_3270;
-// LIB3270_INTERNAL Boolean exiting;
-
-/*
-#if defined(X3270_DISPLAY)
- LIB3270_INTERNAL Boolean *extended_3270font;
- LIB3270_INTERNAL Font *fid;
- LIB3270_INTERNAL Boolean *font_8bit;
-#endif
-*/
-
-// LIB3270_INTERNAL Boolean flipped;
-// LIB3270_INTERNAL char *full_current_host;
-// LIB3270_INTERNAL char *full_efontname;
#if defined(X3270_DBCS) /*[*/
LIB3270_INTERNAL char *full_efontname_dbcs;
#endif /*]*/
-//LIB3270_INTERNAL char *funky_font;
-//LIB3270_INTERNAL char *hostname;
-
-#if defined(X3270_DBCS) /*[*/
-// LIB3270_INTERNAL char *local_encoding;
-
- #if defined(X3270_DISPLAY) /*[*/
-// LIB3270_INTERNAL char *locale_name;
- #endif /*]*/
-
-#endif /*]*/
-
-/*
-#if defined(LOCAL_PROCESS)
- LIB3270_INTERNAL Boolean local_process;
-#endif
-*/
-
-// LIB3270_INTERNAL int maxCOLS;
-// LIB3270_INTERNAL int maxROWS;
-// LIB3270_INTERNAL char *model_name;
-// LIB3270_INTERNAL int model_num;
-// LIB3270_INTERNAL Boolean no_login_host;
-// LIB3270_INTERNAL Boolean non_tn3270e_host;
-// LIB3270_INTERNAL int ov_cols, ov_rows;
-// LIB3270_INTERNAL Boolean passthru_host;
-// extern const char *programname;
-// LIB3270_INTERNAL char *qualified_host;
-// LIB3270_INTERNAL char *reconnect_host;
-// LIB3270_INTERNAL int screen_depth;
-// LIB3270_INTERNAL Boolean scroll_initted;
-
-//#if defined(HAVE_LIBSSL) /*[*/
-// LIB3270_INTERNAL Boolean secure_connection;
-//#endif /*]*/
-
-// LIB3270_INTERNAL Boolean shifted;
-// LIB3270_INTERNAL Boolean ssl_host;
-// LIB3270_INTERNAL Boolean *standard_font;
-// LIB3270_INTERNAL Boolean std_ds_host;
-// LIB3270_INTERNAL char *termtype;
-// LIB3270_INTERNAL Widget toplevel;
-// LIB3270_INTERNAL Boolean visible_control;
-// LIB3270_INTERNAL int *xtra_width;
-
-/*
-#if defined(X3270_DISPLAY)
- LIB3270_INTERNAL Atom a_delete_me;
- LIB3270_INTERNAL Atom a_save_yourself;
- LIB3270_INTERNAL Atom a_state;
- LIB3270_INTERNAL Display *display;
- LIB3270_INTERNAL Pixmap gray;
- LIB3270_INTERNAL Pixel keypadbg_pixel;
- LIB3270_INTERNAL XrmDatabase rdb;
- LIB3270_INTERNAL Window root_window;
- LIB3270_INTERNAL char *user_title;
- LIB3270_INTERNAL unsigned char xk_selector;
-#endif
-*/
-
-/* Connection state */
-// LIB3270_INTERNAL enum ft_state ft_state;
-
/* keyboard modifer bitmap */
#define ShiftKeyDown 0x01
@@ -263,19 +167,7 @@ struct toggle_name {
};
-/* translation lists */ /*
-struct trans_list {
- char *name;
- char *pathname;
- Boolean is_temp;
- Boolean from_server;
- struct trans_list *next;
-};
-LIB3270_INTERNAL struct trans_list *trans_list;
-*/
-
/* input key type */
-// enum keytype { KT_STD, KT_GE };
/* Naming convention for private actions. */
#define PA_PFX "PA-"
@@ -341,8 +233,6 @@ LIB3270_INTERNAL void key_ACharacter(H3270 *hSession, unsigned char c, enum keyt
LIB3270_INTERNAL void lib3270_initialize(void);
LIB3270_INTERNAL int cursor_move(H3270 *session, int baddr);
-// LIB3270_INTERNAL void add_input_calls(H3270 *, void (*)(H3270 *), void (*)(H3270 *));
-
LIB3270_INTERNAL void toggle_rectselect(H3270 *session, struct lib3270_toggle *t, LIB3270_TOGGLE_TYPE tt);
LIB3270_INTERNAL void remove_input_calls(H3270 *session);
@@ -358,3 +248,23 @@ LIB3270_INTERNAL void lib3270_sock_disconnect(H3270 *hSession);
#endif // DEBUG
LIB3270_EXPORT int lib3270_connect_host(H3270 *hSession, const char *hostname, const char *srvc);
+
+LIB3270_INTERNAL int non_blocking(H3270 *session, Boolean on);
+
+#if defined(HAVE_LIBSSL) /*[*/
+
+ LIB3270_INTERNAL void ssl_init(H3270 *session);
+ LIB3270_INTERNAL int ssl_negotiate(H3270 *hSession);
+ LIB3270_INTERNAL void set_ssl_state(H3270 *session, LIB3270_SSL_STATE state);
+
+
+ #if OPENSSL_VERSION_NUMBER >= 0x00907000L /*[*/
+ #define INFO_CONST const
+ #else /*][*/
+ #define INFO_CONST
+ #endif /*]*/
+
+ LIB3270_INTERNAL void ssl_info_callback(INFO_CONST SSL *s, int where, int ret);
+
+#endif /*]*/
+
diff --git a/lib3270.cbp b/lib3270.cbp
index 10de722..f1ebfb2 100644
--- a/lib3270.cbp
+++ b/lib3270.cbp
@@ -189,6 +189,7 @@
+
diff --git a/sources.mak b/sources.mak
index 0bb2e5d..181aae0 100644
--- a/sources.mak
+++ b/sources.mak
@@ -28,7 +28,7 @@
TERMINAL_SOURCES = bounds.c ctlr.c util.c toggles.c screen.c selection.c kybd.c telnet.c \
host.c sf.c ansi.c resolver.c charset.c \
version.c session.c state.c html.c trace_ds.c see.c \
- paste.c
+ paste.c ssl.c
# tables.c utf8.c
diff --git a/ssl.c b/ssl.c
new file mode 100644
index 0000000..fdc8266
--- /dev/null
+++ b/ssl.c
@@ -0,0 +1,356 @@
+/*
+ * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
+ * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
+ * aplicativos mainframe. Registro no INPI sob o nome G3270.
+ *
+ * Copyright (C) <2008>
+ *
+ * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
+ * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
+ * Free Software Foundation.
+ *
+ * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
+ * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
+ * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
+ * obter mais detalhes.
+ *
+ * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
+ * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
+ * St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Este programa está nomeado como ssl.c e possui - linhas de código.
+ *
+ * Contatos:
+ *
+ * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
+ * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
+ * licinio@bb.com.br (Licínio Luis Branco)
+ * kraucer@bb.com.br (Kraucer Fernandes Mazuco)
+ *
+ */
+
+
+#include
+#if defined(HAVE_LIBSSL)
+ #include
+ #include
+#endif
+
+#include "globals.h"
+#include
+#include
+#include
+#include "trace_dsc.h"
+
+static int ssl_3270_ex_index = -1; /**< Index of h3270 handle in SSL session */
+
+/*--[ Implement ]------------------------------------------------------------------------------------*/
+
+#if defined(HAVE_LIBSSL)
+int ssl_negotiate(H3270 *hSession)
+{
+ int rv;
+
+ trace("%s",__FUNCTION__);
+
+ set_ssl_state(hSession,LIB3270_SSL_NEGOTIATING);
+ non_blocking(hSession,False);
+
+ /* Initialize the SSL library. */
+ ssl_init(hSession);
+ if(hSession->ssl_con == NULL)
+ {
+ /* Failed. */
+ popup_an_error(hSession,_( "SSL init failed!"));
+ lib3270_disconnect(hSession);
+ return -1;
+ }
+
+ /* Set up the TLS/SSL connection. */
+ if(SSL_set_fd(hSession->ssl_con, hSession->sock) != 1)
+ {
+ trace_dsn(hSession,"SSL_set_fd failed!\n");
+ #warning Show a better popup here
+ // popup_an_error(hSession,_( "SSL_set_fd failed!"));
+ lib32070_disconnect(hSession);
+ return -1;
+ }
+
+ trace("%s: Running SSL_connect",__FUNCTION__);
+ rv = SSL_connect(hSession->ssl_con);
+ trace("%s: SSL_connect exits with rc=%d",__FUNCTION__,rv);
+
+ if (rv != 1)
+ {
+ int ssl_error = SSL_get_error(hSession->ssl_con,rv);
+
+ if(ssl_error == SSL_ERROR_SYSCALL)
+ {
+ if(!hSession->ssl_error)
+ {
+ trace_dsn(hSession,"SSL_connect failed (ssl_error=%lu)\n",hSession->ssl_error);
+ popup_an_error(hSession,_( "SSL connect failed!"));
+ }
+ else
+ {
+ trace_dsn(hSession,"SSL_connect failed: %s %s\n",
+ ERR_lib_error_string(hSession->ssl_error),
+ ERR_reason_error_string(hSession->ssl_error));
+ popup_an_error(hSession,"%s",_( ERR_reason_error_string(hSession->ssl_error) ));
+ }
+
+ }
+ else
+ {
+ trace_dsn(hSession,"SSL_connect failed (ssl_error=%d errno=%d)\n",ssl_error,errno);
+ popup_an_error(hSession,_( "SSL connect failed!"));
+ }
+
+ lib3270_disconnect(hSession);
+ return -1;
+ }
+
+ /* Success. */
+ if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_DS_TRACE))
+ {
+ char buffer[4096];
+ int alg_bits = 0;
+ const SSL_CIPHER * cipher = SSL_get_current_cipher(hSession->ssl_con);
+ X509 * peer = SSL_get_peer_certificate(hSession->ssl_con);
+
+ trace_dsn(hSession,"TLS/SSL negotiated connection complete. Connection is now secure.\n");
+
+ trace_dsn(hSession,"TLS/SSL cipher description: %s",SSL_CIPHER_description((SSL_CIPHER *) cipher, buffer, 4095));
+ SSL_CIPHER_get_bits(cipher, &alg_bits);
+ trace_dsn(hSession,"%s version %s with %d bits verify=%ld\n",
+ SSL_CIPHER_get_name(cipher),
+ SSL_CIPHER_get_version(cipher),
+ alg_bits,
+ SSL_get_verify_result(hSession->ssl_con));
+
+ if(peer)
+ {
+ BIO * out = BIO_new(BIO_s_mem());
+ unsigned char * data;
+ unsigned char * text;
+ int n;
+
+ X509_print(out,peer);
+
+ n = BIO_get_mem_data(out, &data);
+ text = (unsigned char *) malloc (n+1);
+ text[n] ='\0';
+ memcpy(text,data,n);
+
+ trace_dsn(hSession,"TLS/SSL peer certificate:\n%s\n",text);
+
+ free(text);
+ BIO_free(out);
+ X509_free(peer);
+
+ }
+ }
+
+ if(!SSL_get_verify_result(hSession->ssl_con))
+ set_ssl_state(hSession,LIB3270_SSL_SECURE);
+
+ /* Tell the world that we are (still) connected, now in secure mode. */
+ lib3270_set_connected(hSession);
+ return 0;
+}
+#endif // HAVE_LIBSSL
+
+#if defined(HAVE_LIBSSL) /*[*/
+
+/* Initialize the OpenSSL library. */
+void ssl_init(H3270 *session)
+{
+ static SSL_CTX *ssl_ctx = NULL;
+
+ session->ssl_error = 0;
+ set_ssl_state(session,LIB3270_SSL_UNDEFINED);
+
+ if(ssl_ctx == NULL)
+ {
+ lib3270_write_log(session,"SSL","%s","Initializing SSL context");
+ SSL_load_error_strings();
+ SSL_library_init();
+ ssl_ctx = SSL_CTX_new(SSLv23_method());
+ if(ssl_ctx == NULL)
+ {
+ popup_an_error(session,"SSL_CTX_new failed");
+ session->ssl_host = False;
+ return;
+ }
+ SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL);
+ SSL_CTX_set_info_callback(ssl_ctx, ssl_info_callback);
+ SSL_CTX_set_default_verify_paths(ssl_ctx);
+
+#if defined(_WIN32)
+ {
+ HKEY hKey = 0;
+
+ if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\" PACKAGE_NAME,0,KEY_QUERY_VALUE,&hKey) == ERROR_SUCCESS)
+ {
+ char data[4096];
+ unsigned long datalen = sizeof(data); // data field length(in), data returned length(out)
+ unsigned long datatype; // #defined in winnt.h (predefined types 0-11)
+
+ if(RegQueryValueExA(hKey,"datadir",NULL,&datatype,(LPBYTE) data,&datalen) == ERROR_SUCCESS)
+ {
+ strncat(data,"\\certs",4095);
+
+ trace("Loading certs from \"%s\"",data);
+ SSL_CTX_load_verify_locations(ssl_ctx,NULL,data);
+ }
+ RegCloseKey(hKey);
+ }
+
+
+ }
+
+#endif // _WIN32
+
+ ssl_3270_ex_index = SSL_get_ex_new_index(0,NULL,NULL,NULL,NULL);
+
+
+ }
+
+ if(session->ssl_con)
+ SSL_free(session->ssl_con);
+
+ session->ssl_con = SSL_new(ssl_ctx);
+ if(session->ssl_con == NULL)
+ {
+ popup_an_error(session,"SSL_new failed");
+ session->ssl_host = False;
+ return;
+ }
+
+ SSL_set_ex_data(session->ssl_con,ssl_3270_ex_index,(char *) session);
+
+// SSL_set_verify(session->ssl_con, SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
+ SSL_set_verify(session->ssl_con, 0, NULL);
+
+}
+
+/* Callback for tracing protocol negotiation. */
+void ssl_info_callback(INFO_CONST SSL *s, int where, int ret)
+{
+// H3270 *hSession = lib3270_get_default_session_handle(); // TODO: Find a better way!
+ H3270 *hSession = (H3270 *) SSL_get_ex_data(s,ssl_3270_ex_index);
+
+#ifdef DEBUG
+ trace("%s: hsession=%p, session=%p",__FUNCTION__,hSession,lib3270_get_default_session_handle());
+ if(hSession != lib3270_get_default_session_handle())
+ exit(-1);
+#endif // DEBUG
+
+ switch(where)
+ {
+ case SSL_CB_CONNECT_LOOP:
+ trace_dsn(hSession,"SSL_connect: %s %s\n",SSL_state_string(s), SSL_state_string_long(s));
+ break;
+
+ case SSL_CB_CONNECT_EXIT:
+
+ trace_dsn(hSession,"%s: SSL_CB_CONNECT_EXIT\n",__FUNCTION__);
+
+ if (ret == 0)
+ {
+ trace_dsn(hSession,"SSL_connect: failed in %s\n",SSL_state_string_long(s));
+ }
+ else if (ret < 0)
+ {
+ unsigned long e = ERR_get_error();
+ char err_buf[1024];
+
+ if(e != 0)
+ {
+ hSession->ssl_error = e;
+ (void) ERR_error_string_n(e, err_buf, 1023);
+ }
+#if defined(_WIN32)
+ else if (GetLastError() != 0)
+ {
+ strncpy(err_buf,lib3270_win32_strerror(GetLastError()),1023);
+ }
+#else
+ else if (errno != 0)
+ {
+ strncpy(err_buf, strerror(errno),1023);
+ }
+#endif
+ else
+ {
+ err_buf[0] = '\0';
+ }
+
+ trace_dsn(hSession,"SSL Connect error %d\nMessage: %s\nState: %s\nAlert: %s\n",
+ ret,
+ err_buf,
+ SSL_state_string_long(s),
+ SSL_alert_type_string_long(ret)
+ );
+
+ }
+
+
+ default:
+ trace_dsn(hSession,"SSL Current state is \"%s\"\n",SSL_state_string_long(s));
+ }
+
+// trace("%s: state=%04x where=%04x ret=%d",__FUNCTION__,SSL_state(s),where,ret);
+
+#ifdef DEBUG
+ if(where & SSL_CB_EXIT)
+ {
+ trace("%s: SSL_CB_EXIT ret=%d\n",__FUNCTION__,ret);
+ }
+#endif
+
+ if(where & SSL_CB_ALERT)
+ trace_dsn(hSession,"SSL ALERT: %s\n",SSL_alert_type_string_long(ret));
+
+ if(where & SSL_CB_HANDSHAKE_DONE)
+ {
+ trace_dsn(hSession,"%s: SSL_CB_HANDSHAKE_DONE state=%04x\n",__FUNCTION__,SSL_state(s));
+ if(SSL_state(s) == 0x03)
+ set_ssl_state(hSession,LIB3270_SSL_NEGOTIATED);
+ else
+ set_ssl_state(hSession,LIB3270_SSL_UNSECURE);
+ }
+}
+
+#endif /*]*/
+
+LIB3270_EXPORT LIB3270_SSL_STATE lib3270_get_secure(H3270 *session)
+{
+ CHECK_SESSION_HANDLE(session);
+ return session->secure;
+}
+
+LIB3270_EXPORT int lib3270_is_secure(H3270 *hSession)
+{
+ return lib3270_get_secure(hSession) == LIB3270_SSL_SECURE;
+}
+
+LIB3270_EXPORT long lib3270_get_SSL_verify_result(H3270 *hSession)
+{
+ CHECK_SESSION_HANDLE(hSession);
+#if defined(HAVE_LIBSSL)
+ if(hSession->ssl_con)
+ return SSL_get_verify_result(hSession->ssl_con);
+#endif // HAVE_LIBSSL
+ return -1;
+}
+
+void set_ssl_state(H3270 *session, LIB3270_SSL_STATE state)
+{
+ if(state == session->secure)
+ return;
+
+ trace_dsn(session,"SSL state changes to %d\n",(int) state);
+
+ session->update_ssl(session,session->secure = state);
+}
diff --git a/telnet.c b/telnet.c
index ae7c433..4a094fd 100644
--- a/telnet.c
+++ b/telnet.c
@@ -46,10 +46,6 @@
#endif // !ANDROID
#include
-#if defined(HAVE_LIBSSL)
- #include
- #include
-#endif
#include "globals.h"
#include
@@ -136,8 +132,9 @@ static void net_rawout(H3270 *session, unsigned const char *buf, size_t len);
static void check_in3270(H3270 *session);
static void store3270in(H3270 *hSession, unsigned char c);
static void check_linemode(H3270 *hSession, Boolean init);
-static int non_blocking(H3270 *session, Boolean on);
static int net_connected(H3270 *session);
+static void continue_tls(H3270 *hSession, unsigned char *sbbuf, int len);
+
#if defined(X3270_TN3270E) /*[*/
static int tn3270e_negotiate(H3270 *hSession);
#endif /*]*/
@@ -239,22 +236,6 @@ static const char *trsp_flag[2] = { "POSITIVE-RESPONSE", "NEGATIVE-RESPONSE" };
#define XMIT_ROWS hSession->maxROWS
#define XMIT_COLS hSession->maxCOLS
-#if defined(HAVE_LIBSSL) /*[*/
-
- static void ssl_init(H3270 *session);
-
- #if OPENSSL_VERSION_NUMBER >= 0x00907000L /*[*/
- #define INFO_CONST const
- #else /*][*/
- #define INFO_CONST
- #endif /*]*/
-
- static void ssl_info_callback(INFO_CONST SSL *s, int where, int ret);
- static void continue_tls(H3270 *hSession, unsigned char *sbbuf, int len);
-
- static int ssl_3270_ex_index = -1; /**< Index of h3270 handle in SSL session */
-
-#endif /*]*/
#if defined(_WIN32) /*[*/
#define socket_errno() WSAGetLastError()
@@ -285,16 +266,6 @@ static const char *trsp_flag[2] = { "POSITIVE-RESPONSE", "NEGATIVE-RESPONSE" };
/*--[ Implement ]------------------------------------------------------------------------------------*/
-static void set_ssl_state(H3270 *session, LIB3270_SSL_STATE state)
-{
- if(state == session->secure)
- return;
-
- trace_dsn(session,"SSL state changes to %d\n",(int) state);
-
- session->update_ssl(session,session->secure = state);
-}
-
#if defined(_WIN32) /*[*/
void sockstart(H3270 *session)
{
@@ -801,121 +772,6 @@ static void setup_lus(H3270 *hSession)
hSession->try_lu = *hSession->curr_lu;
}
-#if defined(HAVE_LIBSSL)
-static int ssl_negotiate(H3270 *hSession)
-{
- int rv;
-
- trace("%s",__FUNCTION__);
-
- set_ssl_state(hSession,LIB3270_SSL_NEGOTIATING);
- non_blocking(hSession,False);
-
- /* Initialize the SSL library. */
- ssl_init(hSession);
- if(hSession->ssl_con == NULL)
- {
- /* Failed. */
- popup_an_error(hSession,_( "SSL init failed!"));
- net_disconnect(hSession);
- return -1;
- }
-
- /* Set up the TLS/SSL connection. */
- if(SSL_set_fd(hSession->ssl_con, hSession->sock) != 1)
- {
- trace_dsn(hSession,"SSL_set_fd failed!\n");
- popup_an_error(hSession,_( "SSL_set_fd failed!"));
- net_disconnect(hSession);
- return -1;
- }
-
- trace("%s: Running SSL_connect",__FUNCTION__);
- rv = SSL_connect(hSession->ssl_con);
- trace("%s: SSL_connect exits with rc=%d",__FUNCTION__,rv);
-
- if (rv != 1)
- {
- int ssl_error = SSL_get_error(hSession->ssl_con,rv);
-
- if(ssl_error == SSL_ERROR_SYSCALL)
- {
- if(!hSession->ssl_error)
- {
- trace_dsn(hSession,"SSL_connect failed (ssl_error=%lu)\n",hSession->ssl_error);
- popup_an_error(hSession,_( "SSL connect failed!"));
- }
- else
- {
- trace_dsn(hSession,"SSL_connect failed: %s %s\n",
- ERR_lib_error_string(hSession->ssl_error),
- ERR_reason_error_string(hSession->ssl_error));
- popup_an_error(hSession,"%s",_( ERR_reason_error_string(hSession->ssl_error) ));
- }
-
- }
- else
- {
- trace_dsn(hSession,"SSL_connect failed (ssl_error=%d errno=%d)\n",ssl_error,errno);
- popup_an_error(hSession,_( "SSL connect failed!"));
- }
-
- net_disconnect(hSession);
- return -1;
- }
-
- non_blocking(hSession,True);
-
- /* Success. */
- if(lib3270_get_toggle(hSession,LIB3270_TOGGLE_DS_TRACE))
- {
- char buffer[4096];
- int alg_bits = 0;
- const SSL_CIPHER * cipher = SSL_get_current_cipher(hSession->ssl_con);
- X509 * peer = SSL_get_peer_certificate(hSession->ssl_con);
-
- trace_dsn(hSession,"TLS/SSL negotiated connection complete. Connection is now secure.\n");
-
- trace_dsn(hSession,"TLS/SSL cipher description: %s",SSL_CIPHER_description((SSL_CIPHER *) cipher, buffer, 4095));
- SSL_CIPHER_get_bits(cipher, &alg_bits);
- trace_dsn(hSession,"%s version %s with %d bits verify=%ld\n",
- SSL_CIPHER_get_name(cipher),
- SSL_CIPHER_get_version(cipher),
- alg_bits,
- SSL_get_verify_result(hSession->ssl_con));
-
- if(peer)
- {
- BIO * out = BIO_new(BIO_s_mem());
- unsigned char * data;
- unsigned char * text;
- int n;
-
- X509_print(out,peer);
-
- n = BIO_get_mem_data(out, &data);
- text = (unsigned char *) malloc (n+1);
- text[n] ='\0';
- memcpy(text,data,n);
-
- trace_dsn(hSession,"TLS/SSL peer certificate:\n%s\n",text);
-
- free(text);
- BIO_free(out);
- X509_free(peer);
-
- }
- }
-
- if(!SSL_get_verify_result(hSession->ssl_con))
- set_ssl_state(hSession,LIB3270_SSL_SECURE);
-
- /* Tell the world that we are (still) connected, now in secure mode. */
- lib3270_set_connected(hSession);
- return 0;
-}
-#endif // HAVE_LIBSSL
-
static int net_connected(H3270 *hSession)
{
if(hSession->proxy_type > 0)
@@ -1627,6 +1483,29 @@ static int telnet_fsm(H3270 *hSession, unsigned char c)
return 0;
}
+/**
+ * Process a STARTTLS subnegotiation.
+ */
+static void continue_tls(H3270 *hSession, unsigned char *sbbuf, int len)
+{
+ /* Whatever happens, we're not expecting another SB STARTTLS. */
+ hSession->need_tls_follows = 0;
+
+ /* Make sure the option is FOLLOWS. */
+ if (len < 2 || sbbuf[1] != TLS_FOLLOWS)
+ {
+ /* Trace the junk. */
+ trace_dsn(hSession,"%s ? %s\n", opt(TELOPT_STARTTLS), cmd(SE));
+ popup_an_error(hSession,_( "TLS negotiation failure"));
+ net_disconnect(hSession);
+ return;
+ }
+
+ /* Trace what we got. */
+ trace_dsn(hSession,"%s FOLLOWS %s\n", opt(TELOPT_STARTTLS), cmd(SE));
+ ssl_negotiate(hSession);
+}
+
#if defined(X3270_TN3270E) /*[*/
/* Send a TN3270E terminal type request. */
static void tn3270e_request(H3270 *hSession)
@@ -3127,237 +3006,6 @@ parse_ctlchar(char *s)
}
#endif /*]*/
-/*
- * Set blocking/non-blocking mode on the socket. On error, pops up an error
- * message, but does not close the socket.
- */
-static int non_blocking(H3270 *session, Boolean on)
-{
-# if defined(FIONBIO)
-
- int i = on ? 1 : 0;
-
- if (SOCK_IOCTL(session->sock, FIONBIO, (int *) &i) < 0)
- {
- popup_a_sockerr(session,N_( "Error in ioctl(%s) when setting no blocking mode" ), "FIONBIO");
- return -1;
- }
-
-#else
-
- int f;
-
- if ((f = fcntl(session->sock, F_GETFL, 0)) == -1)
- {
- popup_an_errno(session,errno, _( "Error in fcntl(%s) when setting non blocking mode" ), "F_GETFL" );
- return -1;
- }
-
- if (on)
- f |= O_NDELAY;
- else
- f &= ~O_NDELAY;
-
- if (fcntl(session->sock, F_SETFL, f) < 0)
- {
- popup_an_errno(session,errno, _( "Error in fcntl(%s) when setting non blocking mode" ), "F_SETFL");
- return -1;
- }
-
-#endif // FIONBIO
-
- trace("Socket %d is %s",session->sock, on ? "non-blocking" : "blocking");
-
- return 0;
-}
-
-#if defined(HAVE_LIBSSL) /*[*/
-
-/* Initialize the OpenSSL library. */
-static void ssl_init(H3270 *session)
-{
- static SSL_CTX *ssl_ctx = NULL;
-
- session->ssl_error = 0;
- set_ssl_state(session,LIB3270_SSL_UNDEFINED);
-
- if(ssl_ctx == NULL)
- {
- lib3270_write_log(session,"SSL","%s","Initializing SSL context");
- SSL_load_error_strings();
- SSL_library_init();
- ssl_ctx = SSL_CTX_new(SSLv23_method());
- if(ssl_ctx == NULL)
- {
- popup_an_error(session,"SSL_CTX_new failed");
- session->ssl_host = False;
- return;
- }
- SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL);
- SSL_CTX_set_info_callback(ssl_ctx, ssl_info_callback);
- SSL_CTX_set_default_verify_paths(ssl_ctx);
-
-#if defined(_WIN32)
- {
- HKEY hKey = 0;
-
- if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\" PACKAGE_NAME,0,KEY_QUERY_VALUE,&hKey) == ERROR_SUCCESS)
- {
- char data[4096];
- unsigned long datalen = sizeof(data); // data field length(in), data returned length(out)
- unsigned long datatype; // #defined in winnt.h (predefined types 0-11)
-
- if(RegQueryValueExA(hKey,"datadir",NULL,&datatype,(LPBYTE) data,&datalen) == ERROR_SUCCESS)
- {
- strncat(data,"\\certs",4095);
-
- trace("Loading certs from \"%s\"",data);
- SSL_CTX_load_verify_locations(ssl_ctx,NULL,data);
- }
- RegCloseKey(hKey);
- }
-
-
- }
-
-#endif // _WIN32
-
- ssl_3270_ex_index = SSL_get_ex_new_index(0,NULL,NULL,NULL,NULL);
-
-
- }
-
- if(session->ssl_con)
- SSL_free(session->ssl_con);
-
- session->ssl_con = SSL_new(ssl_ctx);
- if(session->ssl_con == NULL)
- {
- popup_an_error(session,"SSL_new failed");
- session->ssl_host = False;
- return;
- }
-
- SSL_set_ex_data(session->ssl_con,ssl_3270_ex_index,(char *) session);
-
-// SSL_set_verify(session->ssl_con, SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
- SSL_set_verify(session->ssl_con, 0, NULL);
-
-}
-
-/* Callback for tracing protocol negotiation. */
-static void ssl_info_callback(INFO_CONST SSL *s, int where, int ret)
-{
-// H3270 *hSession = lib3270_get_default_session_handle(); // TODO: Find a better way!
- H3270 *hSession = (H3270 *) SSL_get_ex_data(s,ssl_3270_ex_index);
-
-#ifdef DEBUG
- trace("%s: hsession=%p, session=%p",__FUNCTION__,hSession,lib3270_get_default_session_handle());
- if(hSession != lib3270_get_default_session_handle())
- exit(-1);
-#endif // DEBUG
-
- switch(where)
- {
- case SSL_CB_CONNECT_LOOP:
- trace_dsn(hSession,"SSL_connect: %s %s\n",SSL_state_string(s), SSL_state_string_long(s));
- break;
-
- case SSL_CB_CONNECT_EXIT:
-
- trace_dsn(hSession,"%s: SSL_CB_CONNECT_EXIT\n",__FUNCTION__);
-
- if (ret == 0)
- {
- trace_dsn(hSession,"SSL_connect: failed in %s\n",SSL_state_string_long(s));
- }
- else if (ret < 0)
- {
- unsigned long e = ERR_get_error();
- char err_buf[1024];
-
- if(e != 0)
- {
- hSession->ssl_error = e;
- (void) ERR_error_string_n(e, err_buf, 1023);
- }
-#if defined(_WIN32)
- else if (GetLastError() != 0)
- {
- strncpy(err_buf,lib3270_win32_strerror(GetLastError()),1023);
- }
-#else
- else if (errno != 0)
- {
- strncpy(err_buf, strerror(errno),1023);
- }
-#endif
- else
- {
- err_buf[0] = '\0';
- }
-
- trace_dsn(hSession,"SSL Connect error %d\nMessage: %s\nState: %s\nAlert: %s\n",
- ret,
- err_buf,
- SSL_state_string_long(s),
- SSL_alert_type_string_long(ret)
- );
-
- }
-
-
- default:
- trace_dsn(hSession,"SSL Current state is \"%s\"\n",SSL_state_string_long(s));
- }
-
-// trace("%s: state=%04x where=%04x ret=%d",__FUNCTION__,SSL_state(s),where,ret);
-
-#ifdef DEBUG
- if(where & SSL_CB_EXIT)
- {
- trace("%s: SSL_CB_EXIT ret=%d\n",__FUNCTION__,ret);
- }
-#endif
-
- if(where & SSL_CB_ALERT)
- trace_dsn(hSession,"SSL ALERT: %s\n",SSL_alert_type_string_long(ret));
-
- if(where & SSL_CB_HANDSHAKE_DONE)
- {
- trace_dsn(hSession,"%s: SSL_CB_HANDSHAKE_DONE state=%04x\n",__FUNCTION__,SSL_state(s));
- if(SSL_state(s) == 0x03)
- set_ssl_state(hSession,LIB3270_SSL_NEGOTIATED);
- else
- set_ssl_state(hSession,LIB3270_SSL_UNSECURE);
- }
-}
-
-/**
- * Process a STARTTLS subnegotiation.
- */
-static void continue_tls(H3270 *hSession, unsigned char *sbbuf, int len)
-{
- /* Whatever happens, we're not expecting another SB STARTTLS. */
- hSession->need_tls_follows = 0;
-
- /* Make sure the option is FOLLOWS. */
- if (len < 2 || sbbuf[1] != TLS_FOLLOWS)
- {
- /* Trace the junk. */
- trace_dsn(hSession,"%s ? %s\n", opt(TELOPT_STARTTLS), cmd(SE));
- popup_an_error(hSession,_( "TLS negotiation failure"));
- net_disconnect(hSession);
- return;
- }
-
- /* Trace what we got. */
- trace_dsn(hSession,"%s FOLLOWS %s\n", opt(TELOPT_STARTTLS), cmd(SE));
- ssl_negotiate(hSession);
-}
-
-#endif /*]*/
-
/* Return the local address for the socket. */
int net_getsockname(const H3270 *session, void *buf, int *len)
{
@@ -3365,24 +3013,3 @@ int net_getsockname(const H3270 *session, void *buf, int *len)
return -1;
return getsockname(session->sock, buf, (socklen_t *)(void *)len);
}
-
-LIB3270_EXPORT LIB3270_SSL_STATE lib3270_get_secure(H3270 *session)
-{
- CHECK_SESSION_HANDLE(session);
- return session->secure;
-}
-
-LIB3270_EXPORT int lib3270_is_secure(H3270 *hSession)
-{
- return lib3270_get_secure(hSession) == LIB3270_SSL_SECURE;
-}
-
-LIB3270_EXPORT long lib3270_get_SSL_verify_result(H3270 *hSession)
-{
- CHECK_SESSION_HANDLE(hSession);
-#if defined(HAVE_LIBSSL)
- if(hSession->ssl_con)
- return SSL_get_verify_result(hSession->ssl_con);
-#endif // HAVE_LIBSSL
- return -1;
-}
diff --git a/testprogram.c b/testprogram.c
index f6e0e4e..a49f9d7 100644
--- a/testprogram.c
+++ b/testprogram.c
@@ -22,7 +22,7 @@ static void * mainloop(void *dunno)
int main(int numpar, char *param[])
{
H3270 * h;
- char line[4096];
+// char line[4096];
// pthread_t thread;
lib3270_initialize();
@@ -30,10 +30,13 @@ int main(int numpar, char *param[])
session = h = lib3270_session_new("");
printf("3270 session %p created\n]",h);
+ lib3270_set_toggle(session,LIB3270_TOGGLE_DS_TRACE,1);
+
// pthread_create(&thread, NULL, mainloop, NULL);
// pthread_detach(thread);
- lib3270_connect_host(h, "fandezhi.efglobe.com", "telnet");
+ lib3270_connect_host(h, "$HOST3270", "8023");
+// lib3270_connect_host(h, "fandezhi.efglobe.com", "telnet");
// lib3270_connect_host(h, "127.0.0.1", "9090");
mainloop(0);
--
libgit2 0.21.2