source: branches/fc11-dev/server/common/patches/httpd-2.2.x-sni.patch @ 1251

Last change on this file since 1251 was 1146, checked in by mitchb, 16 years ago
Version, context, etc. fixups to build Apache on Fedora 11
File size: 41.2 KB
  • httpd-2.2.11/modules/ssl/ssl_private.h

    http://sni.velox.ch/httpd-2.2.11-sni.20090427.patch - server name indication
    support for mod_ssl / Apache 2.2.11 (RFC 4366, section 3.1)
    
    Last updated 2009-04-27, by Kaspar Brand.
    Provided AS IS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND.
    
    Based on a patch from the EdelKey project (http://www.edelweb.fr/EdelKey/files/),
    includes further improvements by Ruediger Pluem (from httpd trunk).
    
    Needs openssl-SNAP-20060330 / OpenSSL 0.9.8f or later
    to work properly (ftp://ftp.openssl.org/snapshot/). OpenSSL versions
    prior to 0.9.8j must be configured explicitly for TLS extension support
    at compile time ("./config enable-tlsext").
    
     
    3535#include "http_connection.h"
    3636#include "http_request.h"
    3737#include "http_protocol.h"
     38#include "http_vhost.h"
    3839#include "util_script.h"
    3940#include "util_filter.h"
    4041#include "util_ebcdic.h"
    ap_set_module_config(c->conn_config, &ssl_module, 
    129130#define mySrvConfig(srv) (SSLSrvConfigRec *)ap_get_module_config(srv->module_config,  &ssl_module)
    130131#define myDirConfig(req) (SSLDirConfigRec *)ap_get_module_config(req->per_dir_config, &ssl_module)
    131132#define myModConfig(srv) (mySrvConfig((srv)))->mc
     133#define mySrvFromConn(c) (myConnConfig(c))->server
     134#define mySrvConfigFromConn(c) mySrvConfig(mySrvFromConn(c))
     135#define myModConfigFromConn(c) myModConfig(mySrvFromConn(c))
    132136
    133137#define myCtxVarSet(mc,num,val)  mc->rCtx.pV##num = val
    134138#define myCtxVarGet(mc,num,type) (type)(mc->rCtx.pV##num)
    typedef struct { 
    347351    int is_proxy;
    348352    int disabled;
    349353    int non_ssl_request;
     354    server_rec *server;
    350355} SSLConnRec;
    351356
    352357typedef struct {
    struct SSLSrvConfigRec { 
    449454    BOOL             cipher_server_pref;
    450455    modssl_ctx_t    *server;
    451456    modssl_ctx_t    *proxy;
     457#ifndef OPENSSL_NO_TLSEXT
     458    ssl_enabled_t    strict_sni_vhost_check;
     459#endif
    452460};
    453461
    454462/**
    const char *ssl_cmd_SSLOptions(cmd_parms *, void 
    513521const char  *ssl_cmd_SSLRequireSSL(cmd_parms *, void *);
    514522const char  *ssl_cmd_SSLRequire(cmd_parms *, void *, const char *);
    515523const char  *ssl_cmd_SSLUserName(cmd_parms *, void *, const char *);
     524#ifndef OPENSSL_NO_TLSEXT
     525const char  *ssl_cmd_SSLStrictSNIVHostCheck(cmd_parms *cmd, void *dcfg, int flag);
     526#endif
    516527
    517528const char  *ssl_cmd_SSLProxyEngine(cmd_parms *cmd, void *dcfg, int flag);
    518529const char  *ssl_cmd_SSLProxyProtocol(cmd_parms *, void *, const char *);
    int ssl_callback_NewSessionCacheEntry(SSL 
    555566SSL_SESSION *ssl_callback_GetSessionCacheEntry(SSL *, unsigned char *, int, int *);
    556567void         ssl_callback_DelSessionCacheEntry(SSL_CTX *, SSL_SESSION *);
    557568void         ssl_callback_LogTracingState(MODSSL_INFO_CB_ARG_TYPE, int, int);
     569#ifndef OPENSSL_NO_TLSEXT
     570int          ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *);
     571#endif
    558572
    559573/**  Session Cache Support  */
    560574void         ssl_scache_init(server_rec *, apr_pool_t *);
  • httpd-2.2.11/modules/ssl/ssl_engine_init.c

    static void ssl_init_server_check(server_rec *s, 
    358358    }
    359359}
    360360
     361#ifndef OPENSSL_NO_TLSEXT
     362static void ssl_init_ctx_tls_extensions(server_rec *s,
     363                                        apr_pool_t *p,
     364                                        apr_pool_t *ptemp,
     365                                        modssl_ctx_t *mctx)
     366{
     367    /*
     368     * Configure TLS extensions support
     369     */
     370    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
     371                 "Configuring TLS extension handling");
     372
     373    /*
     374     * Server name indication (SNI)
     375     */
     376    if (!SSL_CTX_set_tlsext_servername_callback(mctx->ssl_ctx,
     377                          ssl_callback_ServerNameIndication) ||
     378        !SSL_CTX_set_tlsext_servername_arg(mctx->ssl_ctx, mctx)) {
     379        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     380                     "Unable to initialize TLS servername extension "
     381                     "callback (incompatible OpenSSL version?)");
     382        ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
     383        ssl_die();
     384    }
     385}
     386#endif
     387
    361388static void ssl_init_ctx_protocol(server_rec *s,
    362389                                  apr_pool_t *p,
    363390                                  apr_pool_t *ptemp,
    static void ssl_init_ctx(server_rec *s, 
    690717    if (mctx->pks) {
    691718        /* XXX: proxy support? */
    692719        ssl_init_ctx_cert_chain(s, p, ptemp, mctx);
     720#ifndef OPENSSL_NO_TLSEXT
     721        ssl_init_ctx_tls_extensions(s, p, ptemp, mctx);
     722#endif
    693723    }
    694724}
    695725
    void ssl_init_CheckServers(server_rec *base_server 
    10391069        klen = strlen(key);
    10401070
    10411071        if ((ps = (server_rec *)apr_hash_get(table, key, klen))) {
    1042             ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
     1072            ap_log_error(APLOG_MARK,
     1073#ifdef OPENSSL_NO_TLSEXT
     1074                         APLOG_WARNING,
     1075#else
     1076                         APLOG_DEBUG,
     1077#endif
     1078                         0,
    10431079                         base_server,
     1080#ifdef OPENSSL_NO_TLSEXT
    10441081                         "Init: SSL server IP/port conflict: "
     1082#else
     1083                         "Init: SSL server IP/port overlap: "
     1084#endif
    10451085                         "%s (%s:%d) vs. %s (%s:%d)",
    10461086                         ssl_util_vhostid(p, s),
    10471087                         (s->defn_name ? s->defn_name : "unknown"),
    void ssl_init_CheckServers(server_rec *base_server 
    10581098
    10591099    if (conflict) {
    10601100        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server,
     1101#ifdef OPENSSL_NO_TLSEXT
    10611102                     "Init: You should not use name-based "
    10621103                     "virtual hosts in conjunction with SSL!!");
     1104#else
     1105                     "Init: Name-based SSL virtual hosts only "
     1106                     "work for clients with TLS server name indication "
     1107                     "support (RFC 4366)");
     1108#endif
    10631109    }
    10641110}
    10651111
  • httpd-2.2.11/modules/ssl/ssl_engine_config.c

    static SSLSrvConfigRec *ssl_config_server_new(apr_ 
    169169    sc->vhost_id_len           = 0;     /* set during module init */
    170170    sc->session_cache_timeout  = UNSET;
    171171    sc->cipher_server_pref     = UNSET;
     172#ifndef OPENSSL_NO_TLSEXT
     173    sc->strict_sni_vhost_check = SSL_ENABLED_UNSET;
     174#endif
    172175
    173176    modssl_ctx_init_proxy(sc, p);
    174177
    void *ssl_config_server_merge(apr_pool_t *p, void 
    257260    cfgMergeBool(proxy_enabled);
    258261    cfgMergeInt(session_cache_timeout);
    259262    cfgMergeBool(cipher_server_pref);
     263#ifndef OPENSSL_NO_TLSEXT
     264    cfgMerge(strict_sni_vhost_check, SSL_ENABLED_UNSET);
     265#endif
    260266
    261267    modssl_ctx_cfg_merge_proxy(base->proxy, add->proxy, mrg->proxy);
    262268
    const char *ssl_cmd_SSLUserName(cmd_parms *cmd, vo 
    14111417    return NULL;
    14121418}
    14131419
     1420#ifndef OPENSSL_NO_TLSEXT
     1421const char  *ssl_cmd_SSLStrictSNIVHostCheck(cmd_parms *cmd, void *dcfg, int flag)
     1422{
     1423    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
     1424
     1425    sc->strict_sni_vhost_check = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE;
     1426
     1427    return NULL;
     1428}
     1429#endif
     1430
    14141431void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s)
    14151432{
    14161433    if (!ap_exists_config_define("DUMP_CERTS")) {
  • httpd-2.2.11/modules/ssl/ssl_engine_io.c

    static apr_status_t ssl_io_input_read(bio_filter_i 
    695695                 */
    696696                ap_log_cerror(APLOG_MARK, APLOG_INFO, inctx->rc, c,
    697697                              "SSL library error %d reading data", ssl_err);
    698                 ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, c->base_server);
     698                ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, mySrvFromConn(c));
    699699
    700700            }
    701701            if (inctx->rc == APR_SUCCESS) {
    static apr_status_t ssl_filter_write(ap_filter_t * 
    799799             */
    800800            ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c,
    801801                          "SSL library error %d writing data", ssl_err);
    802             ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, c->base_server);
     802            ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, mySrvFromConn(c));
    803803        }
    804804        if (outctx->rc == APR_SUCCESS) {
    805805            outctx->rc = APR_EGENERAL;
    static apr_status_t ssl_io_filter_error(ap_filter_ 
    861861            ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, f->c,
    862862                         "SSL handshake failed: HTTP spoken on HTTPS port; "
    863863                         "trying to send HTML error page");
    864             ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, f->c->base_server);
     864            ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, sslconn->server);
    865865
    866866            sslconn->non_ssl_request = 1;
    867867            ssl_io_filter_disable(sslconn, f);
    static apr_status_t ssl_filter_io_shutdown(ssl_fil 
    971971    SSL_smart_shutdown(ssl);
    972972
    973973    /* and finally log the fact that we've closed the connection */
    974     if (c->base_server->loglevel >= APLOG_INFO) {
     974    if (mySrvFromConn(c)->loglevel >= APLOG_INFO) {
    975975        ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c,
    976976                      "Connection closed to child %ld with %s shutdown "
    977977                      "(server %s)",
    978                       c->id, type, ssl_util_vhostid(c->pool, c->base_server));
     978                      c->id, type, ssl_util_vhostid(c->pool, mySrvFromConn(c)));
    979979    }
    980980
    981981    /* deallocate the SSL connection */
    static int ssl_io_filter_connect(ssl_filter_ctx_t 
    10211021{
    10221022    conn_rec *c         = (conn_rec *)SSL_get_app_data(filter_ctx->pssl);
    10231023    SSLConnRec *sslconn = myConnConfig(c);
    1024     SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
     1024    SSLSrvConfigRec *sc;
    10251025    X509 *cert;
    10261026    int n;
    10271027    int ssl_err;
    10281028    long verify_result;
     1029    server_rec *server;
    10291030
    10301031    if (SSL_is_init_finished(filter_ctx->pssl)) {
    10311032        return APR_SUCCESS;
    10321033    }
    10331034
     1035    server = mySrvFromConn(c);
    10341036    if (sslconn->is_proxy) {
    10351037        if ((n = SSL_connect(filter_ctx->pssl)) <= 0) {
    10361038            ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c,
    10371039                          "SSL Proxy connect failed");
    1038             ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, c->base_server);
     1040            ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, server);
    10391041            /* ensure that the SSL structures etc are freed, etc: */
    10401042            ssl_filter_io_shutdown(filter_ctx, c, 1);
    10411043            return HTTP_BAD_GATEWAY;
    static int ssl_io_filter_connect(ssl_filter_ctx_t 
    10921094            ap_log_cerror(APLOG_MARK, APLOG_INFO, rc, c,
    10931095                          "SSL library error %d in handshake "
    10941096                          "(server %s)", ssl_err,
    1095                           ssl_util_vhostid(c->pool, c->base_server));
    1096             ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, c->base_server);
     1097                          ssl_util_vhostid(c->pool, server));
     1098            ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, server);
    10971099
    10981100        }
    10991101        if (inctx->rc == APR_SUCCESS) {
    static int ssl_io_filter_connect(ssl_filter_ctx_t 
    11021104
    11031105        return ssl_filter_io_shutdown(filter_ctx, c, 1);
    11041106    }
     1107    sc = mySrvConfig(sslconn->server);
    11051108
    11061109    /*
    11071110     * Check for failed client authentication
    static int ssl_io_filter_connect(ssl_filter_ctx_t 
    11271130                          "accepting certificate based on "
    11281131                          "\"SSLVerifyClient optional_no_ca\" "
    11291132                          "configuration");
    1130             ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, c->base_server);
     1133            ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, server);
    11311134        }
    11321135        else {
    11331136            const char *error = sslconn->verify_error ?
    static int ssl_io_filter_connect(ssl_filter_ctx_t 
    11371140            ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c,
    11381141                         "SSL client authentication failed: %s",
    11391142                         error ? error : "unknown");
    1140             ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, c->base_server);
     1143            ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, server);
    11411144
    11421145            return ssl_filter_io_shutdown(filter_ctx, c, 1);
    11431146        }
    long ssl_io_data_cb(BIO *bio, int cmd, 
    18091812        return rc;
    18101813    if ((c = (conn_rec *)SSL_get_app_data(ssl)) == NULL)
    18111814        return rc;
    1812     s = c->base_server;
     1815    s = mySrvFromConn(c);
    18131816
    18141817    if (   cmd == (BIO_CB_WRITE|BIO_CB_RETURN)
    18151818        || cmd == (BIO_CB_READ |BIO_CB_RETURN) ) {
  • httpd-2.2.11/modules/ssl/ssl_engine_vars.c

    static char *ssl_var_lookup_ssl(apr_pool_t *p, con 
    320320    else if (ssl != NULL && strcEQ(var, "COMPRESS_METHOD")) {
    321321        result = ssl_var_lookup_ssl_compress_meth(ssl);
    322322    }
     323#ifndef OPENSSL_NO_TLSEXT
     324    else if (ssl != NULL && strcEQ(var, "TLS_SNI")) {
     325        result = apr_pstrdup(p, SSL_get_servername(ssl,
     326                                                   TLSEXT_NAMETYPE_host_name));
     327    }
     328#endif
    323329    return result;
    324330}
    325331
    static char *ssl_var_lookup_ssl_cert_verify(apr_po 
    589595    vrc   = SSL_get_verify_result(ssl);
    590596    xs    = SSL_get_peer_certificate(ssl);
    591597
    592     if (vrc == X509_V_OK && verr == NULL && vinfo == NULL && xs == NULL)
     598    if (vrc == X509_V_OK && verr == NULL && xs == NULL)
    593599        /* no client verification done at all */
    594600        result = "NONE";
    595601    else if (vrc == X509_V_OK && verr == NULL && vinfo == NULL && xs != NULL)
  • httpd-2.2.11/modules/ssl/ssl_engine_kernel.c

     
    3131#include "ssl_private.h"
    3232
    3333static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
     34#ifndef OPENSSL_NO_TLSEXT
     35static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s);
     36#endif
    3437
    3538/*
    3639 *  Post Read Request Handler
    int ssl_hook_ReadReq(request_rec *r) 
    3942{
    4043    SSLConnRec *sslconn = myConnConfig(r->connection);
    4144    SSL *ssl;
     45#ifndef OPENSSL_NO_TLSEXT
     46    const char *servername;
     47#endif
    4248
    4349    if (!sslconn) {
    4450        return DECLINED;
    int ssl_hook_ReadReq(request_rec *r) 
    8793    if (!ssl) {
    8894        return DECLINED;
    8995    }
     96#ifndef OPENSSL_NO_TLSEXT
     97    if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
     98        char *host, *scope_id;
     99        apr_port_t port;
     100        apr_status_t rv;
     101
     102        /*
     103         * The SNI extension supplied a hostname. So don't accept requests
     104         * with either no hostname or a different hostname.
     105         */
     106        if (!r->hostname) {
     107            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
     108                        "Hostname %s provided via SNI, but no hostname"
     109                        " provided in HTTP request", servername);
     110            return HTTP_BAD_REQUEST;
     111        }
     112        rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool);
     113        if (rv != APR_SUCCESS || scope_id) {
     114            return HTTP_BAD_REQUEST;
     115        }
     116        if (strcmp(host, servername)) {
     117            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
     118                        "Hostname %s provided via SNI and hostname %s provided"
     119                        " via HTTP are different", servername, host);
     120            return HTTP_BAD_REQUEST;
     121        }
     122    }
     123    else if ((((mySrvConfig(r->server))->strict_sni_vhost_check
     124                == SSL_ENABLED_TRUE)
     125             || (mySrvConfig(sslconn->server))->strict_sni_vhost_check
     126                == SSL_ENABLED_TRUE)
     127             && r->connection->vhost_lookup_data) {
     128        /*
     129         * We are using a name based configuration here, but no hostname was
     130         * provided via SNI. Don't allow that if are requested to do strict
     131         * checking. Check whether this strict checking was setup either in the
     132         * server config we used for handshaking or in our current server.
     133         * This should avoid insecure configuration by accident.
     134         */
     135        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
     136                     "No hostname was provided via SNI for a name based"
     137                     " virtual host");
     138        return HTTP_FORBIDDEN;
     139    }
     140#endif
    90141    SSL_set_app_data2(ssl, r);
    91142
    92143    /*
    static void ssl_configure_env(request_rec *r, SSLC 
    155206 */
    156207int ssl_hook_Access(request_rec *r)
    157208{
    158     SSLDirConfigRec *dc = myDirConfig(r);
    159     SSLSrvConfigRec *sc = mySrvConfig(r->server);
    160     SSLConnRec *sslconn = myConnConfig(r->connection);
    161     SSL *ssl            = sslconn ? sslconn->ssl : NULL;
     209    SSLDirConfigRec *dc         = myDirConfig(r);
     210    SSLSrvConfigRec *sc         = mySrvConfig(r->server);
     211    SSLConnRec *sslconn         = myConnConfig(r->connection);
     212    SSL *ssl                    = sslconn ? sslconn->ssl : NULL;
     213    server_rec *handshakeserver = sslconn ? sslconn->server : NULL;
    162214    SSL_CTX *ctx = NULL;
    163215    apr_array_header_t *requires;
    164216    ssl_require_t *ssl_requires;
    int ssl_hook_Access(request_rec *r) 
    252304     *   has to enable this via ``SSLOptions +OptRenegotiate''. So we do no
    253305     *   implicit optimizations.
    254306     */
    255     if (dc->szCipherSuite) {
     307    if (dc->szCipherSuite || (r->server != handshakeserver)) {
    256308        /* remember old state */
    257309
    258310        if (dc->nOptions & SSL_OPT_OPTRENEGOTIATE) {
    int ssl_hook_Access(request_rec *r) 
    267319        }
    268320
    269321        /* configure new state */
    270         if (!modssl_set_cipher_list(ssl, dc->szCipherSuite)) {
     322        if ((dc->szCipherSuite || sc->server->auth.cipher_suite) &&
     323            !modssl_set_cipher_list(ssl, dc->szCipherSuite ?
     324                                         dc->szCipherSuite :
     325                                         sc->server->auth.cipher_suite)) {
    271326            ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
    272327                         r->server,
    273328                         "Unable to reconfigure (per-directory) "
    int ssl_hook_Access(request_rec *r) 
    334389            sk_SSL_CIPHER_free(cipher_list_old);
    335390        }
    336391
    337         /* tracing */
    338392        if (renegotiate) {
     393#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
     394            if (sc->cipher_server_pref == TRUE) {
     395                SSL_set_options(ssl, SSL_OP_CIPHER_SERVER_PREFERENCE);
     396            }
     397#endif
     398            /* tracing */
    339399            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
    340400                         "Reconfigured cipher suite will force renegotiation");
    341401        }
    int ssl_hook_Access(request_rec *r) 
    348408     * function and not by OpenSSL internally (and our function is aware of
    349409     * both the per-server and per-directory contexts). So we cannot ask
    350410     * OpenSSL about the currently verify depth. Instead we remember it in our
    351      * ap_ctx attached to the SSL* of OpenSSL.  We've to force the
     411     * SSLConnRec attached to the SSL* of OpenSSL.  We've to force the
    352412     * renegotiation if the reconfigured/new verify depth is less than the
    353413     * currently active/remembered verify depth (because this means more
    354414     * restriction on the certificate chain).
    355415     */
    356     if (dc->nVerifyDepth != UNSET) {
    357         /* XXX: doesnt look like sslconn->verify_depth is actually used */
    358         if (!(n = sslconn->verify_depth)) {
    359             sslconn->verify_depth = n = sc->server->auth.verify_depth;
    360         }
    361 
    362         /* determine whether a renegotiation has to be forced */
    363         if (dc->nVerifyDepth < n) {
    364             renegotiate = TRUE;
    365             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
    366                          "Reduced client verification depth will force "
    367                          "renegotiation");
    368         }
     416    n = sslconn->verify_depth ?
     417        sslconn->verify_depth :
     418        (mySrvConfig(handshakeserver))->server->auth.verify_depth;
     419    /* determine the new depth */
     420    sslconn->verify_depth = (dc->nVerifyDepth != UNSET) ?
     421                            dc->nVerifyDepth : sc->server->auth.verify_depth;
     422    if (sslconn->verify_depth < n) {
     423        renegotiate = TRUE;
     424        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
     425                     "Reduced client verification depth will force "
     426                     "renegotiation");
    369427    }
    370428
    371429    /*
    int ssl_hook_Access(request_rec *r) 
    382440     * verification but at least skip the I/O-intensive renegotation
    383441     * handshake.
    384442     */
    385     if (dc->nVerifyClient != SSL_CVERIFY_UNSET) {
     443    if ((dc->nVerifyClient != SSL_CVERIFY_UNSET) ||
     444        (sc->server->auth.verify_mode != SSL_CVERIFY_UNSET)) {
    386445        /* remember old state */
    387446        verify_old = SSL_get_verify_mode(ssl);
    388447        /* configure new state */
    389448        verify = SSL_VERIFY_NONE;
    390449
    391         if (dc->nVerifyClient == SSL_CVERIFY_REQUIRE) {
     450        if ((dc->nVerifyClient == SSL_CVERIFY_REQUIRE) ||
     451            (sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE)) {
    392452            verify |= SSL_VERIFY_PEER_STRICT;
    393453        }
    394454
    395455        if ((dc->nVerifyClient == SSL_CVERIFY_OPTIONAL) ||
    396             (dc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA))
     456            (dc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA) ||
     457            (sc->server->auth.verify_mode == SSL_CVERIFY_OPTIONAL) ||
     458            (sc->server->auth.verify_mode == SSL_CVERIFY_OPTIONAL_NO_CA))
    397459        {
    398460            verify |= SSL_VERIFY_PEER;
    399461        }
    int ssl_hook_Access(request_rec *r) 
    430492                             renegotiate_quick ? "quick " : "");
    431493             }
    432494        }
     495        /* If we're handling a request for a vhost other than the default one,
     496         * then we need to make sure that client authentication is properly
     497         * enforced. For clients supplying an SNI extension, the peer
     498         * certificate verification has happened in the handshake already
     499         * (and r->server == handshakeserver). For non-SNI requests,
     500         * an additional check is needed here. If client authentication
     501         * is configured as mandatory, then we can only proceed if the
     502         * CA list doesn't have to be changed (OpenSSL doesn't provide
     503         * an option to change the list for an existing session).
     504         */
     505        if ((r->server != handshakeserver)
     506            && renegotiate
     507            && ((verify & SSL_VERIFY_PEER) ||
     508                (verify & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))) {
     509            SSLSrvConfigRec *hssc = mySrvConfig(handshakeserver);
     510
     511#define MODSSL_CFG_CA_NE(f, sc1, sc2) \
     512            (sc1->server->auth.f && \
     513             (!sc2->server->auth.f || \
     514              strNE(sc1->server->auth.f, sc2->server->auth.f)))
     515
     516            if (MODSSL_CFG_CA_NE(ca_cert_file, sc, hssc) ||
     517                MODSSL_CFG_CA_NE(ca_cert_path, sc, hssc)) {
     518                if (verify & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
     519                    ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
     520                         "Non-default virtual host with SSLVerify set to "
     521                         "'require' and VirtualHost-specific CA certificate "
     522                         "list is only available to clients with TLS server "
     523                         "name indication (SNI) support");
     524                    modssl_set_verify(ssl, verify_old, NULL);
     525                    return HTTP_FORBIDDEN;
     526                } else
     527                    /* let it pass, possibly with an "incorrect" peer cert,
     528                     * so make sure the SSL_CLIENT_VERIFY environment variable
     529                     * will indicate partial success only, later on.
     530                     */
     531                    sslconn->verify_info = "GENEROUS";
     532            }
     533        }
    433534    }
    434535
    435536    /*
    int ssl_hook_Access(request_rec *r) 
    666767        /*
    667768         * Finally check for acceptable renegotiation results
    668769         */
    669         if (dc->nVerifyClient != SSL_CVERIFY_NONE) {
    670             BOOL do_verify = (dc->nVerifyClient == SSL_CVERIFY_REQUIRE);
     770        if ((dc->nVerifyClient != SSL_CVERIFY_NONE) ||
     771            (sc->server->auth.verify_mode != SSL_CVERIFY_NONE)) {
     772            BOOL do_verify = ((dc->nVerifyClient == SSL_CVERIFY_REQUIRE) ||
     773                              (sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE));
    671774
    672775            if (do_verify && (SSL_get_verify_result(ssl) != X509_V_OK)) {
    673776                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
    int ssl_hook_Fixup(request_rec *r) 
    9971100    SSLDirConfigRec *dc = myDirConfig(r);
    9981101    apr_table_t *env = r->subprocess_env;
    9991102    char *var, *val = "";
     1103#ifndef OPENSSL_NO_TLSEXT
     1104    const char *servername;
     1105#endif
    10001106    STACK_OF(X509) *peer_certs;
    10011107    SSL *ssl;
    10021108    int i;
    int ssl_hook_Fixup(request_rec *r) 
    10181124    /* the always present HTTPS (=HTTP over SSL) flag! */
    10191125    apr_table_setn(env, "HTTPS", "on");
    10201126
     1127#ifndef OPENSSL_NO_TLSEXT
     1128    /* add content of SNI TLS extension (if supplied with ClientHello) */
     1129    if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
     1130        apr_table_set(env, "SSL_TLS_SNI", servername);
     1131    }
     1132#endif
     1133
    10211134    /* standard SSL environment variables */
    10221135    if (dc->nOptions & SSL_OPT_STDENVVARS) {
    10231136        for (i = 0; ssl_hook_Fixup_vars[i]; i++) {
    int ssl_hook_Fixup(request_rec *r) 
    11051218RSA *ssl_callback_TmpRSA(SSL *ssl, int export, int keylen)
    11061219{
    11071220    conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
    1108     SSLModConfigRec *mc = myModConfig(c->base_server);
     1221    SSLModConfigRec *mc = myModConfigFromConn(c);
    11091222    int idx;
    11101223
    11111224    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
    RSA *ssl_callback_TmpRSA(SSL *ssl, int export, int 
    11371250DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen)
    11381251{
    11391252    conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
    1140     SSLModConfigRec *mc = myModConfig(c->base_server);
     1253    SSLModConfigRec *mc = myModConfigFromConn(c);
    11411254    int idx;
    11421255
    11431256    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
    int ssl_callback_SSLVerify(int ok, X509_STORE_CTX 
    11661279    SSL *ssl = X509_STORE_CTX_get_ex_data(ctx,
    11671280                                          SSL_get_ex_data_X509_STORE_CTX_idx());
    11681281    conn_rec *conn      = (conn_rec *)SSL_get_app_data(ssl);
    1169     server_rec *s       = conn->base_server;
    11701282    request_rec *r      = (request_rec *)SSL_get_app_data2(ssl);
     1283    server_rec *s       = r ? r->server : mySrvFromConn(conn);
    11711284
    11721285    SSLSrvConfigRec *sc = mySrvConfig(s);
    11731286    SSLDirConfigRec *dc = r ? myDirConfig(r) : NULL;
    int ssl_callback_SSLVerify(int ok, X509_STORE_CTX 
    12901403
    12911404int ssl_callback_SSLVerify_CRL(int ok, X509_STORE_CTX *ctx, conn_rec *c)
    12921405{
    1293     server_rec *s       = c->base_server;
     1406    SSL *ssl = X509_STORE_CTX_get_ex_data(ctx,
     1407                                          SSL_get_ex_data_X509_STORE_CTX_idx());
     1408    request_rec *r      = (request_rec *)SSL_get_app_data2(ssl);
     1409    server_rec *s       = r ? r->server : mySrvFromConn(c);
    12941410    SSLSrvConfigRec *sc = mySrvConfig(s);
    12951411    SSLConnRec *sslconn = myConnConfig(c);
    12961412    modssl_ctx_t *mctx  = myCtxConfig(sslconn, sc);
    static void modssl_proxy_info_log(server_rec *s, 
    15151631int ssl_callback_proxy_cert(SSL *ssl, MODSSL_CLIENT_CERT_CB_ARG_TYPE **x509, EVP_PKEY **pkey)
    15161632{
    15171633    conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
    1518     server_rec *s = c->base_server;
     1634    server_rec *s = mySrvFromConn(c);
    15191635    SSLSrvConfigRec *sc = mySrvConfig(s);
    15201636    X509_NAME *ca_name, *issuer;
    15211637    X509_INFO *info;
    int ssl_callback_NewSessionCacheEntry(SSL *ssl, SS 
    16131729{
    16141730    /* Get Apache context back through OpenSSL context */
    16151731    conn_rec *conn      = (conn_rec *)SSL_get_app_data(ssl);
    1616     server_rec *s       = conn->base_server;
     1732    server_rec *s       = mySrvFromConn(conn);
    16171733    SSLSrvConfigRec *sc = mySrvConfig(s);
    16181734    long timeout        = sc->session_cache_timeout;
    16191735    BOOL rc;
    SSL_SESSION *ssl_callback_GetSessionCacheEntry(SSL 
    16611777{
    16621778    /* Get Apache context back through OpenSSL context */
    16631779    conn_rec *conn = (conn_rec *)SSL_get_app_data(ssl);
    1664     server_rec *s  = conn->base_server;
     1780    server_rec *s  = mySrvFromConn(conn);
    16651781    SSL_SESSION *session;
    16661782
    16671783    /*
    void ssl_callback_LogTracingState(MODSSL_INFO_CB_A 
    17391855        return;
    17401856    }
    17411857
    1742     s = c->base_server;
     1858    s = mySrvFromConn(c);
    17431859    if (!(sc = mySrvConfig(s))) {
    17441860        return;
    17451861    }
    void ssl_callback_LogTracingState(MODSSL_INFO_CB_A 
    18101926    }
    18111927}
    18121928
     1929#ifndef OPENSSL_NO_TLSEXT
     1930/*
     1931 * This callback function is executed when OpenSSL encounters an extended
     1932 * client hello with a server name indication extension ("SNI", cf. RFC 4366).
     1933 */
     1934int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx)
     1935{
     1936    const char *servername =
     1937                SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
     1938
     1939    if (servername) {
     1940        conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
     1941        if (c) {
     1942            if (ap_vhost_iterate_given_conn(c, ssl_find_vhost,
     1943                                            (void *)servername)) {
     1944                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
     1945                              "SSL virtual host for servername %s found",
     1946                              servername);
     1947                return SSL_TLSEXT_ERR_OK;
     1948            }
     1949            else {
     1950                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
     1951                              "No matching SSL virtual host for servername "
     1952                              "%s found (using default/first virtual host)",
     1953                              servername);
     1954                return SSL_TLSEXT_ERR_ALERT_WARNING;
     1955            }
     1956        }
     1957    }
     1958
     1959    return SSL_TLSEXT_ERR_NOACK;
     1960}
     1961
     1962/*
     1963 * Find a (name-based) SSL virtual host where either the ServerName
     1964 * or one of the ServerAliases matches the supplied name (to be used
     1965 * with ap_vhost_iterate_given_conn())
     1966 */
     1967static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s)
     1968{
     1969    SSLSrvConfigRec *sc;
     1970    SSL *ssl;
     1971    BOOL found = FALSE;
     1972    apr_array_header_t *names;
     1973    int i;
     1974    SSLConnRec *sslcon;
     1975
     1976    /* check ServerName */
     1977    if (!strcasecmp(servername, s->server_hostname)) {
     1978        found = TRUE;
     1979    }
     1980
     1981    /*
     1982     * if not matched yet, check ServerAlias entries
     1983     * (adapted from vhost.c:matches_aliases())
     1984     */
     1985    if (!found) {
     1986        names = s->names;
     1987        if (names) {
     1988            char **name = (char **)names->elts;
     1989            for (i = 0; i < names->nelts; ++i) {
     1990                if (!name[i])
     1991                    continue;
     1992                if (!strcasecmp(servername, name[i])) {
     1993                    found = TRUE;
     1994                    break;
     1995                }
     1996            }
     1997        }
     1998    }
     1999
     2000    /* if still no match, check ServerAlias entries with wildcards */
     2001    if (!found) {
     2002        names = s->wild_names;
     2003        if (names) {
     2004            char **name = (char **)names->elts;
     2005            for (i = 0; i < names->nelts; ++i) {
     2006                if (!name[i])
     2007                    continue;
     2008                if (!ap_strcasecmp_match(servername, name[i])) {
     2009                    found = TRUE;
     2010                    break;
     2011                }
     2012            }
     2013        }
     2014    }
     2015
     2016    /* set SSL_CTX (if matched) */
     2017    sslcon = myConnConfig(c);
     2018    if (found && (ssl = sslcon->ssl) &&
     2019        (sc = mySrvConfig(s))) {
     2020        SSL_set_SSL_CTX(ssl, sc->server->ssl_ctx);
     2021        /*
     2022         * SSL_set_SSL_CTX() only deals with the server cert,
     2023         * so we need to duplicate a few additional settings
     2024         * from the ctx by hand
     2025         */
     2026        SSL_set_options(ssl, SSL_CTX_get_options(ssl->ctx));
     2027        if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) ||
     2028            (SSL_num_renegotiations(ssl) == 0)) {
     2029           /*
     2030            * Only initialize the verification settings from the ctx
     2031            * if they are not yet set, or if we're called when a new
     2032            * SSL connection is set up (num_renegotiations == 0).
     2033            * Otherwise, we would possibly reset a per-directory
     2034            * configuration which was put into effect by ssl_hook_Access.
     2035            */
     2036            SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ssl->ctx),
     2037                           SSL_CTX_get_verify_callback(ssl->ctx));
     2038        }
     2039
     2040        /*
     2041         * Save the found server into our SSLConnRec for later
     2042         * retrieval
     2043         */
     2044        sslcon->server = s;
     2045
     2046        /*
     2047         * There is one special filter callback, which is set
     2048         * very early depending on the base_server's log level.
     2049         * If this is not the first vhost we're now selecting
     2050         * (and the first vhost doesn't use APLOG_DEBUG), then
     2051         * we need to set that callback here.
     2052         */
     2053        if (s->loglevel >= APLOG_DEBUG) {
     2054            BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb);
     2055            BIO_set_callback_arg(SSL_get_rbio(ssl), (void *)ssl);
     2056        }
     2057
     2058        return 1;
     2059    }
     2060
     2061    return 0;
     2062}
     2063#endif
  • httpd-2.2.11/modules/ssl/mod_ssl.c

    static const command_rec ssl_config_cmds[] = { 
    145145                "Use the server's cipher ordering preference")
    146146    SSL_CMD_ALL(UserName, TAKE1,
    147147                "Set user name to SSL variable value")
     148#ifndef OPENSSL_NO_TLSEXT
     149    SSL_CMD_SRV(StrictSNIVHostCheck, FLAG,
     150                "Strict SNI virtual host checking")
     151#endif
    148152
    149153    /*
    150154     * Proxy configuration for remote SSL connections
    static SSLConnRec *ssl_init_connection_ctx(conn_re 
    295299
    296300    sslconn = apr_pcalloc(c->pool, sizeof(*sslconn));
    297301
     302    sslconn->server = c->base_server;
     303
    298304    myConnConfigSet(c, sslconn);
    299305
    300306    return sslconn;
    static SSLConnRec *ssl_init_connection_ctx(conn_re 
    302308
    303309int ssl_proxy_enable(conn_rec *c)
    304310{
    305     SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
     311    SSLSrvConfigRec *sc;
    306312
    307313    SSLConnRec *sslconn = ssl_init_connection_ctx(c);
     314    sc = mySrvConfig(sslconn->server);
    308315
    309316    if (!sc->proxy_enabled) {
    310317        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
    int ssl_proxy_enable(conn_rec *c) 
    322329
    323330int ssl_engine_disable(conn_rec *c)
    324331{
    325     SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
     332    SSLSrvConfigRec *sc;
    326333
    327     SSLConnRec *sslconn;
     334    SSLConnRec *sslconn = myConnConfig(c);
    328335
     336    if (sslconn) {
     337        sc = mySrvConfig(sslconn->server);
     338    }
     339    else {
     340        sc = mySrvConfig(c->base_server);
     341    }
    329342    if (sc->enabled == SSL_ENABLED_FALSE) {
    330343        return 0;
    331344    }
    int ssl_engine_disable(conn_rec *c) 
    339352
    340353int ssl_init_ssl_connection(conn_rec *c)
    341354{
    342     SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
     355    SSLSrvConfigRec *sc;
    343356    SSL *ssl;
    344357    SSLConnRec *sslconn = myConnConfig(c);
    345358    char *vhost_md5;
    346359    modssl_ctx_t *mctx;
     360    server_rec *server;
    347361
     362    if (!sslconn) {
     363        sslconn = ssl_init_connection_ctx(c);
     364    }
     365    server = sslconn->server;
     366    sc = mySrvConfig(server);
     367
    348368    /*
    349369     * Seed the Pseudo Random Number Generator (PRNG)
    350370     */
    351     ssl_rand_seed(c->base_server, c->pool, SSL_RSCTX_CONNECT, "");
     371    ssl_rand_seed(server, c->pool, SSL_RSCTX_CONNECT, "");
    352372
    353     if (!sslconn) {
    354         sslconn = ssl_init_connection_ctx(c);
    355     }
    356 
    357373    mctx = sslconn->is_proxy ? sc->proxy : sc->server;
    358374
    359375    /*
    int ssl_init_ssl_connection(conn_rec *c) 
    365381        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
    366382                      "Unable to create a new SSL connection from the SSL "
    367383                      "context");
    368         ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, c->base_server);
     384        ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, server);
    369385
    370386        c->aborted = 1;
    371387
    int ssl_init_ssl_connection(conn_rec *c) 
    380396    {
    381397        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
    382398                      "Unable to set session id context to `%s'", vhost_md5);
    383         ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, c->base_server);
     399        ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, server);
    384400
    385401        c->aborted = 1;
    386402
    static apr_port_t ssl_hook_default_port(const requ 
    429445
    430446static int ssl_hook_pre_connection(conn_rec *c, void *csd)
    431447{
    432     SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
     448    SSLSrvConfigRec *sc;
    433449    SSLConnRec *sslconn = myConnConfig(c);
    434450
     451    if (sslconn) {
     452        sc = mySrvConfig(sslconn->server);
     453    }
     454    else {
     455        sc = mySrvConfig(c->base_server);
     456    }
    435457    /*
    436458     * Immediately stop processing if SSL is disabled for this connection
    437459     */
  • httpd-2.2.11/modules/ssl/ssl_toolkit_compat.h

    typedef void (*modssl_popfree_fn)(char *data); 
    264264#define SSL_SESS_CACHE_NO_INTERNAL  SSL_SESS_CACHE_NO_INTERNAL_LOOKUP
    265265#endif
    266266
     267#ifndef OPENSSL_NO_TLSEXT
     268#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
     269#define OPENSSL_NO_TLSEXT
     270#endif
     271#endif
     272
    267273#endif /* SSL_TOOLKIT_COMPAT_H */
    268274
    269275/** @} */
  • httpd-2.2.11/docs/manual/mod/mod_ssl.html.en

    to provide the cryptography engine.</p> 
    7575<li><img alt="" src="../images/down.gif" /> <a href="#sslrequiressl">SSLRequireSSL</a></li>
    7676<li><img alt="" src="../images/down.gif" /> <a href="#sslsessioncache">SSLSessionCache</a></li>
    7777<li><img alt="" src="../images/down.gif" /> <a href="#sslsessioncachetimeout">SSLSessionCacheTimeout</a></li>
     78<li><img alt="" src="../images/down.gif" /> <a href="#sslstrictsnivhostcheck">SSLStrictSNIVHostCheck</a></li>
    7879<li><img alt="" src="../images/down.gif" /> <a href="#sslusername">SSLUserName</a></li>
    7980<li><img alt="" src="../images/down.gif" /> <a href="#sslverifyclient">SSLVerifyClient</a></li>
    8081<li><img alt="" src="../images/down.gif" /> <a href="#sslverifydepth">SSLVerifyDepth</a></li>
    SSLSessionCacheTimeout 600 
    16131614
    16141615</div>
    16151616<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
     1617<div class="directive-section"><h2><a name="SSLStrictSNIVHostCheck" id="SSLStrictSNIVHostCheck">SSLStrictSNIVHostCheck</a> <a name="sslstrictsnivhostcheck" id="sslstrictsnivhostcheck">Directive</a></h2>
     1618<table class="directive">
     1619<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Whether to allow non SNI clients to access a name based virtual
     1620host.
     1621</td></tr>
     1622<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>SSLStrictSNIVHostCheck on|off</code></td></tr>
     1623<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>SSLStrictSNIVHostCheck off</code></td></tr>
     1624<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host</td></tr>
     1625<tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Extension</td></tr>
     1626<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_ssl</td></tr>
     1627</table>
     1628<p>
     1629This directive sets whether a non SNI client is allowed to access a name based
     1630virtual host. If set to <code>on</code> in the non default name based virtual
     1631host, non SNI clients are not allowed to access this particular virtual host.
     1632If set to <code>on</code> in the default name based virtual host, non SNI
     1633clients are not allowed to access any name based virtual host belonging to
     1634this IP / port combination.
     1635</p>
     1636
     1637<div class="warning"><p>
     1638This option is only available if httpd was compiled against an SNI capable
     1639version of OpenSSL.
     1640</p></div>
     1641
     1642<div class="example"><h3>Example</h3><p><code>
     1643SSLStrictSNIVHostCheck on
     1644</code></p></div>
     1645
     1646</div>
     1647<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
    16161648<div class="directive-section"><h2><a name="SSLUserName" id="SSLUserName">SSLUserName</a> <a name="sslusername" id="sslusername">Directive</a></h2>
    16171649<table class="directive">
    16181650<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Variable name to determine user name</td></tr>
    SSLVerifyDepth 10 
    17171749<div class="bottomlang">
    17181750<p><span>Available Languages: </span><a href="../en/mod/mod_ssl.html" title="English">&nbsp;en&nbsp;</a></p>
    17191751</div><div id="footer">
    1720 <p class="apache">Copyright 2008 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
     1752<p class="apache">Copyright 2009 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
    17211753<p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div>
    1722 </body></html>
    1723  No newline at end of file
     1754</body></html>
Note: See TracBrowser for help on using the repository browser.