Changeset 2cde026d in mod_gnutls for src/gnutls_hooks.c


Ignore:
Timestamp:
Apr 21, 2015, 8:09:54 AM (5 years ago)
Author:
Thomas Klute <thomas2.klute@…>
Branches:
debian/master, debian/stretch-backports, jessie-backports, master, upstream
Children:
4133f2d
Parents:
73f6f12 (diff), d04f7da (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Thomas Klute <thomas2.klute@…> (04/21/15 06:25:30)
git-committer:
Thomas Klute <thomas2.klute@…> (04/21/15 08:09:54)
Message:

Merge branch 'new-gnutls-api'

Merge my TLS proxy implementation with Nikos Mavrogiannopoulos' changes
to use the new GnuTLS key handling API. Some conflicts had to be
resolved.

In Nikos' branch, structures for credentials and priorities are
allocated in mgs_load_files (gnutls_config.c), rather than during server
config structure creation as before. This makes sense, but his patch
doesn't consider the proxy credentials because they didn't exist at the
time.

To minimize additional changes during the merge, proxy credentials are
now allocated in load_proxy_x509_credentials (gnutls_hooks.c), and
mgs_set_priorities (gnutls_config.c) treats proxy and front end
credentials differently (value of GnuTLSPriorities is stored for
mgs_load_files, GnuTLSProxyPriorities is parsed immediately).

Unified handling of priority strings in mgs_set_priorities should be
restored later (towards parsing in post config), handling front end and
proxy credentials separately makes sense because the latter need only be
loaded when TLS proxy operation is enabled and there are some
differences between client (proxy back end) and server (front end)
operation.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_hooks.c

    r73f6f12 r2cde026d  
    175175
    176176static int cert_retrieve_fn(gnutls_session_t session,
    177                                                         const gnutls_datum_t * req_ca_rdn __attribute__((unused)), int nreqs __attribute__((unused)),
    178                                                         const gnutls_pk_algorithm_t * pk_algos __attribute__((unused)), int pk_algos_length __attribute__((unused)),
    179                                                         gnutls_retr2_st *ret) {
    180 
    181 
    182         _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
    183 
    184         mgs_handle_t *ctxt;
     177                            const gnutls_datum_t * req_ca_rdn __attribute__((unused)),
     178                            int nreqs __attribute__((unused)),
     179                            const gnutls_pk_algorithm_t * pk_algos __attribute__((unused)),
     180                            int pk_algos_length __attribute__((unused)),
     181                            gnutls_pcert_st **pcerts,
     182                            unsigned int *pcert_length,
     183                            gnutls_privkey_t *privkey)
     184{
     185    _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
     186
     187    mgs_handle_t *ctxt;
    185188
    186189    if (session == NULL) {
    187190                // ERROR INVALID SESSION
    188                 ret->ncerts = 0;
    189                 ret->deinit_all = 1;
    190191        return -1;
    191         }
     192    }
     193
    192194    ctxt = gnutls_transport_get_ptr(session);
    193195
    194196    if (gnutls_certificate_type_get(session) == GNUTLS_CRT_X509) {
    195197                // X509 CERTIFICATE
    196                 ret->cert_type = GNUTLS_CRT_X509;
    197                 ret->key_type = GNUTLS_PRIVKEY_X509;
    198         ret->ncerts = ctxt->sc->certs_x509_chain_num;
    199         ret->deinit_all = 0;
    200         ret->cert.x509 = ctxt->sc->certs_x509_chain;
    201         ret->key.x509 = ctxt->sc->privkey_x509;
     198        *pcerts = ctxt->sc->certs_x509_chain;
     199        *pcert_length = ctxt->sc->certs_x509_chain_num;
     200        *privkey = ctxt->sc->privkey_x509;
    202201        return 0;
    203202    } else if (gnutls_certificate_type_get(session) == GNUTLS_CRT_OPENPGP) {
    204203                // OPENPGP CERTIFICATE
    205                 ret->cert_type = GNUTLS_CRT_OPENPGP;
    206                 ret->key_type = GNUTLS_PRIVKEY_OPENPGP;
    207         ret->ncerts = 1;
    208         ret->deinit_all = 0;
    209         ret->cert.pgp = ctxt->sc->cert_pgp;
    210         ret->key.pgp = ctxt->sc->privkey_pgp;
     204        *pcerts = ctxt->sc->cert_pgp;
     205        *pcert_length = 1;
     206        *privkey = ctxt->sc->privkey_pgp;
    211207        return 0;
    212208    } else {
    213209                // UNKNOWN CERTIFICATE
    214                 ret->ncerts = 0;
    215                 ret->deinit_all = 1;
    216210            return -1;
    217211        }
    218212}
    219 
    220 /* 2048-bit group parameters from SRP specification */
    221 const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n"
    222         "MIIBBwKCAQCsa9tBMkqam/Fm3l4TiVgvr3K2ZRmH7gf8MZKUPbVgUKNzKcu0oJnt\n"
    223         "gZPgdXdnoT3VIxKrSwMxDc1/SKnaBP1Q6Ag5ae23Z7DPYJUXmhY6s2YaBfvV+qro\n"
    224         "KRipli8Lk7hV+XmT7Jde6qgNdArb9P90c1nQQdXDPqcdKB5EaxR3O8qXtDoj+4AW\n"
    225         "dr0gekNsZIHx0rkHhxdGGludMuaI+HdIVEUjtSSw1X1ep3onddLs+gMs+9v1L7N4\n"
    226         "YWAnkATleuavh05zA85TKZzMBBx7wwjYKlaY86jQw4JxrjX46dv7tpS1yAPYn3rk\n"
    227         "Nd4jbVJfVHWbZeNy/NaO8g+nER+eSv9zAgEC\n"
    228         "-----END DH PARAMETERS-----\n";
    229213
    230214/* Read the common name or the alternative name of the certificate.
     
    326310    }
    327311
    328 
    329312    s = base_server;
    330313    sc_base = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module);
    331314
    332     gnutls_dh_params_init(&dh_params);
    333 
    334     if (sc_base->dh_params == NULL) {
    335         gnutls_datum_t pdata = {
    336             (void *) static_dh_params,
    337             sizeof(static_dh_params)
    338         };
    339         rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, GNUTLS_X509_FMT_PEM);
    340         /* Generate DH Params
    341         int dh_bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH,
    342                 GNUTLS_SEC_PARAM_NORMAL);
    343         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    344             "GnuTLS: Generating DH Params of %i bits.  "
    345             "To avoid this use GnuTLSDHFile to specify DH Params for this host",
    346             dh_bits);
    347 #if MOD_GNUTLS_DEBUG
    348             ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
    349                     "GnuTLS: Generated DH Params of %i bits",dh_bits);
    350 #endif
    351         rv = gnutls_dh_params_generate2 (dh_params,dh_bits);
    352         */
    353         if (rv < 0) {
    354             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    355                     "GnuTLS: Unable to generate or load DH Params: (%d) %s",
    356                     rv, gnutls_strerror(rv));
    357             exit(rv);
    358         }
    359     } else {
    360         dh_params = sc_base->dh_params;
    361     }
    362315
    363316    rv = mgs_cache_post_config(p, s, sc_base);
     
    374327        sc->cache_config = sc_base->cache_config;
    375328        sc->cache_timeout = sc_base->cache_timeout;
     329
     330        rv = mgs_load_files(p, s);
     331        if (rv != 0) {
     332            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     333                "GnuTLS: Loading required files failed."
     334                " Shutting Down.");
     335            exit(-1);
     336        }
    376337
    377338        /* defaults for unset values: */
     
    387348            sc->client_verify_method = mgs_cvm_cartel;
    388349
    389 
    390350        /* Check if the priorities have been set */
    391351        if (sc->priorities == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) {
     
    405365        }
    406366
    407         gnutls_certificate_set_retrieve_function(sc->certs, cert_retrieve_fn);
    408 
    409 #ifdef ENABLE_SRP
    410         if (sc->srp_tpasswd_conf_file != NULL
    411                 && sc->srp_tpasswd_file != NULL) {
    412             rv = gnutls_srp_set_server_credentials_file
    413                     (sc->srp_creds, sc->srp_tpasswd_file,
    414                     sc->srp_tpasswd_conf_file);
    415 
    416             if (rv < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) {
    417                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0,
    418                         s,
    419                         "[GnuTLS] - Host '%s:%d' is missing a "
    420                         "SRP password or conf File!",
    421                         s->server_hostname, s->port);
    422                 exit(-1);
    423             }
    424         }
     367        /* The call after this comment is a workaround for bug in
     368         * gnutls_certificate_set_retrieve_function2 that ignores
     369         * supported certificate types. Should be fixed in GnuTLS
     370         * 3.3.12.
     371         *
     372         * Details:
     373         * https://lists.gnupg.org/pipermail/gnutls-devel/2015-January/007377.html
     374         * Workaround from:
     375         * https://github.com/vanrein/tlspool/commit/4938102d3d1b086491d147e6c8e4e2a02825fc12 */
     376#if GNUTLS_VERSION_NUMBER < 0x030312
     377        gnutls_certificate_set_retrieve_function(sc->certs, (void *) exit);
    425378#endif
     379
     380        gnutls_certificate_set_retrieve_function2(sc->certs, cert_retrieve_fn);
    426381
    427382        if ((sc->certs_x509_chain == NULL || sc->certs_x509_chain_num < 1) &&
    428383            sc->cert_pgp == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) {
    429384                        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    430                                                 "[GnuTLS] - Host '%s:%d' is missing a Certificate File!",
     385                                                "GnuTLS: Host '%s:%d' is missing a Certificate File!",
    431386                                                s->server_hostname, s->port);
    432387            exit(-1);
    433388        }
    434 
    435389        if (sc->enabled == GNUTLS_ENABLED_TRUE &&
    436             ((sc->certs_x509_chain != NULL && sc->certs_x509_chain_num > 0 && sc->privkey_x509 == NULL) ||
    437              (sc->cert_pgp != NULL && sc->privkey_pgp == NULL))) {
     390            ((sc->certs_x509_chain_num > 0 && sc->privkey_x509 == NULL) ||
     391             (sc->cert_crt_pgp[0] != NULL && sc->privkey_pgp == NULL))) {
    438392                        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    439                                                 "[GnuTLS] - Host '%s:%d' is missing a Private Key File!",
     393                                                "GnuTLS: Host '%s:%d' is missing a Private Key File!",
    440394                                                s->server_hostname, s->port);
    441395            exit(-1);
     
    445399            rv = -1;
    446400            if (sc->certs_x509_chain_num > 0) {
    447                 rv = read_crt_cn(s, p, sc->certs_x509_chain[0], &sc->cert_cn);
     401                rv = read_crt_cn(s, p, sc->certs_x509_crt_chain[0], &sc->cert_cn);
    448402            }
    449403            if (rv < 0 && sc->cert_pgp != NULL) {
    450                 rv = read_pgpcrt_cn(s, p, sc->cert_pgp, &sc->cert_cn);
     404                rv = read_pgpcrt_cn(s, p, sc->cert_crt_pgp[0], &sc->cert_cn);
    451405                        }
    452406
    453407            if (rv < 0) {
    454408                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    455                                                         "[GnuTLS] - Cannot find a certificate for host '%s:%d'!",
     409                                                        "GnuTLS: Cannot find a certificate for host '%s:%d'!",
    456410                                                        s->server_hostname, s->port);
    457411                sc->cert_cn = NULL;
     
    494448}
    495449
    496 void mgs_hook_child_init(apr_pool_t * p, server_rec * s) {
     450void mgs_hook_child_init(apr_pool_t * p, server_rec *s) {
    497451    apr_status_t rv = APR_SUCCESS;
    498     mgs_srvconf_rec *sc = ap_get_module_config(s->module_config,
    499             &gnutls_module);
     452    mgs_srvconf_rec *sc =
     453        (mgs_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module);
    500454
    501455    _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
     456    /* if we use PKCS #11 reinitialize it */
     457
     458    if (mgs_pkcs11_reinit(s) < 0) {
     459            ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
     460                    "GnuTLS: Failed to reinitialize PKCS #11");
     461            exit(-1);
     462    }
     463
    502464    if (sc->cache_type != mgs_cache_none) {
    503465        rv = mgs_cache_child_init(p, s, sc);
    504466        if (rv != APR_SUCCESS) {
    505467            ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
    506                     "[GnuTLS] - Failed to run Cache Init");
     468                    "GnuTLS: Failed to run Cache Init");
    507469        }
    508470    }
     
    625587
    626588    if (tsc->certs_x509_chain_num > 0) {
    627         /* why are we doing this check? */
    628         ret = gnutls_x509_crt_check_hostname(tsc->certs_x509_chain[0], s->server_hostname);
     589        /* this check is there to warn administrator of any missing hostname
     590         * in the certificate. */
     591        ret = gnutls_x509_crt_check_hostname(tsc->certs_x509_crt_chain[0], s->server_hostname);
    629592        if (0 == ret)
    630             ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
    631                          "GnuTLS: Error checking certificate for hostname "
     593            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
     594                         "GnuTLS: the certificate doesn't match requested hostname "
    632595                         "'%s'", s->server_hostname);
    633596    } else {
     
    956919
    957920    if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) {
    958                 mgs_add_common_cert_vars(r, ctxt->sc->certs_x509_chain[0], 0, ctxt->sc->export_certificates_size);
    959         } else if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_OPENPGP) {
    960         mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0, ctxt->sc->export_certificates_size);
    961         }
     921        mgs_add_common_cert_vars(r, ctxt->sc->certs_x509_crt_chain[0], 0, ctxt->sc->export_certificates_size);
     922    } else if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_OPENPGP) {
     923        mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_crt_pgp[0], 0, ctxt->sc->export_certificates_size);
     924    }
    962925
    963926    return rv;
     
    17751738    }
    17761739
     1740    /* allocate credentials structures */
     1741    err = gnutls_certificate_allocate_credentials(&sc->proxy_x509_creds);
     1742    if (err != GNUTLS_E_SUCCESS)
     1743    {
     1744        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1745                     "%s: Failed to initialize proxy credentials: (%d) %s",
     1746                     __func__, err, gnutls_strerror(err));
     1747        return APR_EGENERAL;
     1748    }
     1749    err = gnutls_anon_allocate_client_credentials(&sc->anon_client_creds);
     1750    if (err != GNUTLS_E_SUCCESS)
     1751    {
     1752        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1753                     "%s: Failed to initialize anon credentials for proxy: "
     1754                     "(%d) %s", __func__, err, gnutls_strerror(err));
     1755        return APR_EGENERAL;
     1756    }
     1757
    17771758    /* load certificate and key for client auth, if configured */
    17781759    if (sc->proxy_x509_key_file && sc->proxy_x509_cert_file)
Note: See TracChangeset for help on using the changeset viewer.