Commit f52fccd9 authored by Stefan Eissing's avatar Stefan Eissing
Browse files

branch for integrating mod_md into trunk


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/trunk-md@1804087 13f79535-47bb-0310-9956-ffa450edef68
parent 9292b9c9
Loading
Loading
Loading
Loading
+76 −0
Original line number Diff line number Diff line
@@ -167,6 +167,36 @@ static void ssl_add_version_components(apr_pool_t *p,
                 modver, AP_SERVER_BASEVERSION, incver);
}

/**************************************************************************************************/
/* Managed Domains Interface (temporary here) */

APR_DECLARE_OPTIONAL_FN(int, 
                        md_is_managed, (struct server_rec *));

APR_DECLARE_OPTIONAL_FN(apr_status_t, 
                        md_get_credentials, (struct server_rec *, apr_pool_t *,
                                             const char **pkeyfile, 
                                             const char **pcertfile, 
                                             const char **pchainfile));
APR_DECLARE_OPTIONAL_FN(int, 
                        md_is_challenge, (struct conn_rec *, const char *,
                                          X509 **, EVP_PKEY **));
                                          
static APR_OPTIONAL_FN_TYPE(md_is_managed) *md_is_managed;
static APR_OPTIONAL_FN_TYPE(md_get_credentials) *md_get_credentials;
static APR_OPTIONAL_FN_TYPE(md_is_challenge) *md_is_challenge;

int ssl_is_challenge(conn_rec *c, const char *servername, 
                     X509 **pcert, EVP_PKEY **pkey)
{
    if (md_is_challenge) {
        return md_is_challenge(c, servername, pcert, pkey);
    }
    *pcert = NULL;
    *pkey = NULL;
    return 0;
}

/*
 *  Per-module initialization
 */
@@ -207,6 +237,16 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
    ssl_config_global_create(base_server); /* just to avoid problems */
    ssl_config_global_fix(mc);

    /* Initialize our interface to mod_md, if it is loaded 
     */
    md_is_managed = APR_RETRIEVE_OPTIONAL_FN(md_is_managed);
    md_get_credentials = APR_RETRIEVE_OPTIONAL_FN(md_get_credentials);
    md_is_challenge = APR_RETRIEVE_OPTIONAL_FN(md_is_challenge);
    if (!md_is_managed || !md_get_credentials) {
        md_is_managed = NULL;
        md_get_credentials = NULL;
    }

    /*
     *  try to fix the configuration and open the dedicated SSL
     *  logfile as early as possible
@@ -1662,6 +1702,42 @@ static apr_status_t ssl_init_server_ctx(server_rec *s,
        return APR_EGENERAL;
    }

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO()
                 "Init: (%s) mod_md support is %s.", ssl_util_vhostid(p, s),
                 md_is_managed? "available" : "unavailable");
    if (md_is_managed && md_is_managed(s)) {
        modssl_pk_server_t *const pks = sc->server->pks;
        if (pks->cert_files->nelts > 0 || pks->key_files->nelts > 0) {
            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO()
                         "Init: (%s) You configured certificate/key files on this host, but "
                         "is is covered by a Managed Domain. You need to remove these directives "
                         "for the Managed Domain to take over.", ssl_util_vhostid(p, s));
        }
        else {
            const char *key_file, *cert_file, *chain_file;
            
            rv = md_get_credentials(s, p, &key_file, &cert_file, &chain_file);
            if (rv == APR_SUCCESS) {
                APR_ARRAY_PUSH(pks->key_files, const char *) = key_file;
                APR_ARRAY_PUSH(pks->cert_files, const char *) = cert_file;
                if (chain_file) {
                    sc->server->cert_chain = chain_file;
                }
            }
            else if (APR_STATUS_IS_EAGAIN(rv)) {
                /* Managed Domain not ready yet. This is not a reason to fail the config */
                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO()
                             "Init: (%s) disabling this host for now as certificate/key data "
                             "for the Managed Domain is incomplete.", ssl_util_vhostid(p, s));
                pks->service_unavailable = 1;
                return APR_SUCCESS;
            }
            else {
                return rv;
            }
        }
    }
    
    if ((rv = ssl_init_ctx(s, p, ptemp, sc->server)) != APR_SUCCESS) {
        return rv;
    }
+40 −0
Original line number Diff line number Diff line
@@ -264,6 +264,15 @@ int ssl_hook_ReadReq(request_rec *r)
        return DECLINED;
    }

    if (sslconn->service_unavailable) {
        /* This is set when the SSL properties of this connection are
         * incomplete or if this connection was made to challenge a 
         * particular hostname (ACME). We never serve any request on 
         * such a connection. */
         /* TODO: a retry-after indicator would be nice here */
        return HTTP_SERVICE_UNAVAILABLE;
    }

    if (sslconn->non_ssl_request == NON_SSL_SET_ERROR_MSG) {
        apr_table_setn(r->notes, "error-notes",
                       "Reason: You're speaking plain HTTP to an SSL-enabled "
@@ -2124,6 +2133,8 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc)
static apr_status_t init_vhost(conn_rec *c, SSL *ssl)
{
    const char *servername;
    X509 *cert;
    EVP_PKEY *key;
    
    if (c) {
        SSLConnRec *sslcon = myConnConfig(c);
@@ -2140,8 +2151,35 @@ static apr_status_t init_vhost(conn_rec *c, SSL *ssl)
                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02043)
                              "SSL virtual host for servername %s found",
                              servername);
                
                return APR_SUCCESS;
            }
            else if (ssl_is_challenge(c, servername, &cert, &key)) {
            
                sslcon->service_unavailable = 1;
                if ((SSL_use_certificate(ssl, cert) < 1)) {
                    ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO()
                                  "Failed to configure challenge certificate %s",
                                  servername);
                    return APR_EGENERAL;
                }
                
                if (!SSL_use_PrivateKey(ssl, key)) {
                    ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO()
                                  "error '%s' using Challenge key: %s",
                                  ERR_error_string(ERR_peek_last_error(), NULL), 
                                  servername);
                    return APR_EGENERAL;
                }
                
                if (SSL_check_private_key(ssl) < 1) {
                    ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO()
                                  "Challenbge certificate and private key %s "
                                  "do not match", servername);
                    return APR_EGENERAL;
                }
                
            }
            else {
                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02044)
                              "No matching SSL virtual host for servername "
@@ -2247,6 +2285,8 @@ static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s)
         */
        sslcon->server = s;
        sslcon->cipher_suite = sc->server->auth.cipher_suite;
        sslcon->service_unavailable = sc->server->pks? 
            sc->server->pks->service_unavailable : 0; 
        
        ap_update_child_status_from_server(c->sbh, SERVER_BUSY_READ, c, s);
        /*
+7 −0
Original line number Diff line number Diff line
@@ -522,6 +522,7 @@ typedef struct {
    SSLDirConfigRec *dc;
    
    const char *cipher_suite; /* cipher suite used in last reneg */
    int service_unavailable;  /* thouugh we negotiate SSL, no requests will be served */
} SSLConnRec;

/* BIG FAT WARNING: SSLModConfigRec has unusual memory lifetime: it is
@@ -598,6 +599,9 @@ typedef struct {
     * sent in the CertificateRequest message: */
    const char  *ca_name_path;
    const char  *ca_name_file;
    
    /* TLS service for this server is suspended */
    int service_unavailable;
} modssl_pk_server_t;

typedef struct {
@@ -1065,6 +1069,9 @@ DH *modssl_get_dh_params(unsigned keylen);
extern int ssl_running_on_valgrind;
#endif

int ssl_is_challenge(conn_rec *c, const char *servername, 
                     X509 **pcert, EVP_PKEY **pkey);

#endif /* SSL_PRIVATE_H */
/** @} */
+27 −0
Original line number Diff line number Diff line
@@ -115,6 +115,33 @@ EVP_PKEY *modssl_read_privatekey(const char* filename, EVP_PKEY **key, pem_passw
    return rc;
}

typedef struct {
    const char *pass;
    int pass_len;
} pass_ctx;

static int provide_pass(char *buf, int size, int rwflag, void *baton)
{
    pass_ctx *ctx = baton;
    if (ctx->pass_len > 0) {
        if (ctx->pass_len < size) {
            size = (int)ctx->pass_len;
        }
        memcpy(buf, ctx->pass, size);
    }
    return ctx->pass_len;
}

EVP_PKEY   *modssl_read_encrypted_pkey(const char *filename, EVP_PKEY **key, 
                                       const char *pass, apr_size_t pass_len)
{
    pass_ctx ctx;
    
    ctx.pass = pass;
    ctx.pass_len = pass_len;
    return modssl_read_privatekey(filename, key, provide_pass, &ctx);
}

/*  _________________________________________________________________
**
**  Smart shutdown
+1 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ void modssl_init_app_data2_idx(void);
void       *modssl_get_app_data2(SSL *);
void        modssl_set_app_data2(SSL *, void *);
EVP_PKEY   *modssl_read_privatekey(const char *, EVP_PKEY **, pem_password_cb *, void *);
EVP_PKEY   *modssl_read_encrypted_pkey(const char *, EVP_PKEY **, const char *, apr_size_t);
int         modssl_smart_shutdown(SSL *ssl);
BOOL        modssl_X509_getBC(X509 *, int *, int *);
char       *modssl_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne);