You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@apache.org on 2002/12/14 08:46:46 UTC

cvs commit: httpd-2.0/modules/ssl mod_ssl.c mod_ssl.h ssl_engine_config.c ssl_engine_init.c ssl_engine_io.c ssl_engine_kernel.c ssl_util.c

wrowe       2002/12/13 23:46:46

  Modified:    modules/ssl mod_ssl.c mod_ssl.h ssl_engine_config.c
                        ssl_engine_init.c ssl_engine_io.c
                        ssl_engine_kernel.c ssl_util.c
  Log:
    After some productive feedback and no negative feedback, introduce
    SSLEngine upgrade so that we can begin and continue to support these
    facilities.  This makes it simpler to keep this effort (while we have
    no known clients that support Connection: upgrade at this time), and
    begin refactoring more of SSL into smaller and tighter (and then optional)
    components.
  
  Revision  Changes    Path
  1.75      +54 -30    httpd-2.0/modules/ssl/mod_ssl.c
  
  Index: mod_ssl.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/ssl/mod_ssl.c,v
  retrieving revision 1.74
  retrieving revision 1.75
  diff -u -r1.74 -r1.75
  --- mod_ssl.c	5 Nov 2002 20:47:01 -0000	1.74
  +++ mod_ssl.c	14 Dec 2002 07:46:45 -0000	1.75
  @@ -105,7 +105,7 @@
       /*
        * Per-server context configuration directives
        */
  -    SSL_CMD_SRV(Engine, FLAG,
  +    SSL_CMD_SRV(Engine, TAKE1,
                   "SSL switch for the protocol engine "
                   "(`on', `off')")
       SSL_CMD_ALL(CipherSuite, TAKE1,
  @@ -274,7 +274,7 @@
       return 1;
   }
   
  -static int ssl_hook_pre_connection(conn_rec *c, void *csd)
  +int ssl_init_ssl_connection(conn_rec *c)
   {
       SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
       SSL *ssl;
  @@ -283,40 +283,14 @@
       modssl_ctx_t *mctx;
   
       /*
  -     * Immediately stop processing if SSL is disabled for this connection
  +     * Seed the Pseudo Random Number Generator (PRNG)
        */
  -    if (!(sc && (sc->enabled ||
  -                 (sslconn && sslconn->is_proxy))))
  -    {
  -        return DECLINED;
  -    }
  +    ssl_rand_seed(c->base_server, c->pool, SSL_RSCTX_CONNECT, "");
   
  -    /*
  -     * Create SSL context
  -     */
       if (!sslconn) {
           sslconn = ssl_init_connection_ctx(c);
       }
   
  -    if (sslconn->disabled) {
  -        return DECLINED;
  -    }
  -
  -    /*
  -     * Remember the connection information for
  -     * later access inside callback functions
  -     */
  -
  -    ap_log_error(APLOG_MARK, APLOG_INFO, 0, c->base_server,
  -                 "Connection to child %ld established "
  -                 "(server %s, client %s)", c->id, sc->vhost_id, 
  -                 c->remote_ip ? c->remote_ip : "unknown");
  -
  -    /*
  -     * Seed the Pseudo Random Number Generator (PRNG)
  -     */
  -    ssl_rand_seed(c->base_server, c->pool, SSL_RSCTX_CONNECT, "");
  -
       mctx = sslconn->is_proxy ? sc->proxy : sc->server;
   
       /*
  @@ -390,6 +364,54 @@
       return 443;
   }
   
  +static int ssl_hook_pre_connection(conn_rec *c, void *csd)
  +{
  +    SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
  +    SSLConnRec *sslconn = myConnConfig(c);
  +
  +    /*
  +     * Immediately stop processing if SSL is disabled for this connection
  +     */
  +    if (!(sc && (sc->enabled == TRUE ||
  +                 (sslconn && sslconn->is_proxy))))
  +    {
  +        return DECLINED;
  +    }
  +
  +    /*
  +     * Create SSL context
  +     */
  +    if (!sslconn) {
  +        sslconn = ssl_init_connection_ctx(c);
  +    }
  +
  +    if (sslconn->disabled) {
  +        return DECLINED;
  +    }
  +
  +    /*
  +     * Remember the connection information for
  +     * later access inside callback functions
  +     */
  +
  +    ap_log_error(APLOG_MARK, APLOG_INFO, 0, c->base_server,
  +                 "Connection to child %ld established "
  +                 "(server %s, client %s)", c->id, sc->vhost_id, 
  +                 c->remote_ip ? c->remote_ip : "unknown");
  +
  +    return ssl_init_ssl_connection(c);
  +}
  +
  +
  +static void ssl_hook_Insert_Filter(request_rec *r)
  +{
  +    SSLSrvConfigRec *sc = mySrvConfig(r->server);
  +
  +    if (sc->enabled == UNSET) {
  +        ap_add_output_filter("UPGRADE_FILTER", NULL, r, r->connection);
  +    }
  +}
  +
   /*
    *  the module registration phase
    */
  @@ -410,6 +432,8 @@
       ap_hook_access_checker(ssl_hook_Access,        NULL,NULL, APR_HOOK_MIDDLE);
       ap_hook_auth_checker  (ssl_hook_Auth,          NULL,NULL, APR_HOOK_MIDDLE);
       ap_hook_post_read_request(ssl_hook_ReadReq,    NULL,NULL, APR_HOOK_MIDDLE);
  +    ap_hook_insert_filter (ssl_hook_Insert_Filter, NULL,NULL, APR_HOOK_MIDDLE);
  +/*    ap_hook_handler       (ssl_hook_Upgrade,       NULL,NULL, APR_HOOK_MIDDLE); */
   
       ssl_var_register();
   
  
  
  
  1.123     +4 -1      httpd-2.0/modules/ssl/mod_ssl.h
  
  Index: mod_ssl.h
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/ssl/mod_ssl.h,v
  retrieving revision 1.122
  retrieving revision 1.123
  diff -u -r1.122 -r1.123
  --- mod_ssl.h	5 Nov 2002 20:47:01 -0000	1.122
  +++ mod_ssl.h	14 Dec 2002 07:46:45 -0000	1.123
  @@ -541,7 +541,7 @@
   const char  *ssl_cmd_SSLPassPhraseDialog(cmd_parms *, void *, const char *);
   const char  *ssl_cmd_SSLCryptoDevice(cmd_parms *, void *, const char *);
   const char  *ssl_cmd_SSLRandomSeed(cmd_parms *, void *, const char *, const char *, const char *);
  -const char  *ssl_cmd_SSLEngine(cmd_parms *, void *, int);
  +const char  *ssl_cmd_SSLEngine(cmd_parms *, void *, const char *);
   const char  *ssl_cmd_SSLCipherSuite(cmd_parms *, void *, const char *);
   const char  *ssl_cmd_SSLCertificateFile(cmd_parms *, void *, const char *);
   const char  *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, void *, const char *);
  @@ -588,6 +588,7 @@
   int          ssl_hook_Access(request_rec *);
   int          ssl_hook_Fixup(request_rec *);
   int          ssl_hook_ReadReq(request_rec *);
  +int          ssl_hook_Upgrade(request_rec *);
   
   /*  OpenSSL callbacks */
   RSA         *ssl_callback_TmpRSA(SSL *, int, int);
  @@ -709,6 +710,8 @@
   char        *ssl_util_algotypestr(ssl_algo_t);
   char        *ssl_util_ptxtsub(apr_pool_t *, const char *, const char *, char *);
   void         ssl_util_thread_setup(apr_pool_t *);
  +int          ssl_init_ssl_connection(conn_rec *c);
  +
   
   #define APR_SHM_MAXSIZE (64 * 1024 * 1024)
   #endif /* __MOD_SSL_H__ */
  
  
  
  1.71      +15 -4     httpd-2.0/modules/ssl/ssl_engine_config.c
  
  Index: ssl_engine_config.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/ssl/ssl_engine_config.c,v
  retrieving revision 1.70
  retrieving revision 1.71
  diff -u -r1.70 -r1.71
  --- ssl_engine_config.c	22 Oct 2002 23:18:14 -0000	1.70
  +++ ssl_engine_config.c	14 Dec 2002 07:46:45 -0000	1.71
  @@ -205,7 +205,7 @@
       SSLSrvConfigRec *sc = apr_palloc(p, sizeof(*sc));
   
       sc->mc                     = NULL;
  -    sc->enabled                = UNSET;
  +    sc->enabled                = FALSE;
       sc->proxy_enabled          = UNSET;
       sc->vhost_id               = NULL;  /* set during module init */
       sc->vhost_id_len           = 0;     /* set during module init */
  @@ -581,13 +581,24 @@
       return NULL;
   }
   
  -const char *ssl_cmd_SSLEngine(cmd_parms *cmd, void *dcfg, int flag)
  +const char *ssl_cmd_SSLEngine(cmd_parms *cmd, void *dcfg, const char *arg)
   {
       SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
   
  -    sc->enabled = flag ? TRUE : FALSE;
  -
  +    if (!strcasecmp(arg, "On")) {
  +        sc->enabled = TRUE;
       return NULL;
  +    }
  +    else if (!strcasecmp(arg, "Off")) {
  +        sc->enabled = FALSE;
  +        return NULL;
  +    }
  +    else if (!strcasecmp(arg, "Optional")) {
  +        sc->enabled = UNSET;
  +        return NULL;
  +    }
  +
  +    return "Argument must be On, Off, or Optional";
   }
   
   const char *ssl_cmd_SSLCipherSuite(cmd_parms *cmd,
  
  
  
  1.107     +7 -2      httpd-2.0/modules/ssl/ssl_engine_init.c
  
  Index: ssl_engine_init.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/ssl/ssl_engine_init.c,v
  retrieving revision 1.106
  retrieving revision 1.107
  diff -u -r1.106 -r1.107
  --- ssl_engine_init.c	11 Nov 2002 13:16:17 -0000	1.106
  +++ ssl_engine_init.c	14 Dec 2002 07:46:45 -0000	1.107
  @@ -247,11 +247,13 @@
           sc->vhost_id = ssl_util_vhostid(p, s);
           sc->vhost_id_len = strlen(sc->vhost_id);
   
  +#if 0
  +       /* If sc->enabled is UNSET, then SSL is optional on this vhost  */
           /* Fix up stuff that may not have been set */
           if (sc->enabled == UNSET) {
               sc->enabled = FALSE;
           }
  -
  +#endif
           if (sc->proxy_enabled == UNSET) {
               sc->proxy_enabled = FALSE;
           }
  @@ -982,6 +984,9 @@
                                 apr_pool_t *ptemp,
                                 SSLSrvConfigRec *sc)
   {
  +    /* A bit of a hack, but initialize the server if SSL is optional or
  +     * not.
  +     */
       if (sc->enabled) {
           ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
                        "Configuring server for SSL protocol");
  @@ -1010,7 +1015,7 @@
       for (s = base_server; s; s = s->next) {
           sc = mySrvConfig(s);
   
  -        if (sc->enabled && (s->port == DEFAULT_HTTP_PORT)) {
  +        if ((sc->enabled == TRUE) && (s->port == DEFAULT_HTTP_PORT)) {
               ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
                            base_server,
                            "Init: (%s) You configured HTTPS(%d) "
  
  
  
  1.102     +88 -0     httpd-2.0/modules/ssl/ssl_engine_io.c
  
  Index: ssl_engine_io.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/ssl/ssl_engine_io.c,v
  retrieving revision 1.101
  retrieving revision 1.102
  diff -u -r1.101 -r1.102
  --- ssl_engine_io.c	23 Nov 2002 21:19:03 -0000	1.101
  +++ ssl_engine_io.c	14 Dec 2002 07:46:45 -0000	1.102
  @@ -1181,6 +1181,89 @@
       return APR_SUCCESS;
   }
   
  +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;
  +    SSLConnRec *sslconn;
  +    SSL *ssl;
  +
  +    /* 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);
  +    }
  +    connection = apr_table_get(r->headers_in, "Connection");
  +
  +    apr_table_unset(r->headers_out, "Upgrade");
  +
  +    /* XXX: I don't think the requirement that the client sends exactly 
  +     * "Connection: Upgrade" is correct; the only requirement here is 
  +     * on the client to send a  Connection header including the "upgrade" 
  +     * token.
  +     */
  +    if (strcmp(connection, "Upgrade") || strcmp(upgrade, "TLS/1.0")) {
  +        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);
  +    }
  +
  +    ssl_init_ssl_connection(f->c);
  +
  +    ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
  +                 "Awaiting re-negotiation handshake");
  +
  +    sslconn = myConnConfig(f->c);
  +    ssl = sslconn->ssl;
  +
  +    SSL_set_state(ssl, SSL_ST_ACCEPT);
  +    SSL_do_handshake(ssl);
  +
  +    if (SSL_get_state(ssl) != SSL_ST_OK) {
  +        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
  +                     "Re-negotiation handshake failed: "
  +                "Not accepted by client!?");
  +
  +        return AP_FILTER_ERROR;
  +    }
  +
  +    return OK;
  +}
  +
   static apr_status_t ssl_io_filter_input(ap_filter_t *f,
                                           apr_bucket_brigade *bb,
                                           ap_input_mode_t mode,
  @@ -1393,6 +1476,11 @@
   
   void ssl_io_filter_register(apr_pool_t *p)
   {
  +    /* This filter MUST be after the HTTP_HEADER filter, but it also must be
  +     * a resource-level filter so it has the request_rec.
  +     */
  +    ap_register_output_filter ("UPGRADE_FILTER", ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5);
  +
       ap_register_input_filter  (ssl_io_filter, ssl_io_filter_input,  NULL, AP_FTYPE_CONNECTION + 5);
       ap_register_output_filter (ssl_io_filter, ssl_io_filter_output, NULL, AP_FTYPE_CONNECTION + 5);
       return;
  
  
  
  1.83      +14 -0     httpd-2.0/modules/ssl/ssl_engine_kernel.c
  
  Index: ssl_engine_kernel.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/ssl/ssl_engine_kernel.c,v
  retrieving revision 1.82
  retrieving revision 1.83
  diff -u -r1.82 -r1.83
  --- ssl_engine_kernel.c	5 Nov 2002 20:47:01 -0000	1.82
  +++ ssl_engine_kernel.c	14 Dec 2002 07:46:45 -0000	1.83
  @@ -223,6 +223,16 @@
        * Support for SSLRequireSSL directive
        */
       if (dc->bSSLRequired && !ssl) {
  +        if (sc->enabled == UNSET) {
  +            /* This vhost was configured for optional SSL, just tell the
  +             * client that we need to upgrade.
  +             */
  +            apr_table_setn(r->err_headers_out, "Upgrade", "TLS/1.0, HTTP/1.1");
  +            apr_table_setn(r->err_headers_out, "Connection", "Upgrade");
  +
  +            return HTTP_UPGRADE_REQUIRED;
  +        }
  +
           ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 
                         "access to %s failed, reason: %s",
                         r->filename, "SSL connection required");
  @@ -1013,6 +1023,10 @@
       STACK_OF(X509) *peer_certs;
       SSL *ssl;
       int i;
  +
  +    if (sc->enabled == UNSET) {
  +        apr_table_setn(r->headers_out, "Upgrade", "TLS/1.0, HTTP/1.1");
  +    }
   
       /*
        * Check to see if SSL is on
  
  
  
  1.36      +1 -1      httpd-2.0/modules/ssl/ssl_util.c
  
  Index: ssl_util.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/ssl/ssl_util.c,v
  retrieving revision 1.35
  retrieving revision 1.36
  diff -u -r1.35 -r1.36
  --- ssl_util.c	14 Oct 2002 04:15:58 -0000	1.35
  +++ ssl_util.c	14 Dec 2002 07:46:45 -0000	1.36
  @@ -84,7 +84,7 @@
           port = s->port;
       else {
           sc = mySrvConfig(s);
  -        if (sc->enabled)
  +        if (sc->enabled == TRUE)
               port = DEFAULT_HTTPS_PORT;
           else
               port = DEFAULT_HTTP_PORT;