diff --git a/src/include/lib3270.h b/src/include/lib3270.h index af079c5..5b0ed2b 100644 --- a/src/include/lib3270.h +++ b/src/include/lib3270.h @@ -138,7 +138,7 @@ { LIB3270_FLAG_BOXSOLID, /**< System available */ LIB3270_FLAG_UNDERA, /**< Control Unit STATUS */ - LIB3270_FLAG_SECURE, /**< Security status */ +// LIB3270_FLAG_SECURE, /**< Security status */ LIB3270_FLAG_TYPEAHEAD, LIB3270_FLAG_PRINTER, LIB3270_FLAG_REVERSE, @@ -213,6 +213,20 @@ /** + * SSL state + * + */ + typedef enum lib3270_ssl_state + { + LIB3270_SSL_UNSECURE, /**< No secure connection */ + LIB3270_SSL_SECURE, /**< Connection secure */ + LIB3270_SSL_NEGOTIATING, /**< Negotiating SSL */ + LIB3270_SSL_UNDEFINED /**< Undefined */ + } LIB3270_SSL_STATE; + + #define LIB3270_SSL_FAILED LIB3270_SSL_UNSECURE + + /** * Notification message types. * */ @@ -611,6 +625,9 @@ LIB3270_EXPORT int lib3270_in_tn3270e(H3270 *h); LIB3270_EXPORT int lib3270_in_e(H3270 *h); + LIB3270_EXPORT LIB3270_SSL_STATE lib3270_get_secure(H3270 *session); + + /** * Call non gui function. * diff --git a/src/include/lib3270/session.h b/src/include/lib3270/session.h index 9a63ec7..ebabdf8 100644 --- a/src/include/lib3270/session.h +++ b/src/include/lib3270/session.h @@ -71,7 +71,7 @@ unsigned short sz; /**< Struct size */ // Connection info - int secure_connection; +// int secure_connection; int sock; /**< Network socket */ int net_sock; LIB3270_CSTATE cstate; /**< Connection state */ @@ -81,6 +81,8 @@ int selected : 1; /**< Has selected region? */ int rectsel : 1; /**< Selected region is a rectangle ? */ + LIB3270_SSL_STATE secure; + struct lib3270_toggle toggle[LIB3270_TOGGLE_COUNT]; // Network & Termtype @@ -177,6 +179,7 @@ void (*update_connect)(H3270 *session, unsigned char connected); void (*update_model)(H3270 *session, const char *name, int model, int rows, int cols); void (*update_selection)(H3270 *session, int start, int end); + void (*update_ssl)(H3270 *session, LIB3270_SSL_STATE state); void (*set_timer)(H3270 *session, unsigned char on); void (*erase)(H3270 *session); diff --git a/src/lib3270/api.h b/src/lib3270/api.h index ff1e3fc..2fb7d6b 100644 --- a/src/lib3270/api.h +++ b/src/lib3270/api.h @@ -157,7 +157,7 @@ #define OIA_FLAG_BOXSOLID LIB3270_FLAG_BOXSOLID #define OIA_FLAG_UNDERA LIB3270_FLAG_UNDERA - #define OIA_FLAG_SECURE LIB3270_FLAG_SECURE +// #define OIA_FLAG_SECURE LIB3270_FLAG_SECURE #define OIA_FLAG_TYPEAHEAD LIB3270_FLAG_TYPEAHEAD #define OIA_FLAG_PRINTER LIB3270_FLAG_PRINTER #define OIA_FLAG_REVERSE LIB3270_FLAG_REVERSE @@ -356,7 +356,7 @@ LOCAL_EXTERN void Input_String(const unsigned char *str); LOCAL_EXTERN void screen_size(int *rows, int *cols); - #define query_secure_connection(h) lib3270_get_ssl_state(h) +// #define query_secure_connection(h) lib3270_get_ssl_state(h) #define lib3270_paste_string(str) lib3270_set_string(NULL,str) #define get_3270_terminal_size(h,r,c) lib3270_get_screen_size(h,r,c) diff --git a/src/lib3270/init.c b/src/lib3270/init.c index 8a8322b..308833f 100644 --- a/src/lib3270/init.c +++ b/src/lib3270/init.c @@ -118,6 +118,10 @@ static void message(H3270 *session, LIB3270_NOTIFY id , const char *title, const lib3270_write_log(session,"%s",text); } +static void update_ssl(H3270 *session, LIB3270_SSL_STATE state) +{ +} + static void lib3270_session_init(H3270 *hSession, const char *model) { int ovc, ovr; @@ -144,6 +148,7 @@ static void lib3270_session_init(H3270 *hSession, const char *model) hSession->update_selection = update_selection; hSession->cursor = set_cursor; hSession->message = message; + hSession->update_ssl = update_ssl; hSession->sock = -1; hSession->model_num = -1; diff --git a/src/lib3270/screen.c b/src/lib3270/screen.c index 843a6cf..d83186a 100644 --- a/src/lib3270/screen.c +++ b/src/lib3270/screen.c @@ -546,15 +546,19 @@ static void status_connect(H3270 *session, int connected, void *dunno) else id = LIB3270_STATUS_CONNECTED; -#if defined(HAVE_LIBSSL) /*[*/ +/* +#if defined(HAVE_LIBSSL) set_status(session,OIA_FLAG_SECURE,session->secure_connection); -#endif /*]*/ +#endif +*/ } else { set_status(session,OIA_FLAG_BOXSOLID,False); +/* set_status(session,OIA_FLAG_SECURE,False); +*/ id = LIB3270_STATUS_DISCONNECTED; } diff --git a/src/lib3270/telnet.c b/src/lib3270/telnet.c index c1e3a42..2530dff 100644 --- a/src/lib3270/telnet.c +++ b/src/lib3270/telnet.c @@ -351,8 +351,19 @@ static void output_possible(H3270 *session); #endif /*]*/ +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +void set_ssl_state(H3270 *session, LIB3270_SSL_STATE state) +{ + if(state == session->secure) + return; + + trace_dsn("SSL state changes to %d",(int) state); + trace("SSL state changes to %d",(int) state); + + session->update_ssl(session,session->secure = state); +} - #if defined(_WIN32) /*[*/ void sockstart(H3270 *session) { @@ -477,6 +488,8 @@ int net_connect(H3270 *session, const char *host, char *portname, Boolean ls, Bo #define close_fail { (void) SOCK_CLOSE(session->sock); session->sock = -1; return -1; } + set_ssl_state(session,LIB3270_SSL_UNSECURE); + #if defined(_WIN32) sockstart(session); #endif @@ -763,44 +776,49 @@ static void net_connected(H3270 *session) #if defined(HAVE_LIBSSL) /*[*/ /* Set up SSL. */ - if(session->ssl_host && !session->secure_connection) + if(session->ssl_con && session->secure == LIB3270_SSL_UNDEFINED) { int rc; + set_ssl_state(session,LIB3270_SSL_NEGOTIATING); + if (SSL_set_fd(session->ssl_con, session->sock) != 1) { trace_dsn("Can't set fd!\n"); popup_system_error(&h3270,_( "Connection failed" ), _( "Can't set SSL socket file descriptor" ), "%s", SSL_state_string_long(session->ssl_con)); + set_ssl_state(session,LIB3270_SSL_UNSECURE); } + else + { + non_blocking(False); + rc = SSL_connect(session->ssl_con); - non_blocking(False); - rc = SSL_connect(session->ssl_con); + if(rc != 1) + { + unsigned long e = ERR_get_error(); + const char * state = SSL_state_string_long(session->ssl_con); - if(rc != 1) - { - unsigned long e = ERR_get_error(); - const char * state = SSL_state_string_long(session->ssl_con); + trace_dsn("TLS/SSL tunneled connection failed with error %ld, rc=%d and state=%s",e,rc,state); - trace_dsn("TLS/SSL tunneled connection failed with error %ld, rc=%d and state=%s",e,rc,state); + host_disconnect(session,True); - host_disconnect(session,True); + if(e != session->last_ssl_error) + { + session->message( &h3270, + LIB3270_NOTIFY_ERROR, + _( "Connection failed" ), + _( "SSL negotiation failed" ), + state); + session->last_ssl_error = e; + } + return; - if(e != session->last_ssl_error) - { - session->message( &h3270, - LIB3270_NOTIFY_ERROR, - _( "Connection failed" ), - _( "SSL negotiation failed" ), - state); - session->last_ssl_error = e; } - return; - + non_blocking(True); } - non_blocking(True); - session->secure_connection = True; - trace_dsn("TLS/SSL tunneled connection complete. Connection is now secure.\n"); +// session->secure_connection = True; +// trace_dsn("TLS/SSL tunneled connection complete. Connection is now secure.\n"); /* Tell everyone else again. */ host_connected(session); @@ -897,18 +915,22 @@ static void output_possible(H3270 *session) */ void net_disconnect(void) { -#if defined(HAVE_LIBSSL) /*[*/ +#if defined(HAVE_LIBSSL) if (h3270.ssl_con != NULL) { SSL_shutdown(h3270.ssl_con); SSL_free(h3270.ssl_con); h3270.ssl_con = NULL; } - h3270.secure_connection = False; -#endif /*]*/ +#endif + + set_ssl_state(&h3270,LIB3270_SSL_UNSECURE); + if (CONNECTED) (void) shutdown(h3270.sock, 2); + (void) SOCK_CLOSE(h3270.sock); + h3270.sock = -1; trace_dsn("SENT disconnect\n"); @@ -3233,6 +3255,8 @@ static void ssl_init(H3270 *session) { static SSL_CTX *ssl_ctx = NULL; + set_ssl_state(session,LIB3270_SSL_UNDEFINED); + if(ssl_ctx == NULL) { lib3270_write_log(session,"%s","Initializing SSL context"); @@ -3293,6 +3317,9 @@ static void client_info_callback(INFO_CONST SSL *s, int where, int ret) break; case SSL_CB_CONNECT_EXIT: + + trace("%s: SSL_CB_CONNECT_EXIT",__FUNCTION__); + if (ret == 0) { trace_dsn("SSL_connect: failed in %s\n",SSL_state_string_long(s)); @@ -3349,6 +3376,15 @@ static void client_info_callback(INFO_CONST SSL *s, int where, int ret) if(where & SSL_CB_ALERT) lib3270_write_log(NULL,"SSL","ALERT: %s",SSL_alert_type_string_long(ret)); + + if(where & SSL_CB_HANDSHAKE_DONE) + { + trace("%s: SSL_CB_HANDSHAKE_DONE state=%04x",__FUNCTION__,SSL_state(s)); + if(SSL_state(s) == 0x03) + set_ssl_state(&h3270,LIB3270_SSL_SECURE); + else + set_ssl_state(&h3270,LIB3270_SSL_UNSECURE); + } } /* Process a STARTTLS subnegotiation. */ @@ -3406,10 +3442,10 @@ static void continue_tls(unsigned char *sbbuf, int len) return; } - h3270.secure_connection = True; +// h3270.secure_connection = True; /* Success. */ - trace_dsn("TLS/SSL negotiated connection complete. Connection is now secure.\n"); +// trace_dsn("TLS/SSL negotiated connection complete. Connection is now secure.\n"); /* Tell the world that we are (still) connected, now in secure mode. */ host_connected(&h3270); @@ -3455,6 +3491,13 @@ net_proxy_port(void) return NULL; } +LIB3270_EXPORT LIB3270_SSL_STATE lib3270_get_secure(H3270 *session) +{ + CHECK_SESSION_HANDLE(session); + return session->secure; +} + +/* LIB3270_EXPORT int lib3270_get_ssl_state(H3270 *h) { CHECK_SESSION_HANDLE(h); @@ -3465,6 +3508,7 @@ LIB3270_EXPORT int lib3270_get_ssl_state(H3270 *h) return 0; #endif } +*/ /* int Get3270Socket(void) diff --git a/src/pw3270/v3270/oia.c b/src/pw3270/v3270/oia.c index 978ea6a..c73cb50 100644 --- a/src/pw3270/v3270/oia.c +++ b/src/pw3270/v3270/oia.c @@ -306,18 +306,10 @@ void v3270_draw_ssl_status(cairo_t *cr, H3270 *host, struct v3270_metrics *metri { cairo_surface_t * icon; double sz = rect->width < rect->height ? rect->width : rect->height; - int idx = lib3270_get_ssl_state(host) ? 1 : 0; - - static const struct - { - unsigned short width; - unsigned short height; - unsigned char * bits; - } bitmap[] = - { - { unlocked_width, unlocked_height, unlocked_bits }, - { locked_width, locked_height, locked_bits }, - }; + int idx = 0; // lib3270_get_ssl_state(host) ? 1 : 0; + unsigned short width; + unsigned short height; + unsigned char * bits; #ifdef DEBUG cairo_set_source_rgb(cr,0.1,0.1,0.1); @@ -330,15 +322,42 @@ void v3270_draw_ssl_status(cairo_t *cr, H3270 *host, struct v3270_metrics *metri cairo_rectangle(cr, 0, 0, rect->width, rect->height); cairo_fill(cr); - gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_FOREGROUND); + switch(lib3270_get_secure(host)) + { + case LIB3270_SSL_UNSECURE: /**< No secure connection */ + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_FOREGROUND); + width = unlocked_width; + height = unlocked_height; + bits = (unsigned char *) unlocked_bits; + break; + + case LIB3270_SSL_SECURE: /**< Connection secure */ + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_FOREGROUND); + width = locked_width; + height = locked_height; + bits = (unsigned char *) locked_bits; + break; + + case LIB3270_SSL_NEGOTIATING: /**< Negotiating SSL */ + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_STATUS_WARNING); + width = locked_width; + height = locked_height; + bits = (unsigned char *) locked_bits; + break; + + default: + return; + + } + - icon = cairo_image_surface_create_for_data( (unsigned char *) bitmap[idx].bits, + icon = cairo_image_surface_create_for_data( bits, CAIRO_FORMAT_A1, - bitmap[idx].width,bitmap[idx].height, + width,height, cairo_format_stride_for_width(CAIRO_FORMAT_A1,locked_width)); - cairo_scale(cr, sz / ((double) bitmap[idx].width), - sz / ((double) bitmap[idx].height)); + cairo_scale(cr, sz / ((double) width), + sz / ((double) height)); cairo_mask_surface(cr,icon,(rect->width-sz)/2,(rect->height-sz)/2); @@ -985,6 +1004,22 @@ void v3270_stop_timer(GtkWidget *widget) } +void v3270_update_ssl(H3270 *session, LIB3270_SSL_STATE state) +{ + v3270 * terminal = GTK_V3270(session->widget); + cairo_t * cr; + GdkRectangle * r; + + if(!terminal->surface) + return; + + cr = set_update_region(terminal,&r,V3270_OIA_SSL); + v3270_draw_ssl_status(cr,terminal->host,&terminal->metrics,terminal->color,r); + gtk_widget_queue_draw_area(GTK_WIDGET(terminal),r->x,r->y,r->width,r->height); + cairo_destroy(cr); + +} + void v3270_update_oia(H3270 *session, LIB3270_FLAG id, unsigned char on) { cairo_t *cr; @@ -1011,12 +1046,14 @@ void v3270_update_oia(H3270 *session, LIB3270_FLAG id, unsigned char on) cairo_destroy(cr); break; +/* case LIB3270_FLAG_SECURE: cr = set_update_region(terminal,&r,V3270_OIA_SSL); v3270_draw_ssl_status(cr,terminal->host,&terminal->metrics,terminal->color,r); gtk_widget_queue_draw_area(GTK_WIDGET(terminal),r->x,r->y,r->width,r->height); cairo_destroy(cr); break; +*/ case LIB3270_FLAG_TYPEAHEAD: update_text_field(terminal,on,V3270_OIA_TYPEAHEAD,"T"); diff --git a/src/pw3270/v3270/private.h b/src/pw3270/v3270/private.h index a4fe1fc..3eb067e 100644 --- a/src/pw3270/v3270/private.h +++ b/src/pw3270/v3270/private.h @@ -224,6 +224,7 @@ void v3270_update_luname(GtkWidget *widget,const gchar *name); void v3270_update_message(v3270 *widget, LIB3270_MESSAGE id); void v3270_update_cursor(H3270 *session, unsigned short row, unsigned short col, unsigned char c, unsigned short attr); void v3270_update_oia(H3270 *session, LIB3270_FLAG id, unsigned char on); +void v3270_update_ssl(H3270 *session, LIB3270_SSL_STATE state); // Keyboard & Mouse gboolean v3270_key_press_event(GtkWidget *widget, GdkEventKey *event); diff --git a/src/pw3270/v3270/widget.c b/src/pw3270/v3270/widget.c index 793efc5..eb8e782 100644 --- a/src/pw3270/v3270/widget.c +++ b/src/pw3270/v3270/widget.c @@ -769,6 +769,7 @@ static void v3270_init(v3270 *widget) widget->host->changed = changed; widget->host->ctlr_done = ctlr_done; widget->host->message = message; + widget->host->update_ssl = v3270_update_ssl; // Setup input method widget->input_method = gtk_im_multicontext_new(); -- libgit2 0.21.2