source: mod_gnutls/src/gnutls_config.c @ 47a3f49

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

Allow loading of an additional PKCS #11 provider library

When using PKCS #11, it may not be desirable to add the PKCS #11 module
to be used by mod_gnutls to the system wide config, and we definitely
cannot demand it for tests.

To work around such problems, add the new configuration parameter
"GnuTLSP11Module", which may contain the path of a library to load. Note
that the value is only used if present in the base server configuration
(not a virtual host), and that the library is used in addition to
system defaults (if any).

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