source: mod_gnutls/src/gnutls_config.c @ 809c422

debian/masterdebian/stretch-backportsjessie-backportsupstream
Last change on this file since 809c422 was 809c422, checked in by Thomas Klute <thomas2.klute@…>, 5 years ago

TLS proxy: Add support for CRLs to back end server verification

When configured as a TLS proxy, mod_gnutls can now use CRLs to check if
the certificate provided by a back end server is still valid. The CRL
file must be provided externally, the new configuration option
"GnuTLSProxyCRLFile" is used to load it.

  • Property mode set to 100644
File size: 24.5 KB
RevLine 
[46b85d8]1/**
2 *  Copyright 2004-2005 Paul Querna
[e183628]3 *  Copyright 2008 Nikos Mavrogiannopoulos
4 *  Copyright 2011 Dash Shendy
[46b85d8]5 *
6 *  Licensed under the Apache License, Version 2.0 (the "License");
7 *  you may not use this file except in compliance with the License.
8 *  You may obtain a copy of the License at
9 *
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 *
12 *  Unless required by applicable law or agreed to in writing, software
13 *  distributed under the License is distributed on an "AS IS" BASIS,
14 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 *  See the License for the specific language governing permissions and
16 *  limitations under the License.
17 *
18 */
19
20#include "mod_gnutls.h"
[2aaf4f5]21#include "apr_lib.h"
[46b85d8]22
[55dc3f0]23#ifdef APLOG_USE_MODULE
24APLOG_USE_MODULE(gnutls);
25#endif
26
[7bebb42]27static int load_datum_from_file(apr_pool_t * pool,
[e183628]28        const char *file, gnutls_datum_t * data) {
29    apr_file_t *fp;
30    apr_finfo_t finfo;
31    apr_status_t rv;
32    apr_size_t br = 0;
[7bebb42]33
[e183628]34    rv = apr_file_open(&fp, file, APR_READ | APR_BINARY,
35            APR_OS_DEFAULT, pool);
36    if (rv != APR_SUCCESS) {
37        return rv;
38    }
[7bebb42]39
[e183628]40    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp);
[7bebb42]41
[e183628]42    if (rv != APR_SUCCESS) {
43        return rv;
44    }
[7bebb42]45
[e183628]46    data->data = apr_palloc(pool, finfo.size + 1);
47    rv = apr_file_read_full(fp, data->data, finfo.size, &br);
[7bebb42]48
[e183628]49    if (rv != APR_SUCCESS) {
50        return rv;
51    }
52    apr_file_close(fp);
[7bebb42]53
[e183628]54    data->data[br] = '\0';
55    data->size = br;
[7bebb42]56
[e183628]57    return 0;
[46b85d8]58}
59
[fd82e59]60const char *mgs_set_dh_file(cmd_parms * parms, void *dummy __attribute__((unused)),
[e183628]61        const char *arg) {
62    int ret;
63    gnutls_datum_t data;
64    const char *file;
65    apr_pool_t *spool;
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    }
79
80    ret = gnutls_dh_params_init(&sc->dh_params);
81    if (ret < 0) {
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
98    apr_pool_destroy(spool);
99
100    return NULL;
[7bebb42]101}
102
[0de1839]103const char *mgs_set_cert_file(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg)
104{
[e183628]105    int ret;
106    gnutls_datum_t data;
107    const char *file;
108    apr_pool_t *spool;
109
[3b4c0d0]110    mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server->module_config, &gnutls_module);
[e183628]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) {
[3b4c0d0]116                apr_pool_destroy(spool);
117        return apr_psprintf(parms->pool, "GnuTLS: Error Reading Certificate '%s'", file);
[e183628]118    }
119
[3b4c0d0]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);
[e183628]122    if (ret < 0) {
[3b4c0d0]123                apr_pool_destroy(spool);
124        return apr_psprintf(parms->pool, "GnuTLS: Failed to Import Certificate '%s': (%d) %s", file, ret, gnutls_strerror(ret));
[e183628]125    }
[671b64f]126
[3b4c0d0]127        apr_pool_destroy(spool);
[e183628]128    return NULL;
129
[46b85d8]130}
131
[fd82e59]132const char *mgs_set_key_file(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg) {
[3b4c0d0]133
[e183628]134    int ret;
135    gnutls_datum_t data;
136    const char *file;
137    apr_pool_t *spool;
[929d313]138    const char *out;
[3b4c0d0]139
140        mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server->module_config, &gnutls_module);
[671b64f]141
[3b4c0d0]142        apr_pool_create(&spool, parms->pool);
[e183628]143
144    file = ap_server_root_relative(spool, arg);
145
146    if (load_datum_from_file(spool, file, &data) != 0) {
[929d313]147        out = apr_psprintf(parms->pool, "GnuTLS: Error Reading Private Key '%s'", file);
[3b4c0d0]148                apr_pool_destroy(spool);
[929d313]149        return out;
[e183628]150    }
151
152    ret = gnutls_x509_privkey_init(&sc->privkey_x509);
[3b4c0d0]153
[e183628]154    if (ret < 0) {
[3b4c0d0]155                apr_pool_destroy(spool);
156        return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize: (%d) %s", ret, gnutls_strerror(ret));
[e183628]157    }
158
[3b4c0d0]159    ret = gnutls_x509_privkey_import(sc->privkey_x509, &data, GNUTLS_X509_FMT_PEM);
[e183628]160
[3b4c0d0]161    if (ret < 0) {
162        ret = gnutls_x509_privkey_import_pkcs8(sc->privkey_x509, &data, GNUTLS_X509_FMT_PEM, NULL, GNUTLS_PKCS_PLAIN);
163        }
[e183628]164
165    if (ret < 0) {
[929d313]166        out = apr_psprintf(parms->pool, "GnuTLS: Failed to Import Private Key '%s': (%d) %s", file, ret, gnutls_strerror(ret));
[3b4c0d0]167                apr_pool_destroy(spool);
[929d313]168        return out;
[e183628]169    }
[3b4c0d0]170
[e183628]171    apr_pool_destroy(spool);
[3b4c0d0]172
[e183628]173    return NULL;
[46b85d8]174}
175
[fd82e59]176const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy __attribute__((unused)),
[e183628]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);
213    return NULL;
[e5bbda4]214}
215
[fd82e59]216const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy __attribute__((unused)),
[e183628]217        const char *arg) {
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);
254    return NULL;
[e5bbda4]255}
256
[fd82e59]257const char *mgs_set_tickets(cmd_parms * parms, void *dummy __attribute__((unused)),
[e183628]258        const char *arg) {
259    mgs_srvconf_rec *sc =
260            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
261            module_config,
262            &gnutls_module);
263
264    sc->tickets = 0;
265    if (strcasecmp("on", arg) == 0) {
266        sc->tickets = 1;
267    }
268
269    return NULL;
[ae233c2]270}
271
[e5bbda4]272
[787dab7]273#ifdef ENABLE_SRP
274
[fd82e59]275const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy __attribute__((unused)),
[e183628]276        const char *arg) {
277    mgs_srvconf_rec *sc =
278            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
279            module_config,
280            &gnutls_module);
[7bebb42]281
[e183628]282    sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg);
[7bebb42]283
[e183628]284    return NULL;
[7bebb42]285}
286
[fd82e59]287const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy __attribute__((unused)),
[e183628]288        const char *arg) {
289    mgs_srvconf_rec *sc =
290            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
291            module_config,
292            &gnutls_module);
[7bebb42]293
[e183628]294    sc->srp_tpasswd_conf_file =
295            ap_server_root_relative(parms->pool, arg);
[7bebb42]296
[e183628]297    return NULL;
[7bebb42]298}
299
[787dab7]300#endif
301
[fd82e59]302const char *mgs_set_cache(cmd_parms * parms, void *dummy __attribute__((unused)),
[e183628]303        const char *type, const char *arg) {
304    const char *err;
305    mgs_srvconf_rec *sc =
306            ap_get_module_config(parms->server->module_config,
307            &gnutls_module);
308    if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) {
309        return err;
310    }
311
312    if (strcasecmp("none", type) == 0) {
313        sc->cache_type = mgs_cache_none;
314        sc->cache_config = NULL;
315        return NULL;
316    } else if (strcasecmp("dbm", type) == 0) {
317        sc->cache_type = mgs_cache_dbm;
318    } else if (strcasecmp("gdbm", type) == 0) {
319        sc->cache_type = mgs_cache_gdbm;
320    }
[46b85d8]321#if HAVE_APR_MEMCACHE
[e183628]322    else if (strcasecmp("memcache", type) == 0) {
323        sc->cache_type = mgs_cache_memcache;
324    }
[46b85d8]325#endif
[e183628]326    else {
327        return "Invalid Type for GnuTLSCache!";
328    }
329
330    if (arg == NULL)
331        return "Invalid argument 2 for GnuTLSCache!";
332
333    if (sc->cache_type == mgs_cache_dbm
334            || sc->cache_type == mgs_cache_gdbm) {
335        sc->cache_config =
336                ap_server_root_relative(parms->pool, arg);
337    } else {
338        sc->cache_config = apr_pstrdup(parms->pool, arg);
339    }
340
341    return NULL;
[46b85d8]342}
343
[fd82e59]344const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy __attribute__((unused)),
[e183628]345        const char *arg) {
346    int argint;
[480aba1]347    const char *err;
[e183628]348    mgs_srvconf_rec *sc =
349            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
350            module_config,
351            &gnutls_module);
352
[480aba1]353    if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) {
354        return err;
355    }
356
[e183628]357    argint = atoi(arg);
358
359    if (argint < 0) {
360        return "GnuTLSCacheTimeout: Invalid argument";
361    } else if (argint == 0) {
362        sc->cache_timeout = 0;
363    } else {
364        sc->cache_timeout = apr_time_from_sec(argint);
365    }
366
367    return NULL;
[e02dd8c]368}
369
[fd82e59]370const char *mgs_set_client_verify_method(cmd_parms * parms, void *dummy __attribute__((unused)),
[cf2b905]371        const char *arg) {
372    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)ap_get_module_config(parms->server->module_config, &gnutls_module);
373
374    if (strcasecmp("cartel", arg) == 0) {
375        sc->client_verify_method = mgs_cvm_cartel;
376    } else if (strcasecmp("msva", arg) == 0) {
377#ifdef ENABLE_MSVA
378        sc->client_verify_method = mgs_cvm_msva;
379#else
380        return "GnuTLSClientVerifyMethod: msva is not supported";
381#endif
382    } else {
383        return "GnuTLSClientVerifyMethod: Invalid argument";
384    }
385
386    return NULL;
387}
388
[fd82e59]389const char *mgs_set_client_verify(cmd_parms * parms,
390                                  void *dirconf,
391                                  const char *arg) {
[e183628]392    int mode;
393
394    if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) {
395        mode = GNUTLS_CERT_IGNORE;
396    } else if (strcasecmp("optional", arg) == 0
397            || strcasecmp("request", arg) == 0) {
398        mode = GNUTLS_CERT_REQUEST;
399    } else if (strcasecmp("require", arg) == 0) {
400        mode = GNUTLS_CERT_REQUIRE;
401    } else {
402        return "GnuTLSClientVerify: Invalid argument";
403    }
404
405    /* This was set from a directory context */
406    if (parms->path) {
[fd82e59]407        mgs_dirconf_rec *dc = (mgs_dirconf_rec *) dirconf;
[e183628]408        dc->client_verify_mode = mode;
409    } else {
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;
[46b85d8]418}
419
[8663ace]420#define INIT_CA_SIZE 128
[e183628]421
[fd82e59]422const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy __attribute__((unused)),
[e183628]423        const char *arg) {
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);
481    return NULL;
[46b85d8]482}
483
[fd82e59]484const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy __attribute__((unused)),
[e183628]485        const char *arg) {
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);
521    return NULL;
[e5bbda4]522}
523
[fd82e59]524const char *mgs_set_proxy_engine(cmd_parms * parms, void *dummy __attribute__((unused)),
[33826c5]525        const char *arg) {
[671b64f]526
527    mgs_srvconf_rec *sc =(mgs_srvconf_rec *)
[33826c5]528            ap_get_module_config(parms->server->module_config, &gnutls_module);
[671b64f]529
[33826c5]530    if (!strcasecmp(arg, "On")) {
531        sc->proxy_enabled = GNUTLS_ENABLED_TRUE;
532    } else if (!strcasecmp(arg, "Off")) {
533        sc->proxy_enabled = GNUTLS_ENABLED_FALSE;
534    } else {
535        return "SSLProxyEngine must be set to 'On' or 'Off'";
536    }
537
538    return NULL;
539}
540
[fd82e59]541const char *mgs_set_enabled(cmd_parms * parms, void *dummy __attribute__((unused)),
[e183628]542        const char *arg) {
543    mgs_srvconf_rec *sc =
544            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
545            module_config,
546            &gnutls_module);
547    if (!strcasecmp(arg, "On")) {
548        sc->enabled = GNUTLS_ENABLED_TRUE;
549    } else if (!strcasecmp(arg, "Off")) {
550        sc->enabled = GNUTLS_ENABLED_FALSE;
551    } else {
552        return "GnuTLSEnable must be set to 'On' or 'Off'";
553    }
554
555    return NULL;
[7bebb42]556}
557
[fd82e59]558const char *mgs_set_export_certificates_size(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg) {
[7d1ab49]559    mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server->module_config, &gnutls_module);
560    if (!strcasecmp(arg, "On")) {
[2aaf4f5]561        sc->export_certificates_size = 16 * 1024;
[7d1ab49]562    } else if (!strcasecmp(arg, "Off")) {
[2aaf4f5]563        sc->export_certificates_size = 0;
[7d1ab49]564    } else {
[2aaf4f5]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        }
[7d1ab49]575    }
576
577    return NULL;
578}
579
[fd82e59]580const char *mgs_set_priorities(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg) {
[e183628]581
[3b4c0d0]582        int ret;
[e183628]583    const char *err;
584
[671b64f]585    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
[3b4c0d0]586                                                  ap_get_module_config(parms->server->module_config, &gnutls_module);
[e183628]587
588    ret = gnutls_priority_init(&sc->priorities, arg, &err);
[3b4c0d0]589
[e183628]590    if (ret < 0) {
[3b4c0d0]591        if (ret == GNUTLS_E_INVALID_REQUEST) {
[671b64f]592            return apr_psprintf(parms->pool,
[3b4c0d0]593                                                                "GnuTLS: Syntax error parsing priorities string at: %s", err);
594                }
[e183628]595        return "Error setting priorities";
596    }
597
598    return NULL;
[46b85d8]599}
600
[040387c]601static mgs_srvconf_rec *_mgs_config_server_create(apr_pool_t * p, char** err) {
[e183628]602    mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof (*sc));
603    int ret;
604
[040387c]605    sc->enabled = GNUTLS_ENABLED_UNSET;
[e183628]606
607    ret = gnutls_certificate_allocate_credentials(&sc->certs);
608    if (ret < 0) {
[040387c]609        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
610                            ": (%d) %s", ret,
611                            gnutls_strerror(ret));
612        return NULL;
[e183628]613    }
614
615    ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds);
616    if (ret < 0) {
[040387c]617        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
618                            ": (%d) %s", ret,
619                            gnutls_strerror(ret));
620        return NULL;
[e183628]621    }
[beb14d9]622
623    /* FIXME: not ideal, should be called only if SSLProxyEngine is
624     * enabled */
625    ret = gnutls_anon_allocate_client_credentials(&sc->anon_client_creds);
626    if (ret < 0)
627    {
628        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
629                            ": (%d) %s", ret,
630                            gnutls_strerror(ret));
631        return NULL;
632    }
[0de1839]633
634    sc->proxy_x509_key_file = NULL;
635    sc->proxy_x509_cert_file = NULL;
636    sc->proxy_x509_ca_file = NULL;
[809c422]637    sc->proxy_x509_crl_file = NULL;
[0de1839]638    ret = gnutls_certificate_allocate_credentials(&sc->proxy_x509_creds);
639    if (ret < 0)
640    {
641        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
642                            ": (%d) %s", ret,
643                            gnutls_strerror(ret));
644        return NULL;
645    }
646
[787dab7]647#ifdef ENABLE_SRP
[e183628]648    ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds);
649    if (ret < 0) {
[040387c]650        *err =  apr_psprintf(p, "GnuTLS: Failed to initialize"
651                             ": (%d) %s", ret,
652                             gnutls_strerror(ret));
653        return NULL;
[e183628]654    }
655
656    sc->srp_tpasswd_conf_file = NULL;
657    sc->srp_tpasswd_file = NULL;
[787dab7]658#endif
659
[e183628]660    sc->privkey_x509 = NULL;
[3b4c0d0]661        /* Initialize all Certificate Chains */
[040387c]662    /* FIXME: how do we indicate that this is unset for a merge? (that
663     * is, how can a subordinate server override the chain by setting
664     * an empty one?  what would that even look like in the
665     * configuration?) */
[3b4c0d0]666        sc->certs_x509_chain = malloc(MAX_CHAIN_SIZE * sizeof (*sc->certs_x509_chain));
667    sc->certs_x509_chain_num = 0;
[040387c]668    sc->cache_timeout = -1; /* -1 means "unset" */
669    sc->cache_type = mgs_cache_unset;
[8400c2e]670    sc->cache_config = NULL;
[040387c]671    sc->tickets = GNUTLS_ENABLED_UNSET;
672    sc->priorities = NULL;
673    sc->dh_params = NULL;
674    sc->proxy_enabled = GNUTLS_ENABLED_UNSET;
[2aaf4f5]675    sc->export_certificates_size = -1;
[671b64f]676    sc->client_verify_method = mgs_cvm_unset;
677
[040387c]678/* this relies on GnuTLS never changing the gnutls_certificate_request_t enum to define -1 */
[671b64f]679    sc->client_verify_mode = -1;
[7bebb42]680
[040387c]681    return sc;
682}
683
[fd82e59]684void *mgs_config_server_create(apr_pool_t * p,
685                               server_rec * s __attribute__((unused))) {
[040387c]686    char *err = NULL;
687    mgs_srvconf_rec *sc = _mgs_config_server_create(p, &err);
688    if (sc) return sc; else return err;
689}
690
691#define gnutls_srvconf_merge(t, unset) sc->t = (add->t == unset) ? base->t : add->t
692#define gnutls_srvconf_assign(t) sc->t = add->t
693
694void *mgs_config_server_merge(apr_pool_t *p, void *BASE, void *ADD) {
695    int i;
696    char *err = NULL;
697    mgs_srvconf_rec *base = (mgs_srvconf_rec *)BASE;
698    mgs_srvconf_rec *add = (mgs_srvconf_rec *)ADD;
699    mgs_srvconf_rec *sc = _mgs_config_server_create(p, &err);
700    if (NULL == sc) return err;
701
702    gnutls_srvconf_merge(enabled, GNUTLS_ENABLED_UNSET);
703    gnutls_srvconf_merge(tickets, GNUTLS_ENABLED_UNSET);
704    gnutls_srvconf_merge(proxy_enabled, GNUTLS_ENABLED_UNSET);
[2aaf4f5]705    gnutls_srvconf_merge(export_certificates_size, -1);
[cf2b905]706    gnutls_srvconf_merge(client_verify_method, mgs_cvm_unset);
[040387c]707    gnutls_srvconf_merge(client_verify_mode, -1);
708    gnutls_srvconf_merge(srp_tpasswd_file, NULL);
709    gnutls_srvconf_merge(srp_tpasswd_conf_file, NULL);
710    gnutls_srvconf_merge(privkey_x509, NULL);
711    gnutls_srvconf_merge(priorities, NULL);
712    gnutls_srvconf_merge(dh_params, NULL);
713
[0de1839]714    gnutls_srvconf_merge(proxy_x509_key_file, NULL);
715    gnutls_srvconf_merge(proxy_x509_cert_file, NULL);
716    gnutls_srvconf_merge(proxy_x509_ca_file, NULL);
[809c422]717    gnutls_srvconf_merge(proxy_x509_crl_file, NULL);
[0de1839]718
[040387c]719    /* FIXME: the following items are pre-allocated, and should be
720     * properly disposed of before assigning in order to avoid leaks;
721     * so at the moment, we can't actually have them in the config.
[671b64f]722     * what happens during de-allocation?
[040387c]723
724     * This is probably leaky.
725     */
726    gnutls_srvconf_assign(certs);
727    gnutls_srvconf_assign(anon_creds);
[beb14d9]728    gnutls_srvconf_assign(anon_client_creds);
[040387c]729    gnutls_srvconf_assign(srp_creds);
730    gnutls_srvconf_assign(certs_x509_chain);
731    gnutls_srvconf_assign(certs_x509_chain_num);
732
733    /* how do these get transferred cleanly before the data from ADD
734     * goes away? */
735    gnutls_srvconf_assign(cert_cn);
736    for (i = 0; i < MAX_CERT_SAN; i++)
737        gnutls_srvconf_assign(cert_san[i]);
738    gnutls_srvconf_assign(ca_list);
739    gnutls_srvconf_assign(ca_list_size);
740    gnutls_srvconf_assign(cert_pgp);
741    gnutls_srvconf_assign(pgp_list);
742    gnutls_srvconf_assign(privkey_pgp);
[7bebb42]743
[e183628]744    return sc;
[46b85d8]745}
746
[040387c]747#undef gnutls_srvconf_merge
748#undef gnutls_srvconf_assign
749
[fd82e59]750void *mgs_config_dir_merge(apr_pool_t * p,
751                           void *basev __attribute__((unused)),
752                           void *addv __attribute__((unused))) {
[e183628]753    mgs_dirconf_rec *new;
754    /*    mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */
755    mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv;
[e02dd8c]756
[e183628]757    new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof (mgs_dirconf_rec));
758    new->client_verify_mode = add->client_verify_mode;
759    return new;
[84cb5b2]760}
761
[fd82e59]762void *mgs_config_dir_create(apr_pool_t * p,
763                            char *dir __attribute__((unused))) {
[e183628]764    mgs_dirconf_rec *dc = apr_palloc(p, sizeof (*dc));
765    dc->client_verify_mode = -1;
766    return dc;
[46b85d8]767}
[040387c]768
[0de1839]769/*
770 * Store paths to proxy credentials
771 *
772 * This function copies the paths provided in the configuration file
773 * into the server configuration. The post configuration hook takes
774 * care of actually loading the credentials, which means than invalid
775 * paths or the like will be detected there.
776 */
777const char *mgs_store_cred_path(cmd_parms * parms,
778                                void *dummy __attribute__((unused)),
779                                const char *arg)
780{
781    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
782        ap_get_module_config(parms->server->module_config, &gnutls_module);
783
784    /* parms->directive->directive contains the directive string */
785    if (!strcasecmp(parms->directive->directive, "GnuTLSProxyKeyFile"))
786        sc->proxy_x509_key_file = apr_pstrdup(parms->pool, arg);
787    else if (!strcasecmp(parms->directive->directive,
788                         "GnuTLSProxyCertificateFile"))
789        sc->proxy_x509_cert_file = apr_pstrdup(parms->pool, arg);
790    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyCAFile"))
791        sc->proxy_x509_ca_file = apr_pstrdup(parms->pool, arg);
[809c422]792    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyCRLFile"))
793        sc->proxy_x509_crl_file = apr_pstrdup(parms->pool, arg);
[0de1839]794    return NULL;
795}
Note: See TracBrowser for help on using the repository browser.