httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bnicho...@apache.org
Subject cvs commit: httpd-2.0/modules/arch/netware mod_nw_ssl.c
Date Wed, 14 Jul 2004 16:23:31 GMT
bnicholes    2004/07/14 09:23:30

  Modified:    modules/arch/netware Tag: APACHE_2_0_BRANCH 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
  No                   revision
  No                   revision
  1.7.2.11  +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.7.2.10
  retrieving revision 1.7.2.11
  diff -u -r1.7.2.10 -r1.7.2.11
  --- mod_nw_ssl.c	16 Mar 2004 03:09:59 -0000	1.7.2.10
  +++ mod_nw_ssl.c	14 Jul 2004 16:23:30 -0000	1.7.2.11
  @@ -48,6 +48,8 @@
   #include "apr_portable.h"
   #include "apr_optional.h"
   
  +#include <unilib.h>
  +
   #ifndef SO_TLS_UNCLEAN_SHUTDOWN
   #define SO_TLS_UNCLEAN_SHUTDOWN 0
   #endif
  @@ -82,6 +84,7 @@
   
   typedef struct NWSSLSrvConfigRec NWSSLSrvConfigRec;
   typedef struct seclisten_rec seclisten_rec;
  +typedef struct seclistenup_rec seclistenup_rec;
   
   struct seclisten_rec {
       seclisten_rec *next;
  @@ -91,11 +94,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;
   };
   
  @@ -103,6 +114,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)
   
  @@ -191,6 +203,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)
   {
  @@ -334,6 +359,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)
  @@ -379,7 +478,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;
  @@ -393,6 +492,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 :<port-number>";
  +	        
  +	    *(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;
  @@ -426,6 +576,7 @@
                            apr_pool_t *ptemp)
   {
       ap_seclisteners = NULL;
  +    ap_seclistenersup = NULL;
       certlist = apr_array_make(pconf, 1, sizeof(char *));
   
       return OK;
  @@ -437,6 +588,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;
   }
  @@ -448,7 +602,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);
   
  @@ -484,6 +640,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;
  @@ -493,6 +665,7 @@
   {
       NWSSLSrvConfigRec *new = apr_palloc(p, sizeof(NWSSLSrvConfigRec));
       new->sltable = apr_table_make(p, 5);
  +    new->slutable = apr_table_make(p, 5);
       return new;
   }
   
  @@ -504,7 +677,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;
  @@ -512,18 +685,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;
  @@ -760,12 +953,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}
  @@ -773,12 +1083,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_var_lookup);
       
  
  
  

Mime
View raw message