source: mod_gnutls/src/gnutls_config.c @ 771ca63

debian/masterdebian/stretch-backportsjessie-backportsmsvaupstream
Last change on this file since 771ca63 was 771ca63, checked in by Nikos Mavrogiannopoulos <nmav@…>, 9 years ago

The GnuTLSCache variable now can be given the specific
option "sdbm" instead of "dbm". "dbm" will use the default
dbm type of libapr while sdbm will force sdbm to be used.

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