source: mod_gnutls/src/gnutls_config.c @ beb14d9

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

Proof of concept: Support for proxy back end connections using TLS

This commit enables TLS on proxy back end connections if requested from
mod_proxy. Since mod_gnutls acts as client instead of server on proxy
back end connections, TLS session setup is quite different.

Note that this implementation is not finished, in particular the proxy
back end connection is hard coded to use the same X.509 credentials as
the server side, which severely restricts usable certificate
combinations.

Some typos in comments and an error message related to TLS handshake are
fixed as well.

  • Property mode set to 100644
File size: 22.6 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#ifdef ENABLE_SRP
634    ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds);
635    if (ret < 0) {
636        *err =  apr_psprintf(p, "GnuTLS: Failed to initialize"
637                             ": (%d) %s", ret,
638                             gnutls_strerror(ret));
639        return NULL;
640    }
641
642    sc->srp_tpasswd_conf_file = NULL;
643    sc->srp_tpasswd_file = NULL;
644#endif
645
646    sc->privkey_x509 = NULL;
647        /* Initialize all Certificate Chains */
648    /* FIXME: how do we indicate that this is unset for a merge? (that
649     * is, how can a subordinate server override the chain by setting
650     * an empty one?  what would that even look like in the
651     * configuration?) */
652        sc->certs_x509_chain = malloc(MAX_CHAIN_SIZE * sizeof (*sc->certs_x509_chain));
653    sc->certs_x509_chain_num = 0;
654    sc->cache_timeout = -1; /* -1 means "unset" */
655    sc->cache_type = mgs_cache_unset;
656    sc->cache_config = NULL;
657    sc->tickets = GNUTLS_ENABLED_UNSET;
658    sc->priorities = NULL;
659    sc->dh_params = NULL;
660    sc->proxy_enabled = GNUTLS_ENABLED_UNSET;
661    sc->export_certificates_size = -1;
662    sc->client_verify_method = mgs_cvm_unset;
663
664/* this relies on GnuTLS never changing the gnutls_certificate_request_t enum to define -1 */
665    sc->client_verify_mode = -1;
666
667    return sc;
668}
669
670void *mgs_config_server_create(apr_pool_t * p,
671                               server_rec * s __attribute__((unused))) {
672    char *err = NULL;
673    mgs_srvconf_rec *sc = _mgs_config_server_create(p, &err);
674    if (sc) return sc; else return err;
675}
676
677#define gnutls_srvconf_merge(t, unset) sc->t = (add->t == unset) ? base->t : add->t
678#define gnutls_srvconf_assign(t) sc->t = add->t
679
680void *mgs_config_server_merge(apr_pool_t *p, void *BASE, void *ADD) {
681    int i;
682    char *err = NULL;
683    mgs_srvconf_rec *base = (mgs_srvconf_rec *)BASE;
684    mgs_srvconf_rec *add = (mgs_srvconf_rec *)ADD;
685    mgs_srvconf_rec *sc = _mgs_config_server_create(p, &err);
686    if (NULL == sc) return err;
687
688    gnutls_srvconf_merge(enabled, GNUTLS_ENABLED_UNSET);
689    gnutls_srvconf_merge(tickets, GNUTLS_ENABLED_UNSET);
690    gnutls_srvconf_merge(proxy_enabled, GNUTLS_ENABLED_UNSET);
691    gnutls_srvconf_merge(export_certificates_size, -1);
692    gnutls_srvconf_merge(client_verify_method, mgs_cvm_unset);
693    gnutls_srvconf_merge(client_verify_mode, -1);
694    gnutls_srvconf_merge(srp_tpasswd_file, NULL);
695    gnutls_srvconf_merge(srp_tpasswd_conf_file, NULL);
696    gnutls_srvconf_merge(privkey_x509, NULL);
697    gnutls_srvconf_merge(priorities, NULL);
698    gnutls_srvconf_merge(dh_params, NULL);
699
700    /* FIXME: the following items are pre-allocated, and should be
701     * properly disposed of before assigning in order to avoid leaks;
702     * so at the moment, we can't actually have them in the config.
703     * what happens during de-allocation?
704
705     * This is probably leaky.
706     */
707    gnutls_srvconf_assign(certs);
708    gnutls_srvconf_assign(anon_creds);
709    gnutls_srvconf_assign(anon_client_creds);
710    gnutls_srvconf_assign(srp_creds);
711    gnutls_srvconf_assign(certs_x509_chain);
712    gnutls_srvconf_assign(certs_x509_chain_num);
713
714    /* how do these get transferred cleanly before the data from ADD
715     * goes away? */
716    gnutls_srvconf_assign(cert_cn);
717    for (i = 0; i < MAX_CERT_SAN; i++)
718        gnutls_srvconf_assign(cert_san[i]);
719    gnutls_srvconf_assign(ca_list);
720    gnutls_srvconf_assign(ca_list_size);
721    gnutls_srvconf_assign(cert_pgp);
722    gnutls_srvconf_assign(pgp_list);
723    gnutls_srvconf_assign(privkey_pgp);
724
725    return sc;
726}
727
728#undef gnutls_srvconf_merge
729#undef gnutls_srvconf_assign
730
731void *mgs_config_dir_merge(apr_pool_t * p,
732                           void *basev __attribute__((unused)),
733                           void *addv __attribute__((unused))) {
734    mgs_dirconf_rec *new;
735    /*    mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */
736    mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv;
737
738    new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof (mgs_dirconf_rec));
739    new->client_verify_mode = add->client_verify_mode;
740    return new;
741}
742
743void *mgs_config_dir_create(apr_pool_t * p,
744                            char *dir __attribute__((unused))) {
745    mgs_dirconf_rec *dc = apr_palloc(p, sizeof (*dc));
746    dc->client_verify_mode = -1;
747    return dc;
748}
749
Note: See TracBrowser for help on using the repository browser.