source: mod_gnutls/src/gnutls_config.c @ bd24203

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

Support X.509 auth for TLS proxy connections

This commit adds support for X.509 certificate based authentication for
TLS proxy back end connections, including both server certificate
checking and (optionally) TLS client authentication. Some functions used
for this require GnuTLS 3.1.4 or later, so requirements change
accordingly.

Three new configuration parameters are added:

GnuTLSProxyCAFile FILEPATH

The given file must contain trusted CA certificates for server
verification. Required.

GnuTLSProxyKeyFile FILEPATH
GnuTLSProxyCertificateFile FILEPATH

Key and certificate for TLS client auth towards TLS back end servers. If
not set, TLS client auth is disabled.

  • Property mode set to 100644
File size: 24.3 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    ret = gnutls_certificate_allocate_credentials(&sc->proxy_x509_creds);
638    if (ret < 0)
639    {
640        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
641                            ": (%d) %s", ret,
642                            gnutls_strerror(ret));
643        return NULL;
644    }
645
646#ifdef ENABLE_SRP
647    ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds);
648    if (ret < 0) {
649        *err =  apr_psprintf(p, "GnuTLS: Failed to initialize"
650                             ": (%d) %s", ret,
651                             gnutls_strerror(ret));
652        return NULL;
653    }
654
655    sc->srp_tpasswd_conf_file = NULL;
656    sc->srp_tpasswd_file = NULL;
657#endif
658
659    sc->privkey_x509 = NULL;
660        /* Initialize all Certificate Chains */
661    /* FIXME: how do we indicate that this is unset for a merge? (that
662     * is, how can a subordinate server override the chain by setting
663     * an empty one?  what would that even look like in the
664     * configuration?) */
665        sc->certs_x509_chain = malloc(MAX_CHAIN_SIZE * sizeof (*sc->certs_x509_chain));
666    sc->certs_x509_chain_num = 0;
667    sc->cache_timeout = -1; /* -1 means "unset" */
668    sc->cache_type = mgs_cache_unset;
669    sc->cache_config = NULL;
670    sc->tickets = GNUTLS_ENABLED_UNSET;
671    sc->priorities = NULL;
672    sc->dh_params = NULL;
673    sc->proxy_enabled = GNUTLS_ENABLED_UNSET;
674    sc->export_certificates_size = -1;
675    sc->client_verify_method = mgs_cvm_unset;
676
677/* this relies on GnuTLS never changing the gnutls_certificate_request_t enum to define -1 */
678    sc->client_verify_mode = -1;
679
680    return sc;
681}
682
683void *mgs_config_server_create(apr_pool_t * p,
684                               server_rec * s __attribute__((unused))) {
685    char *err = NULL;
686    mgs_srvconf_rec *sc = _mgs_config_server_create(p, &err);
687    if (sc) return sc; else return err;
688}
689
690#define gnutls_srvconf_merge(t, unset) sc->t = (add->t == unset) ? base->t : add->t
691#define gnutls_srvconf_assign(t) sc->t = add->t
692
693void *mgs_config_server_merge(apr_pool_t *p, void *BASE, void *ADD) {
694    int i;
695    char *err = NULL;
696    mgs_srvconf_rec *base = (mgs_srvconf_rec *)BASE;
697    mgs_srvconf_rec *add = (mgs_srvconf_rec *)ADD;
698    mgs_srvconf_rec *sc = _mgs_config_server_create(p, &err);
699    if (NULL == sc) return err;
700
701    gnutls_srvconf_merge(enabled, GNUTLS_ENABLED_UNSET);
702    gnutls_srvconf_merge(tickets, GNUTLS_ENABLED_UNSET);
703    gnutls_srvconf_merge(proxy_enabled, GNUTLS_ENABLED_UNSET);
704    gnutls_srvconf_merge(export_certificates_size, -1);
705    gnutls_srvconf_merge(client_verify_method, mgs_cvm_unset);
706    gnutls_srvconf_merge(client_verify_mode, -1);
707    gnutls_srvconf_merge(srp_tpasswd_file, NULL);
708    gnutls_srvconf_merge(srp_tpasswd_conf_file, NULL);
709    gnutls_srvconf_merge(privkey_x509, NULL);
710    gnutls_srvconf_merge(priorities, NULL);
711    gnutls_srvconf_merge(dh_params, NULL);
712
713    gnutls_srvconf_merge(proxy_x509_key_file, NULL);
714    gnutls_srvconf_merge(proxy_x509_cert_file, NULL);
715    gnutls_srvconf_merge(proxy_x509_ca_file, NULL);
716
717    /* FIXME: the following items are pre-allocated, and should be
718     * properly disposed of before assigning in order to avoid leaks;
719     * so at the moment, we can't actually have them in the config.
720     * what happens during de-allocation?
721
722     * This is probably leaky.
723     */
724    gnutls_srvconf_assign(certs);
725    gnutls_srvconf_assign(anon_creds);
726    gnutls_srvconf_assign(anon_client_creds);
727    gnutls_srvconf_assign(srp_creds);
728    gnutls_srvconf_assign(certs_x509_chain);
729    gnutls_srvconf_assign(certs_x509_chain_num);
730
731    /* how do these get transferred cleanly before the data from ADD
732     * goes away? */
733    gnutls_srvconf_assign(cert_cn);
734    for (i = 0; i < MAX_CERT_SAN; i++)
735        gnutls_srvconf_assign(cert_san[i]);
736    gnutls_srvconf_assign(ca_list);
737    gnutls_srvconf_assign(ca_list_size);
738    gnutls_srvconf_assign(cert_pgp);
739    gnutls_srvconf_assign(pgp_list);
740    gnutls_srvconf_assign(privkey_pgp);
741
742    return sc;
743}
744
745#undef gnutls_srvconf_merge
746#undef gnutls_srvconf_assign
747
748void *mgs_config_dir_merge(apr_pool_t * p,
749                           void *basev __attribute__((unused)),
750                           void *addv __attribute__((unused))) {
751    mgs_dirconf_rec *new;
752    /*    mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */
753    mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv;
754
755    new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof (mgs_dirconf_rec));
756    new->client_verify_mode = add->client_verify_mode;
757    return new;
758}
759
760void *mgs_config_dir_create(apr_pool_t * p,
761                            char *dir __attribute__((unused))) {
762    mgs_dirconf_rec *dc = apr_palloc(p, sizeof (*dc));
763    dc->client_verify_mode = -1;
764    return dc;
765}
766
767/*
768 * Store paths to proxy credentials
769 *
770 * This function copies the paths provided in the configuration file
771 * into the server configuration. The post configuration hook takes
772 * care of actually loading the credentials, which means than invalid
773 * paths or the like will be detected there.
774 */
775const char *mgs_store_cred_path(cmd_parms * parms,
776                                void *dummy __attribute__((unused)),
777                                const char *arg)
778{
779    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
780        ap_get_module_config(parms->server->module_config, &gnutls_module);
781
782    /* parms->directive->directive contains the directive string */
783    if (!strcasecmp(parms->directive->directive, "GnuTLSProxyKeyFile"))
784        sc->proxy_x509_key_file = apr_pstrdup(parms->pool, arg);
785    else if (!strcasecmp(parms->directive->directive,
786                         "GnuTLSProxyCertificateFile"))
787        sc->proxy_x509_cert_file = apr_pstrdup(parms->pool, arg);
788    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyCAFile"))
789        sc->proxy_x509_ca_file = apr_pstrdup(parms->pool, arg);
790    /* TODO: Add CRL parameter */
791    return NULL;
792}
Note: See TracBrowser for help on using the repository browser.