Hi list, attached is the announced patch to support ssl-enabled inter-box connections and various ssl specific (potential) bug fixes.
General changes: * supporing ssl-enabled connections between bearerbox and [smsbox|wapbox] * various additional ssl configuration checking * changed the status page to show also ssl-enabled connections (for details have a look in the ChangeLog section, as far as you have time :)) Could the SSL coders around have a review on this, please. If there are no objections, I will commit the patch to CVS in a coupld of hours. Stipe [EMAIL PROTECTED] ------------------------------------------------------------------- Wapme Systems AG Münsterstr. 248 40470 Düsseldorf Tel: +49-211-74845-0 Fax: +49-211-74845-299 E-Mail: [EMAIL PROTECTED] Internet: http://www.wapme-systems.de ------------------------------------------------------------------- wapme.net - wherever you are
diff -urN gateway/ChangeLog gateway-new/ChangeLog --- gateway/ChangeLog Thu Dec 20 15:46:29 2001 +++ gateway-new/ChangeLog Thu Dec 20 19:21:38 2001 @@ -1,3 +1,45 @@ +2001-12-20 Stipe Tolj <[EMAIL PROTECTED]> + * doc/userguide/userguide.xml: added documentation for the introduced + configuration directives "smsbox-port-ssl" and "wapbox-port-ssl" in + the core group. + * gw/bb_boxc.c: added parameters for calling ssl-enabled box connection + using boolean configuration directives "smsbox-port-ssl" for bearerbox + to smsbox communication and "wapbox-port-ssl" for bearerbox to wapbox + communication. Changed the way boxc_status() displays the current + status of kannel's boxes, including ssl information for internal conn. + * gw/bb_http.c: Commented out call to use_global_server_certkey_file() + within httpadmin_start(), this is now done globaly by conn_config_ssl(). + * gw/bearerbox.c: added checking in starter() if corresponding cert and + key files are specified in the conf file for ssl-enabled inter-box + connections. Changed the way the status is displayed. + * gw/shared.c: added OpenSSL version string within widely used + version_report_string(). Added information that established inter-box + connections are ssl-enabled if so. + * gw/shared.h: changed declaration of connect_to_bearerbox() to include + ssl flag. + * gw/smsbox.c: added handling for "smsbox-port-ssl" conf directive. + * gw/wapbox.c: added handling for "wapbox-port-ssl" conf directive. + * gwlib/cfg.def: added "smsbox-port-ssl" and "wapbox-port-ssl" to allow + boolean configuration of ssl-enabled internal box connections. + * gwlib/conn.c: changed the way ssl connections are established in + conn_wrap_fd() and checked. Fixes also a not previosly detected bug, + that causes non-ssl enabled connections on the same port as wanted + for ssl, hence SSL_accept() = -1 was not handled correctly. Fixed + a potential (non-reported) bug in conn_destroy() that causes errors + if we call unlocked_write() in case of ssl-enabled connection. + Added function conn_get_ssl() to return the corresponding pointer. + * gwlib/conn.h: included declaration of conn_config_ssl() and + conn_get_ssl(). + * gwlib/gwlib.h: added header file inlusion for ssl.h. + * gwlib/http.c: added information to display if HTTP clients are using + ssl to connect to an ssl-enabled HTTP server. + Fixed potential bug if client_create() is called, but the previous + ssl-enabled conn_wrap_fd() has failed, now we check. + * gwlib/http.h: added response code for HTTP_BAD_REQUEST. + * gwlib/ssl.c: added file to hold all ssl specific code. + * gwlib/ssl.h: added file for declaration of all code implemented + in ssl.c. + 2001-12-20: Andreas Fink <[EMAIL PROTECTED]> * gw/smsc_emi2.c: fixed a problem resulting in timing out at high load. *gw/bb_smscconn.c, gw/msg-decl.h, gw/smsbox.c: diff -urN gateway/doc/userguide/userguide.xml gateway-new/doc/userguide/userguide.xml --- gateway/doc/userguide/userguide.xml Thu Dec 20 15:46:30 2001 +++ gateway-new/doc/userguide/userguide.xml Thu Dec 20 16:47:28 2001 @@ -968,12 +968,34 @@ As with admin-port, this can be anything you want. Must be set if you want to handle any SMS traffic. </entry></row> + + <row><entry><literal>smsbox-port-ssl (o)</literal></entry> + <entry>bool</entry> + <entry valign=bottom> + If set to true, the smsbox connection module will be SSL-enabled. + Your smsboxes will have to connect using SSL to the bearerbox + then. This is used to secure communication between bearerbox + and smsboxes in case they are in seperate networks operated and + the TCP communication is not secured on a lower network layer. + Defaults to "no". + </entry></row> <row><entry><literal>wapbox-port (c)</literal></entry> <entry>port-number</entry> <entry valign=bottom> Like smsbox-port, but for wapbox-connections. If not set, Kannel cannot handle WAP traffic + </entry></row> + + <row><entry><literal>wapbox-port-ssl (o)</literal></entry> + <entry>bool</entry> + <entry valign=bottom> + If set to true, the wapbox connection module will be SSL-enabled. + Your wapboxes will have to connect using SSL to the bearerbox + then. This is used to secure communication between bearerbox + and wapboxes in case they are in seperate networks operated and + the TCP communication is not secured on a lower network layer. + Defaults to "no". </entry></row> <row><entry><literal>box-deny-ip</literal></entry> diff -urN gateway/gw/bb_boxc.c gateway-new/gw/bb_boxc.c --- gateway/gw/bb_boxc.c Fri Oct 19 02:44:21 2001 +++ gateway-new/gw/bb_boxc.c Thu Dec 20 18:11:30 2001 @@ -42,7 +42,9 @@ static List *smsbox_list = NULL; static long smsbox_port; +static int smsbox_port_ssl = 0; static long wapbox_port; +static int wapbox_port_ssl = 0; static Octstr *box_allow_ip; static Octstr *box_deny_ip; @@ -250,14 +252,14 @@ */ -static Boxc *boxc_create(int fd, Octstr *ip) +static Boxc *boxc_create(int fd, Octstr *ip, int ssl) { Boxc *boxc; boxc = gw_malloc(sizeof(Boxc)); boxc->is_wap = 0; boxc->load = 0; - boxc->conn = conn_wrap_fd(fd, 0); + boxc->conn = conn_wrap_fd(fd, ssl); boxc->id = boxid++; /* XXX MUTEX! fix later... */ boxc->client_ip = ip; boxc->alive = 1; @@ -280,7 +282,7 @@ -static Boxc *accept_boxc(int fd) +static Boxc *accept_boxc(int fd, int ssl) { Boxc *newconn; Octstr *ip; @@ -303,9 +305,20 @@ octstr_destroy(ip); return NULL; } - newconn = boxc_create(newfd, ip); + newconn = boxc_create(newfd, ip, ssl); - info(0, "Client connected from <%s>", octstr_get_cstr(ip)); + /* + * check if the SSL handshake was successfull, otherwise + * this is no valid box connection any more + */ + if (ssl && !conn_get_ssl(newconn->conn)) + return NULL; + + if (ssl) + info(0, "Client connected from <%s> using SSL", octstr_get_cstr(ip)); + else + info(0, "Client connected from <%s>", octstr_get_cstr(ip)); + /* XXX TODO: do the hand-shake, baby, yeah-yeah! */ @@ -322,7 +335,7 @@ list_add_producer(flow_threads); fd = (int)arg; - newconn = accept_boxc(fd); + newconn = accept_boxc(fd, smsbox_port_ssl); if (newconn == NULL) { list_remove_producer(flow_threads); return; @@ -363,7 +376,7 @@ list_add_producer(flow_threads); fd = (int)arg; - newconn = accept_boxc(fd); + newconn = accept_boxc(fd, wapbox_port_ssl); if (newconn == NULL) { list_remove_producer(flow_threads); return; @@ -721,6 +734,13 @@ error(0, "Missing smsbox-port variable, cannot start smsboxes"); return -1; } +#ifdef HAVE_LIBSSL + cfg_get_bool(&smsbox_port_ssl, grp, octstr_imm("smsbox-port-ssl")); +#endif /* HAVE_LIBSSL */ + + if (smsbox_port_ssl) + debug("bb", 0, "smsbox connection module is SSL-enabled"); + smsbox_list = list_create(); /* have a list of connections */ list_add_producer(outgoing_sms); @@ -761,6 +781,10 @@ error(0, "Missing wapbox-port variable, cannot start WAP"); return -1; } +#ifdef HAVE_LIBSSL + cfg_get_bool(&wapbox_port_ssl, grp, octstr_imm("wapbox-port-ssl")); +#endif /* HAVE_LIBSSL */ + box_allow_ip = cfg_get(grp, octstr_imm("box-allow-ip")); if (box_allow_ip == NULL) box_allow_ip = octstr_create(""); @@ -830,15 +854,28 @@ t = orig - bi->connect_time; if (status_type == BBSTATUS_XML) octstr_format_append(tmp, - "<box>\n\t\t<type>wapbox</type>\n\t\t<IP>%s</IP>\n\t\t<status>" - "on-line %ldd %ldh %ldm %lds</status>\n\t</box>\n", + "<box>\n\t\t<type>wapbox</type>\n\t\t<IP>%s</IP>\n" + "\t\t<status>on-line %ldd %ldh %ldm %lds</status>\n" + "\t\t<ssl>%s</ssl>\n\t</box>\n", octstr_get_cstr(bi->client_ip), - t/3600/24, t/3600%24, t/60%60, t%60); + t/3600/24, t/3600%24, t/60%60, t%60, +#ifdef HAVE_LIBSSL + conn_get_ssl(bi->conn) != NULL ? "yes" : "no" +#else + "not installed" +#endif + ); else octstr_format_append(tmp, - "%swapbox %s (on-line %ldd %ldh %ldm %lds)%s", + "%swapbox, IP %s (on-line %ldd %ldh %ldm %lds) %s %s", ws, octstr_get_cstr(bi->client_ip), - t/3600/24, t/3600%24, t/60%60, t%60, lb); + t/3600/24, t/3600%24, t/60%60, t%60, +#ifdef HAVE_LIBSSL + conn_get_ssl(bi->conn) != NULL ? "using SSL" : "", +#else + "", +#endif + lb); boxes++; } list_unlock(wapbox_list); @@ -851,14 +888,27 @@ continue; t = orig - bi->connect_time; if (status_type == BBSTATUS_XML) - octstr_format_append(tmp, "<box>\n\t\t<type>smsbox</type>\n\t\t<IP>%s</IP>\n\t\t<status>" - "on-line %ldd %ldh %ldm %lds</status>\n\t\t</box>", + octstr_format_append(tmp, +"<box>\n\t\t<type>smsbox</type>\n\t\t<IP>%s</IP>\n" + "\t\t<status>on-line %ldd %ldh %ldm %lds</status>\n" + "\t\t<ssl>%s</ssl>\n\t</box>", octstr_get_cstr(bi->client_ip), - t/3600/24, t/3600%24, t/60%60, t%60); + t/3600/24, t/3600%24, t/60%60, t%60, +#ifdef HAVE_LIBSSL + conn_get_ssl(bi->conn) != NULL ? "yes" : "no" +#else + "not installed" +#endif + ); else - octstr_format_append(tmp, "%ssmsbox %s (on-line %ldd %ldh %ldm %lds)%s", + octstr_format_append(tmp, "%ssmsbox, IP %s (on-line %ldd %ldh %ldm +%lds) %s %s", ws, octstr_get_cstr(bi->client_ip), - t/3600/24, t/3600%24, t/60%60, t%60, lb); + t/3600/24, t/3600%24, t/60%60, t%60, +#ifdef HAVE_LIBSSL + conn_get_ssl(bi->conn) != NULL ? "using SSL" : "", +#else + "", +#endif + lb); boxes++; } list_unlock(smsbox_list); diff -urN gateway/gw/bb_http.c gateway-new/gw/bb_http.c --- gateway/gw/bb_http.c Fri Oct 19 02:44:21 2001 +++ gateway-new/gw/bb_http.c Thu Dec 20 18:44:31 2001 @@ -316,10 +316,14 @@ ssl_server_cert_file = cfg_get(grp, octstr_imm("ssl-server-cert-file")); ssl_server_key_file = cfg_get(grp, octstr_imm("ssl-server-key-file")); if (ssl_server_cert_file != NULL && ssl_server_key_file != NULL) { + /* we are fine here, the following call is now in conn_config_ssl(), + * so there is no reason to do this twice. + use_global_server_certkey_file(ssl_server_cert_file, ssl_server_key_file); + */ } else if (ssl) { - panic(0, "You MUST specify cert and key files within core group for SSL!"); + panic(0, "You MUST specify cert and key files within core group for +SSL-enabled HTTP servers!"); } octstr_destroy(ssl_server_cert_file); diff -urN gateway/gw/bearerbox.c gateway-new/gw/bearerbox.c --- gateway/gw/bearerbox.c Thu Dec 6 16:22:53 2001 +++ gateway-new/gw/bearerbox.c Thu Dec 20 18:37:47 2001 @@ -273,7 +273,12 @@ CfgGroup *grp; Octstr *log, *val; long loglevel; - +#ifdef HAVE_LIBSSL + Octstr *ssl_server_cert_file; + Octstr *ssl_server_key_file; + int ssl_enabled = 0; +#endif /* HAVE_LIBSSL */ + grp = cfg_get_single_group(cfg, octstr_imm("core")); @@ -306,6 +311,27 @@ } conn_config_ssl (grp); + + /* + * Make sure we have "ssl-server-cert-file" and "ssl-server-key-file" specified + * in the core group since we need it to run SSL-enabled internal box + * connections configured via "smsbox-port-ssl = yes" and "wapbox-port-ssl = yes". + * Check only these, because for "admin-port-ssl" and "sendsms-port-ssl" for the + * SSL-enabled HTTP servers are probed within gw/bb_http.c:httpadmin_start() + */ +#ifdef HAVE_LIBSSL + ssl_server_cert_file = cfg_get(grp, octstr_imm("ssl-server-cert-file")); + ssl_server_key_file = cfg_get(grp, octstr_imm("ssl-server-key-file")); + if (ssl_server_cert_file != NULL && ssl_server_key_file != NULL) { + /* we are fine, at least files are specified in the configuration */ + } else { + cfg_get_bool(&ssl_enabled, grp, octstr_imm("smsbox-port-ssl")); + cfg_get_bool(&ssl_enabled, grp, octstr_imm("wapbox-port-ssl")); + if (ssl_enabled) { + panic(0, "You MUST specify cert and key files within core group for +SSL-enabled inter-box connections!"); + } + } +#endif /* HAVE_LIBSSL */ /* if all seems to be OK by the first glimpse, real start-up */ @@ -600,11 +626,11 @@ else s = "going down"; - version = version_report_string(""); + version = version_report_string("bearerbox"); if (status_type == BBSTATUS_HTML) { frmt = "%s</p>\n\n" - " <p>Status: uptime %ldd %ldh %ldm %lds, %s</p>\n\n" + " <p>Status: %s, uptime %ldd %ldh %ldm %lds</p>\n\n" " <p>WDP: received %ld (%ld queued), sent %ld " "(%ld queued)</p>\n\n" " <p>SMS: received %ld (%ld queued), sent %ld " @@ -612,7 +638,7 @@ footer = "<p>"; } else if (status_type == BBSTATUS_WML) { frmt = "%s</p>\n\n" - " <p>Status: uptime %ldd %ldh %ldm %lds, %s</p>\n\n" + " <p>Status: %s, uptime %ldd %ldh %ldm %lds</p>\n\n" " <p>WDP: received %ld (%ld queued)<br/>\n" " WDP: sent %ld (%ld queued)</p>\n\n" " <p>SMS: received %ld (%ld queued)<br/>\n" @@ -621,14 +647,14 @@ footer = "<p>"; } else if (status_type == BBSTATUS_XML) { frmt = "<version>%s</version>\n" - "<status>uptime %ldd %ldh %ldm %lds, %s</status>\n" + "<status>%s, uptime %ldd %ldh %ldm %lds</status>\n" "\t<wdp>\n\t\t<received><total>%ld</total><queued>%ld</queued></received>\n\t\t<sent><total>%ld" "</total><queued>%ld</queued></sent>\n\t</wdp>\n" "\t<sms>\n\t\t<received><total>%ld</total><queued>%ld</queued></received>\n\t\t<sent><total>%ld" "</total><queued>%ld</queued></sent>\n\t\t<storesize>%ld</storesize>\n\t</sms>\n"; footer = ""; } else { - frmt = "%s\n\nStatus: uptime %ldd %ldh %ldm %lds, %s\n\n" + frmt = "%s\n\nStatus: %s, uptime %ldd %ldh %ldm %lds\n\n" "WDP: received %ld (%ld queued), sent %ld (%ld queued)\n\n" "SMS: received %ld (%ld queued), sent %ld (%ld queued), " "store size %ld\n\n"; @@ -637,7 +663,7 @@ sprintf(buf, frmt, octstr_get_cstr(version), - t/3600/24, t/3600%24, t/60%60, t%60, s, + s, t/3600/24, t/3600%24, t/60%60, t%60, counter_value(incoming_wdp_counter), list_len(incoming_wdp) + boxc_incoming_wdp_queue(), counter_value(outgoing_wdp_counter), diff -urN gateway/gw/shared.c gateway-new/gw/shared.c --- gateway/gw/shared.c Thu Oct 11 18:18:33 2001 +++ gateway-new/gw/shared.c Thu Dec 20 16:47:28 2001 @@ -6,6 +6,9 @@ #include <sys/utsname.h> #include <xmlversion.h> +#ifdef HAVE_LIBSSL +#include <openssl/opensslv.h> +#endif #include "gwlib/gwlib.h" #include "shared.h" @@ -34,13 +37,19 @@ "System %s, release %s, version %s, machine %s.\n" "Hostname %s, IP %s.\n" "Libxml version %s.\n" - "Using %s malloc.\n", +#ifdef HAVE_LIBSSL + "Using %s.\n" +#endif + "Using %s malloc.\n", boxname, VERSION, u.sysname, u.release, u.version, u.machine, octstr_get_cstr(get_official_name()), octstr_get_cstr(get_official_ip()), LIBXML_VERSION_STRING, - octstr_get_cstr(gwmem_type())); +#ifdef HAVE_LIBSSL + OPENSSL_VERSION_TEXT, +#endif + octstr_get_cstr(gwmem_type())); } @@ -52,13 +61,23 @@ static Connection *bb_conn; -void connect_to_bearerbox(Octstr *host, int port, Octstr *our_host) +void connect_to_bearerbox(Octstr *host, int port, int ssl, Octstr *our_host) { +#ifdef HAVE_LIBSSL + if (ssl) + bb_conn = conn_open_ssl(host, port, NULL, our_host); + /* XXX add certkeyfile to be given to conn_open_ssl */ + else +#endif /* HAVE_LIBSSL */ bb_conn = conn_open_tcp(host, port, our_host); if (bb_conn == NULL) panic(0, "Couldn't connect to the bearerbox."); - info(0, "Connected to bearerbox at %s port %d.", - octstr_get_cstr(host), port); + if (ssl) + info(0, "Connected to bearerbox at %s port %d using SSL.", + octstr_get_cstr(host), port); + else + info(0, "Connected to bearerbox at %s port %d.", + octstr_get_cstr(host), port); } diff -urN gateway/gw/shared.h gateway-new/gw/shared.h --- gateway/gw/shared.h Mon Oct 8 20:43:04 2001 +++ gateway-new/gw/shared.h Thu Dec 20 16:47:28 2001 @@ -45,7 +45,7 @@ /* * Open a connection to the bearerbox. */ -void connect_to_bearerbox(Octstr *host, int port, Octstr *our_host); +void connect_to_bearerbox(Octstr *host, int port, int ssl, Octstr *our_host); /* diff -urN gateway/gw/smsbox.c gateway-new/gw/smsbox.c --- gateway/gw/smsbox.c Thu Dec 20 15:46:30 2001 +++ gateway-new/gw/smsbox.c Thu Dec 20 16:47:28 2001 @@ -36,6 +36,7 @@ static Cfg *cfg; static long bb_port; +static int bb_ssl = 0; static long sendsms_port = 0; static Octstr *bb_host; static char *pid_file; @@ -1894,6 +1895,7 @@ int ssl = 0; bb_port = BB_DEFAULT_SMSBOX_PORT; + bb_ssl = 0; bb_host = octstr_create(BB_DEFAULT_HOST); heartbeat_freq = BB_DEFAULT_HEARTBEAT; logfile = NULL; @@ -1908,6 +1910,9 @@ if (cfg_get_integer(&bb_port, grp, octstr_imm("smsbox-port")) == -1) panic(0, "Missing or bad 'smsbox-port' in core group"); +#ifdef HAVE_LIBSSL + cfg_get_bool(&bb_ssl, grp, octstr_imm("smsbox-port-ssl")); +#endif /* HAVE_LIBSSL */ cfg_get_integer(&http_proxy_port, grp, octstr_imm("http-proxy-port")); @@ -2077,7 +2082,7 @@ gwthread_create(obey_request_thread, NULL); gwthread_create(url_result_thread, NULL); - connect_to_bearerbox(bb_host, bb_port, NULL /* bb_our_host */); + connect_to_bearerbox(bb_host, bb_port, bb_ssl, NULL /* bb_our_host */); /* XXX add our_host if required */ heartbeat_thread = heartbeat_start(write_to_bearerbox, heartbeat_freq, diff -urN gateway/gw/wapbox.c gateway-new/gw/wapbox.c --- gateway/gw/wapbox.c Thu Dec 13 11:25:57 2001 +++ gateway-new/gw/wapbox.c Thu Dec 20 17:56:33 2001 @@ -38,6 +38,7 @@ static Octstr *bearerbox_host; static long bearerbox_port = BB_DEFAULT_WAPBOX_PORT; +static int bearerbox_ssl = 0; static long heartbeat_freq = BB_DEFAULT_HEARTBEAT; static long heartbeat_thread; static Counter *sequence_counter = NULL; @@ -78,6 +79,10 @@ if (cfg_get_integer(&bearerbox_port,grp,octstr_imm("wapbox-port")) == -1) panic(0, "No 'wapbox-port' in core group"); +#ifdef HAVE_LIBSSL + cfg_get_bool(&bearerbox_ssl, grp, octstr_imm("wapbox-port-ssl")); +#endif /* HAVE_LIBSSL */ + http_proxy_host = cfg_get(grp, octstr_imm("http-proxy-host")); http_proxy_port = -1; @@ -429,7 +434,7 @@ if (bearerbox_host == NULL) bearerbox_host = octstr_create(BB_DEFAULT_HOST); - connect_to_bearerbox(bearerbox_host, bearerbox_port, NULL + connect_to_bearerbox(bearerbox_host, bearerbox_port, bearerbox_ssl, NULL /* bearerbox_our_port */); wap_push_ota_bb_address_set(bearerbox_host); diff -urN gateway/gwlib/cfg.def gateway-new/gwlib/cfg.def --- gateway/gwlib/cfg.def Tue Dec 18 08:05:40 2001 +++ gateway-new/gwlib/cfg.def Thu Dec 20 16:47:28 2001 @@ -26,7 +26,9 @@ OCTSTR(admin-deny-ip) OCTSTR(admin-allow-ip) OCTSTR(smsbox-port) + OCTSTR(smsbox-port-ssl) OCTSTR(wapbox-port) + OCTSTR(wapbox-port-ssl) OCTSTR(box-deny-ip) OCTSTR(box-allow-ip) OCTSTR(udp-deny-ip) diff -urN gateway/gwlib/conn.c gateway-new/gwlib/conn.c --- gateway/gwlib/conn.c Thu Dec 13 11:59:24 2001 +++ gateway-new/gwlib/conn.c Thu Dec 20 19:31:55 2001 @@ -26,6 +26,7 @@ #ifdef HAVE_LIBSSL #include <openssl/ssl.h> +#include <openssl/err.h> SSL_CTX *global_ssl_context = NULL; SSL_CTX *global_server_ssl_context = NULL; @@ -423,6 +424,7 @@ { Connection *conn; unsigned long err; + int rc; if (socket_set_blocking(fd, 0) < 0) return NULL; @@ -461,14 +463,94 @@ BIO_set_nbio(SSL_get_wbio(conn->ssl), 0); conn->ssl_mutex = mutex_create(); - if (!SSL_accept(conn->ssl)) { - if ((err = ERR_get_error())) { - error(0, "SSL: Access failed: %.256s", ERR_error_string(err, NULL)); - } - error(0, "SSL: disconnected."); - SSL_free(conn->ssl); - goto error; - } + + /* + * now enter the SSL handshake phase + */ + + /* + * For non-blocking BIO we may return from SSL_accept(). In this + * case we check for SSL_get_error() = SSL_ERROR_WANT_[READ|WRITE] + * and loop the SSL_accept() until we have come through. + */ + while (((rc = SSL_accept(conn->ssl)) <= 0) && + ((SSL_get_error(conn->ssl, rc) == SSL_ERROR_WANT_READ) || + (SSL_get_error(conn->ssl, rc) == SSL_ERROR_WANT_WRITE))) + {} + + /* + * If SSL_accept() has failed then check which reason it may + * have been and log the error. + */ + if (rc <= 0) { + + if (SSL_get_error(conn->ssl, rc) == SSL_ERROR_ZERO_RETURN) { + /* + * The case where the connection was closed before any data + * was transferred. That's not a real error and can occur + * sporadically with some clients. + */ + warning(0, "SSL: handshake stopped: connection was closed"); + warning(0, "SSL: OpenSSL: %.256s", ERR_error_string(ERR_get_error(), +NULL)); + + SSL_set_shutdown(conn->ssl, SSL_RECEIVED_SHUTDOWN); + SSL_smart_shutdown(conn->ssl); + } + else if (ERR_GET_REASON(ERR_peek_error()) == SSL_R_HTTP_REQUEST) { + /* + * The case where OpenSSL has recognized a HTTP request: + * This means the client speaks plain HTTP on our HTTPS + * port. Hmmmm... At least for this error we can be more friendly + * and try to provide him with a HTML error page. We have only one + * problem: OpenSSL has already read some bytes from the HTTP + * request. So we have to skip the request line manually. + */ + char ca[2]; + int rv; + + warning(0, "SSL: handshake failed: HTTP spoken on HTTPS port"); + warning(0, "SSL: OpenSSL: %.256s", ERR_error_string(ERR_get_error(), +NULL)); + + /* first: skip the remaining bytes of the request line */ + do { + do { + rv = read(conn->fd, ca, 1); + } while (rv == -1 && errno == EINTR); + } while (rv > 0 && ca[0] != '\012' /*LF*/); + + /* second: kick away the SSL stuff */ + SSL_set_shutdown(conn->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); + SSL_smart_shutdown(conn->ssl); + + /* tell the user how to access using the HTTPS scheme */ + //SSL_http_hint(conn, HTTP_BAD_REQUEST); + } + else if (SSL_get_error(conn->ssl, rc) == SSL_ERROR_SYSCALL) { + if (errno > 0) + warning(0, "SSL: handshake interrupted by system (stop button +pressed in browser?!)"); + else + warning(0, "SSL: spurious handshake interrupt (one of OpenSSL +confusions?!)"); + error(0, "SSL: OpenSSL: %.256s", ERR_error_string(ERR_get_error(), +NULL)); + + SSL_set_shutdown(conn->ssl, SSL_RECEIVED_SHUTDOWN); + SSL_smart_shutdown(conn->ssl); + } + else { + /* + * ok, anything else is a fatal error + */ + warning(0, "SSL: handshake failed with fatal error"); + warning(0, "SSL: OpenSSL: %.256s", ERR_error_string(ERR_get_error(), +NULL)); + + SSL_set_shutdown(conn->ssl, SSL_RECEIVED_SHUTDOWN); + SSL_smart_shutdown(conn->ssl); + } + + warning(0, "SSL: disconnecting."); + goto error; + + } /* SSL error */ + } else { conn->ssl = NULL; conn->peer_certificate = NULL; @@ -497,8 +579,10 @@ fdset_unregister(conn->registered, conn->fd); if (conn->fd >= 0) { - /* Try to flush any remaining data */ - unlocked_write(conn); + /* Try to flush any remaining data, only in case this is + * not a SSL connection. Otherwise this crashes the bearerbox + * at least on the Cygwin platform + */ #ifdef HAVE_LIBSSL if (conn->ssl != NULL) { mutex_lock(conn->ssl_mutex); @@ -508,8 +592,11 @@ X509_free(conn->peer_certificate); mutex_unlock(conn->ssl_mutex); mutex_destroy(conn->ssl_mutex); - } + } + else #endif /* HAVE_LIBSSL */ + unlocked_write(conn); + ret = close(conn->fd); if (ret < 0) error(errno, "conn_destroy: error on close"); @@ -1188,8 +1275,7 @@ return preverify_ok; } -void -conn_config_ssl (CfgGroup *grp) +void conn_config_ssl (CfgGroup *grp) { Octstr *ssl_client_certkey_file = NULL; Octstr *ssl_server_cert_file = NULL; @@ -1240,10 +1326,17 @@ octstr_destroy(ssl_trusted_ca_file); } +SSL *conn_get_ssl(Connection *conn) +{ + if (conn != NULL) + return conn->ssl; + else + return NULL; +} + #else -void -conn_config_ssl (CfgGroup *grp) +void conn_config_ssl (CfgGroup *grp) { info(0, "SSL not supported, no SSL initialization done."); } diff -urN gateway/gwlib/conn.h gateway-new/gwlib/conn.h --- gateway/gwlib/conn.h Thu Dec 6 16:22:53 2001 +++ gateway-new/gwlib/conn.h Thu Dec 20 16:47:28 2001 @@ -197,6 +197,7 @@ #ifdef HAVE_LIBSSL #include <openssl/x509.h> +#include <openssl/ssl.h> /* Returns the SSL peer certificate for the given Connection or NULL * if none. @@ -230,4 +231,16 @@ * key matches with the certificate and will panic if it doesn't. */ void use_global_server_certkey_file(Octstr *certfile, Octstr *keyfile); + +/* Configures all global variables for client and server SSL mode + * from the values specified within the configuration file. + */ +void conn_config_ssl(CfgGroup *grp); + +/* Returns the pointer to the SSL structure of the Connection given. + * This should be used for determining if certain connections are + * SSL enabled outside of the scope of conn.c. + */ +SSL *conn_get_ssl(Connection *conn); + #endif /* HAVE_LIBSSL */ diff -urN gateway/gwlib/gwlib.h gateway-new/gwlib/gwlib.h --- gateway/gwlib/gwlib.h Fri Jan 26 16:18:07 2001 +++ gateway-new/gwlib/gwlib.h Thu Dec 20 16:47:28 2001 @@ -35,6 +35,7 @@ #include "counter.h" #include "charset.h" #include "conn.h" +#include "ssl.h" #include "parse.h" #include "protected.h" #include "accesslog.h" diff -urN gateway/gwlib/http.c gateway-new/gwlib/http.c --- gateway/gwlib/http.c Fri Oct 19 02:45:12 2001 +++ gateway-new/gwlib/http.c Thu Dec 20 16:47:28 2001 @@ -1370,6 +1370,12 @@ { HTTPClient *p; +#ifdef HAVE_LIBSSL + if (conn_get_ssl(conn)) + debug("gwlib.http", 0, "HTTP: Creating SSL-enabled HTTPClient for `%s', using +cipher '%s'.", + octstr_get_cstr(ip), SSL_get_cipher_version(conn_get_ssl(conn))); + else +#endif debug("gwlib.http", 0, "HTTP: Creating HTTPClient for `%s'.", octstr_get_cstr(ip)); p = gw_malloc(sizeof(*p)); @@ -1710,10 +1716,18 @@ ports[i] = -1; ssl[i] = 0; } else { - conn = conn_wrap_fd(fd, ssl[i]); - client = client_create(ports[i], conn, host_ip(addr)); - conn_register(conn, server_fdset, receive_request, - client); + /* + * Be aware that conn_wrap_fd() will return NULL if SSL handshake + * has failed, so we only client_create() if there is an conn. + */ + if ((conn = conn_wrap_fd(fd, ssl[i]))) { + client = client_create(ports[i], conn, host_ip(addr)); + conn_register(conn, server_fdset, receive_request, + client); + } else { + error(0, "HTTP: unsuccessfull SSL handshake for client `%s'", + octstr_get_cstr(host_ip(addr))); + } } } } diff -urN gateway/gwlib/http.h gateway-new/gwlib/http.h --- gateway/gwlib/http.h Fri Oct 19 02:45:12 2001 +++ gateway-new/gwlib/http.h Thu Dec 20 16:47:29 2001 @@ -92,6 +92,7 @@ HTTP_SEE_OTHER = 303, HTTP_NOT_MODIFIED = 304, HTTP_TEMPORARY_REDIRECT = 307, + HTTP_BAD_REQUEST = 400, HTTP_NOT_FOUND = 404, HTTP_REQUEST_ENTITY_TOO_LARGE = 413, HTTP_INTERNAL_SERVER_ERROR = 500, diff -urN gateway/gwlib/ssl.c gateway-new/gwlib/ssl.c --- gateway/gwlib/ssl.c Thu Jan 1 00:00:00 1970 +++ gateway-new/gwlib/ssl.c Thu Dec 20 20:08:32 2001 @@ -0,0 +1,41 @@ +/* + * ssl.c - implements SSL specific routines and types + * + * This file implements the secure socket layer (SSL) specific + * routines and types. + * + * This product includes software developed by Ralf S. Engelschall + * <[EMAIL PROTECTED]> for use in the mod_ssl project + * (http://www.modssl.org/). + * + * Stipe Tolj <[EMAIL PROTECTED]> + * for Kannel Project and Wapme Systems AG + */ + +#include "gwlib/gwlib.h" + +#ifdef HAVE_LIBSSL + +#include <openssl/ssl.h> + +int SSL_smart_shutdown(SSL *ssl) +{ + int i; + int rc; + + /* + * Repeat the calls, because SSL_shutdown internally dispatches through a + * little state machine. Usually only one or two interation should be + * needed, so we restrict the total number of restrictions in order to + * avoid process hangs in case the client played bad with the socket + * connection and OpenSSL cannot recognize it. + */ + rc = 0; + for (i = 0; i < 4 /* max 2x pending + 2x data = 4 */; i++) { + if ((rc = SSL_shutdown(ssl))) + break; + } + return rc; +} + +#endif /* HAVE_LIBSSL */ diff -urN gateway/gwlib/ssl.h gateway-new/gwlib/ssl.h --- gateway/gwlib/ssl.h Thu Jan 1 00:00:00 1970 +++ gateway-new/gwlib/ssl.h Thu Dec 20 20:09:03 2001 @@ -0,0 +1,15 @@ +/* + * ssl.h - declares SSL specific routines and types + * + * This file defines the secure socket layer (SSL) specific + * routines and types. + * + * Stipe Tolj <[EMAIL PROTECTED]> + * for Kannel Project and Wapme Systems AG + */ + +#ifdef HAVE_LIBSSL + +int SSL_smart_shutdown(SSL *ssl); + +#endif /* HAVE_LIBSSL */