source: mod_gnutls/src/gnutls_config.c @ 33826c5

debian/masterdebian/stretch-backportsjessie-backportsmsvaupstream
Last change on this file since 33826c5 was 33826c5, checked in by Dash Shendy <neuromancer@…>, 8 years ago

mod_proxy support

  • Property mode set to 100644
File size: 19.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_rsa_export_file(cmd_parms * parms, void *dummy,
99        const char *arg) {
100    int ret;
101    gnutls_datum_t data;
102    const char *file;
103    apr_pool_t *spool;
104    mgs_srvconf_rec *sc =
105            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
106            module_config,
107            &gnutls_module);
108
109    apr_pool_create(&spool, parms->pool);
110
111    file = ap_server_root_relative(spool, arg);
112
113    if (load_datum_from_file(spool, file, &data) != 0) {
114        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
115                "RSA params '%s'", file);
116    }
117
118    ret = gnutls_rsa_params_init(&sc->rsa_params);
119    if (ret < 0) {
120        return apr_psprintf(parms->pool,
121                "GnuTLS: Failed to initialize"
122                ": (%d) %s", ret,
123                gnutls_strerror(ret));
124    }
125
126    ret =
127            gnutls_rsa_params_import_pkcs1(sc->rsa_params, &data,
128            GNUTLS_X509_FMT_PEM);
129    if (ret != 0) {
130        return apr_psprintf(parms->pool,
131                "GnuTLS: Failed to Import "
132                "RSA params '%s': (%d) %s", file, ret,
133                gnutls_strerror(ret));
134    }
135
136    apr_pool_destroy(spool);
137    return NULL;
138}
139
140const char *mgs_set_cert_file(cmd_parms * parms, void *dummy,
141        const char *arg) {
142    int ret;
143    gnutls_datum_t data;
144    const char *file;
145    apr_pool_t *spool;
146    mgs_srvconf_rec *sc =
147            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
148            module_config,
149            &gnutls_module);
150    apr_pool_create(&spool, parms->pool);
151
152    file = ap_server_root_relative(spool, arg);
153
154    if (load_datum_from_file(spool, file, &data) != 0) {
155        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
156                "Certificate '%s'", file);
157    }
158
159    sc->certs_x509_num = MAX_CHAIN_SIZE;
160    ret =
161            gnutls_x509_crt_list_import(sc->certs_x509,
162            &sc->certs_x509_num, &data,
163            GNUTLS_X509_FMT_PEM, 0);
164    if (ret < 0) {
165        return apr_psprintf(parms->pool,
166                "GnuTLS: Failed to Import "
167                "Certificate '%s': (%d) %s", file, ret,
168                gnutls_strerror(ret));
169    }
170
171    apr_pool_destroy(spool);
172    return NULL;
173}
174
175const char *mgs_set_key_file(cmd_parms * parms, void *dummy,
176        const char *arg) {
177    int ret;
178    gnutls_datum_t data;
179    const char *file;
180    apr_pool_t *spool;
181    mgs_srvconf_rec *sc =
182            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
183            module_config,
184            &gnutls_module);
185    apr_pool_create(&spool, parms->pool);
186
187    file = ap_server_root_relative(spool, arg);
188
189    if (load_datum_from_file(spool, file, &data) != 0) {
190        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
191                "Private Key '%s'", file);
192    }
193
194    ret = gnutls_x509_privkey_init(&sc->privkey_x509);
195    if (ret < 0) {
196        return apr_psprintf(parms->pool,
197                "GnuTLS: Failed to initialize"
198                ": (%d) %s", ret,
199                gnutls_strerror(ret));
200    }
201
202    ret =
203            gnutls_x509_privkey_import(sc->privkey_x509, &data,
204            GNUTLS_X509_FMT_PEM);
205
206    if (ret < 0)
207        ret =
208            gnutls_x509_privkey_import_pkcs8(sc->privkey_x509,
209            &data,
210            GNUTLS_X509_FMT_PEM,
211            NULL,
212            GNUTLS_PKCS_PLAIN);
213
214    if (ret < 0) {
215        return apr_psprintf(parms->pool,
216                "GnuTLS: Failed to Import "
217                "Private Key '%s': (%d) %s", file, ret,
218                gnutls_strerror(ret));
219    }
220    apr_pool_destroy(spool);
221    return NULL;
222}
223
224const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy,
225        const char *arg) {
226    int ret;
227    gnutls_datum_t data;
228    const char *file;
229    apr_pool_t *spool;
230    mgs_srvconf_rec *sc =
231            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
232            module_config,
233            &gnutls_module);
234    apr_pool_create(&spool, parms->pool);
235
236    file = ap_server_root_relative(spool, arg);
237
238    if (load_datum_from_file(spool, file, &data) != 0) {
239        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
240                "Certificate '%s'", file);
241    }
242
243    ret = gnutls_openpgp_crt_init(&sc->cert_pgp);
244    if (ret < 0) {
245        return apr_psprintf(parms->pool, "GnuTLS: Failed to Init "
246                "PGP Certificate: (%d) %s", ret,
247                gnutls_strerror(ret));
248    }
249
250    ret =
251            gnutls_openpgp_crt_import(sc->cert_pgp, &data,
252            GNUTLS_OPENPGP_FMT_BASE64);
253    if (ret < 0) {
254        return apr_psprintf(parms->pool,
255                "GnuTLS: Failed to Import "
256                "PGP Certificate '%s': (%d) %s", file,
257                ret, gnutls_strerror(ret));
258    }
259
260    apr_pool_destroy(spool);
261    return NULL;
262}
263
264const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy,
265        const char *arg) {
266    int ret;
267    gnutls_datum_t data;
268    const char *file;
269    apr_pool_t *spool;
270    mgs_srvconf_rec *sc =
271            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
272            module_config,
273            &gnutls_module);
274    apr_pool_create(&spool, parms->pool);
275
276    file = ap_server_root_relative(spool, arg);
277
278    if (load_datum_from_file(spool, file, &data) != 0) {
279        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
280                "Private Key '%s'", file);
281    }
282
283    ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp);
284    if (ret < 0) {
285        return apr_psprintf(parms->pool,
286                "GnuTLS: Failed to initialize"
287                ": (%d) %s", ret,
288                gnutls_strerror(ret));
289    }
290
291    ret =
292            gnutls_openpgp_privkey_import(sc->privkey_pgp, &data,
293            GNUTLS_OPENPGP_FMT_BASE64, NULL,
294            0);
295    if (ret != 0) {
296        return apr_psprintf(parms->pool,
297                "GnuTLS: Failed to Import "
298                "PGP Private Key '%s': (%d) %s", file,
299                ret, gnutls_strerror(ret));
300    }
301    apr_pool_destroy(spool);
302    return NULL;
303}
304
305const char *mgs_set_tickets(cmd_parms * parms, void *dummy,
306        const char *arg) {
307    mgs_srvconf_rec *sc =
308            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
309            module_config,
310            &gnutls_module);
311
312    sc->tickets = 0;
313    if (strcasecmp("on", arg) == 0) {
314        sc->tickets = 1;
315    }
316
317    return NULL;
318}
319
320
321#ifdef ENABLE_SRP
322
323const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy,
324        const char *arg) {
325    mgs_srvconf_rec *sc =
326            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
327            module_config,
328            &gnutls_module);
329
330    sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg);
331
332    return NULL;
333}
334
335const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy,
336        const char *arg) {
337    mgs_srvconf_rec *sc =
338            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
339            module_config,
340            &gnutls_module);
341
342    sc->srp_tpasswd_conf_file =
343            ap_server_root_relative(parms->pool, arg);
344
345    return NULL;
346}
347
348#endif
349
350const char *mgs_set_cache(cmd_parms * parms, void *dummy,
351        const char *type, const char *arg) {
352    const char *err;
353    mgs_srvconf_rec *sc =
354            ap_get_module_config(parms->server->module_config,
355            &gnutls_module);
356    if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) {
357        return err;
358    }
359
360    if (strcasecmp("none", type) == 0) {
361        sc->cache_type = mgs_cache_none;
362        sc->cache_config = NULL;
363        return NULL;
364    } else if (strcasecmp("dbm", type) == 0) {
365        sc->cache_type = mgs_cache_dbm;
366    } else if (strcasecmp("gdbm", type) == 0) {
367        sc->cache_type = mgs_cache_gdbm;
368    }
369#if HAVE_APR_MEMCACHE
370    else if (strcasecmp("memcache", type) == 0) {
371        sc->cache_type = mgs_cache_memcache;
372    }
373#endif
374    else {
375        return "Invalid Type for GnuTLSCache!";
376    }
377
378    if (arg == NULL)
379        return "Invalid argument 2 for GnuTLSCache!";
380
381    if (sc->cache_type == mgs_cache_dbm
382            || sc->cache_type == mgs_cache_gdbm) {
383        sc->cache_config =
384                ap_server_root_relative(parms->pool, arg);
385    } else {
386        sc->cache_config = apr_pstrdup(parms->pool, arg);
387    }
388
389    return NULL;
390}
391
392const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy,
393        const char *arg) {
394    int argint;
395    mgs_srvconf_rec *sc =
396            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
397            module_config,
398            &gnutls_module);
399
400    argint = atoi(arg);
401
402    if (argint < 0) {
403        return "GnuTLSCacheTimeout: Invalid argument";
404    } else if (argint == 0) {
405        sc->cache_timeout = 0;
406    } else {
407        sc->cache_timeout = apr_time_from_sec(argint);
408    }
409
410    return NULL;
411}
412
413const char *mgs_set_client_verify(cmd_parms * parms, void *dummy,
414        const char *arg) {
415    int mode;
416
417    if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) {
418        mode = GNUTLS_CERT_IGNORE;
419    } else if (strcasecmp("optional", arg) == 0
420            || strcasecmp("request", arg) == 0) {
421        mode = GNUTLS_CERT_REQUEST;
422    } else if (strcasecmp("require", arg) == 0) {
423        mode = GNUTLS_CERT_REQUIRE;
424    } else {
425        return "GnuTLSClientVerify: Invalid argument";
426    }
427
428    /* This was set from a directory context */
429    if (parms->path) {
430        mgs_dirconf_rec *dc = (mgs_dirconf_rec *) dummy;
431        dc->client_verify_mode = mode;
432    } else {
433        mgs_srvconf_rec *sc =
434                (mgs_srvconf_rec *)
435                ap_get_module_config(parms->server->module_config,
436                &gnutls_module);
437        sc->client_verify_mode = mode;
438    }
439
440    return NULL;
441}
442
443#define INIT_CA_SIZE 128
444
445const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy,
446        const char *arg) {
447    int rv;
448    const char *file;
449    apr_pool_t *spool;
450    gnutls_datum_t data;
451
452    mgs_srvconf_rec *sc =
453            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
454            module_config,
455            &gnutls_module);
456    apr_pool_create(&spool, parms->pool);
457
458    file = ap_server_root_relative(spool, arg);
459
460    if (load_datum_from_file(spool, file, &data) != 0) {
461        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
462                "Client CA File '%s'", file);
463    }
464
465    sc->ca_list_size = INIT_CA_SIZE;
466    sc->ca_list = malloc(sc->ca_list_size * sizeof (*sc->ca_list));
467    if (sc->ca_list == NULL) {
468        return apr_psprintf(parms->pool,
469                "mod_gnutls: Memory allocation error");
470    }
471
472    rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size,
473            &data, GNUTLS_X509_FMT_PEM,
474            GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
475    if (rv < 0 && rv != GNUTLS_E_SHORT_MEMORY_BUFFER) {
476        return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
477                "Client CA File '%s': (%d) %s", file,
478                rv, gnutls_strerror(rv));
479    }
480
481    if (INIT_CA_SIZE < sc->ca_list_size) {
482        sc->ca_list =
483                realloc(sc->ca_list,
484                sc->ca_list_size * sizeof (*sc->ca_list));
485        if (sc->ca_list == NULL) {
486            return apr_psprintf(parms->pool,
487                    "mod_gnutls: Memory allocation error");
488        }
489
490        /* re-read */
491        rv = gnutls_x509_crt_list_import(sc->ca_list,
492                &sc->ca_list_size, &data,
493                GNUTLS_X509_FMT_PEM, 0);
494
495        if (rv < 0) {
496            return apr_psprintf(parms->pool,
497                    "GnuTLS: Failed to load "
498                    "Client CA File '%s': (%d) %s",
499                    file, rv, gnutls_strerror(rv));
500        }
501    }
502
503    apr_pool_destroy(spool);
504    return NULL;
505}
506
507const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy,
508        const char *arg) {
509    int rv;
510    const char *file;
511    apr_pool_t *spool;
512    gnutls_datum_t data;
513
514    mgs_srvconf_rec *sc =
515            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
516            module_config,
517            &gnutls_module);
518    apr_pool_create(&spool, parms->pool);
519
520    file = ap_server_root_relative(spool, arg);
521
522    if (load_datum_from_file(spool, file, &data) != 0) {
523        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
524                "Keyring File '%s'", file);
525    }
526
527    rv = gnutls_openpgp_keyring_init(&sc->pgp_list);
528    if (rv < 0) {
529        return apr_psprintf(parms->pool,
530                "GnuTLS: Failed to initialize"
531                "keyring: (%d) %s", rv,
532                gnutls_strerror(rv));
533    }
534
535    rv = gnutls_openpgp_keyring_import(sc->pgp_list, &data,
536            GNUTLS_OPENPGP_FMT_BASE64);
537    if (rv < 0) {
538        return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
539                "Keyring File '%s': (%d) %s", file, rv,
540                gnutls_strerror(rv));
541    }
542
543    apr_pool_destroy(spool);
544    return NULL;
545}
546
547const char *mgs_set_proxy_engine(cmd_parms * parms, void *dummy,
548        const char *arg) {
549   
550    mgs_srvconf_rec *sc =(mgs_srvconf_rec *) 
551            ap_get_module_config(parms->server->module_config, &gnutls_module);
552   
553    if (!strcasecmp(arg, "On")) {
554        sc->proxy_enabled = GNUTLS_ENABLED_TRUE;
555    } else if (!strcasecmp(arg, "Off")) {
556        sc->proxy_enabled = GNUTLS_ENABLED_FALSE;
557    } else {
558        return "SSLProxyEngine must be set to 'On' or 'Off'";
559    }
560
561    return NULL;
562}
563
564const char *mgs_set_enabled(cmd_parms * parms, void *dummy,
565        const char *arg) {
566    mgs_srvconf_rec *sc =
567            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
568            module_config,
569            &gnutls_module);
570    if (!strcasecmp(arg, "On")) {
571        sc->enabled = GNUTLS_ENABLED_TRUE;
572    } else if (!strcasecmp(arg, "Off")) {
573        sc->enabled = GNUTLS_ENABLED_FALSE;
574    } else {
575        return "GnuTLSEnable must be set to 'On' or 'Off'";
576    }
577
578    return NULL;
579}
580
581const char *mgs_set_export_certificates_enabled(cmd_parms * parms,
582        void *dummy,
583        const char *arg) {
584    mgs_srvconf_rec *sc =
585            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
586            module_config,
587            &gnutls_module);
588    if (!strcasecmp(arg, "On")) {
589        sc->export_certificates_enabled = GNUTLS_ENABLED_TRUE;
590    } else if (!strcasecmp(arg, "Off")) {
591        sc->export_certificates_enabled = GNUTLS_ENABLED_FALSE;
592    } else {
593        return
594        "GnuTLSExportCertificates must be set to 'On' or 'Off'";
595    }
596
597    return NULL;
598}
599
600const char *mgs_set_priorities(cmd_parms * parms, void *dummy,
601        const char *arg) {
602    int ret;
603    const char *err;
604    mgs_srvconf_rec *sc =
605            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
606            module_config,
607            &gnutls_module);
608
609
610    ret = gnutls_priority_init(&sc->priorities, arg, &err);
611    if (ret < 0) {
612        if (ret == GNUTLS_E_INVALID_REQUEST)
613            return apr_psprintf(parms->pool,
614                "GnuTLS: Syntax error parsing priorities string at: %s",
615                err);
616        return "Error setting priorities";
617    }
618
619    return NULL;
620}
621
622void *mgs_config_server_create(apr_pool_t * p, server_rec * s) {
623    mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof (*sc));
624    int ret;
625
626    sc->enabled = GNUTLS_ENABLED_FALSE;
627
628    ret = gnutls_certificate_allocate_credentials(&sc->certs);
629    if (ret < 0) {
630        return apr_psprintf(p, "GnuTLS: Failed to initialize"
631                ": (%d) %s", ret,
632                gnutls_strerror(ret));
633    }
634
635    ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds);
636    if (ret < 0) {
637        return apr_psprintf(p, "GnuTLS: Failed to initialize"
638                ": (%d) %s", ret,
639                gnutls_strerror(ret));
640    }
641#ifdef ENABLE_SRP
642    ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds);
643    if (ret < 0) {
644        return apr_psprintf(p, "GnuTLS: Failed to initialize"
645                ": (%d) %s", ret,
646                gnutls_strerror(ret));
647    }
648
649    sc->srp_tpasswd_conf_file = NULL;
650    sc->srp_tpasswd_file = NULL;
651#endif
652
653    sc->privkey_x509 = NULL;
654    memset(sc->certs_x509, 0, sizeof (sc->certs_x509));
655    sc->certs_x509_num = 0;
656    sc->cache_timeout = apr_time_from_sec(300);
657    sc->cache_type = mgs_cache_none;
658    sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache");
659    sc->tickets = 1; /* by default enable session tickets */
660
661    sc->client_verify_mode = GNUTLS_CERT_IGNORE;
662
663    return sc;
664}
665
666void *mgs_config_dir_merge(apr_pool_t * p, void *basev, void *addv) {
667    mgs_dirconf_rec *new;
668    /*    mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */
669    mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv;
670
671    new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof (mgs_dirconf_rec));
672    new->client_verify_mode = add->client_verify_mode;
673    return new;
674}
675
676void *mgs_config_dir_create(apr_pool_t * p, char *dir) {
677    mgs_dirconf_rec *dc = apr_palloc(p, sizeof (*dc));
678    dc->client_verify_mode = -1;
679    return dc;
680}
Note: See TracBrowser for help on using the repository browser.