Changes in src/gnutls_config.c [d04f7da:f030883] in mod_gnutls


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_config.c

    rd04f7da rf030883  
    2020#include "mod_gnutls.h"
    2121#include "apr_lib.h"
    22 #include <gnutls/abstract.h>
    23 
    24 #define INIT_CA_SIZE 128
    2522
    2623#ifdef APLOG_USE_MODULE
     
    2825#endif
    2926
    30 static int pin_callback(void *user, int attempt __attribute__((unused)),
    31                         const char *token_url __attribute__((unused)),
    32                         const char *token_label, unsigned int flags,
    33                         char *pin, size_t pin_max)
    34 {
    35     mgs_srvconf_rec *sc = user;
    36 
    37     if (sc->pin == NULL || flags & GNUTLS_PIN_FINAL_TRY ||
    38         flags & GNUTLS_PIN_WRONG) {
    39         return -1;
    40     }
    41 
    42     if (token_label && strcmp(token_label, "SRK") == 0) {
    43          snprintf(pin, pin_max, "%s", sc->srk_pin);
    44     } else {
    45          snprintf(pin, pin_max, "%s", sc->pin);
    46     }
    47     return 0;
    48 }
    49 
    5027static int load_datum_from_file(apr_pool_t * pool,
    51                                 const char *file, gnutls_datum_t * data)
    52 {
     28        const char *file, gnutls_datum_t * data) {
    5329    apr_file_t *fp;
    5430    apr_finfo_t finfo;
     
    5733
    5834    rv = apr_file_open(&fp, file, APR_READ | APR_BINARY,
    59                        APR_OS_DEFAULT, pool);
     35            APR_OS_DEFAULT, pool);
    6036    if (rv != APR_SUCCESS) {
    61         return rv;
     37        return rv;
    6238    }
    6339
     
    6541
    6642    if (rv != APR_SUCCESS) {
    67         return rv;
     43        return rv;
    6844    }
    6945
     
    7248
    7349    if (rv != APR_SUCCESS) {
    74         return rv;
     50        return rv;
    7551    }
    7652    apr_file_close(fp);
     
    8258}
    8359
    84 /* 2048-bit group parameters from SRP specification */
    85 const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n"
    86         "MIIBBwKCAQCsa9tBMkqam/Fm3l4TiVgvr3K2ZRmH7gf8MZKUPbVgUKNzKcu0oJnt\n"
    87         "gZPgdXdnoT3VIxKrSwMxDc1/SKnaBP1Q6Ag5ae23Z7DPYJUXmhY6s2YaBfvV+qro\n"
    88         "KRipli8Lk7hV+XmT7Jde6qgNdArb9P90c1nQQdXDPqcdKB5EaxR3O8qXtDoj+4AW\n"
    89         "dr0gekNsZIHx0rkHhxdGGludMuaI+HdIVEUjtSSw1X1ep3onddLs+gMs+9v1L7N4\n"
    90         "YWAnkATleuavh05zA85TKZzMBBx7wwjYKlaY86jQw4JxrjX46dv7tpS1yAPYn3rk\n"
    91         "Nd4jbVJfVHWbZeNy/NaO8g+nER+eSv9zAgEC\n"
    92         "-----END DH PARAMETERS-----\n";
    93 
    94 int mgs_load_files(apr_pool_t * p, server_rec * s)
    95 {
     60const char *mgs_set_dh_file(cmd_parms * parms, void *dummy __attribute__((unused)),
     61        const char *arg) {
     62    int ret;
     63    gnutls_datum_t data;
     64    const char *file;
    9665    apr_pool_t *spool;
    97     const char *file;
    98     gnutls_datum_t data;
    99     int ret;
    100     mgs_srvconf_rec *sc =
    101         (mgs_srvconf_rec *) ap_get_module_config(s->module_config,
    102                                                  &gnutls_module);
    103 
    104     apr_pool_create(&spool, p);
    105 
    106     sc->cert_pgp = apr_pcalloc(p, sizeof(sc->cert_pgp[0]));
    107     sc->cert_crt_pgp = apr_pcalloc(p, sizeof(sc->cert_crt_pgp[0]));
    108     sc->certs_x509_chain =
    109         apr_pcalloc(p, MAX_CHAIN_SIZE * sizeof(sc->certs_x509_chain[0]));
    110     sc->certs_x509_crt_chain =
    111         apr_pcalloc(p,
    112                     MAX_CHAIN_SIZE * sizeof(sc->certs_x509_crt_chain[0]));
    113 
    114     ret = gnutls_certificate_allocate_credentials(&sc->certs);
    115     if (ret < 0) {
    116         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    117                      "GnuTLS: Failed to initialize" ": (%d) %s", ret,
    118                      gnutls_strerror(ret));
    119         ret = -1;
    120         goto cleanup;
    121     }
    122 
    123     ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds);
    124     if (ret < 0) {
    125         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    126                      "GnuTLS: Failed to initialize" ": (%d) %s", ret,
    127                      gnutls_strerror(ret));
    128         ret = -1;
    129         goto cleanup;
    130     }
    131 
    132     /* Load SRP parameters */
    133 #ifdef ENABLE_SRP
    134     ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds);
    135     if (ret < 0) {
    136         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    137                      "GnuTLS: Failed to initialize" ": (%d) %s", ret,
    138                      gnutls_strerror(ret));
    139         ret = -1;
    140         goto cleanup;
    141     }
    142 
    143     if (sc->srp_tpasswd_conf_file != NULL && sc->srp_tpasswd_file != NULL) {
    144         ret = gnutls_srp_set_server_credentials_file
    145             (sc->srp_creds, sc->srp_tpasswd_file,
    146              sc->srp_tpasswd_conf_file);
    147 
    148         if (ret < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) {
    149             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0,
    150                          s,
    151                          "GnuTLS: Host '%s:%d' is missing a "
    152                          "SRP password or conf File!",
    153                          s->server_hostname, s->port);
    154             ret = -1;
    155             goto cleanup;
    156         }
    157     }
    158 #endif
     66    mgs_srvconf_rec *sc =
     67            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     68            module_config,
     69            &gnutls_module);
     70
     71    apr_pool_create(&spool, parms->pool);
     72
     73    file = ap_server_root_relative(spool, arg);
     74
     75    if (load_datum_from_file(spool, file, &data) != 0) {
     76        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
     77                "DH params '%s'", file);
     78    }
    15979
    16080    ret = gnutls_dh_params_init(&sc->dh_params);
    16181    if (ret < 0) {
    162             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    163                          "GnuTLS: Failed to initialize"
    164                          ": (%d) %s", ret, gnutls_strerror(ret));
    165             ret = -1;
    166             goto cleanup;
    167     }
    168 
    169     /* Load DH parameters */
    170     if (sc->dh_file) {
    171         if (load_datum_from_file(spool, sc->dh_file, &data) != 0) {
    172             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    173                          "GnuTLS: Error Reading " "DH params '%s'", sc->dh_file);
    174             ret = -1;
    175             goto cleanup;
    176         }
    177 
    178         ret =
    179             gnutls_dh_params_import_pkcs3(sc->dh_params, &data,
    180                                           GNUTLS_X509_FMT_PEM);
    181         if (ret < 0) {
    182             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    183                          "GnuTLS: Failed to Import "
    184                          "DH params '%s': (%d) %s", sc->dh_file, ret,
    185                          gnutls_strerror(ret));
    186             ret = -1;
    187             goto cleanup;
    188         }
    189     } else {
    190         gnutls_datum_t pdata = {
    191             (void *) static_dh_params,
    192             sizeof(static_dh_params)
    193         };
    194 
    195         ret = gnutls_dh_params_import_pkcs3(sc->dh_params, &pdata, GNUTLS_X509_FMT_PEM);
    196         if (ret < 0) {
    197             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    198                     "GnuTLS: Unable to generate or load DH Params: (%d) %s",
    199                     ret, gnutls_strerror(ret));
    200             ret = -1;
    201             goto cleanup;
    202         }
    203     }
    204 
    205     if (sc->x509_cert_file != NULL) {
    206         unsigned int chain_num, i;
    207         unsigned format = GNUTLS_X509_FMT_PEM;
    208 
    209         /* Load X.509 certificate */
    210         if (strncmp(sc->x509_cert_file, "pkcs11:", 7) == 0) {
    211             gnutls_pkcs11_obj_t obj;
    212 
    213             file = sc->x509_cert_file;
    214 
    215             ret = gnutls_pkcs11_obj_init(&obj);
    216             if (ret < 0) {
    217                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    218                              "GnuTLS: Error Initializing PKCS #11 object");
    219                 ret = -1;
    220                 goto cleanup;
    221             }
    222 
    223             gnutls_pkcs11_obj_set_pin_function(obj, pin_callback, sc);
    224 
    225             ret = gnutls_pkcs11_obj_import_url(obj, file, GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
    226             if (ret < 0) {
    227                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    228                              "GnuTLS: Error Importing PKCS #11 object: '%s': %s",
    229                              file, gnutls_strerror(ret));
    230                 ret = -1;
    231                 goto cleanup;
    232             }
    233 
    234             format = GNUTLS_X509_FMT_DER;
    235             ret = gnutls_pkcs11_obj_export2(obj, &data);
    236             if (ret < 0) {
    237                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    238                              "GnuTLS: Error Exporting a PKCS #11 object: '%s': %s",
    239                              file, gnutls_strerror(ret));
    240                 ret = -1;
    241                 goto cleanup;
    242             }
    243 
    244             gnutls_pkcs11_obj_deinit(obj);
    245         } else {
    246             file = ap_server_root_relative(spool, sc->x509_cert_file);
    247 
    248             ret = gnutls_load_file(file, &data);
    249             if (ret < 0) {
    250                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    251                              "GnuTLS: Error Reading Certificate '%s': %s",
    252                              file, gnutls_strerror(ret));
    253                 ret = -1;
    254                 goto cleanup;
    255             }
    256         }
    257 
    258         ret =
    259             gnutls_x509_crt_list_import2(&sc->certs_x509_crt_chain,
    260                                         &chain_num, &data, format,
    261                                         GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED);
    262         gnutls_free(data.data);
    263         sc->certs_x509_chain_num = chain_num;
    264 
    265         if (ret < 0) {
    266             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    267                          "GnuTLS: Failed to Import Certificate Chain '%s': (%d) %s",
    268                          file, ret, gnutls_strerror(ret));
    269             ret = -1;
    270             goto cleanup;
    271         }
    272 
    273         for (i = 0; i < chain_num; i++) {
    274             ret =
    275                 gnutls_pcert_import_x509(&sc->certs_x509_chain[i],
    276                                          sc->certs_x509_crt_chain[i], 0);
    277             if (ret < 0) {
    278                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    279                              "GnuTLS: Failed to Import pCertificate '%s': (%d) %s",
    280                              file, ret, gnutls_strerror(ret));
    281                 ret = -1;
    282                 goto cleanup;
    283             }
    284         }
    285         sc->certs_x509_chain_num = chain_num;
    286     }
    287 
    288     if (sc->x509_key_file) {
    289         ret = gnutls_privkey_init(&sc->privkey_x509);
    290         if (ret < 0) {
    291             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    292                          "GnuTLS: Failed to initialize: (%d) %s", ret,
    293                          gnutls_strerror(ret));
    294             ret = -1;
    295             goto cleanup;
    296         }
    297 
    298         if (gnutls_url_is_supported(sc->x509_key_file) != 0) {
    299             file = sc->x509_key_file;
    300 
    301             gnutls_privkey_set_pin_function(sc->privkey_x509, pin_callback,
    302                                             sc);
    303 
    304             ret = gnutls_privkey_import_url(sc->privkey_x509, file, 0);
    305 
    306             if (ret < 0) {
    307                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    308                              "GnuTLS: Failed to Import Private Key URL '%s': (%d) %s",
    309                              file, ret, gnutls_strerror(ret));
    310                 ret = -1;
    311                 goto cleanup;
    312             }
    313         } else {
    314             file = ap_server_root_relative(spool, sc->x509_key_file);
    315 
    316             if (load_datum_from_file(spool, file, &data) != 0) {
    317                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    318                              "GnuTLS: Error Reading Private Key '%s'",
    319                              file);
    320                 ret = -1;
    321                 goto cleanup;
    322             }
    323 
    324             ret =
    325                 gnutls_privkey_import_x509_raw(sc->privkey_x509, &data,
    326                                                GNUTLS_X509_FMT_PEM, sc->pin,
    327                                                0);
    328 
    329             if (ret < 0) {
    330                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    331                              "GnuTLS: Failed to Import Private Key '%s': (%d) %s",
    332                              file, ret, gnutls_strerror(ret));
    333                 ret = -1;
    334                 goto cleanup;
    335             }
    336         }
    337     }
    338 
    339     /* Load the X.509 CA file */
    340     if (sc->x509_ca_file) {
    341         if (load_datum_from_file(spool, sc->x509_ca_file, &data) != 0) {
    342             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    343                          "GnuTLS: Error Reading " "Client CA File '%s'",
    344                          sc->x509_ca_file);
    345             ret = -1;
    346             goto cleanup;
    347         }
    348 
    349         ret = gnutls_x509_crt_list_import2(&sc->ca_list, &sc->ca_list_size,
    350                                          &data, GNUTLS_X509_FMT_PEM, 0);
    351         if (ret < 0) {
    352             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    353                          "GnuTLS: Failed to load "
    354                          "Client CA File '%s': (%d) %s", sc->x509_ca_file,
    355                          ret, gnutls_strerror(ret));
    356             ret = -1;
    357             goto cleanup;
    358         }
    359     }
    360 
    361     if (sc->pgp_cert_file) {
    362         if (load_datum_from_file(spool, sc->pgp_cert_file, &data) != 0) {
    363             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    364                          "GnuTLS: Error Reading " "Certificate '%s'",
    365                          sc->pgp_cert_file);
    366             ret = -1;
    367             goto cleanup;
    368         }
    369 
    370         ret = gnutls_openpgp_crt_init(&sc->cert_crt_pgp[0]);
    371         if (ret < 0) {
    372             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    373                          "GnuTLS: Failed to Init "
    374                          "PGP Certificate: (%d) %s", ret,
    375                          gnutls_strerror(ret));
    376             ret = -1;
    377             goto cleanup;
    378         }
    379 
    380         ret =
    381             gnutls_openpgp_crt_import(sc->cert_crt_pgp[0], &data,
    382                                       GNUTLS_OPENPGP_FMT_BASE64);
    383         if (ret < 0) {
    384             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    385                          "GnuTLS: Failed to Import "
    386                          "PGP Certificate: (%d) %s", ret,
    387                          gnutls_strerror(ret));
    388             ret = -1;
    389             goto cleanup;
    390         }
    391 
    392         ret =
    393             gnutls_pcert_import_openpgp(sc->cert_pgp, sc->cert_crt_pgp[0],
    394                                         0);
    395         if (ret < 0) {
    396             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    397                          "GnuTLS: Failed to Import "
    398                          "PGP pCertificate: (%d) %s", ret,
    399                          gnutls_strerror(ret));
    400             ret = -1;
    401             goto cleanup;
    402         }
    403     }
    404 
    405     /* Load the PGP key file */
    406     if (sc->pgp_key_file) {
    407         if (load_datum_from_file(spool, sc->pgp_key_file, &data) != 0) {
    408             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    409                          "GnuTLS: Error Reading " "Private Key '%s'",
    410                          sc->pgp_key_file);
    411             ret = -1;
    412             goto cleanup;
    413         }
    414 
    415         ret = gnutls_privkey_init(&sc->privkey_pgp);
    416         if (ret < 0) {
    417             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    418                          "GnuTLS: Failed to initialize"
    419                          ": (%d) %s", ret, gnutls_strerror(ret));
    420             ret = -1;
    421             goto cleanup;
    422         }
    423 
    424 #if GNUTLS_VERSION_NUMBER < 0x030312
    425         /* GnuTLS versions before 3.3.12 contain a bug in
    426          * gnutls_privkey_import_openpgp_raw which frees data that is
    427          * accessed when the key is used, leading to segfault. Loading
    428          * the key into a gnutls_openpgp_privkey_t and then assigning
    429          * it to the gnutls_privkey_t works around the bug, hence this
    430          * chain of gnutls_openpgp_privkey_init,
    431          * gnutls_openpgp_privkey_import and
    432          * gnutls_privkey_import_openpgp. */
    433         ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp_internal);
    434         if (ret != 0) {
    435             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    436                          "GnuTLS: Failed to initialize "
    437                          "PGP Private Key '%s': (%d) %s",
    438                          sc->pgp_key_file, ret, gnutls_strerror(ret));
    439             ret = -1;
    440             goto cleanup;
    441         }
    442 
    443         ret = gnutls_openpgp_privkey_import(sc->privkey_pgp_internal, &data,
    444                                             GNUTLS_OPENPGP_FMT_BASE64, NULL, 0);
    445         if (ret != 0) {
    446             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    447                          "GnuTLS: Failed to Import "
    448                          "PGP Private Key '%s': (%d) %s",
    449                          sc->pgp_key_file, ret, gnutls_strerror(ret));
    450             ret = -1;
    451             goto cleanup;
    452         }
    453 
    454         ret = gnutls_privkey_import_openpgp(sc->privkey_pgp,
    455                                             sc->privkey_pgp_internal, 0);
    456         if (ret != 0)
    457         {
    458             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    459                          "GnuTLS: Failed to assign PGP Private Key '%s' "
    460                          "to gnutls_privkey_t structure: (%d) %s",
    461                          sc->pgp_key_file, ret, gnutls_strerror(ret));
    462             ret = -1;
    463             goto cleanup;
    464         }
    465 #else
    466         ret = gnutls_privkey_import_openpgp_raw(sc->privkey_pgp, &data,
    467                                                 GNUTLS_OPENPGP_FMT_BASE64,
    468                                                 NULL, NULL);
    469         if (ret != 0)
    470         {
    471             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    472                          "GnuTLS: Failed to Import "
    473                          "PGP Private Key '%s': (%d) %s",
    474                          sc->pgp_key_file, ret, gnutls_strerror(ret));
    475             ret = -1;
    476             goto cleanup;
    477         }
    478 #endif
    479     }
    480 
    481     /* Load the keyring file */
    482     if (sc->pgp_ring_file) {
    483         if (load_datum_from_file(spool, sc->pgp_ring_file, &data) != 0) {
    484             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    485                          "GnuTLS: Error Reading " "Keyring File '%s'",
    486                          sc->pgp_ring_file);
    487             ret = -1;
    488             goto cleanup;
    489         }
    490 
    491         ret = gnutls_openpgp_keyring_init(&sc->pgp_list);
    492         if (ret < 0) {
    493             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    494                          "GnuTLS: Failed to initialize"
    495                          "keyring: (%d) %s", ret, gnutls_strerror(ret));
    496             ret = -1;
    497             goto cleanup;
    498         }
    499 
    500         ret = gnutls_openpgp_keyring_import(sc->pgp_list, &data,
    501                                            GNUTLS_OPENPGP_FMT_BASE64);
    502         if (ret < 0) {
    503             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    504                          "GnuTLS: Failed to load "
    505                          "Keyring File '%s': (%d) %s", sc->pgp_ring_file,
    506                          ret, gnutls_strerror(ret));
    507             ret = -1;
    508             goto cleanup;
    509         }
    510     }
    511 
    512     if (sc->priorities_str) {
    513         const char *err;
    514         ret = gnutls_priority_init(&sc->priorities, sc->priorities_str, &err);
    515 
    516         if (ret < 0) {
    517             if (ret == GNUTLS_E_INVALID_REQUEST) {
    518                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    519                              "GnuTLS: Syntax error parsing priorities string at: %s",
    520                              err);
    521             } else {
    522                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    523                              "GnuTLS: error parsing priorities string");
    524 
    525             }
    526             ret = -1;
    527             goto cleanup;
    528         }
    529     }
    530 
    531     ret = 0;
    532   cleanup:
     82        return apr_psprintf(parms->pool,
     83                "GnuTLS: Failed to initialize"
     84                ": (%d) %s", ret,
     85                gnutls_strerror(ret));
     86    }
     87
     88    ret =
     89            gnutls_dh_params_import_pkcs3(sc->dh_params, &data,
     90            GNUTLS_X509_FMT_PEM);
     91    if (ret < 0) {
     92        return apr_psprintf(parms->pool,
     93                "GnuTLS: Failed to Import "
     94                "DH params '%s': (%d) %s", file, ret,
     95                gnutls_strerror(ret));
     96    }
     97
    53398    apr_pool_destroy(spool);
    53499
    535     return ret;
    536 }
    537 
    538 int mgs_pkcs11_reinit(server_rec * base_server)
     100    return NULL;
     101}
     102
     103const char *mgs_set_cert_file(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg)
    539104{
    540105    int ret;
    541     server_rec *s;
    542     mgs_srvconf_rec *sc;
    543 
    544     gnutls_pkcs11_reinit();
    545 
    546     for (s = base_server; s; s = s->next) {
    547         sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module);
    548 
    549             /* gnutls caches the session in a private key, so we need to open
    550              * a new one */
    551             if (sc->x509_key_file && gnutls_url_is_supported(sc->x509_key_file) != 0) {
    552                 gnutls_privkey_deinit(sc->privkey_x509);
    553 
    554                 ret = gnutls_privkey_init(&sc->privkey_x509);
    555                 if (ret < 0) {
    556                     ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
    557                                  "GnuTLS: Failed to initialize: (%d) %s", ret,
    558                                  gnutls_strerror(ret));
    559                     goto fail;
    560                 }
    561 
    562                 gnutls_privkey_set_pin_function(sc->privkey_x509, pin_callback, sc);
    563 
    564                 ret = gnutls_privkey_import_url(sc->privkey_x509, sc->x509_key_file, 0);
    565                 if (ret < 0) {
    566                     ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
    567                              "GnuTLS: Failed to Re-Import Private Key URL '%s': (%d) %s",
    568                              sc->x509_key_file, ret, gnutls_strerror(ret));
    569                     goto fail;
    570                 }
    571             }
    572     }
    573 
    574     return 0;
    575 
    576  fail:
    577     gnutls_privkey_deinit(sc->privkey_x509);
    578     return -1;
    579 }
    580 
    581 const char *mgs_set_dh_file(cmd_parms * parms, void *dummy __attribute__((unused)),
    582         const char *arg) {
    583     mgs_srvconf_rec *sc =
    584         (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    585                                                  module_config,
    586                                                  &gnutls_module);
    587 
    588     sc->dh_file = ap_server_root_relative(parms->pool, arg);
    589 
    590     return NULL;
    591 }
    592 
    593 const char *mgs_set_cert_file(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg) {
    594 
    595     mgs_srvconf_rec *sc =
    596         (mgs_srvconf_rec *) ap_get_module_config(parms->
    597                                                  server->module_config,
    598                                                  &gnutls_module);
    599 
    600     sc->x509_cert_file = apr_pstrdup(parms->pool, arg);
    601 
     106    gnutls_datum_t data;
     107    const char *file;
     108    apr_pool_t *spool;
     109
     110    mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server->module_config, &gnutls_module);
     111    apr_pool_create(&spool, parms->pool);
     112
     113    file = ap_server_root_relative(spool, arg);
     114
     115    if (load_datum_from_file(spool, file, &data) != 0) {
     116                apr_pool_destroy(spool);
     117        return apr_psprintf(parms->pool, "GnuTLS: Error Reading Certificate '%s'", file);
     118    }
     119
     120    sc->certs_x509_chain_num = MAX_CHAIN_SIZE;
     121    ret = gnutls_x509_crt_list_import(sc->certs_x509_chain, &sc->certs_x509_chain_num, &data, GNUTLS_X509_FMT_PEM, 0);
     122    if (ret < 0) {
     123                apr_pool_destroy(spool);
     124        return apr_psprintf(parms->pool, "GnuTLS: Failed to Import Certificate '%s': (%d) %s", file, ret, gnutls_strerror(ret));
     125    }
     126
     127        apr_pool_destroy(spool);
    602128    return NULL;
    603129
     
    606132const char *mgs_set_key_file(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg) {
    607133
    608     mgs_srvconf_rec *sc =
    609         (mgs_srvconf_rec *) ap_get_module_config(parms->
    610                                                  server->module_config,
    611                                                  &gnutls_module);
    612 
    613     sc->x509_key_file = apr_pstrdup(parms->pool, arg);
     134    int ret;
     135    gnutls_datum_t data;
     136    const char *file;
     137    apr_pool_t *spool;
     138    const char *out;
     139
     140        mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server->module_config, &gnutls_module);
     141
     142        apr_pool_create(&spool, parms->pool);
     143
     144    file = ap_server_root_relative(spool, arg);
     145
     146    if (load_datum_from_file(spool, file, &data) != 0) {
     147        out = apr_psprintf(parms->pool, "GnuTLS: Error Reading Private Key '%s'", file);
     148                apr_pool_destroy(spool);
     149        return out;
     150    }
     151
     152    ret = gnutls_x509_privkey_init(&sc->privkey_x509);
     153
     154    if (ret < 0) {
     155                apr_pool_destroy(spool);
     156        return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize: (%d) %s", ret, gnutls_strerror(ret));
     157    }
     158
     159    ret = gnutls_x509_privkey_import(sc->privkey_x509, &data, GNUTLS_X509_FMT_PEM);
     160
     161    if (ret < 0) {
     162        ret = gnutls_x509_privkey_import_pkcs8(sc->privkey_x509, &data, GNUTLS_X509_FMT_PEM, NULL, GNUTLS_PKCS_PLAIN);
     163        }
     164
     165    if (ret < 0) {
     166        out = apr_psprintf(parms->pool, "GnuTLS: Failed to Import Private Key '%s': (%d) %s", file, ret, gnutls_strerror(ret));
     167                apr_pool_destroy(spool);
     168        return out;
     169    }
     170
     171    apr_pool_destroy(spool);
    614172
    615173    return NULL;
     
    617175
    618176const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy __attribute__((unused)),
    619         const char *arg)
    620 {
    621     mgs_srvconf_rec *sc =
    622         (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    623                                                  module_config,
    624                                                  &gnutls_module);
    625 
    626     sc->pgp_cert_file = ap_server_root_relative(parms->pool, arg);
    627 
     177        const char *arg) {
     178    int ret;
     179    gnutls_datum_t data;
     180    const char *file;
     181    apr_pool_t *spool;
     182    mgs_srvconf_rec *sc =
     183            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     184            module_config,
     185            &gnutls_module);
     186    apr_pool_create(&spool, parms->pool);
     187
     188    file = ap_server_root_relative(spool, arg);
     189
     190    if (load_datum_from_file(spool, file, &data) != 0) {
     191        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
     192                "Certificate '%s'", file);
     193    }
     194
     195    ret = gnutls_openpgp_crt_init(&sc->cert_pgp);
     196    if (ret < 0) {
     197        return apr_psprintf(parms->pool, "GnuTLS: Failed to Init "
     198                "PGP Certificate: (%d) %s", ret,
     199                gnutls_strerror(ret));
     200    }
     201
     202    ret =
     203            gnutls_openpgp_crt_import(sc->cert_pgp, &data,
     204            GNUTLS_OPENPGP_FMT_BASE64);
     205    if (ret < 0) {
     206        return apr_psprintf(parms->pool,
     207                "GnuTLS: Failed to Import "
     208                "PGP Certificate '%s': (%d) %s", file,
     209                ret, gnutls_strerror(ret));
     210    }
     211
     212    apr_pool_destroy(spool);
    628213    return NULL;
    629214}
     
    631216const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy __attribute__((unused)),
    632217        const char *arg) {
    633     mgs_srvconf_rec *sc =
    634         (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    635                                                  module_config,
    636                                                  &gnutls_module);
    637 
    638     sc->pgp_key_file = ap_server_root_relative(parms->pool, arg);
    639 
     218    int ret;
     219    gnutls_datum_t data;
     220    const char *file;
     221    apr_pool_t *spool;
     222    mgs_srvconf_rec *sc =
     223            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     224            module_config,
     225            &gnutls_module);
     226    apr_pool_create(&spool, parms->pool);
     227
     228    file = ap_server_root_relative(spool, arg);
     229
     230    if (load_datum_from_file(spool, file, &data) != 0) {
     231        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
     232                "Private Key '%s'", file);
     233    }
     234
     235    ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp);
     236    if (ret < 0) {
     237        return apr_psprintf(parms->pool,
     238                "GnuTLS: Failed to initialize"
     239                ": (%d) %s", ret,
     240                gnutls_strerror(ret));
     241    }
     242
     243    ret =
     244            gnutls_openpgp_privkey_import(sc->privkey_pgp, &data,
     245            GNUTLS_OPENPGP_FMT_BASE64, NULL,
     246            0);
     247    if (ret != 0) {
     248        return apr_psprintf(parms->pool,
     249                "GnuTLS: Failed to Import "
     250                "PGP Private Key '%s': (%d) %s", file,
     251                ret, gnutls_strerror(ret));
     252    }
     253    apr_pool_destroy(spool);
    640254    return NULL;
    641255}
     
    644258        const char *arg) {
    645259    mgs_srvconf_rec *sc =
    646         (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    647                                                 module_config,
    648                                                 &gnutls_module);
     260            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     261            module_config,
     262            &gnutls_module);
    649263
    650264    sc->tickets = 0;
    651265    if (strcasecmp("on", arg) == 0) {
    652         sc->tickets = 1;
     266        sc->tickets = 1;
    653267    }
    654268
     
    662276        const char *arg) {
    663277    mgs_srvconf_rec *sc =
    664         (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    665                                                 module_config,
    666                                                 &gnutls_module);
     278            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     279            module_config,
     280            &gnutls_module);
    667281
    668282    sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg);
     
    674288        const char *arg) {
    675289    mgs_srvconf_rec *sc =
    676         (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    677                                                  module_config,
    678                                                  &gnutls_module);
    679 
    680     sc->srp_tpasswd_conf_file = ap_server_root_relative(parms->pool, arg);
     290            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     291            module_config,
     292            &gnutls_module);
     293
     294    sc->srp_tpasswd_conf_file =
     295            ap_server_root_relative(parms->pool, arg);
    681296
    682297    return NULL;
     
    689304    const char *err;
    690305    mgs_srvconf_rec *sc =
    691         ap_get_module_config(parms->server->module_config,
    692                              &gnutls_module);
     306            ap_get_module_config(parms->server->module_config,
     307            &gnutls_module);
    693308    if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) {
    694         return err;
     309        return err;
    695310    }
    696311
    697312    if (strcasecmp("none", type) == 0) {
    698         sc->cache_type = mgs_cache_none;
    699         sc->cache_config = NULL;
    700         return NULL;
     313        sc->cache_type = mgs_cache_none;
     314        sc->cache_config = NULL;
     315        return NULL;
    701316    } else if (strcasecmp("dbm", type) == 0) {
    702         sc->cache_type = mgs_cache_dbm;
     317        sc->cache_type = mgs_cache_dbm;
    703318    } else if (strcasecmp("gdbm", type) == 0) {
    704         sc->cache_type = mgs_cache_gdbm;
     319        sc->cache_type = mgs_cache_gdbm;
    705320    }
    706321#if HAVE_APR_MEMCACHE
    707322    else if (strcasecmp("memcache", type) == 0) {
    708         sc->cache_type = mgs_cache_memcache;
     323        sc->cache_type = mgs_cache_memcache;
    709324    }
    710325#endif
    711326    else {
    712         return "Invalid Type for GnuTLSCache!";
     327        return "Invalid Type for GnuTLSCache!";
    713328    }
    714329
    715330    if (arg == NULL)
    716         return "Invalid argument 2 for GnuTLSCache!";
     331        return "Invalid argument 2 for GnuTLSCache!";
    717332
    718333    if (sc->cache_type == mgs_cache_dbm
    719         || sc->cache_type == mgs_cache_gdbm) {
    720         sc->cache_config = ap_server_root_relative(parms->pool, arg);
     334            || sc->cache_type == mgs_cache_gdbm) {
     335        sc->cache_config =
     336                ap_server_root_relative(parms->pool, arg);
    721337    } else {
    722         sc->cache_config = apr_pstrdup(parms->pool, arg);
     338        sc->cache_config = apr_pstrdup(parms->pool, arg);
    723339    }
    724340
     
    731347    const char *err;
    732348    mgs_srvconf_rec *sc =
    733         (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    734                                                 module_config,
    735                                                 &gnutls_module);
     349            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     350            module_config,
     351            &gnutls_module);
    736352
    737353    if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) {
    738         return err;
     354        return err;
    739355    }
    740356
     
    742358
    743359    if (argint < 0) {
    744         return "GnuTLSCacheTimeout: Invalid argument";
     360        return "GnuTLSCacheTimeout: Invalid argument";
    745361    } else if (argint == 0) {
    746         sc->cache_timeout = 0;
     362        sc->cache_timeout = 0;
    747363    } else {
    748         sc->cache_timeout = apr_time_from_sec(argint);
     364        sc->cache_timeout = apr_time_from_sec(argint);
    749365    }
    750366
     
    757373
    758374    if (strcasecmp("cartel", arg) == 0) {
    759         sc->client_verify_method = mgs_cvm_cartel;
     375        sc->client_verify_method = mgs_cvm_cartel;
    760376    } else if (strcasecmp("msva", arg) == 0) {
    761377#ifdef ENABLE_MSVA
    762         sc->client_verify_method = mgs_cvm_msva;
     378        sc->client_verify_method = mgs_cvm_msva;
    763379#else
    764         return "GnuTLSClientVerifyMethod: msva is not supported";
     380        return "GnuTLSClientVerifyMethod: msva is not supported";
    765381#endif
    766382    } else {
    767         return "GnuTLSClientVerifyMethod: Invalid argument";
     383        return "GnuTLSClientVerifyMethod: Invalid argument";
    768384    }
    769385
     
    777393
    778394    if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) {
    779         mode = GNUTLS_CERT_IGNORE;
     395        mode = GNUTLS_CERT_IGNORE;
    780396    } else if (strcasecmp("optional", arg) == 0
    781                || strcasecmp("request", arg) == 0) {
    782         mode = GNUTLS_CERT_REQUEST;
     397            || strcasecmp("request", arg) == 0) {
     398        mode = GNUTLS_CERT_REQUEST;
    783399    } else if (strcasecmp("require", arg) == 0) {
    784         mode = GNUTLS_CERT_REQUIRE;
     400        mode = GNUTLS_CERT_REQUIRE;
    785401    } else {
    786         return "GnuTLSClientVerify: Invalid argument";
     402        return "GnuTLSClientVerify: Invalid argument";
    787403    }
    788404
     
    792408        dc->client_verify_mode = mode;
    793409    } else {
    794         mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    795             ap_get_module_config(parms->server->module_config,
    796                                  &gnutls_module);
    797         sc->client_verify_mode = mode;
    798     }
    799 
    800     return NULL;
    801 }
     410        mgs_srvconf_rec *sc =
     411                (mgs_srvconf_rec *)
     412                ap_get_module_config(parms->server->module_config,
     413                &gnutls_module);
     414        sc->client_verify_mode = mode;
     415    }
     416
     417    return NULL;
     418}
     419
     420#define INIT_CA_SIZE 128
    802421
    803422const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy __attribute__((unused)),
    804423        const char *arg) {
    805     mgs_srvconf_rec *sc =
    806         (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    807                                                  module_config,
    808                                                  &gnutls_module);
    809 
    810     sc->x509_ca_file = ap_server_root_relative(parms->pool, arg);
    811 
     424    int rv;
     425    const char *file;
     426    apr_pool_t *spool;
     427    gnutls_datum_t data;
     428
     429    mgs_srvconf_rec *sc =
     430            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     431            module_config,
     432            &gnutls_module);
     433    apr_pool_create(&spool, parms->pool);
     434
     435    file = ap_server_root_relative(spool, arg);
     436
     437    if (load_datum_from_file(spool, file, &data) != 0) {
     438        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
     439                "Client CA File '%s'", file);
     440    }
     441
     442    sc->ca_list_size = INIT_CA_SIZE;
     443    sc->ca_list = malloc(sc->ca_list_size * sizeof (*sc->ca_list));
     444    if (sc->ca_list == NULL) {
     445        return apr_psprintf(parms->pool,
     446                "mod_gnutls: Memory allocation error");
     447    }
     448
     449    rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size,
     450            &data, GNUTLS_X509_FMT_PEM,
     451            GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
     452    if (rv < 0 && rv != GNUTLS_E_SHORT_MEMORY_BUFFER) {
     453        return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
     454                "Client CA File '%s': (%d) %s", file,
     455                rv, gnutls_strerror(rv));
     456    }
     457
     458    if (INIT_CA_SIZE < sc->ca_list_size) {
     459        sc->ca_list =
     460                realloc(sc->ca_list,
     461                sc->ca_list_size * sizeof (*sc->ca_list));
     462        if (sc->ca_list == NULL) {
     463            return apr_psprintf(parms->pool,
     464                    "mod_gnutls: Memory allocation error");
     465        }
     466
     467        /* re-read */
     468        rv = gnutls_x509_crt_list_import(sc->ca_list,
     469                &sc->ca_list_size, &data,
     470                GNUTLS_X509_FMT_PEM, 0);
     471
     472        if (rv < 0) {
     473            return apr_psprintf(parms->pool,
     474                    "GnuTLS: Failed to load "
     475                    "Client CA File '%s': (%d) %s",
     476                    file, rv, gnutls_strerror(rv));
     477        }
     478    }
     479
     480    apr_pool_destroy(spool);
    812481    return NULL;
    813482}
     
    815484const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy __attribute__((unused)),
    816485        const char *arg) {
    817     mgs_srvconf_rec *sc =
    818         (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    819                                                  module_config,
    820                                                  &gnutls_module);
    821 
    822     sc->pgp_ring_file = ap_server_root_relative(parms->pool, arg);
    823 
     486    int rv;
     487    const char *file;
     488    apr_pool_t *spool;
     489    gnutls_datum_t data;
     490
     491    mgs_srvconf_rec *sc =
     492            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     493            module_config,
     494            &gnutls_module);
     495    apr_pool_create(&spool, parms->pool);
     496
     497    file = ap_server_root_relative(spool, arg);
     498
     499    if (load_datum_from_file(spool, file, &data) != 0) {
     500        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
     501                "Keyring File '%s'", file);
     502    }
     503
     504    rv = gnutls_openpgp_keyring_init(&sc->pgp_list);
     505    if (rv < 0) {
     506        return apr_psprintf(parms->pool,
     507                "GnuTLS: Failed to initialize"
     508                "keyring: (%d) %s", rv,
     509                gnutls_strerror(rv));
     510    }
     511
     512    rv = gnutls_openpgp_keyring_import(sc->pgp_list, &data,
     513            GNUTLS_OPENPGP_FMT_BASE64);
     514    if (rv < 0) {
     515        return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
     516                "Keyring File '%s': (%d) %s", file, rv,
     517                gnutls_strerror(rv));
     518    }
     519
     520    apr_pool_destroy(spool);
    824521    return NULL;
    825522}
     
    828525        const char *arg) {
    829526
    830     mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    831         ap_get_module_config(parms->server->module_config, &gnutls_module);
     527    mgs_srvconf_rec *sc =(mgs_srvconf_rec *)
     528            ap_get_module_config(parms->server->module_config, &gnutls_module);
    832529
    833530    if (!strcasecmp(arg, "On")) {
    834         sc->proxy_enabled = GNUTLS_ENABLED_TRUE;
     531        sc->proxy_enabled = GNUTLS_ENABLED_TRUE;
    835532    } else if (!strcasecmp(arg, "Off")) {
    836         sc->proxy_enabled = GNUTLS_ENABLED_FALSE;
     533        sc->proxy_enabled = GNUTLS_ENABLED_FALSE;
    837534    } else {
    838         return "SSLProxyEngine must be set to 'On' or 'Off'";
     535        return "SSLProxyEngine must be set to 'On' or 'Off'";
    839536    }
    840537
     
    845542        const char *arg) {
    846543    mgs_srvconf_rec *sc =
    847         (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    848                                                 module_config,
    849                                                 &gnutls_module);
     544            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     545            module_config,
     546            &gnutls_module);
    850547    if (!strcasecmp(arg, "On")) {
    851         sc->enabled = GNUTLS_ENABLED_TRUE;
     548        sc->enabled = GNUTLS_ENABLED_TRUE;
    852549    } else if (!strcasecmp(arg, "Off")) {
    853         sc->enabled = GNUTLS_ENABLED_FALSE;
     550        sc->enabled = GNUTLS_ENABLED_FALSE;
    854551    } else {
    855         return "GnuTLSEnable must be set to 'On' or 'Off'";
     552        return "GnuTLSEnable must be set to 'On' or 'Off'";
    856553    }
    857554
     
    862559    mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server->module_config, &gnutls_module);
    863560    if (!strcasecmp(arg, "On")) {
    864         sc->export_certificates_size = 16 * 1024;
     561        sc->export_certificates_size = 16 * 1024;
    865562    } else if (!strcasecmp(arg, "Off")) {
    866         sc->export_certificates_size = 0;
     563        sc->export_certificates_size = 0;
    867564    } else {
    868         char *endptr;
    869         sc->export_certificates_size = strtol(arg, &endptr, 10);
    870         while (apr_isspace(*endptr))
    871             endptr++;
    872         if (*endptr == '\0' || *endptr == 'b' || *endptr == 'B') {
    873             ;
    874         } else if (*endptr == 'k' || *endptr == 'K') {
    875             sc->export_certificates_size *= 1024;
    876         } else {
    877             return
    878                 "GnuTLSExportCertificates must be set to a size (in bytes) or 'On' or 'Off'";
    879         }
    880     }
    881 
    882     return NULL;
    883 }
    884 
    885 const char *mgs_set_priorities(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg)
     565        char* endptr;
     566        sc->export_certificates_size = strtol(arg, &endptr, 10);
     567        while (apr_isspace(*endptr)) endptr++;
     568        if (*endptr == '\0' || *endptr == 'b' || *endptr == 'B') {
     569            ;
     570        } else if (*endptr == 'k' || *endptr == 'K') {
     571            sc->export_certificates_size *= 1024;
     572        } else {
     573            return "GnuTLSExportCertificates must be set to a size (in bytes) or 'On' or 'Off'";
     574        }
     575    }
     576
     577    return NULL;
     578}
     579
     580
     581
     582/*
     583 * Initialize a GnuTLS priorities cache from a configuration
     584 * string. Used for GnuTLSPriorities and GnuTLSProxyPriorities.
     585 */
     586const char *mgs_set_priorities(cmd_parms * parms,
     587                               void *dummy __attribute__((unused)),
     588                               const char *arg)
    886589{
     590    int ret;
     591    const char *err;
     592
    887593    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    888         ap_get_module_config(parms->server->module_config, &gnutls_module);
    889 
    890     sc->priorities_str = apr_pstrdup(parms->pool, arg);
    891 
    892     return NULL;
    893 }
    894 
    895 const char *mgs_set_pin(cmd_parms * parms, void *dummy __attribute__((unused)),
    896                         const char *arg)
    897 {
    898 
    899     mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    900         ap_get_module_config(parms->server->module_config, &gnutls_module);
    901 
    902     sc->pin = apr_pstrdup(parms->pool, arg);
    903 
    904     return NULL;
    905 }
    906 
    907 const char *mgs_set_srk_pin(cmd_parms * parms,
    908                             void *dummy __attribute__((unused)),
    909                             const char *arg)
    910 {
    911 
    912     mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    913         ap_get_module_config(parms->server->module_config, &gnutls_module);
    914 
    915     sc->srk_pin = apr_pstrdup(parms->pool, arg);
    916 
    917     return NULL;
    918 }
    919 
    920 static mgs_srvconf_rec *_mgs_config_server_create(apr_pool_t * p,
    921                                                   char **err __attribute__((unused)))
    922 {
    923     mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc));
     594        ap_get_module_config(parms->server->module_config, &gnutls_module);
     595
     596    /* Setting a priority cache works the same no matter for which
     597     * option. Just point the pointer at the right one. */
     598    gnutls_priority_t *prio = NULL;
     599    if (!strcasecmp(parms->directive->directive, "GnuTLSPriorities"))
     600        prio = &sc->priorities;
     601    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyPriorities"))
     602        prio = &sc->proxy_priorities;
     603    else
     604        /* Can't happen unless there's a serious bug in mod_gnutls or Apache */
     605        return apr_psprintf(parms->pool,
     606                            "mod_gnutls: %s called for invalid option '%s'",
     607                            __func__, parms->directive->directive);
     608
     609    ret = gnutls_priority_init(prio, arg, &err);
     610    if (ret < 0)
     611    {
     612        if (ret == GNUTLS_E_INVALID_REQUEST)
     613            return apr_psprintf(parms->pool,
     614                                "mod_gnutls: Syntax error parsing priorities "
     615                                "string for %s at: %s",
     616                                parms->directive->directive, err);
     617        return  apr_psprintf(parms->pool,
     618                             "Error setting priorities: %s (%d)",
     619                             gnutls_strerror(ret), ret);
     620    }
     621
     622    return NULL;
     623}
     624
     625static mgs_srvconf_rec *_mgs_config_server_create(apr_pool_t * p, char** err) {
     626    mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof (*sc));
     627    int ret;
    924628
    925629    sc->enabled = GNUTLS_ENABLED_UNSET;
    926630
     631    ret = gnutls_certificate_allocate_credentials(&sc->certs);
     632    if (ret < 0) {
     633        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
     634                            ": (%d) %s", ret,
     635                            gnutls_strerror(ret));
     636        return NULL;
     637    }
     638
     639    ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds);
     640    if (ret < 0) {
     641        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
     642                            ": (%d) %s", ret,
     643                            gnutls_strerror(ret));
     644        return NULL;
     645    }
     646
     647    /* FIXME: not ideal, should be called only if SSLProxyEngine is
     648     * enabled */
     649    ret = gnutls_anon_allocate_client_credentials(&sc->anon_client_creds);
     650    if (ret < 0)
     651    {
     652        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
     653                            ": (%d) %s", ret,
     654                            gnutls_strerror(ret));
     655        return NULL;
     656    }
     657
     658    sc->proxy_x509_key_file = NULL;
     659    sc->proxy_x509_cert_file = NULL;
     660    sc->proxy_x509_ca_file = NULL;
     661    sc->proxy_x509_crl_file = NULL;
     662    sc->proxy_priorities = NULL;
     663    ret = gnutls_certificate_allocate_credentials(&sc->proxy_x509_creds);
     664    if (ret < 0)
     665    {
     666        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
     667                            ": (%d) %s", ret,
     668                            gnutls_strerror(ret));
     669        return NULL;
     670    }
     671
     672#ifdef ENABLE_SRP
     673    ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds);
     674    if (ret < 0) {
     675        *err =  apr_psprintf(p, "GnuTLS: Failed to initialize"
     676                             ": (%d) %s", ret,
     677                             gnutls_strerror(ret));
     678        return NULL;
     679    }
     680
     681    sc->srp_tpasswd_conf_file = NULL;
     682    sc->srp_tpasswd_file = NULL;
     683#endif
    927684
    928685    sc->privkey_x509 = NULL;
    929     sc->privkey_pgp = NULL;
     686        /* Initialize all Certificate Chains */
     687    /* FIXME: how do we indicate that this is unset for a merge? (that
     688     * is, how can a subordinate server override the chain by setting
     689     * an empty one?  what would that even look like in the
     690     * configuration?) */
     691        sc->certs_x509_chain = malloc(MAX_CHAIN_SIZE * sizeof (*sc->certs_x509_chain));
    930692    sc->certs_x509_chain_num = 0;
    931     sc->cache_timeout = -1;     /* -1 means "unset" */
     693    sc->cache_timeout = -1; /* -1 means "unset" */
    932694    sc->cache_type = mgs_cache_unset;
    933695    sc->cache_config = NULL;
     
    949711    char *err = NULL;
    950712    mgs_srvconf_rec *sc = _mgs_config_server_create(p, &err);
    951     if (sc)
    952         return sc;
    953     else
    954         return err;
     713    if (sc) return sc; else return err;
    955714}
    956715
     
    958717#define gnutls_srvconf_assign(t) sc->t = add->t
    959718
    960 void *mgs_config_server_merge(apr_pool_t * p, void *BASE, void *ADD)
    961 {
     719void *mgs_config_server_merge(apr_pool_t *p, void *BASE, void *ADD) {
    962720    int i;
    963721    char *err = NULL;
    964     mgs_srvconf_rec *base = (mgs_srvconf_rec *) BASE;
    965     mgs_srvconf_rec *add = (mgs_srvconf_rec *) ADD;
     722    mgs_srvconf_rec *base = (mgs_srvconf_rec *)BASE;
     723    mgs_srvconf_rec *add = (mgs_srvconf_rec *)ADD;
    966724    mgs_srvconf_rec *sc = _mgs_config_server_create(p, &err);
    967     if (NULL == sc)
    968         return err;
     725    if (NULL == sc) return err;
    969726
    970727    gnutls_srvconf_merge(enabled, GNUTLS_ENABLED_UNSET);
     
    976733    gnutls_srvconf_merge(srp_tpasswd_file, NULL);
    977734    gnutls_srvconf_merge(srp_tpasswd_conf_file, NULL);
    978     gnutls_srvconf_merge(x509_cert_file, NULL);
    979 
    980     gnutls_srvconf_merge(x509_key_file, NULL);
    981     gnutls_srvconf_merge(x509_ca_file, NULL);
    982     gnutls_srvconf_merge(pin, NULL);
    983     gnutls_srvconf_merge(pgp_cert_file, NULL);
    984     gnutls_srvconf_merge(pgp_key_file, NULL);
    985     gnutls_srvconf_merge(pgp_ring_file, NULL);
    986     gnutls_srvconf_merge(dh_file, NULL);
    987     gnutls_srvconf_merge(priorities_str, NULL);
     735    gnutls_srvconf_merge(privkey_x509, NULL);
     736    gnutls_srvconf_merge(priorities, NULL);
     737    gnutls_srvconf_merge(dh_params, NULL);
     738
     739    gnutls_srvconf_merge(proxy_x509_key_file, NULL);
     740    gnutls_srvconf_merge(proxy_x509_cert_file, NULL);
     741    gnutls_srvconf_merge(proxy_x509_ca_file, NULL);
     742    gnutls_srvconf_merge(proxy_x509_crl_file, NULL);
     743    gnutls_srvconf_merge(proxy_priorities, NULL);
    988744
    989745    /* FIXME: the following items are pre-allocated, and should be
    990746     * properly disposed of before assigning in order to avoid leaks;
    991747     * so at the moment, we can't actually have them in the config.
    992      * what happens during de-allocation? */
    993     gnutls_srvconf_assign(ca_list);
    994     gnutls_srvconf_assign(ca_list_size);
    995     gnutls_srvconf_assign(cert_pgp);
    996     gnutls_srvconf_assign(cert_crt_pgp);
    997     gnutls_srvconf_assign(pgp_list);
     748     * what happens during de-allocation?
     749
     750     * This is probably leaky.
     751     */
    998752    gnutls_srvconf_assign(certs);
    999753    gnutls_srvconf_assign(anon_creds);
     754    gnutls_srvconf_assign(anon_client_creds);
    1000755    gnutls_srvconf_assign(srp_creds);
    1001756    gnutls_srvconf_assign(certs_x509_chain);
    1002     gnutls_srvconf_assign(certs_x509_crt_chain);
    1003757    gnutls_srvconf_assign(certs_x509_chain_num);
    1004758
     
    1007761    gnutls_srvconf_assign(cert_cn);
    1008762    for (i = 0; i < MAX_CERT_SAN; i++)
    1009         gnutls_srvconf_assign(cert_san[i]);
     763        gnutls_srvconf_assign(cert_san[i]);
     764    gnutls_srvconf_assign(ca_list);
     765    gnutls_srvconf_assign(ca_list_size);
     766    gnutls_srvconf_assign(cert_pgp);
     767    gnutls_srvconf_assign(pgp_list);
     768    gnutls_srvconf_assign(privkey_pgp);
    1010769
    1011770    return sc;
     
    1022781    mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv;
    1023782
    1024     new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof(mgs_dirconf_rec));
     783    new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof (mgs_dirconf_rec));
    1025784    new->client_verify_mode = add->client_verify_mode;
    1026785    return new;
     
    1033792    return dc;
    1034793}
     794
     795/*
     796 * Store paths to proxy credentials
     797 *
     798 * This function copies the paths provided in the configuration file
     799 * into the server configuration. The post configuration hook takes
     800 * care of actually loading the credentials, which means than invalid
     801 * paths or the like will be detected there.
     802 */
     803const char *mgs_store_cred_path(cmd_parms * parms,
     804                                void *dummy __attribute__((unused)),
     805                                const char *arg)
     806{
     807    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     808        ap_get_module_config(parms->server->module_config, &gnutls_module);
     809
     810    /* parms->directive->directive contains the directive string */
     811    if (!strcasecmp(parms->directive->directive, "GnuTLSProxyKeyFile"))
     812        sc->proxy_x509_key_file = apr_pstrdup(parms->pool, arg);
     813    else if (!strcasecmp(parms->directive->directive,
     814                         "GnuTLSProxyCertificateFile"))
     815        sc->proxy_x509_cert_file = apr_pstrdup(parms->pool, arg);
     816    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyCAFile"))
     817        sc->proxy_x509_ca_file = apr_pstrdup(parms->pool, arg);
     818    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyCRLFile"))
     819        sc->proxy_x509_crl_file = apr_pstrdup(parms->pool, arg);
     820    return NULL;
     821}
Note: See TracChangeset for help on using the changeset viewer.