source: mod_gnutls/src/gnutls_config.c @ cc74801e

asynciodebian/masterdebian/stretch-backportsmainproxy-ticketupstream
Last change on this file since cc74801e was cc74801e, checked in by Thomas Klute <thomas2.klute@…>, 7 years ago

Move generated vhost-wide OCSP config into a private structure

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