Return-Path: Delivered-To: apmail-httpd-cvs-archive@www.apache.org Received: (qmail 74836 invoked from network); 13 Jul 2004 19:31:01 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur-2.apache.org with SMTP; 13 Jul 2004 19:31:01 -0000 Received: (qmail 10070 invoked by uid 500); 13 Jul 2004 19:31:00 -0000 Delivered-To: apmail-httpd-cvs-archive@httpd.apache.org Received: (qmail 9885 invoked by uid 500); 13 Jul 2004 19:30:59 -0000 Mailing-List: contact cvs-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list cvs@httpd.apache.org Received: (qmail 9872 invoked by uid 500); 13 Jul 2004 19:30:59 -0000 Delivered-To: apmail-httpd-2.0-cvs@apache.org Received: (qmail 9869 invoked by uid 99); 13 Jul 2004 19:30:59 -0000 X-ASF-Spam-Status: No, hits=0.5 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.27.1) with SMTP; Tue, 13 Jul 2004 12:30:59 -0700 Received: (qmail 74803 invoked by uid 1285); 13 Jul 2004 19:30:58 -0000 Date: 13 Jul 2004 19:30:58 -0000 Message-ID: <20040713193058.74802.qmail@minotaur.apache.org> From: bnicholes@apache.org To: httpd-2.0-cvs@apache.org Subject: cvs commit: httpd-2.0/modules/arch/netware mod_nw_ssl.c X-Virus-Checked: Checked X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N bnicholes 2004/07/13 12:30:58 Modified: docs/manual/mod mod_nw_ssl.xml docs/manual/platform netware.xml modules/arch/netware mod_nw_ssl.c Log: Add the new directive NWSSLUpgradeable to mod_nw_ssl to allow a non-secure connection to be upgraded to secure connections Revision Changes Path 1.7 +16 -1 httpd-2.0/docs/manual/mod/mod_nw_ssl.xml Index: mod_nw_ssl.xml =================================================================== RCS file: /home/cvs/httpd-2.0/docs/manual/mod/mod_nw_ssl.xml,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- mod_nw_ssl.xml 17 Apr 2004 10:49:23 -0000 1.6 +++ mod_nw_ssl.xml 13 Jul 2004 19:30:58 -0000 1.7 @@ -62,4 +62,19 @@ + +NWSSLUpgradeable +Allows a connection to be upgraded to an SSL connection upon request +NWSSLUpgradeable [IP-address:]portnumber +server config + + +

Allow a connection that was created on the specified address + and/or port to be upgraded to an SSL connection upon request from + the client. The address and/or port must have already be defined + previously with a Listen + directive.

+
+
+ 1.12 +5 -1 httpd-2.0/docs/manual/platform/netware.xml Index: netware.xml =================================================================== RCS file: /home/cvs/httpd-2.0/docs/manual/platform/netware.xml,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- netware.xml 17 Apr 2004 11:18:04 -0000 1.11 +++ netware.xml 13 Jul 2004 19:30:58 -0000 1.12 @@ -413,6 +413,10 @@
  • NWSSLTrustedCerts - Adds trusted certificates that are used to create secure connections to proxied servers.
  • +
      +
    • NWSSLUpgradeable - + Allow a connection created on the specified address/port to be upgraded to an SSL connection.
    • +
    1.20 +319 -6 httpd-2.0/modules/arch/netware/mod_nw_ssl.c Index: mod_nw_ssl.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/arch/netware/mod_nw_ssl.c,v retrieving revision 1.19 retrieving revision 1.20 diff -u -r1.19 -r1.20 --- mod_nw_ssl.c 16 Mar 2004 02:49:15 -0000 1.19 +++ mod_nw_ssl.c 13 Jul 2004 19:30:58 -0000 1.20 @@ -48,6 +48,8 @@ #include "apr_portable.h" #include "apr_optional.h" +#include + #ifndef SO_TLS_UNCLEAN_SHUTDOWN #define SO_TLS_UNCLEAN_SHUTDOWN 0 #endif @@ -86,6 +88,7 @@ typedef struct NWSSLSrvConfigRec NWSSLSrvConfigRec; typedef struct seclisten_rec seclisten_rec; +typedef struct seclistenup_rec seclistenup_rec; struct seclisten_rec { seclisten_rec *next; @@ -95,11 +98,19 @@ char key[MAX_KEY]; int mutual; char *addr; - int port; + apr_port_t port; +}; + +struct seclistenup_rec { + seclistenup_rec *next; + char key[MAX_KEY]; + char *addr; + apr_port_t port; }; struct NWSSLSrvConfigRec { apr_table_t *sltable; + apr_table_t *slutable; apr_pool_t *pPool; }; @@ -107,6 +118,7 @@ static unicode_t** certarray = NULL; static int numcerts = 0; static seclisten_rec* ap_seclisteners = NULL; +static seclistenup_rec* ap_seclistenersup = NULL; #define get_nwssl_cfg(srv) (NWSSLSrvConfigRec *) ap_get_module_config(srv->module_config, &nwssl_module) @@ -195,6 +207,19 @@ return -1; } +static char *get_port_key(conn_rec *c) +{ + seclistenup_rec *sl; + + for (sl = ap_seclistenersup; sl; sl = sl->next) { + if ((sl->port == (c->local_addr)->port) && + ((strcmp(sl->addr, "0.0.0.0") == 0) || (strcmp(sl->addr, c->local_ip) == 0))) { + return sl->key; + } + } + return NULL; +} + static int make_secure_socket(apr_pool_t *pconf, const struct sockaddr_in *server, char* key, int mutual, server_rec *sconf) { @@ -338,6 +363,80 @@ return rcode; } +int SSLize_Socket(SOCKET socketHnd, char *key, request_rec *r) +{ + int rcode; + struct tlsserveropts sWS2Opts; + struct nwtlsopts sNWTLSOpts; + unicode_t SASKey[512]; + unsigned long ulFlag; + + memset((char *)&sWS2Opts, 0, sizeof(struct tlsserveropts)); + memset((char *)&sNWTLSOpts, 0, sizeof(struct nwtlsopts)); + + + ulFlag = SO_TLS_ENABLE; + rcode = WSAIoctl(socketHnd, SO_TLS_SET_FLAGS, &ulFlag, sizeof(unsigned long), NULL, 0, NULL, NULL, NULL); + if(rcode) + { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "Error: %d with WSAIoctl(SO_TLS_SET_FLAGS, SO_TLS_ENABLE)", WSAGetLastError()); + goto ERR; + } + + + ulFlag = SO_TLS_SERVER; + rcode = WSAIoctl(socketHnd, SO_TLS_SET_FLAGS, &ulFlag, sizeof(unsigned long),NULL, 0, NULL, NULL, NULL); + + if(rcode) + { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "Error: %d with WSAIoctl(SO_TLS_SET_FLAGS, SO_TLS_SERVER)", WSAGetLastError()); + goto ERR; + } + + loc2uni(UNI_LOCAL_DEFAULT, SASKey, key, 0, 0); + + //setup the tlsserveropts struct + sWS2Opts.wallet = SASKey; + sWS2Opts.walletlen = unilen(SASKey); + sWS2Opts.sidtimeout = 0; + sWS2Opts.sidentries = 0; + sWS2Opts.siddir = NULL; + sWS2Opts.options = &sNWTLSOpts; + + //setup the nwtlsopts structure + + sNWTLSOpts.walletProvider = WAL_PROV_KMO; + sNWTLSOpts.keysList = NULL; + sNWTLSOpts.numElementsInKeyList = 0; + sNWTLSOpts.reservedforfutureuse = NULL; + sNWTLSOpts.reservedforfutureCRL = NULL; + sNWTLSOpts.reservedforfutureCRLLen = NULL; + sNWTLSOpts.reserved1 = NULL; + sNWTLSOpts.reserved2 = NULL; + sNWTLSOpts.reserved3 = NULL; + + + rcode = WSAIoctl(socketHnd, + SO_TLS_SET_SERVER, + &sWS2Opts, + sizeof(struct tlsserveropts), + NULL, + 0, + NULL, + NULL, + NULL); + if(SOCKET_ERROR == rcode) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "Error: %d with WSAIoctl(SO_TLS_SET_SERVER)", WSAGetLastError()); + goto ERR; + } + +ERR: + return rcode; +} + static const char *set_secure_listener(cmd_parms *cmd, void *dummy, const char *ips, const char* key, const char* mutual) @@ -383,7 +482,7 @@ if (!port) return "Port must be numeric"; - apr_table_set(sc->sltable, ports, "T"); + apr_table_set(sc->sltable, ports, addr); new->local_addr.sin_port = htons(port); new->fd = -1; @@ -397,6 +496,57 @@ return NULL; } +static const char *set_secure_upgradeable_listener(cmd_parms *cmd, void *dummy, + const char *ips, const char* key) +{ + NWSSLSrvConfigRec* sc = get_nwssl_cfg(cmd->server); + seclistenup_rec *listen_node; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + char *ports, *addr; + unsigned short port; + seclistenup_rec *new; + + if (err != NULL) + return err; + + ports = strchr(ips, ':'); + + if (ports != NULL) { + if (ports == ips) + return "Missing IP address"; + else if (ports[1] == '\0') + return "Address must end in :"; + + *(ports++) = '\0'; + } + else { + ports = (char*)ips; + } + + if (ports == ips) { + addr = apr_pstrdup(cmd->pool, "0.0.0.0"); + } + else { + addr = apr_pstrdup(cmd->pool, ips); + } + + port = atoi(ports); + + if (!port) + return "Port must be numeric"; + + apr_table_set(sc->slutable, ports, addr); + + new = apr_pcalloc(cmd->pool, sizeof(seclistenup_rec)); + new->next = ap_seclistenersup; + strcpy(new->key, key); + new->addr = addr; + new->port = port; + ap_seclistenersup = new; + + return err; +} + static apr_status_t nwssl_socket_cleanup(void *data) { ap_listen_rec* slr = (ap_listen_rec*)data; @@ -430,6 +580,7 @@ apr_pool_t *ptemp) { ap_seclisteners = NULL; + ap_seclistenersup = NULL; certlist = apr_array_make(pconf, 1, sizeof(char *)); return OK; @@ -441,6 +592,9 @@ if (apr_table_get(c->notes, "nwconv-ssl")) { convert_secure_socket(c, (apr_socket_t*)csd); } + else { + ap_set_module_config(c->conn_config, &nwssl_module, csd); + } return OK; } @@ -452,7 +606,9 @@ ap_listen_rec* lr; apr_socket_t* sd; apr_status_t status; - + seclistenup_rec *slu; + int found; + for (sl = ap_seclisteners; sl != NULL; sl = sl->next) { sl->fd = find_secure_listener(sl); @@ -488,6 +644,22 @@ return HTTP_INTERNAL_SERVER_ERROR; } } + + for (slu = ap_seclistenersup; slu; slu = slu->next) { + /* Check the listener list for a matching upgradeable listener */ + found = 0; + for (lr = ap_listeners; lr; lr = lr->next) { + if (slu->port == lr->bind_addr->port) { + found = 1; + break; + } + } + if (!found) { + ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, plog, + "No Listen directive found for upgradeable listener %s:%d", slu->addr, slu->port); + } + } + build_cert_list(pconf); return OK; @@ -497,6 +669,7 @@ { NWSSLSrvConfigRec *new = apr_palloc(p, sizeof(NWSSLSrvConfigRec)); new->sltable = apr_table_make(p, 5); + new->slutable = apr_table_make(p, 5); return new; } @@ -508,7 +681,7 @@ return merged; } -static int isSecureConn (const server_rec *s, const conn_rec *c) +static int isSecureConnEx (const server_rec *s, const conn_rec *c, const apr_table_t *t) { NWSSLSrvConfigRec *sc = get_nwssl_cfg(s); const char *s_secure = NULL; @@ -516,18 +689,38 @@ int ret = 0; itoa((c->local_addr)->port, port, 10); - s_secure = apr_table_get(sc->sltable, port); - if (s_secure) + s_secure = apr_table_get(t, port); + if (s_secure && + ((strcmp(s_secure, "0.0.0.0") == 0) || (strcmp(s_secure, c->local_ip) == 0))) ret = 1; return ret; } +static int isSecureConn (const server_rec *s, const conn_rec *c) +{ + NWSSLSrvConfigRec *sc = get_nwssl_cfg(s); + + return isSecureConnEx (s, c, sc->sltable); +} + +static int isSecureConnUpgradeable (const server_rec *s, const conn_rec *c) +{ + NWSSLSrvConfigRec *sc = get_nwssl_cfg(s); + + return isSecureConnEx (s, c, sc->slutable); +} + static int isSecure (const request_rec *r) { return isSecureConn (r->server, r->connection); } +static int isSecureUpgradeable (const request_rec *r) +{ + return isSecureConnUpgradeable (r->server, r->connection); +} + static int nwssl_hook_Fixup(request_rec *r) { int i; @@ -764,12 +957,129 @@ return (char *)result; } +static apr_status_t ssl_io_filter_Upgrade(ap_filter_t *f, + apr_bucket_brigade *bb) + +{ +#define SWITCH_STATUS_LINE "HTTP/1.1 101 Switching Protocols" +#define UPGRADE_HEADER "Upgrade: TLS/1.0, HTTP/1.1" +#define CONNECTION_HEADER "Connection: Upgrade" + const char *upgrade; + const char *connection; + apr_bucket_brigade *upgradebb; + request_rec *r = f->r; + apr_socket_t *csd = NULL; + char *key; + unicode_t keyFileName[512]; + int ret; + char *token_string; + char *token; + char *token_state; + + /* Just remove the filter, if it doesn't work the first time, it won't + * work at all for this request. + */ + ap_remove_output_filter(f); + + /* No need to ensure that this is a server with optional SSL, the filter + * is only inserted if that is true. + */ + + upgrade = apr_table_get(r->headers_in, "Upgrade"); + if (upgrade == NULL) { + return ap_pass_brigade(f->next, bb); + } + token_string = apr_pstrdup(r->pool,upgrade); + token = apr_strtok(token_string,", ",&token_state); + while (token && strcmp(token,"TLS/1.0")) { + apr_strtok(NULL,", ",&token_state); + } + // "Upgrade: TLS/1.0" header not found, don't do Upgrade + if (!token) { + return ap_pass_brigade(f->next, bb); + } + + connection = apr_table_get(r->headers_in, "Connection"); + token_string = apr_pstrdup(r->pool,connection); + token = apr_strtok(token_string,",",&token_state); + while (token && strcmp(token,"Upgrade")) { + apr_strtok(NULL,",",&token_state); + } + // "Connection: Upgrade" header not found, don't do Upgrade + if (!token) { + return ap_pass_brigade(f->next, bb); + } + + apr_table_unset(r->headers_out, "Upgrade"); + + if (r) { + csd = (apr_socket_t*)ap_get_module_config(r->connection->conn_config, &nwssl_module); + } + else { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "Unable to get upgradeable socket handle"); + return ap_pass_brigade(f->next, bb); + } + + + if (r->method_number == M_OPTIONS) { + apr_bucket *b = NULL; + /* This is a mandatory SSL upgrade. */ + + upgradebb = apr_brigade_create(r->pool, f->c->bucket_alloc); + + ap_fputstrs(f->next, upgradebb, SWITCH_STATUS_LINE, CRLF, + UPGRADE_HEADER, CRLF, CONNECTION_HEADER, CRLF, CRLF, NULL); + + b = apr_bucket_flush_create(f->c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(upgradebb, b); + ap_pass_brigade(f->next, upgradebb); + } + else { + /* This is optional, and should be configurable, for now don't bother + * doing anything. + */ + return ap_pass_brigade(f->next, bb); + } + + key = get_port_key(r->connection); + + if (csd && key) { + int sockdes; + apr_os_sock_get(&sockdes, csd); + + + ret = SSLize_Socket(sockdes, key, r); + } + else { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "Upgradeable socket handle not found"); + return ap_pass_brigade(f->next, bb); + } + + ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, + "Awaiting re-negotiation handshake"); + + return ap_pass_brigade(f->next, bb); +} + +static void ssl_hook_Insert_Filter(request_rec *r) +{ + NWSSLSrvConfigRec *sc = get_nwssl_cfg(r->server); + + if (isSecureUpgradeable (r)) { + ap_add_output_filter("UPGRADE_FILTER", NULL, r, r->connection); + } +} static const command_rec nwssl_module_cmds[] = { AP_INIT_TAKE23("SecureListen", set_secure_listener, NULL, RSRC_CONF, "specify an address and/or port with a key pair name.\n" "Optional third parameter of MUTUAL configures the port for mutual authentication."), + AP_INIT_TAKE2("NWSSLUpgradeable", set_secure_upgradeable_listener, NULL, RSRC_CONF, + "specify an address and/or port with a key pair name, that can be upgraded to an SSL connection.\n" + "The address and/or port must have already be defined using a Listen directive."), AP_INIT_ITERATE("NWSSLTrustedCerts", set_trusted_certs, NULL, RSRC_CONF, "Adds trusted certificates that are used to create secure connections to proxied servers"), {NULL} @@ -777,12 +1087,15 @@ static void register_hooks(apr_pool_t *p) { + ap_register_output_filter ("UPGRADE_FILTER", ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); + ap_hook_pre_config(nwssl_pre_config, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_pre_connection(nwssl_pre_connection, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_post_config(nwssl_post_config, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_fixups(nwssl_hook_Fixup, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_http_method(nwssl_hook_http_method, NULL,NULL, APR_HOOK_MIDDLE); ap_hook_default_port (nwssl_hook_default_port, NULL,NULL, APR_HOOK_MIDDLE); + ap_hook_insert_filter (ssl_hook_Insert_Filter, NULL,NULL, APR_HOOK_MIDDLE); APR_REGISTER_OPTIONAL_FN(ssl_is_https); APR_REGISTER_OPTIONAL_FN(ssl_var_lookup);