source: mod_gnutls/src/gnutls_config.c @ 3b4c0d0

debian/masterdebian/stretch-backportsjessie-backportsmsvaupstream
Last change on this file since 3b4c0d0 was 3b4c0d0, checked in by Dash Shendy <neuromancer@…>, 7 years ago
  • Added Comments to Header Structures
  • Refactored the following:

mod_gnutls.h.in:

  • struct mgs_srvconf_rec{}

gnutls_config.c:

  • mgs_set_cert_file()
  • mgs_set_key_file()
  • mgs_set_priorities()
  • mgs_config_server_create()

gnutls_hooks.c

  • mgs_hook_pre_config()
  • mgs_select_virtual_server_cb()
  • cert_retrieve_fn()
  • read_crt_cn()
  • mgs_hook_post_config()
  • mgs_find_sni_server()
  • mgs_add_common_cert_vars()
  • mgs_add_common_pgpcert_vars()

Signed-off-by: Dash Shendy <neuromancer@…>

  • Property mode set to 100644
File size: 17.2 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
22static int load_datum_from_file(apr_pool_t * pool,
23        const char *file, gnutls_datum_t * data) {
24    apr_file_t *fp;
25    apr_finfo_t finfo;
26    apr_status_t rv;
27    apr_size_t br = 0;
28
29    rv = apr_file_open(&fp, file, APR_READ | APR_BINARY,
30            APR_OS_DEFAULT, pool);
31    if (rv != APR_SUCCESS) {
32        return rv;
33    }
34
35    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp);
36
37    if (rv != APR_SUCCESS) {
38        return rv;
39    }
40
41    data->data = apr_palloc(pool, finfo.size + 1);
42    rv = apr_file_read_full(fp, data->data, finfo.size, &br);
43
44    if (rv != APR_SUCCESS) {
45        return rv;
46    }
47    apr_file_close(fp);
48
49    data->data[br] = '\0';
50    data->size = br;
51
52    return 0;
53}
54
55const char *mgs_set_dh_file(cmd_parms * parms, void *dummy,
56        const char *arg) {
57    int ret;
58    gnutls_datum_t data;
59    const char *file;
60    apr_pool_t *spool;
61    mgs_srvconf_rec *sc =
62            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
63            module_config,
64            &gnutls_module);
65
66    apr_pool_create(&spool, parms->pool);
67
68    file = ap_server_root_relative(spool, arg);
69
70    if (load_datum_from_file(spool, file, &data) != 0) {
71        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
72                "DH params '%s'", file);
73    }
74
75    ret = gnutls_dh_params_init(&sc->dh_params);
76    if (ret < 0) {
77        return apr_psprintf(parms->pool,
78                "GnuTLS: Failed to initialize"
79                ": (%d) %s", ret,
80                gnutls_strerror(ret));
81    }
82
83    ret =
84            gnutls_dh_params_import_pkcs3(sc->dh_params, &data,
85            GNUTLS_X509_FMT_PEM);
86    if (ret < 0) {
87        return apr_psprintf(parms->pool,
88                "GnuTLS: Failed to Import "
89                "DH params '%s': (%d) %s", file, ret,
90                gnutls_strerror(ret));
91    }
92
93    apr_pool_destroy(spool);
94
95    return NULL;
96}
97
98const char *mgs_set_cert_file(cmd_parms * parms, void *dummy, const char *arg) {
99
100    int ret;
101    gnutls_datum_t data;
102    const char *file;
103    apr_pool_t *spool;
104
105    mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server->module_config, &gnutls_module);
106    apr_pool_create(&spool, parms->pool);
107
108    file = ap_server_root_relative(spool, arg);
109
110    if (load_datum_from_file(spool, file, &data) != 0) {
111                apr_pool_destroy(spool);
112        return apr_psprintf(parms->pool, "GnuTLS: Error Reading Certificate '%s'", file);
113    }
114
115    sc->certs_x509_chain_num = MAX_CHAIN_SIZE;
116    ret = gnutls_x509_crt_list_import(sc->certs_x509_chain, &sc->certs_x509_chain_num, &data, GNUTLS_X509_FMT_PEM, 0);
117    if (ret < 0) {
118                apr_pool_destroy(spool);
119        return apr_psprintf(parms->pool, "GnuTLS: Failed to Import Certificate '%s': (%d) %s", file, ret, gnutls_strerror(ret));
120    }
121   
122        apr_pool_destroy(spool);
123    return NULL;
124
125}
126
127const char *mgs_set_key_file(cmd_parms * parms, void *dummy, const char *arg) {
128
129    int ret;
130    gnutls_datum_t data;
131    const char *file;
132    apr_pool_t *spool;
133
134        mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server->module_config, &gnutls_module);
135   
136        apr_pool_create(&spool, parms->pool);
137
138    file = ap_server_root_relative(spool, arg);
139
140    if (load_datum_from_file(spool, file, &data) != 0) {
141                apr_pool_destroy(spool);
142        return apr_psprintf(parms->pool, "GnuTLS: Error Reading Private Key '%s'", file);
143    }
144
145    ret = gnutls_x509_privkey_init(&sc->privkey_x509);
146
147    if (ret < 0) {
148                apr_pool_destroy(spool);
149        return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize: (%d) %s", ret, gnutls_strerror(ret));
150    }
151
152    ret = gnutls_x509_privkey_import(sc->privkey_x509, &data, GNUTLS_X509_FMT_PEM);
153
154    if (ret < 0) {
155        ret = gnutls_x509_privkey_import_pkcs8(sc->privkey_x509, &data, GNUTLS_X509_FMT_PEM, NULL, GNUTLS_PKCS_PLAIN);
156        }
157
158    if (ret < 0) {
159                apr_pool_destroy(spool);
160        return apr_psprintf(parms->pool, "GnuTLS: Failed to Import Private Key '%s': (%d) %s", file, ret, gnutls_strerror(ret));
161    }
162
163    apr_pool_destroy(spool);
164
165    return NULL;
166}
167
168const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy,
169        const char *arg) {
170    int ret;
171    gnutls_datum_t data;
172    const char *file;
173    apr_pool_t *spool;
174    mgs_srvconf_rec *sc =
175            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
176            module_config,
177            &gnutls_module);
178    apr_pool_create(&spool, parms->pool);
179
180    file = ap_server_root_relative(spool, arg);
181
182    if (load_datum_from_file(spool, file, &data) != 0) {
183        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
184                "Certificate '%s'", file);
185    }
186
187    ret = gnutls_openpgp_crt_init(&sc->cert_pgp);
188    if (ret < 0) {
189        return apr_psprintf(parms->pool, "GnuTLS: Failed to Init "
190                "PGP Certificate: (%d) %s", ret,
191                gnutls_strerror(ret));
192    }
193
194    ret =
195            gnutls_openpgp_crt_import(sc->cert_pgp, &data,
196            GNUTLS_OPENPGP_FMT_BASE64);
197    if (ret < 0) {
198        return apr_psprintf(parms->pool,
199                "GnuTLS: Failed to Import "
200                "PGP Certificate '%s': (%d) %s", file,
201                ret, gnutls_strerror(ret));
202    }
203
204    apr_pool_destroy(spool);
205    return NULL;
206}
207
208const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy,
209        const char *arg) {
210    int ret;
211    gnutls_datum_t data;
212    const char *file;
213    apr_pool_t *spool;
214    mgs_srvconf_rec *sc =
215            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
216            module_config,
217            &gnutls_module);
218    apr_pool_create(&spool, parms->pool);
219
220    file = ap_server_root_relative(spool, arg);
221
222    if (load_datum_from_file(spool, file, &data) != 0) {
223        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
224                "Private Key '%s'", file);
225    }
226
227    ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp);
228    if (ret < 0) {
229        return apr_psprintf(parms->pool,
230                "GnuTLS: Failed to initialize"
231                ": (%d) %s", ret,
232                gnutls_strerror(ret));
233    }
234
235    ret =
236            gnutls_openpgp_privkey_import(sc->privkey_pgp, &data,
237            GNUTLS_OPENPGP_FMT_BASE64, NULL,
238            0);
239    if (ret != 0) {
240        return apr_psprintf(parms->pool,
241                "GnuTLS: Failed to Import "
242                "PGP Private Key '%s': (%d) %s", file,
243                ret, gnutls_strerror(ret));
244    }
245    apr_pool_destroy(spool);
246    return NULL;
247}
248
249const char *mgs_set_tickets(cmd_parms * parms, void *dummy,
250        const char *arg) {
251    mgs_srvconf_rec *sc =
252            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
253            module_config,
254            &gnutls_module);
255
256    sc->tickets = 0;
257    if (strcasecmp("on", arg) == 0) {
258        sc->tickets = 1;
259    }
260
261    return NULL;
262}
263
264
265#ifdef ENABLE_SRP
266
267const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy,
268        const char *arg) {
269    mgs_srvconf_rec *sc =
270            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
271            module_config,
272            &gnutls_module);
273
274    sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg);
275
276    return NULL;
277}
278
279const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy,
280        const char *arg) {
281    mgs_srvconf_rec *sc =
282            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
283            module_config,
284            &gnutls_module);
285
286    sc->srp_tpasswd_conf_file =
287            ap_server_root_relative(parms->pool, arg);
288
289    return NULL;
290}
291
292#endif
293
294const char *mgs_set_cache(cmd_parms * parms, void *dummy,
295        const char *type, const char *arg) {
296    const char *err;
297    mgs_srvconf_rec *sc =
298            ap_get_module_config(parms->server->module_config,
299            &gnutls_module);
300    if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) {
301        return err;
302    }
303
304    if (strcasecmp("none", type) == 0) {
305        sc->cache_type = mgs_cache_none;
306        sc->cache_config = NULL;
307        return NULL;
308    } else if (strcasecmp("dbm", type) == 0) {
309        sc->cache_type = mgs_cache_dbm;
310    } else if (strcasecmp("gdbm", type) == 0) {
311        sc->cache_type = mgs_cache_gdbm;
312    }
313#if HAVE_APR_MEMCACHE
314    else if (strcasecmp("memcache", type) == 0) {
315        sc->cache_type = mgs_cache_memcache;
316    }
317#endif
318    else {
319        return "Invalid Type for GnuTLSCache!";
320    }
321
322    if (arg == NULL)
323        return "Invalid argument 2 for GnuTLSCache!";
324
325    if (sc->cache_type == mgs_cache_dbm
326            || sc->cache_type == mgs_cache_gdbm) {
327        sc->cache_config =
328                ap_server_root_relative(parms->pool, arg);
329    } else {
330        sc->cache_config = apr_pstrdup(parms->pool, arg);
331    }
332
333    return NULL;
334}
335
336const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy,
337        const char *arg) {
338    int argint;
339    mgs_srvconf_rec *sc =
340            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
341            module_config,
342            &gnutls_module);
343
344    argint = atoi(arg);
345
346    if (argint < 0) {
347        return "GnuTLSCacheTimeout: Invalid argument";
348    } else if (argint == 0) {
349        sc->cache_timeout = 0;
350    } else {
351        sc->cache_timeout = apr_time_from_sec(argint);
352    }
353
354    return NULL;
355}
356
357const char *mgs_set_client_verify(cmd_parms * parms, void *dummy,
358        const char *arg) {
359    int mode;
360
361    if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) {
362        mode = GNUTLS_CERT_IGNORE;
363    } else if (strcasecmp("optional", arg) == 0
364            || strcasecmp("request", arg) == 0) {
365        mode = GNUTLS_CERT_REQUEST;
366    } else if (strcasecmp("require", arg) == 0) {
367        mode = GNUTLS_CERT_REQUIRE;
368    } else {
369        return "GnuTLSClientVerify: Invalid argument";
370    }
371
372    /* This was set from a directory context */
373    if (parms->path) {
374        mgs_dirconf_rec *dc = (mgs_dirconf_rec *) dummy;
375        dc->client_verify_mode = mode;
376    } else {
377        mgs_srvconf_rec *sc =
378                (mgs_srvconf_rec *)
379                ap_get_module_config(parms->server->module_config,
380                &gnutls_module);
381        sc->client_verify_mode = mode;
382    }
383
384    return NULL;
385}
386
387#define INIT_CA_SIZE 128
388
389const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy,
390        const char *arg) {
391    int rv;
392    const char *file;
393    apr_pool_t *spool;
394    gnutls_datum_t data;
395
396    mgs_srvconf_rec *sc =
397            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
398            module_config,
399            &gnutls_module);
400    apr_pool_create(&spool, parms->pool);
401
402    file = ap_server_root_relative(spool, arg);
403
404    if (load_datum_from_file(spool, file, &data) != 0) {
405        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
406                "Client CA File '%s'", file);
407    }
408
409    sc->ca_list_size = INIT_CA_SIZE;
410    sc->ca_list = malloc(sc->ca_list_size * sizeof (*sc->ca_list));
411    if (sc->ca_list == NULL) {
412        return apr_psprintf(parms->pool,
413                "mod_gnutls: Memory allocation error");
414    }
415
416    rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size,
417            &data, GNUTLS_X509_FMT_PEM,
418            GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
419    if (rv < 0 && rv != GNUTLS_E_SHORT_MEMORY_BUFFER) {
420        return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
421                "Client CA File '%s': (%d) %s", file,
422                rv, gnutls_strerror(rv));
423    }
424
425    if (INIT_CA_SIZE < sc->ca_list_size) {
426        sc->ca_list =
427                realloc(sc->ca_list,
428                sc->ca_list_size * sizeof (*sc->ca_list));
429        if (sc->ca_list == NULL) {
430            return apr_psprintf(parms->pool,
431                    "mod_gnutls: Memory allocation error");
432        }
433
434        /* re-read */
435        rv = gnutls_x509_crt_list_import(sc->ca_list,
436                &sc->ca_list_size, &data,
437                GNUTLS_X509_FMT_PEM, 0);
438
439        if (rv < 0) {
440            return apr_psprintf(parms->pool,
441                    "GnuTLS: Failed to load "
442                    "Client CA File '%s': (%d) %s",
443                    file, rv, gnutls_strerror(rv));
444        }
445    }
446
447    apr_pool_destroy(spool);
448    return NULL;
449}
450
451const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy,
452        const char *arg) {
453    int rv;
454    const char *file;
455    apr_pool_t *spool;
456    gnutls_datum_t data;
457
458    mgs_srvconf_rec *sc =
459            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
460            module_config,
461            &gnutls_module);
462    apr_pool_create(&spool, parms->pool);
463
464    file = ap_server_root_relative(spool, arg);
465
466    if (load_datum_from_file(spool, file, &data) != 0) {
467        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
468                "Keyring File '%s'", file);
469    }
470
471    rv = gnutls_openpgp_keyring_init(&sc->pgp_list);
472    if (rv < 0) {
473        return apr_psprintf(parms->pool,
474                "GnuTLS: Failed to initialize"
475                "keyring: (%d) %s", rv,
476                gnutls_strerror(rv));
477    }
478
479    rv = gnutls_openpgp_keyring_import(sc->pgp_list, &data,
480            GNUTLS_OPENPGP_FMT_BASE64);
481    if (rv < 0) {
482        return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
483                "Keyring File '%s': (%d) %s", file, rv,
484                gnutls_strerror(rv));
485    }
486
487    apr_pool_destroy(spool);
488    return NULL;
489}
490
491const char *mgs_set_proxy_engine(cmd_parms * parms, void *dummy,
492        const char *arg) {
493   
494    mgs_srvconf_rec *sc =(mgs_srvconf_rec *) 
495            ap_get_module_config(parms->server->module_config, &gnutls_module);
496   
497    if (!strcasecmp(arg, "On")) {
498        sc->proxy_enabled = GNUTLS_ENABLED_TRUE;
499    } else if (!strcasecmp(arg, "Off")) {
500        sc->proxy_enabled = GNUTLS_ENABLED_FALSE;
501    } else {
502        return "SSLProxyEngine must be set to 'On' or 'Off'";
503    }
504
505    return NULL;
506}
507
508const char *mgs_set_enabled(cmd_parms * parms, void *dummy,
509        const char *arg) {
510    mgs_srvconf_rec *sc =
511            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
512            module_config,
513            &gnutls_module);
514    if (!strcasecmp(arg, "On")) {
515        sc->enabled = GNUTLS_ENABLED_TRUE;
516    } else if (!strcasecmp(arg, "Off")) {
517        sc->enabled = GNUTLS_ENABLED_FALSE;
518    } else {
519        return "GnuTLSEnable must be set to 'On' or 'Off'";
520    }
521
522    return NULL;
523}
524
525const char *mgs_set_priorities(cmd_parms * parms, void *dummy, const char *arg) {
526
527        int ret;
528    const char *err;
529
530    mgs_srvconf_rec *sc = (mgs_srvconf_rec *) 
531                                                  ap_get_module_config(parms->server->module_config, &gnutls_module);
532
533    ret = gnutls_priority_init(&sc->priorities, arg, &err);
534
535    if (ret < 0) {
536        if (ret == GNUTLS_E_INVALID_REQUEST) {
537            return apr_psprintf(parms->pool, 
538                                                                "GnuTLS: Syntax error parsing priorities string at: %s", err);
539                }
540        return "Error setting priorities";
541    }
542
543    return NULL;
544}
545
546void *mgs_config_server_create(apr_pool_t * p, server_rec * s) {
547    mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof (*sc));
548    int ret;
549
550    sc->enabled = GNUTLS_ENABLED_FALSE;
551
552    ret = gnutls_certificate_allocate_credentials(&sc->certs);
553    if (ret < 0) {
554        return apr_psprintf(p, "GnuTLS: Failed to initialize"
555                ": (%d) %s", ret,
556                gnutls_strerror(ret));
557    }
558
559    ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds);
560    if (ret < 0) {
561        return apr_psprintf(p, "GnuTLS: Failed to initialize"
562                ": (%d) %s", ret,
563                gnutls_strerror(ret));
564    }
565#ifdef ENABLE_SRP
566    ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds);
567    if (ret < 0) {
568        return apr_psprintf(p, "GnuTLS: Failed to initialize"
569                ": (%d) %s", ret,
570                gnutls_strerror(ret));
571    }
572
573    sc->srp_tpasswd_conf_file = NULL;
574    sc->srp_tpasswd_file = NULL;
575#endif
576
577    sc->privkey_x509 = NULL;
578        /* Initialize all Certificate Chains */
579        sc->certs_x509_chain = malloc(MAX_CHAIN_SIZE * sizeof (*sc->certs_x509_chain));
580    sc->certs_x509_chain_num = 0;
581    sc->cache_timeout = apr_time_from_sec(300);
582    sc->cache_type = mgs_cache_none;
583    sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache");
584        /* By default enable session tickets */
585    sc->tickets = GNUTLS_ENABLED_TRUE; 
586
587    sc->client_verify_mode = GNUTLS_CERT_IGNORE;
588
589    return sc;
590}
591
592void *mgs_config_dir_merge(apr_pool_t * p, void *basev, void *addv) {
593    mgs_dirconf_rec *new;
594    /*    mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */
595    mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv;
596
597    new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof (mgs_dirconf_rec));
598    new->client_verify_mode = add->client_verify_mode;
599    return new;
600}
601
602void *mgs_config_dir_create(apr_pool_t * p, char *dir) {
603    mgs_dirconf_rec *dc = apr_palloc(p, sizeof (*dc));
604    dc->client_verify_mode = -1;
605    return dc;
606}
Note: See TracBrowser for help on using the repository browser.