source: mod_gnutls/src/gnutls_config.c @ f030883

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

Set GnuTLS priorities for proxy connections separately

Until now, proxy connections were configured with the same priorities as
the server side. This commit introduces the new configuration option
"GnuTLSProxyPriorities" to set the priorities for proxy connections
separately. Note that GnuTLSProxyPriorities MUST be set when
SSLProxyEngine is enabled.

Since the parameters to GnuTLSPriorities and GnuTLSProxyPriorities need
the same processing, mgs_set_priorities has been rewritten to select the
priority cache to write to based on the option name, rather than adding
a new function to handle GnuTLSProxyPriorities.

  • Property mode set to 100644
File size: 25.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
580
581
582/*
583 * Initialize a GnuTLS priorities cache from a configuration
584 * string. Used for GnuTLSPriorities and GnuTLSProxyPriorities.
585 */
586const char *mgs_set_priorities(cmd_parms * parms,
587                               void *dummy __attribute__((unused)),
588                               const char *arg)
589{
590    int ret;
591    const char *err;
592
593    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
594        ap_get_module_config(parms->server->module_config, &gnutls_module);
595
596    /* Setting a priority cache works the same no matter for which
597     * option. Just point the pointer at the right one. */
598    gnutls_priority_t *prio = NULL;
599    if (!strcasecmp(parms->directive->directive, "GnuTLSPriorities"))
600        prio = &sc->priorities;
601    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyPriorities"))
602        prio = &sc->proxy_priorities;
603    else
604        /* Can't happen unless there's a serious bug in mod_gnutls or Apache */
605        return apr_psprintf(parms->pool,
606                            "mod_gnutls: %s called for invalid option '%s'",
607                            __func__, parms->directive->directive);
608
609    ret = gnutls_priority_init(prio, arg, &err);
610    if (ret < 0)
611    {
612        if (ret == GNUTLS_E_INVALID_REQUEST)
613            return apr_psprintf(parms->pool,
614                                "mod_gnutls: Syntax error parsing priorities "
615                                "string for %s at: %s",
616                                parms->directive->directive, err);
617        return  apr_psprintf(parms->pool,
618                             "Error setting priorities: %s (%d)",
619                             gnutls_strerror(ret), ret);
620    }
621
622    return NULL;
623}
624
625static mgs_srvconf_rec *_mgs_config_server_create(apr_pool_t * p, char** err) {
626    mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof (*sc));
627    int ret;
628
629    sc->enabled = GNUTLS_ENABLED_UNSET;
630
631    ret = gnutls_certificate_allocate_credentials(&sc->certs);
632    if (ret < 0) {
633        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
634                            ": (%d) %s", ret,
635                            gnutls_strerror(ret));
636        return NULL;
637    }
638
639    ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds);
640    if (ret < 0) {
641        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
642                            ": (%d) %s", ret,
643                            gnutls_strerror(ret));
644        return NULL;
645    }
646
647    /* FIXME: not ideal, should be called only if SSLProxyEngine is
648     * enabled */
649    ret = gnutls_anon_allocate_client_credentials(&sc->anon_client_creds);
650    if (ret < 0)
651    {
652        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
653                            ": (%d) %s", ret,
654                            gnutls_strerror(ret));
655        return NULL;
656    }
657
658    sc->proxy_x509_key_file = NULL;
659    sc->proxy_x509_cert_file = NULL;
660    sc->proxy_x509_ca_file = NULL;
661    sc->proxy_x509_crl_file = NULL;
662    sc->proxy_priorities = NULL;
663    ret = gnutls_certificate_allocate_credentials(&sc->proxy_x509_creds);
664    if (ret < 0)
665    {
666        *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
667                            ": (%d) %s", ret,
668                            gnutls_strerror(ret));
669        return NULL;
670    }
671
672#ifdef ENABLE_SRP
673    ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds);
674    if (ret < 0) {
675        *err =  apr_psprintf(p, "GnuTLS: Failed to initialize"
676                             ": (%d) %s", ret,
677                             gnutls_strerror(ret));
678        return NULL;
679    }
680
681    sc->srp_tpasswd_conf_file = NULL;
682    sc->srp_tpasswd_file = NULL;
683#endif
684
685    sc->privkey_x509 = NULL;
686        /* Initialize all Certificate Chains */
687    /* FIXME: how do we indicate that this is unset for a merge? (that
688     * is, how can a subordinate server override the chain by setting
689     * an empty one?  what would that even look like in the
690     * configuration?) */
691        sc->certs_x509_chain = malloc(MAX_CHAIN_SIZE * sizeof (*sc->certs_x509_chain));
692    sc->certs_x509_chain_num = 0;
693    sc->cache_timeout = -1; /* -1 means "unset" */
694    sc->cache_type = mgs_cache_unset;
695    sc->cache_config = NULL;
696    sc->tickets = GNUTLS_ENABLED_UNSET;
697    sc->priorities = NULL;
698    sc->dh_params = NULL;
699    sc->proxy_enabled = GNUTLS_ENABLED_UNSET;
700    sc->export_certificates_size = -1;
701    sc->client_verify_method = mgs_cvm_unset;
702
703/* this relies on GnuTLS never changing the gnutls_certificate_request_t enum to define -1 */
704    sc->client_verify_mode = -1;
705
706    return sc;
707}
708
709void *mgs_config_server_create(apr_pool_t * p,
710                               server_rec * s __attribute__((unused))) {
711    char *err = NULL;
712    mgs_srvconf_rec *sc = _mgs_config_server_create(p, &err);
713    if (sc) return sc; else return err;
714}
715
716#define gnutls_srvconf_merge(t, unset) sc->t = (add->t == unset) ? base->t : add->t
717#define gnutls_srvconf_assign(t) sc->t = add->t
718
719void *mgs_config_server_merge(apr_pool_t *p, void *BASE, void *ADD) {
720    int i;
721    char *err = NULL;
722    mgs_srvconf_rec *base = (mgs_srvconf_rec *)BASE;
723    mgs_srvconf_rec *add = (mgs_srvconf_rec *)ADD;
724    mgs_srvconf_rec *sc = _mgs_config_server_create(p, &err);
725    if (NULL == sc) return err;
726
727    gnutls_srvconf_merge(enabled, GNUTLS_ENABLED_UNSET);
728    gnutls_srvconf_merge(tickets, GNUTLS_ENABLED_UNSET);
729    gnutls_srvconf_merge(proxy_enabled, GNUTLS_ENABLED_UNSET);
730    gnutls_srvconf_merge(export_certificates_size, -1);
731    gnutls_srvconf_merge(client_verify_method, mgs_cvm_unset);
732    gnutls_srvconf_merge(client_verify_mode, -1);
733    gnutls_srvconf_merge(srp_tpasswd_file, NULL);
734    gnutls_srvconf_merge(srp_tpasswd_conf_file, NULL);
735    gnutls_srvconf_merge(privkey_x509, NULL);
736    gnutls_srvconf_merge(priorities, NULL);
737    gnutls_srvconf_merge(dh_params, NULL);
738
739    gnutls_srvconf_merge(proxy_x509_key_file, NULL);
740    gnutls_srvconf_merge(proxy_x509_cert_file, NULL);
741    gnutls_srvconf_merge(proxy_x509_ca_file, NULL);
742    gnutls_srvconf_merge(proxy_x509_crl_file, NULL);
743    gnutls_srvconf_merge(proxy_priorities, NULL);
744
745    /* FIXME: the following items are pre-allocated, and should be
746     * properly disposed of before assigning in order to avoid leaks;
747     * so at the moment, we can't actually have them in the config.
748     * what happens during de-allocation?
749
750     * This is probably leaky.
751     */
752    gnutls_srvconf_assign(certs);
753    gnutls_srvconf_assign(anon_creds);
754    gnutls_srvconf_assign(anon_client_creds);
755    gnutls_srvconf_assign(srp_creds);
756    gnutls_srvconf_assign(certs_x509_chain);
757    gnutls_srvconf_assign(certs_x509_chain_num);
758
759    /* how do these get transferred cleanly before the data from ADD
760     * goes away? */
761    gnutls_srvconf_assign(cert_cn);
762    for (i = 0; i < MAX_CERT_SAN; i++)
763        gnutls_srvconf_assign(cert_san[i]);
764    gnutls_srvconf_assign(ca_list);
765    gnutls_srvconf_assign(ca_list_size);
766    gnutls_srvconf_assign(cert_pgp);
767    gnutls_srvconf_assign(pgp_list);
768    gnutls_srvconf_assign(privkey_pgp);
769
770    return sc;
771}
772
773#undef gnutls_srvconf_merge
774#undef gnutls_srvconf_assign
775
776void *mgs_config_dir_merge(apr_pool_t * p,
777                           void *basev __attribute__((unused)),
778                           void *addv __attribute__((unused))) {
779    mgs_dirconf_rec *new;
780    /*    mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */
781    mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv;
782
783    new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof (mgs_dirconf_rec));
784    new->client_verify_mode = add->client_verify_mode;
785    return new;
786}
787
788void *mgs_config_dir_create(apr_pool_t * p,
789                            char *dir __attribute__((unused))) {
790    mgs_dirconf_rec *dc = apr_palloc(p, sizeof (*dc));
791    dc->client_verify_mode = -1;
792    return dc;
793}
794
795/*
796 * Store paths to proxy credentials
797 *
798 * This function copies the paths provided in the configuration file
799 * into the server configuration. The post configuration hook takes
800 * care of actually loading the credentials, which means than invalid
801 * paths or the like will be detected there.
802 */
803const char *mgs_store_cred_path(cmd_parms * parms,
804                                void *dummy __attribute__((unused)),
805                                const char *arg)
806{
807    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
808        ap_get_module_config(parms->server->module_config, &gnutls_module);
809
810    /* parms->directive->directive contains the directive string */
811    if (!strcasecmp(parms->directive->directive, "GnuTLSProxyKeyFile"))
812        sc->proxy_x509_key_file = apr_pstrdup(parms->pool, arg);
813    else if (!strcasecmp(parms->directive->directive,
814                         "GnuTLSProxyCertificateFile"))
815        sc->proxy_x509_cert_file = apr_pstrdup(parms->pool, arg);
816    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyCAFile"))
817        sc->proxy_x509_ca_file = apr_pstrdup(parms->pool, arg);
818    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyCRLFile"))
819        sc->proxy_x509_crl_file = apr_pstrdup(parms->pool, arg);
820    return NULL;
821}
Note: See TracBrowser for help on using the repository browser.