source: mod_gnutls/src/gnutls_config.c @ a2368a4

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

Allow loading more than one PKCS #11 module using GnuTLSP11Module

This commit allows multiple modules to be loaded using the
GnuTLSP11Module directive. Each occurrence of GnuTLSP11Module causes the
given module to be added to a list, and all modules on that list are
loaded.

Commit f21d2a6dba6378b18d015dde88193fcad70d8728 disabled modules
configured through the system wide p11-kit configuration if
GnuTLSP11Module is set. With that change, using multiple PKCS #11
modules required using the system configuration, since only one module
could be loaded using GnuTLSP11Module.

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