source: mod_gnutls/src/gnutls_config.c @ a2b4ab6

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

Use GnuTLS known DH parameters

If the user does not configure the DH parameters to use, mod_gnutls
now estimates the GnuTLS security parameter based on the private key
and uses the matching DH group built into GnuTLS. Using one of the
known DH groups is recommended by the GnuTLS developers.

Using built-in DH groups requires compiling against GnuTLS version
3.5.6 or newer. Otherwise the ffdhe2048 DH group as defined in RFC
7919, Appendix A.1 is the new default, which is the built-in for
security parameter "medium" in current GnuTLS versions.

  • Property mode set to 100644
File size: 39.8 KB
Line 
1/*
2 *  Copyright 2004-2005 Paul Querna
3 *  Copyright 2008, 2014 Nikos Mavrogiannopoulos
4 *  Copyright 2011 Dash Shendy
5 *  Copyright 2015-2016 Thomas Klute
6 *
7 *  Licensed under the Apache License, Version 2.0 (the "License");
8 *  you may not use this file except in compliance with the License.
9 *  You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 *  Unless required by applicable law or agreed to in writing, software
14 *  distributed under the License is distributed on an "AS IS" BASIS,
15 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 *  See the License for the specific language governing permissions and
17 *  limitations under the License.
18 */
19
20#include "gnutls_config.h"
21#include "mod_gnutls.h"
22#include "gnutls_ocsp.h"
23#include "apr_lib.h"
24#include <gnutls/abstract.h>
25
26#define INIT_CA_SIZE 128
27
28#ifdef APLOG_USE_MODULE
29APLOG_USE_MODULE(gnutls);
30#endif
31
32static int pin_callback(void *user, int attempt __attribute__((unused)),
33                        const char *token_url __attribute__((unused)),
34                        const char *token_label, unsigned int flags,
35                        char *pin, size_t pin_max)
36{
37    mgs_srvconf_rec *sc = user;
38
39    if (sc->pin == NULL || flags & GNUTLS_PIN_FINAL_TRY ||
40        flags & GNUTLS_PIN_WRONG) {
41        return -1;
42    }
43
44    if (token_label && strcmp(token_label, "SRK") == 0) {
45         snprintf(pin, pin_max, "%s", sc->srk_pin);
46    } else {
47         snprintf(pin, pin_max, "%s", sc->pin);
48    }
49    return 0;
50}
51
52static int load_datum_from_file(apr_pool_t * pool,
53                                const char *file, gnutls_datum_t * data)
54{
55    apr_file_t *fp;
56    apr_finfo_t finfo;
57    apr_status_t rv;
58    apr_size_t br = 0;
59
60    rv = apr_file_open(&fp, file, APR_READ | APR_BINARY,
61                       APR_OS_DEFAULT, pool);
62    if (rv != APR_SUCCESS) {
63        return rv;
64    }
65
66    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp);
67
68    if (rv != APR_SUCCESS) {
69        return rv;
70    }
71
72    data->data = apr_palloc(pool, finfo.size + 1);
73    rv = apr_file_read_full(fp, data->data, finfo.size, &br);
74
75    if (rv != APR_SUCCESS) {
76        return rv;
77    }
78    apr_file_close(fp);
79
80    data->data[br] = '\0';
81    data->size = br;
82
83    return 0;
84}
85
86
87
88/**
89 * Clean up the various GnuTLS data structures allocated by
90 * mgs_load_files()
91 */
92static apr_status_t mgs_pool_free_credentials(void *arg)
93{
94    mgs_srvconf_rec *sc = (mgs_srvconf_rec *) arg;
95
96    if (sc->certs)
97    {
98        gnutls_certificate_free_credentials(sc->certs);
99        sc->certs = NULL;
100    }
101
102    if (sc->anon_creds)
103    {
104        gnutls_anon_free_server_credentials(sc->anon_creds);
105        sc->anon_creds = NULL;
106    }
107
108#ifdef ENABLE_SRP
109    if (sc->srp_creds)
110    {
111        gnutls_srp_free_server_credentials(sc->srp_creds);
112        sc->srp_creds = NULL;
113    }
114#endif
115
116    if (sc->dh_params)
117    {
118        gnutls_dh_params_deinit(sc->dh_params);
119        sc->dh_params = NULL;
120    }
121
122    for (unsigned int i = 0; i < sc->certs_x509_chain_num; i++)
123    {
124        gnutls_pcert_deinit(&sc->certs_x509_chain[i]);
125        gnutls_x509_crt_deinit(sc->certs_x509_crt_chain[i]);
126    }
127
128    if (sc->privkey_x509)
129    {
130        gnutls_privkey_deinit(sc->privkey_x509);
131        sc->privkey_x509 = NULL;
132    }
133
134    if (sc->ca_list)
135    {
136        for (unsigned int i = 0; i < sc->ca_list_size; i++)
137        {
138            gnutls_x509_crt_deinit(sc->ca_list[i]);
139        }
140        gnutls_free(sc->ca_list);
141        sc->ca_list = NULL;
142    }
143
144    if (sc->cert_pgp)
145    {
146        gnutls_pcert_deinit(&sc->cert_pgp[0]);
147        sc->cert_pgp = NULL;
148        gnutls_openpgp_crt_deinit(sc->cert_crt_pgp[0]);
149        sc->cert_crt_pgp = NULL;
150    }
151
152    if (sc->privkey_pgp)
153    {
154        gnutls_privkey_deinit(sc->privkey_pgp);
155        sc->privkey_pgp = NULL;
156#if GNUTLS_VERSION_NUMBER < 0x030312
157        gnutls_openpgp_privkey_deinit(sc->privkey_pgp_internal);
158        sc->privkey_pgp_internal = NULL;
159#endif
160    }
161
162    if (sc->pgp_list)
163    {
164        gnutls_openpgp_keyring_deinit(sc->pgp_list);
165        sc->pgp_list = NULL;
166    }
167
168    if (sc->priorities)
169    {
170        gnutls_priority_deinit(sc->priorities);
171        sc->priorities = NULL;
172    }
173
174    return APR_SUCCESS;
175}
176
177int mgs_load_files(apr_pool_t *pconf, apr_pool_t *ptemp, server_rec *s)
178{
179    apr_pool_t *spool;
180    const char *file;
181    gnutls_datum_t data;
182    int ret;
183    mgs_srvconf_rec *sc =
184        (mgs_srvconf_rec *) ap_get_module_config(s->module_config,
185                                                 &gnutls_module);
186
187    apr_pool_create(&spool, ptemp);
188
189    /* Cleanup function for the GnuTLS structures allocated below */
190    apr_pool_cleanup_register(pconf, sc, mgs_pool_free_credentials,
191                              apr_pool_cleanup_null);
192
193    if (sc->certs == NULL)
194    {
195        ret = gnutls_certificate_allocate_credentials(&sc->certs);
196        if (ret < 0) {
197            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
198                         "GnuTLS: Failed to initialize" ": (%d) %s", ret,
199                         gnutls_strerror(ret));
200            ret = -1;
201            goto cleanup;
202        }
203    }
204
205    if (sc->anon_creds == NULL)
206    {
207        ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds);
208        if (ret < 0) {
209            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
210                         "GnuTLS: Failed to initialize" ": (%d) %s", ret,
211                         gnutls_strerror(ret));
212            ret = -1;
213            goto cleanup;
214        }
215    }
216
217    /* Load SRP parameters */
218#ifdef ENABLE_SRP
219    if (sc->srp_creds == NULL)
220    {
221        ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds);
222        if (ret < 0) {
223            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
224                         "GnuTLS: Failed to initialize" ": (%d) %s", ret,
225                         gnutls_strerror(ret));
226            ret = -1;
227            goto cleanup;
228        }
229    }
230
231    if (sc->srp_tpasswd_conf_file != NULL && sc->srp_tpasswd_file != NULL)
232    {
233        ret = gnutls_srp_set_server_credentials_file
234            (sc->srp_creds, sc->srp_tpasswd_file,
235             sc->srp_tpasswd_conf_file);
236
237        if (ret < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) {
238            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
239                         "GnuTLS: Host '%s:%d' is missing a "
240                         "SRP password or conf File!",
241                         s->server_hostname, s->port);
242            ret = -1;
243            goto cleanup;
244        }
245    }
246#endif
247
248    /* Load user provided DH parameters, if any */
249    if (sc->dh_file)
250    {
251        if (sc->dh_params == NULL)
252        {
253            ret = gnutls_dh_params_init(&sc->dh_params);
254            if (ret < 0) {
255                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
256                             "GnuTLS: Failed to initialize"
257                             ": (%d) %s", ret, gnutls_strerror(ret));
258                ret = -1;
259                goto cleanup;
260            }
261        }
262
263        if (load_datum_from_file(spool, sc->dh_file, &data) != 0) {
264            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
265                         "GnuTLS: Error Reading " "DH params '%s'", sc->dh_file);
266            ret = -1;
267            goto cleanup;
268        }
269
270        ret =
271            gnutls_dh_params_import_pkcs3(sc->dh_params, &data,
272                                          GNUTLS_X509_FMT_PEM);
273        if (ret < 0) {
274            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
275                         "GnuTLS: Failed to Import "
276                         "DH params '%s': (%d) %s", sc->dh_file, ret,
277                         gnutls_strerror(ret));
278            ret = -1;
279            goto cleanup;
280        }
281    }
282
283    if (sc->x509_cert_file != NULL && sc->certs_x509_crt_chain == NULL)
284    {
285        sc->certs_x509_chain =
286            apr_pcalloc(pconf,
287                        MAX_CHAIN_SIZE * sizeof(sc->certs_x509_chain[0]));
288        sc->certs_x509_crt_chain =
289            apr_pcalloc(pconf,
290                        MAX_CHAIN_SIZE * sizeof(sc->certs_x509_crt_chain[0]));
291        unsigned int chain_num = MAX_CHAIN_SIZE;
292        unsigned format = GNUTLS_X509_FMT_PEM;
293
294        /* Load X.509 certificate */
295        if (strncmp(sc->x509_cert_file, "pkcs11:", 7) == 0) {
296            gnutls_pkcs11_obj_t obj;
297
298            file = sc->x509_cert_file;
299
300            ret = gnutls_pkcs11_obj_init(&obj);
301            if (ret < 0) {
302                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
303                             "GnuTLS: Error Initializing PKCS #11 object");
304                ret = -1;
305                goto cleanup;
306            }
307
308            gnutls_pkcs11_obj_set_pin_function(obj, pin_callback, sc);
309
310            ret = gnutls_pkcs11_obj_import_url(obj, file,
311                                               GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
312            if (ret < 0) {
313                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
314                             "GnuTLS: Error Importing PKCS #11 object: "
315                             "'%s': %s",
316                             file, gnutls_strerror(ret));
317                ret = -1;
318                goto cleanup;
319            }
320
321            format = GNUTLS_X509_FMT_DER;
322            ret = gnutls_pkcs11_obj_export2(obj, &data);
323            if (ret < 0) {
324                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
325                             "GnuTLS: Error Exporting a PKCS #11 object: "
326                             "'%s': %s",
327                             file, gnutls_strerror(ret));
328                ret = -1;
329                goto cleanup;
330            }
331
332            gnutls_pkcs11_obj_deinit(obj);
333        } else {
334            file = ap_server_root_relative(spool, sc->x509_cert_file);
335
336            ret = gnutls_load_file(file, &data);
337            if (ret < 0) {
338                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
339                             "GnuTLS: Error Reading Certificate '%s': %s",
340                             file, gnutls_strerror(ret));
341                ret = -1;
342                goto cleanup;
343            }
344        }
345
346        ret = gnutls_x509_crt_list_import(sc->certs_x509_crt_chain,
347                                          &chain_num, &data, format,
348                                          GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED);
349        gnutls_free(data.data);
350        sc->certs_x509_chain_num = chain_num;
351
352        if (ret < 0) {
353            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
354                         "GnuTLS: Failed to Import Certificate Chain "
355                         "'%s': (%d) %s",
356                         file, ret, gnutls_strerror(ret));
357            ret = -1;
358            goto cleanup;
359        }
360
361        for (unsigned int i = 0; i < chain_num; i++)
362        {
363            ret =
364                gnutls_pcert_import_x509(&sc->certs_x509_chain[i],
365                                         sc->certs_x509_crt_chain[i], 0);
366            if (ret < 0) {
367                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
368                             "GnuTLS: Failed to Import pCertificate "
369                             "'%s': (%d) %s",
370                             file, ret, gnutls_strerror(ret));
371                ret = -1;
372                goto cleanup;
373            }
374        }
375        sc->certs_x509_chain_num = chain_num;
376    }
377
378    if (sc->x509_key_file && sc->privkey_x509 == NULL)
379    {
380        ret = gnutls_privkey_init(&sc->privkey_x509);
381        if (ret < 0) {
382            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
383                         "GnuTLS: Failed to initialize: (%d) %s", ret,
384                         gnutls_strerror(ret));
385            ret = -1;
386            goto cleanup;
387        }
388
389        if (gnutls_url_is_supported(sc->x509_key_file) != 0) {
390            file = sc->x509_key_file;
391
392            gnutls_privkey_set_pin_function(sc->privkey_x509, pin_callback,
393                                            sc);
394
395            ret = gnutls_privkey_import_url(sc->privkey_x509, file, 0);
396
397            if (ret < 0) {
398                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
399                             "GnuTLS: Failed to Import Private Key URL "
400                             "'%s': (%d) %s",
401                             file, ret, gnutls_strerror(ret));
402                ret = -1;
403                goto cleanup;
404            }
405        } else {
406            file = ap_server_root_relative(spool, sc->x509_key_file);
407
408            if (load_datum_from_file(spool, file, &data) != 0) {
409                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
410                             "GnuTLS: Error Reading Private Key '%s'",
411                             file);
412                ret = -1;
413                goto cleanup;
414            }
415
416            ret =
417                gnutls_privkey_import_x509_raw(sc->privkey_x509, &data,
418                                               GNUTLS_X509_FMT_PEM, sc->pin,
419                                               0);
420
421            if (ret < 0) {
422                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
423                             "GnuTLS: Failed to Import Private Key "
424                             "'%s': (%d) %s",
425                             file, ret, gnutls_strerror(ret));
426                ret = -1;
427                goto cleanup;
428            }
429        }
430    }
431
432    /* Load the X.509 CA file */
433    if (sc->x509_ca_file)
434    {
435        if (load_datum_from_file(spool, sc->x509_ca_file, &data) != 0) {
436            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
437                         "GnuTLS: Error Reading " "Client CA File '%s'",
438                         sc->x509_ca_file);
439            ret = -1;
440            goto cleanup;
441        }
442
443        ret = gnutls_x509_crt_list_import2(&sc->ca_list, &sc->ca_list_size,
444                                           &data, GNUTLS_X509_FMT_PEM, 0);
445        if (ret < 0) {
446            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
447                         "GnuTLS: Failed to load "
448                         "Client CA File '%s': (%d) %s", sc->x509_ca_file,
449                         ret, gnutls_strerror(ret));
450            ret = -1;
451            goto cleanup;
452        }
453    }
454
455    if (sc->pgp_cert_file && sc->cert_pgp == NULL)
456    {
457        sc->cert_pgp = apr_pcalloc(pconf, sizeof(sc->cert_pgp[0]));
458        sc->cert_crt_pgp = apr_pcalloc(pconf, sizeof(sc->cert_crt_pgp[0]));
459
460        if (load_datum_from_file(spool, sc->pgp_cert_file, &data) != 0) {
461            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
462                         "GnuTLS: Error Reading " "Certificate '%s'",
463                         sc->pgp_cert_file);
464            ret = -1;
465            goto cleanup;
466        }
467
468        ret = gnutls_openpgp_crt_init(&sc->cert_crt_pgp[0]);
469        if (ret < 0) {
470            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
471                         "GnuTLS: Failed to Init "
472                         "PGP Certificate: (%d) %s", ret,
473                         gnutls_strerror(ret));
474            ret = -1;
475            goto cleanup;
476        }
477
478        ret = gnutls_openpgp_crt_import(sc->cert_crt_pgp[0], &data,
479                                        GNUTLS_OPENPGP_FMT_BASE64);
480        if (ret < 0) {
481            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
482                         "GnuTLS: Failed to Import "
483                         "PGP Certificate: (%d) %s", ret,
484                         gnutls_strerror(ret));
485            ret = -1;
486            goto cleanup;
487        }
488
489        ret = gnutls_pcert_import_openpgp(sc->cert_pgp,
490                                          sc->cert_crt_pgp[0], 0);
491        if (ret < 0) {
492            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
493                         "GnuTLS: Failed to Import "
494                         "PGP pCertificate: (%d) %s", ret,
495                         gnutls_strerror(ret));
496            ret = -1;
497            goto cleanup;
498        }
499    }
500
501    /* Load the PGP key file */
502    if (sc->pgp_key_file && sc->privkey_pgp == NULL)
503    {
504        if (load_datum_from_file(spool, sc->pgp_key_file, &data) != 0) {
505            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
506                         "GnuTLS: Error Reading " "Private Key '%s'",
507                         sc->pgp_key_file);
508            ret = -1;
509            goto cleanup;
510        }
511
512        ret = gnutls_privkey_init(&sc->privkey_pgp);
513        if (ret < 0) {
514            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
515                         "GnuTLS: Failed to initialize"
516                         ": (%d) %s", ret, gnutls_strerror(ret));
517            ret = -1;
518            goto cleanup;
519        }
520
521#if GNUTLS_VERSION_NUMBER < 0x030312
522        /* GnuTLS versions before 3.3.12 contain a bug in
523         * gnutls_privkey_import_openpgp_raw which frees data that is
524         * accessed when the key is used, leading to segfault. Loading
525         * the key into a gnutls_openpgp_privkey_t and then assigning
526         * it to the gnutls_privkey_t works around the bug, hence this
527         * chain of gnutls_openpgp_privkey_init,
528         * gnutls_openpgp_privkey_import and
529         * gnutls_privkey_import_openpgp. */
530        ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp_internal);
531        if (ret != 0) {
532            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
533                         "GnuTLS: Failed to initialize "
534                         "PGP Private Key '%s': (%d) %s",
535                         sc->pgp_key_file, ret, gnutls_strerror(ret));
536            ret = -1;
537            goto cleanup;
538        }
539
540        ret = gnutls_openpgp_privkey_import(sc->privkey_pgp_internal, &data,
541                                            GNUTLS_OPENPGP_FMT_BASE64, NULL, 0);
542        if (ret != 0) {
543            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
544                         "GnuTLS: Failed to Import "
545                         "PGP Private Key '%s': (%d) %s",
546                         sc->pgp_key_file, ret, gnutls_strerror(ret));
547            ret = -1;
548            goto cleanup;
549        }
550
551        ret = gnutls_privkey_import_openpgp(sc->privkey_pgp,
552                                            sc->privkey_pgp_internal, 0);
553        if (ret != 0)
554        {
555            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
556                         "GnuTLS: Failed to assign PGP Private Key '%s' "
557                         "to gnutls_privkey_t structure: (%d) %s",
558                         sc->pgp_key_file, ret, gnutls_strerror(ret));
559            ret = -1;
560            goto cleanup;
561        }
562#else
563        ret = gnutls_privkey_import_openpgp_raw(sc->privkey_pgp, &data,
564                                                GNUTLS_OPENPGP_FMT_BASE64,
565                                                NULL, NULL);
566        if (ret != 0)
567        {
568            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
569                         "GnuTLS: Failed to Import "
570                         "PGP Private Key '%s': (%d) %s",
571                         sc->pgp_key_file, ret, gnutls_strerror(ret));
572            ret = -1;
573            goto cleanup;
574        }
575#endif
576    }
577
578    /* Load the keyring file */
579    if (sc->pgp_ring_file && sc->pgp_list == NULL)
580    {
581        if (load_datum_from_file(spool, sc->pgp_ring_file, &data) != 0) {
582            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
583                         "GnuTLS: Error Reading " "Keyring File '%s'",
584                         sc->pgp_ring_file);
585            ret = -1;
586            goto cleanup;
587        }
588
589        ret = gnutls_openpgp_keyring_init(&sc->pgp_list);
590        if (ret < 0) {
591            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
592                         "GnuTLS: Failed to initialize"
593                         "keyring: (%d) %s", ret, gnutls_strerror(ret));
594            ret = -1;
595            goto cleanup;
596        }
597
598        ret = gnutls_openpgp_keyring_import(sc->pgp_list, &data,
599                                            GNUTLS_OPENPGP_FMT_BASE64);
600        if (ret < 0) {
601            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
602                         "GnuTLS: Failed to load "
603                         "Keyring File '%s': (%d) %s", sc->pgp_ring_file,
604                         ret, gnutls_strerror(ret));
605            ret = -1;
606            goto cleanup;
607        }
608    }
609
610    if (sc->priorities_str && sc->priorities == NULL)
611    {
612        const char *err;
613        ret = gnutls_priority_init(&sc->priorities, sc->priorities_str, &err);
614
615        if (ret < 0) {
616            if (ret == GNUTLS_E_INVALID_REQUEST) {
617                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
618                             "GnuTLS: Syntax error parsing priorities string at: %s",
619                             err);
620            } else {
621                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
622                             "GnuTLS: error parsing priorities string");
623
624            }
625            ret = -1;
626            goto cleanup;
627        }
628    }
629
630    ret = 0;
631 cleanup:
632    apr_pool_destroy(spool);
633
634    return ret;
635}
636
637int mgs_pkcs11_reinit(server_rec * base_server)
638{
639    int ret;
640    server_rec *s;
641    mgs_srvconf_rec *sc;
642
643    gnutls_pkcs11_reinit();
644
645    for (s = base_server; s; s = s->next) {
646        sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module);
647
648            /* gnutls caches the session in a private key, so we need to open
649             * a new one */
650            if (sc->x509_key_file && gnutls_url_is_supported(sc->x509_key_file) != 0) {
651                gnutls_privkey_deinit(sc->privkey_x509);
652
653                ret = gnutls_privkey_init(&sc->privkey_x509);
654                if (ret < 0) {
655                    ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
656                                 "GnuTLS: Failed to initialize: (%d) %s", ret,
657                                 gnutls_strerror(ret));
658                    goto fail;
659                }
660
661                gnutls_privkey_set_pin_function(sc->privkey_x509, pin_callback, sc);
662
663                ret = gnutls_privkey_import_url(sc->privkey_x509, sc->x509_key_file, 0);
664                if (ret < 0) {
665                    ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
666                             "GnuTLS: Failed to Re-Import Private Key URL '%s': (%d) %s",
667                             sc->x509_key_file, ret, gnutls_strerror(ret));
668                    goto fail;
669                }
670            }
671    }
672
673    return 0;
674
675 fail:
676    gnutls_privkey_deinit(sc->privkey_x509);
677    return -1;
678}
679
680const char *mgs_set_dh_file(cmd_parms * parms, void *dummy __attribute__((unused)),
681        const char *arg) {
682    mgs_srvconf_rec *sc =
683        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
684                                                 module_config,
685                                                 &gnutls_module);
686
687    sc->dh_file = ap_server_root_relative(parms->pool, arg);
688
689    return NULL;
690}
691
692const char *mgs_set_cert_file(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg) {
693
694    mgs_srvconf_rec *sc =
695        (mgs_srvconf_rec *) ap_get_module_config(parms->
696                                                 server->module_config,
697                                                 &gnutls_module);
698
699    sc->x509_cert_file = apr_pstrdup(parms->pool, arg);
700
701    return NULL;
702
703}
704
705const char *mgs_set_key_file(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg) {
706
707    mgs_srvconf_rec *sc =
708        (mgs_srvconf_rec *) ap_get_module_config(parms->
709                                                 server->module_config,
710                                                 &gnutls_module);
711
712    sc->x509_key_file = apr_pstrdup(parms->pool, arg);
713
714    return NULL;
715}
716
717const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy __attribute__((unused)),
718        const char *arg)
719{
720    mgs_srvconf_rec *sc =
721        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
722                                                 module_config,
723                                                 &gnutls_module);
724
725    sc->pgp_cert_file = ap_server_root_relative(parms->pool, arg);
726
727    return NULL;
728}
729
730const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy __attribute__((unused)),
731        const char *arg) {
732    mgs_srvconf_rec *sc =
733        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
734                                                 module_config,
735                                                 &gnutls_module);
736
737    sc->pgp_key_file = ap_server_root_relative(parms->pool, arg);
738
739    return NULL;
740}
741
742const char *mgs_set_tickets(cmd_parms *parms,
743                            void *dummy __attribute__((unused)),
744                            const int arg)
745{
746    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
747        ap_get_module_config(parms->server->module_config, &gnutls_module);
748
749    if (arg)
750        sc->tickets = GNUTLS_ENABLED_TRUE;
751    else
752        sc->tickets = GNUTLS_ENABLED_FALSE;
753
754    return NULL;
755}
756
757
758#ifdef ENABLE_SRP
759
760const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy __attribute__((unused)),
761        const char *arg) {
762    mgs_srvconf_rec *sc =
763        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
764                                                 module_config,
765                                                 &gnutls_module);
766
767    sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg);
768
769    return NULL;
770}
771
772const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy __attribute__((unused)),
773        const char *arg) {
774    mgs_srvconf_rec *sc =
775        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
776                                                 module_config,
777                                                 &gnutls_module);
778
779    sc->srp_tpasswd_conf_file = ap_server_root_relative(parms->pool, arg);
780
781    return NULL;
782}
783
784#endif
785
786const char *mgs_set_cache(cmd_parms * parms, void *dummy __attribute__((unused)),
787        const char *type, const char *arg) {
788    const char *err;
789    mgs_srvconf_rec *sc =
790        ap_get_module_config(parms->server->module_config,
791                             &gnutls_module);
792    if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) {
793        return err;
794    }
795
796    if (strcasecmp("none", type) == 0) {
797        sc->cache_type = mgs_cache_none;
798        sc->cache_config = NULL;
799        return NULL;
800    } else if (strcasecmp("dbm", type) == 0) {
801        sc->cache_type = mgs_cache_dbm;
802    } else if (strcasecmp("gdbm", type) == 0) {
803        sc->cache_type = mgs_cache_gdbm;
804    }
805#if HAVE_APR_MEMCACHE
806    else if (strcasecmp("memcache", type) == 0) {
807        sc->cache_type = mgs_cache_memcache;
808    }
809#endif
810    else {
811        return "Invalid Type for GnuTLSCache!";
812    }
813
814    if (arg == NULL)
815        return "Invalid argument 2 for GnuTLSCache!";
816
817    if (sc->cache_type == mgs_cache_dbm
818        || sc->cache_type == mgs_cache_gdbm) {
819        sc->cache_config = ap_server_root_relative(parms->pool, arg);
820    } else {
821        sc->cache_config = apr_pstrdup(parms->pool, arg);
822    }
823
824    return NULL;
825}
826
827const char *mgs_set_timeout(cmd_parms * parms,
828                            void *dummy __attribute__((unused)),
829                            const char *arg)
830{
831    apr_int64_t argint = apr_atoi64(arg);
832    /* timeouts cannot be negative */
833    if (argint < 0)
834        return apr_psprintf(parms->pool, "%s: Invalid argument",
835                            parms->directive->directive);
836
837    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
838        ap_get_module_config(parms->server->module_config, &gnutls_module);
839
840    if (!apr_strnatcasecmp(parms->directive->directive, "GnuTLSCacheTimeout"))
841    {
842        const char *err;
843        if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY)))
844            return err;
845        sc->cache_timeout = apr_time_from_sec(argint);
846    }
847    else if (!apr_strnatcasecmp(parms->directive->directive,
848                                "GnuTLSOCSPCacheTimeout"))
849        sc->ocsp_cache_time = apr_time_from_sec(argint);
850    else if (!apr_strnatcasecmp(parms->directive->directive,
851                                "GnuTLSOCSPFailureTimeout"))
852        sc->ocsp_failure_timeout = apr_time_from_sec(argint);
853    else if (!apr_strnatcasecmp(parms->directive->directive,
854                                "GnuTLSOCSPSocketTimeout"))
855        sc->ocsp_socket_timeout = apr_time_from_sec(argint);
856    else
857        /* Can't happen unless there's a serious bug in mod_gnutls or Apache */
858        return apr_psprintf(parms->pool,
859                            "mod_gnutls: %s called for invalid option '%s'",
860                            __func__, parms->directive->directive);
861
862    return NULL;
863}
864
865const char *mgs_set_client_verify_method(cmd_parms * parms, void *dummy __attribute__((unused)),
866        const char *arg) {
867    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)ap_get_module_config(parms->server->module_config, &gnutls_module);
868
869    if (strcasecmp("cartel", arg) == 0) {
870        sc->client_verify_method = mgs_cvm_cartel;
871    } else if (strcasecmp("msva", arg) == 0) {
872#ifdef ENABLE_MSVA
873        sc->client_verify_method = mgs_cvm_msva;
874#else
875        return "GnuTLSClientVerifyMethod: msva is not supported";
876#endif
877    } else {
878        return "GnuTLSClientVerifyMethod: Invalid argument";
879    }
880
881    return NULL;
882}
883
884const char *mgs_set_client_verify(cmd_parms * parms,
885                                  void *dirconf,
886                                  const char *arg) {
887    int mode;
888
889    if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) {
890        mode = GNUTLS_CERT_IGNORE;
891    } else if (strcasecmp("optional", arg) == 0
892               || strcasecmp("request", arg) == 0) {
893        mode = GNUTLS_CERT_REQUEST;
894    } else if (strcasecmp("require", arg) == 0) {
895        mode = GNUTLS_CERT_REQUIRE;
896    } else {
897        return "GnuTLSClientVerify: Invalid argument";
898    }
899
900    /* This was set from a directory context */
901    if (parms->path) {
902        mgs_dirconf_rec *dc = (mgs_dirconf_rec *) dirconf;
903        dc->client_verify_mode = mode;
904    } else {
905        mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
906            ap_get_module_config(parms->server->module_config,
907                                 &gnutls_module);
908        sc->client_verify_mode = mode;
909    }
910
911    return NULL;
912}
913
914const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy __attribute__((unused)),
915        const char *arg) {
916    mgs_srvconf_rec *sc =
917        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
918                                                 module_config,
919                                                 &gnutls_module);
920
921    sc->x509_ca_file = ap_server_root_relative(parms->pool, arg);
922
923    return NULL;
924}
925
926const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy __attribute__((unused)),
927        const char *arg) {
928    mgs_srvconf_rec *sc =
929        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
930                                                 module_config,
931                                                 &gnutls_module);
932
933    sc->pgp_ring_file = ap_server_root_relative(parms->pool, arg);
934
935    return NULL;
936}
937
938/*
939 * Enable TLS proxy operation if arg is true, disable it otherwise.
940 */
941const char *mgs_set_proxy_engine(cmd_parms *parms,
942                                 void *dummy __attribute__((unused)),
943                                 const int arg)
944{
945    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
946        ap_get_module_config(parms->server->module_config, &gnutls_module);
947
948    if (arg)
949        sc->proxy_enabled = GNUTLS_ENABLED_TRUE;
950    else
951        sc->proxy_enabled = GNUTLS_ENABLED_FALSE;
952
953    return NULL;
954}
955
956/*
957 * Enable TLS for the server/vhost if arg is true, disable it
958 * otherwise.
959 */
960const char *mgs_set_enabled(cmd_parms *parms,
961                            void *dummy __attribute__((unused)),
962                            const int arg)
963{
964    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
965        ap_get_module_config(parms->server->module_config, &gnutls_module);
966
967    if (arg)
968        sc->enabled = GNUTLS_ENABLED_TRUE;
969    else
970        sc->enabled = GNUTLS_ENABLED_FALSE;
971
972    return NULL;
973}
974
975const char *mgs_set_export_certificates_size(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg) {
976    mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server->module_config, &gnutls_module);
977    if (!strcasecmp(arg, "On")) {
978        sc->export_certificates_size = 16 * 1024;
979    } else if (!strcasecmp(arg, "Off")) {
980        sc->export_certificates_size = 0;
981    } else {
982        char *endptr;
983        sc->export_certificates_size = strtol(arg, &endptr, 10);
984        while (apr_isspace(*endptr))
985            endptr++;
986        if (*endptr == '\0' || *endptr == 'b' || *endptr == 'B') {
987            ;
988        } else if (*endptr == 'k' || *endptr == 'K') {
989            sc->export_certificates_size *= 1024;
990        } else {
991            return
992                "GnuTLSExportCertificates must be set to a size (in bytes) or 'On' or 'Off'";
993        }
994    }
995
996    return NULL;
997}
998
999
1000
1001/*
1002 * Store GnuTLS priority strings. Used for GnuTLSPriorities and
1003 * GnuTLSProxyPriorities.
1004 */
1005const char *mgs_set_priorities(cmd_parms * parms,
1006                               void *dummy __attribute__((unused)),
1007                               const char *arg)
1008{
1009    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
1010        ap_get_module_config(parms->server->module_config, &gnutls_module);
1011
1012    if (!strcasecmp(parms->directive->directive, "GnuTLSPriorities"))
1013        sc->priorities_str = apr_pstrdup(parms->pool, arg);
1014    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyPriorities"))
1015        sc->proxy_priorities_str = apr_pstrdup(parms->pool, arg);
1016    else
1017        /* Can't happen unless there's a serious bug in mod_gnutls or Apache */
1018        return apr_psprintf(parms->pool,
1019                            "mod_gnutls: %s called for invalid option '%s'",
1020                            __func__, parms->directive->directive);
1021
1022    return NULL;
1023}
1024
1025
1026
1027const char *mgs_set_pin(cmd_parms * parms, void *dummy __attribute__((unused)),
1028                        const char *arg)
1029{
1030
1031    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
1032        ap_get_module_config(parms->server->module_config, &gnutls_module);
1033
1034    sc->pin = apr_pstrdup(parms->pool, arg);
1035
1036    return NULL;
1037}
1038
1039const char *mgs_set_srk_pin(cmd_parms * parms,
1040                            void *dummy __attribute__((unused)),
1041                            const char *arg)
1042{
1043
1044    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
1045        ap_get_module_config(parms->server->module_config, &gnutls_module);
1046
1047    sc->srk_pin = apr_pstrdup(parms->pool, arg);
1048
1049    return NULL;
1050}
1051
1052
1053
1054static mgs_srvconf_rec *_mgs_config_server_create(apr_pool_t * p,
1055                                                  char **err __attribute__((unused)))
1056{
1057    mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc));
1058
1059    sc->enabled = GNUTLS_ENABLED_UNSET;
1060
1061    sc->privkey_x509 = NULL;
1062    sc->anon_creds = NULL;
1063#ifdef ENABLE_SRP
1064    sc->srp_creds = NULL;
1065#endif
1066    sc->certs = NULL;
1067    sc->certs_x509_chain = NULL;
1068    sc->certs_x509_crt_chain = NULL;
1069    sc->certs_x509_chain_num = 0;
1070    sc->p11_modules = NULL;
1071    sc->pin = NULL;
1072
1073    sc->cert_pgp = NULL;
1074    sc->cert_crt_pgp = NULL;
1075    sc->privkey_pgp = NULL;
1076#if GNUTLS_VERSION_NUMBER < 0x030312
1077    sc->privkey_pgp_internal = NULL;
1078#endif
1079    sc->pgp_list = NULL;
1080
1081    sc->priorities_str = NULL;
1082    sc->cache_timeout = MGS_TIMEOUT_UNSET;
1083    sc->cache_type = mgs_cache_unset;
1084    sc->cache_config = NULL;
1085    sc->cache = NULL;
1086    sc->tickets = GNUTLS_ENABLED_UNSET;
1087    sc->priorities = NULL;
1088    sc->dh_params = NULL;
1089    sc->dh_file = NULL;
1090    sc->ca_list = NULL;
1091    sc->ca_list_size = 0;
1092    sc->proxy_enabled = GNUTLS_ENABLED_UNSET;
1093    sc->export_certificates_size = -1;
1094    sc->client_verify_method = mgs_cvm_unset;
1095
1096    sc->proxy_x509_key_file = NULL;
1097    sc->proxy_x509_cert_file = NULL;
1098    sc->proxy_x509_ca_file = NULL;
1099    sc->proxy_x509_crl_file = NULL;
1100    sc->proxy_priorities_str = NULL;
1101    sc->proxy_x509_creds = NULL;
1102    sc->anon_client_creds = NULL;
1103    sc->proxy_priorities = NULL;
1104    sc->proxy_x509_tl = NULL;
1105
1106    sc->ocsp_staple = GNUTLS_ENABLED_UNSET;
1107    sc->ocsp_check_nonce = GNUTLS_ENABLED_UNSET;
1108    sc->ocsp_response_file = NULL;
1109    sc->ocsp_mutex = NULL;
1110    sc->ocsp_cache_time = MGS_TIMEOUT_UNSET;
1111    sc->ocsp_failure_timeout = MGS_TIMEOUT_UNSET;
1112    sc->ocsp_socket_timeout = MGS_TIMEOUT_UNSET;
1113
1114/* this relies on GnuTLS never changing the gnutls_certificate_request_t enum to define -1 */
1115    sc->client_verify_mode = -1;
1116
1117    return sc;
1118}
1119
1120void *mgs_config_server_create(apr_pool_t * p,
1121                               server_rec * s __attribute__((unused))) {
1122    char *err = NULL;
1123    mgs_srvconf_rec *sc = _mgs_config_server_create(p, &err);
1124    if (sc)
1125        return sc;
1126    else
1127        return err;
1128}
1129
1130#define gnutls_srvconf_merge(t, unset) sc->t = (add->t == unset) ? base->t : add->t
1131#define gnutls_srvconf_assign(t) sc->t = add->t
1132
1133void *mgs_config_server_merge(apr_pool_t * p, void *BASE, void *ADD)
1134{
1135    int i;
1136    char *err = NULL;
1137    mgs_srvconf_rec *base = (mgs_srvconf_rec *) BASE;
1138    mgs_srvconf_rec *add = (mgs_srvconf_rec *) ADD;
1139    mgs_srvconf_rec *sc = _mgs_config_server_create(p, &err);
1140    if (NULL == sc)
1141        return err;
1142
1143    gnutls_srvconf_merge(enabled, GNUTLS_ENABLED_UNSET);
1144    gnutls_srvconf_merge(tickets, GNUTLS_ENABLED_UNSET);
1145    gnutls_srvconf_merge(proxy_enabled, GNUTLS_ENABLED_UNSET);
1146    gnutls_srvconf_merge(export_certificates_size, -1);
1147    gnutls_srvconf_merge(client_verify_method, mgs_cvm_unset);
1148    gnutls_srvconf_merge(client_verify_mode, -1);
1149    gnutls_srvconf_merge(srp_tpasswd_file, NULL);
1150    gnutls_srvconf_merge(srp_tpasswd_conf_file, NULL);
1151    gnutls_srvconf_merge(x509_cert_file, NULL);
1152
1153    gnutls_srvconf_merge(x509_key_file, NULL);
1154    gnutls_srvconf_merge(x509_ca_file, NULL);
1155    gnutls_srvconf_merge(p11_modules, NULL);
1156    gnutls_srvconf_merge(pin, NULL);
1157    gnutls_srvconf_merge(pgp_cert_file, NULL);
1158    gnutls_srvconf_merge(pgp_key_file, NULL);
1159    gnutls_srvconf_merge(pgp_ring_file, NULL);
1160    gnutls_srvconf_merge(dh_file, NULL);
1161    gnutls_srvconf_merge(priorities_str, NULL);
1162
1163    gnutls_srvconf_merge(proxy_x509_key_file, NULL);
1164    gnutls_srvconf_merge(proxy_x509_cert_file, NULL);
1165    gnutls_srvconf_merge(proxy_x509_ca_file, NULL);
1166    gnutls_srvconf_merge(proxy_x509_crl_file, NULL);
1167    gnutls_srvconf_merge(proxy_priorities_str, NULL);
1168    gnutls_srvconf_merge(proxy_priorities, NULL);
1169
1170    gnutls_srvconf_merge(ocsp_staple, GNUTLS_ENABLED_UNSET);
1171    gnutls_srvconf_merge(ocsp_check_nonce, GNUTLS_ENABLED_UNSET);
1172    gnutls_srvconf_assign(ocsp_response_file);
1173    gnutls_srvconf_merge(ocsp_cache_time, MGS_TIMEOUT_UNSET);
1174    gnutls_srvconf_merge(ocsp_failure_timeout, MGS_TIMEOUT_UNSET);
1175    gnutls_srvconf_merge(ocsp_socket_timeout, MGS_TIMEOUT_UNSET);
1176
1177    gnutls_srvconf_assign(ca_list);
1178    gnutls_srvconf_assign(ca_list_size);
1179    gnutls_srvconf_assign(cert_pgp);
1180    gnutls_srvconf_assign(cert_crt_pgp);
1181    gnutls_srvconf_assign(pgp_list);
1182    gnutls_srvconf_assign(certs);
1183    gnutls_srvconf_assign(anon_creds);
1184    gnutls_srvconf_assign(srp_creds);
1185    gnutls_srvconf_assign(certs_x509_chain);
1186    gnutls_srvconf_assign(certs_x509_crt_chain);
1187    gnutls_srvconf_assign(certs_x509_chain_num);
1188
1189    /* how do these get transferred cleanly before the data from ADD
1190     * goes away? */
1191    gnutls_srvconf_assign(cert_cn);
1192    for (i = 0; i < MAX_CERT_SAN; i++)
1193        gnutls_srvconf_assign(cert_san[i]);
1194
1195    return sc;
1196}
1197
1198#undef gnutls_srvconf_merge
1199#undef gnutls_srvconf_assign
1200
1201void *mgs_config_dir_merge(apr_pool_t * p,
1202                           void *basev __attribute__((unused)),
1203                           void *addv __attribute__((unused))) {
1204    mgs_dirconf_rec *new;
1205    /*    mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */
1206    mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv;
1207
1208    new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof(mgs_dirconf_rec));
1209    new->client_verify_mode = add->client_verify_mode;
1210    return new;
1211}
1212
1213void *mgs_config_dir_create(apr_pool_t * p,
1214                            char *dir __attribute__((unused))) {
1215    mgs_dirconf_rec *dc = apr_palloc(p, sizeof (*dc));
1216    dc->client_verify_mode = -1;
1217    return dc;
1218}
1219
1220
1221
1222/*
1223 * Store paths to proxy credentials
1224 *
1225 * This function copies the paths provided in the configuration file
1226 * into the server configuration. The post configuration hook takes
1227 * care of actually loading the credentials, which means than invalid
1228 * paths or the like will be detected there.
1229 */
1230const char *mgs_store_cred_path(cmd_parms * parms,
1231                                void *dummy __attribute__((unused)),
1232                                const char *arg)
1233{
1234    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
1235        ap_get_module_config(parms->server->module_config, &gnutls_module);
1236
1237    /* parms->directive->directive contains the directive string */
1238    if (!strcasecmp(parms->directive->directive, "GnuTLSProxyKeyFile"))
1239        sc->proxy_x509_key_file = apr_pstrdup(parms->pool, arg);
1240    else if (!strcasecmp(parms->directive->directive,
1241                         "GnuTLSProxyCertificateFile"))
1242        sc->proxy_x509_cert_file = apr_pstrdup(parms->pool, arg);
1243    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyCAFile"))
1244        sc->proxy_x509_ca_file = apr_pstrdup(parms->pool, arg);
1245    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyCRLFile"))
1246        sc->proxy_x509_crl_file = apr_pstrdup(parms->pool, arg);
1247    return NULL;
1248}
1249
1250
1251
1252/*
1253 * Record PKCS #11 module to load. Note that the value is only used in
1254 * the base config, settings in virtual hosts are ignored.
1255 */
1256const char *mgs_set_p11_module(cmd_parms * parms,
1257                               void *dummy __attribute__((unused)),
1258                               const char *arg)
1259{
1260    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
1261        ap_get_module_config(parms->server->module_config, &gnutls_module);
1262    /* initialize PKCS #11 module list if necessary */
1263    if (sc->p11_modules == NULL)
1264        sc->p11_modules = apr_array_make(parms->pool, 2, sizeof(char*));
1265
1266    *(char **) apr_array_push(sc->p11_modules) = apr_pstrdup(parms->pool, arg);
1267
1268    return NULL;
1269}
Note: See TracBrowser for help on using the repository browser.