source: mod_gnutls/src/gnutls_config.c @ fe0c93a

asynciodebian/masterdebian/stretch-backportsjessie-backportsmainmsvaproxy-ticketupstream
Last change on this file since fe0c93a was b59327c, checked in by Nikos Mavrogiannopoulos <nmav@…>, 12 years ago

GnuTLSCache can now take a single argument (none).

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