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
Line 
1/**
2 *  Copyright 2004-2005 Paul Querna
3 *  Copyright 2008 Nikos Mavrogiannopoulos
4 *  Copyright 2011 Dash Shendy
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"
21#include "apr_lib.h"
22
23#ifdef APLOG_USE_MODULE
24APLOG_USE_MODULE(gnutls);
25#endif
26
27static int load_datum_from_file(apr_pool_t * pool,
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;
33
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    }
39
40    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp);
41
42    if (rv != APR_SUCCESS) {
43        return rv;
44    }
45
46    data->data = apr_palloc(pool, finfo.size + 1);
47    rv = apr_file_read_full(fp, data->data, finfo.size, &br);
48
49    if (rv != APR_SUCCESS) {
50        return rv;
51    }
52    apr_file_close(fp);
53
54    data->data[br] = '\0';
55    data->size = br;
56
57    return 0;
58}
59
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;
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;
101}
102
103const char *mgs_set_cert_file(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg)
104{
105    int ret;
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);
128    return NULL;
129
130}
131
132const char *mgs_set_key_file(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg) {
133
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);
172
173    return NULL;
174}
175
176const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy __attribute__((unused)),
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;
214}
215
216const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy __attribute__((unused)),
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;
255}
256
257const char *mgs_set_tickets(cmd_parms * parms, void *dummy __attribute__((unused)),
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;
270}
271
272
273#ifdef ENABLE_SRP
274
275const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy __attribute__((unused)),
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);
281
282    sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg);
283
284    return NULL;
285}
286
287const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy __attribute__((unused)),
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);
293
294    sc->srp_tpasswd_conf_file =
295            ap_server_root_relative(parms->pool, arg);
296
297    return NULL;
298}
299
300#endif
301
302const char *mgs_set_cache(cmd_parms * parms, void *dummy __attribute__((unused)),
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    }
321#if HAVE_APR_MEMCACHE
322    else if (strcasecmp("memcache", type) == 0) {
323        sc->cache_type = mgs_cache_memcache;
324    }
325#endif
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;
342}
343
344const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy __attribute__((unused)),
345        const char *arg) {
346    int argint;
347    const char *err;
348    mgs_srvconf_rec *sc =
349            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
350            module_config,
351            &gnutls_module);
352
353    if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) {
354        return err;
355    }
356
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;
368}
369
370const char *mgs_set_client_verify_method(cmd_parms * parms, void *dummy __attribute__((unused)),
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
389const char *mgs_set_client_verify(cmd_parms * parms,
390                                  void *dirconf,
391                                  const char *arg) {
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) {
407        mgs_dirconf_rec *dc = (mgs_dirconf_rec *) dirconf;
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;
418}
419
420#define INIT_CA_SIZE 128
421
422const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy __attribute__((unused)),
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;
482}
483
484const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy __attribute__((unused)),
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;
522}
523
524const char *mgs_set_proxy_engine(cmd_parms * parms, void *dummy __attribute__((unused)),
525        const char *arg) {
526
527    mgs_srvconf_rec *sc =(mgs_srvconf_rec *)
528            ap_get_module_config(parms->server->module_config, &gnutls_module);
529
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
541const char *mgs_set_enabled(cmd_parms * parms, void *dummy __attribute__((unused)),
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;
556}
557
558const char *mgs_set_export_certificates_size(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg) {
559    mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server->module_config, &gnutls_module);
560    if (!strcasecmp(arg, "On")) {
561        sc->export_certificates_size = 16 * 1024;
562    } else if (!strcasecmp(arg, "Off")) {
563        sc->export_certificates_size = 0;
564    } else {
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
580const char *mgs_set_priorities(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg) {
581
582        int ret;
583    const char *err;
584
585    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
586                                                  ap_get_module_config(parms->server->module_config, &gnutls_module);
587
588    ret = gnutls_priority_init(&sc->priorities, arg, &err);
589
590    if (ret < 0) {
591        if (ret == GNUTLS_E_INVALID_REQUEST) {
592            return apr_psprintf(parms->pool,
593                                                                "GnuTLS: Syntax error parsing priorities string at: %s", err);
594                }
595        return "Error setting priorities";
596    }
597
598    return NULL;
599}
600
601static mgs_srvconf_rec *_mgs_config_server_create(apr_pool_t * p, char** err) {
602    mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof (*sc));
603    int ret;
604
605    sc->enabled = GNUTLS_ENABLED_UNSET;
606
607    ret = gnutls_certificate_allocate_credentials(&sc->certs);
608    if (ret < 0) {
609        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
610                            ": (%d) %s", ret,
611                            gnutls_strerror(ret));
612        return NULL;
613    }
614
615    ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds);
616    if (ret < 0) {
617        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
618                            ": (%d) %s", ret,
619                            gnutls_strerror(ret));
620        return NULL;
621    }
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    }
633
634    sc->proxy_x509_key_file = NULL;
635    sc->proxy_x509_cert_file = NULL;
636    sc->proxy_x509_ca_file = NULL;
637    sc->proxy_x509_crl_file = NULL;
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
647#ifdef ENABLE_SRP
648    ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds);
649    if (ret < 0) {
650        *err =  apr_psprintf(p, "GnuTLS: Failed to initialize"
651                             ": (%d) %s", ret,
652                             gnutls_strerror(ret));
653        return NULL;
654    }
655
656    sc->srp_tpasswd_conf_file = NULL;
657    sc->srp_tpasswd_file = NULL;
658#endif
659
660    sc->privkey_x509 = NULL;
661        /* Initialize all Certificate Chains */
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?) */
666        sc->certs_x509_chain = malloc(MAX_CHAIN_SIZE * sizeof (*sc->certs_x509_chain));
667    sc->certs_x509_chain_num = 0;
668    sc->cache_timeout = -1; /* -1 means "unset" */
669    sc->cache_type = mgs_cache_unset;
670    sc->cache_config = NULL;
671    sc->tickets = GNUTLS_ENABLED_UNSET;
672    sc->priorities = NULL;
673    sc->dh_params = NULL;
674    sc->proxy_enabled = GNUTLS_ENABLED_UNSET;
675    sc->export_certificates_size = -1;
676    sc->client_verify_method = mgs_cvm_unset;
677
678/* this relies on GnuTLS never changing the gnutls_certificate_request_t enum to define -1 */
679    sc->client_verify_mode = -1;
680
681    return sc;
682}
683
684void *mgs_config_server_create(apr_pool_t * p,
685                               server_rec * s __attribute__((unused))) {
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);
705    gnutls_srvconf_merge(export_certificates_size, -1);
706    gnutls_srvconf_merge(client_verify_method, mgs_cvm_unset);
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
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);
717    gnutls_srvconf_merge(proxy_x509_crl_file, NULL);
718
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.
722     * what happens during de-allocation?
723
724     * This is probably leaky.
725     */
726    gnutls_srvconf_assign(certs);
727    gnutls_srvconf_assign(anon_creds);
728    gnutls_srvconf_assign(anon_client_creds);
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);
743
744    return sc;
745}
746
747#undef gnutls_srvconf_merge
748#undef gnutls_srvconf_assign
749
750void *mgs_config_dir_merge(apr_pool_t * p,
751                           void *basev __attribute__((unused)),
752                           void *addv __attribute__((unused))) {
753    mgs_dirconf_rec *new;
754    /*    mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */
755    mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv;
756
757    new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof (mgs_dirconf_rec));
758    new->client_verify_mode = add->client_verify_mode;
759    return new;
760}
761
762void *mgs_config_dir_create(apr_pool_t * p,
763                            char *dir __attribute__((unused))) {
764    mgs_dirconf_rec *dc = apr_palloc(p, sizeof (*dc));
765    dc->client_verify_mode = -1;
766    return dc;
767}
768
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);
792    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyCRLFile"))
793        sc->proxy_x509_crl_file = apr_pstrdup(parms->pool, arg);
794    return NULL;
795}
Note: See TracBrowser for help on using the repository browser.