source: mod_gnutls/src/gnutls_config.c @ 7ef38d4

debian/masterdebian/stretch-backportsjessie-backportsmsvaupstream
Last change on this file since 7ef38d4 was 7ef38d4, checked in by Nokis Mavrogiannopoulos <nmav@…>, 11 years ago

if private key import fails try as pkcs8 key.

  • Property mode set to 100644
File size: 16.5 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
288
289#ifdef ENABLE_SRP
290
291const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy,
292                                     const char *arg)
293{
294    mgs_srvconf_rec *sc =
295        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
296                                                 module_config,
297                                                 &gnutls_module);
298
299    sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg);
300
301    return NULL;
302}
303
304const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy,
305                                          const char *arg)
306{
307    mgs_srvconf_rec *sc =
308        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
309                                                 module_config,
310                                                 &gnutls_module);
311
312    sc->srp_tpasswd_conf_file = ap_server_root_relative(parms->pool, arg);
313
314    return NULL;
315}
316
317#endif
318
319const char *mgs_set_cache(cmd_parms * parms, void *dummy,
320                          const char *type, const char *arg)
321{
322    const char *err;
323    mgs_srvconf_rec *sc = ap_get_module_config(parms->server->
324                                               module_config,
325                                               &gnutls_module);
326    if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) {
327        return err;
328    }
329
330    if (strcasecmp("none", type) == 0) {
331        sc->cache_type = mgs_cache_none;
332    } else if (strcasecmp("dbm", type) == 0) {
333        sc->cache_type = mgs_cache_dbm;
334    }
335#if HAVE_APR_MEMCACHE
336    else if (strcasecmp("memcache", type) == 0) {
337        sc->cache_type = mgs_cache_memcache;
338    }
339#endif
340    else {
341        return "Invalid Type for GnuTLSCache!";
342    }
343
344    if (sc->cache_type == mgs_cache_dbm) {
345        sc->cache_config = ap_server_root_relative(parms->pool, arg);
346    } else {
347        sc->cache_config = apr_pstrdup(parms->pool, arg);
348    }
349
350    return NULL;
351}
352
353const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy,
354                                  const char *arg)
355{
356    int argint;
357    mgs_srvconf_rec *sc =
358        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
359                                                 module_config,
360                                                 &gnutls_module);
361
362    argint = atoi(arg);
363
364    if (argint < 0) {
365        return "GnuTLSCacheTimeout: Invalid argument";
366    } else if (argint == 0) {
367        sc->cache_timeout = 0;
368    } else {
369        sc->cache_timeout = apr_time_from_sec(argint);
370    }
371
372    return NULL;
373}
374
375const char *mgs_set_client_verify(cmd_parms * parms, void *dummy,
376                                  const char *arg)
377{
378    int mode;
379
380    if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) {
381        mode = GNUTLS_CERT_IGNORE;
382    } else if (strcasecmp("optional", arg) == 0
383               || strcasecmp("request", arg) == 0) {
384        mode = GNUTLS_CERT_REQUEST;
385    } else if (strcasecmp("require", arg) == 0) {
386        mode = GNUTLS_CERT_REQUIRE;
387    } else {
388        return "GnuTLSClientVerify: Invalid argument";
389    }
390
391    /* This was set from a directory context */
392    if (parms->path) {
393        mgs_dirconf_rec *dc = (mgs_dirconf_rec *) dummy;
394        dc->client_verify_mode = mode;
395    } else {
396        mgs_srvconf_rec *sc =
397            (mgs_srvconf_rec *) ap_get_module_config(parms->server->
398                                                     module_config,
399                                                     &gnutls_module);
400        sc->client_verify_mode = mode;
401    }
402
403    return NULL;
404}
405
406#define INIT_CA_SIZE 128
407const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy,
408                                   const char *arg)
409{
410    int rv;
411    const char *file;
412    apr_pool_t *spool;
413    gnutls_datum_t data;
414
415    mgs_srvconf_rec *sc =
416        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
417                                                 module_config,
418                                                 &gnutls_module);
419    apr_pool_create(&spool, parms->pool);
420
421    file = ap_server_root_relative(spool, arg);
422
423    if (load_datum_from_file(spool, file, &data) != 0) {
424        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
425                            "Client CA File '%s'", file);
426    }
427
428    sc->ca_list_size = INIT_CA_SIZE;
429    sc->ca_list = malloc(sc->ca_list_size * sizeof(*sc->ca_list));
430    if (sc->ca_list == NULL) {
431                return apr_psprintf(parms->pool, "mod_gnutls: Memory allocation error");
432    }
433
434    rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size,
435                                     &data, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
436    if (rv < 0 && rv != GNUTLS_E_SHORT_MEMORY_BUFFER) {
437                        return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
438                            "Client CA File '%s': (%d) %s", file, rv,
439                            gnutls_strerror(rv));
440    }
441   
442    if (INIT_CA_SIZE < sc->ca_list_size) {
443                    sc->ca_list = realloc(sc->ca_list, sc->ca_list_size*sizeof(*sc->ca_list));
444                    if (sc->ca_list == NULL) {
445                                return apr_psprintf(parms->pool, "mod_gnutls: Memory allocation error");
446                    }
447
448                /* re-read */
449                rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size,
450                                     &data, GNUTLS_X509_FMT_PEM, 0);
451
452                    if (rv < 0) {
453                                        return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
454                                            "Client CA File '%s': (%d) %s", file, rv,
455                                            gnutls_strerror(rv));
456                    }
457    }
458
459    apr_pool_destroy(spool);
460    return NULL;
461}
462
463const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy,
464                                   const char *arg)
465{
466    int rv;
467    const char *file;
468    apr_pool_t *spool;
469    gnutls_datum_t data;
470
471    mgs_srvconf_rec *sc =
472        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
473                                                 module_config,
474                                                 &gnutls_module);
475    apr_pool_create(&spool, parms->pool);
476
477    file = ap_server_root_relative(spool, arg);
478
479    if (load_datum_from_file(spool, file, &data) != 0) {
480        return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
481                            "Keyring File '%s'", file);
482    }
483
484    rv = gnutls_openpgp_keyring_init(&sc->pgp_list);
485    if (rv < 0) {
486        return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize"
487                            "keyring: (%d) %s", rv, gnutls_strerror(rv));
488    }
489
490    rv = gnutls_openpgp_keyring_import(sc->pgp_list, &data, GNUTLS_OPENPGP_FMT_BASE64);
491    if (rv < 0) {
492        return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
493                            "Keyring File '%s': (%d) %s", file, rv,
494                            gnutls_strerror(rv));
495    }
496
497    apr_pool_destroy(spool);
498    return NULL;
499}
500
501const char *mgs_set_enabled(cmd_parms * parms, void *dummy,
502                            const char *arg)
503{
504    mgs_srvconf_rec *sc =
505        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
506                                                 module_config,
507                                                 &gnutls_module);
508    if (!strcasecmp(arg, "On")) {
509        sc->enabled = GNUTLS_ENABLED_TRUE;
510    } else if (!strcasecmp(arg, "Off")) {
511        sc->enabled = GNUTLS_ENABLED_FALSE;
512    } else {
513        return "GnuTLSEnable must be set to 'On' or 'Off'";
514    }
515
516    return NULL;
517}
518
519const char *mgs_set_export_certificates_enabled(cmd_parms * parms, void *dummy,
520                            const char *arg)
521{
522    mgs_srvconf_rec *sc =
523        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
524                                                 module_config,
525                                                 &gnutls_module);
526    if (!strcasecmp(arg, "On")) {
527        sc->export_certificates_enabled = GNUTLS_ENABLED_TRUE;
528    } else if (!strcasecmp(arg, "Off")) {
529        sc->export_certificates_enabled = GNUTLS_ENABLED_FALSE;
530    } else {
531        return "GnuTLSExportCertificates must be set to 'On' or 'Off'";
532    }
533
534    return NULL;
535}
536
537
538const char *mgs_set_priorities(cmd_parms * parms, void *dummy, const char *arg)
539{
540    int ret;
541    const char *err;
542    mgs_srvconf_rec *sc =
543        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
544                                                 module_config,
545                                                 &gnutls_module);
546
547
548    ret = gnutls_priority_init( &sc->priorities, arg, &err);
549    if (ret < 0) {
550      if (ret == GNUTLS_E_INVALID_REQUEST)
551        return apr_psprintf(parms->pool, "GnuTLS: Syntax error parsing priorities string at: %s", err);
552      return "Error setting priorities";
553    }
554
555    return NULL;
556}
557
558void *mgs_config_server_create(apr_pool_t * p, server_rec * s)
559{
560    mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc));
561    int ret;
562   
563    sc->enabled = GNUTLS_ENABLED_FALSE;
564
565    ret = gnutls_certificate_allocate_credentials(&sc->certs);
566    if (ret < 0) {
567        return apr_psprintf(p, "GnuTLS: Failed to initialize"
568                            ": (%d) %s", ret, gnutls_strerror(ret));
569    }
570
571    ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds);
572    if (ret < 0) {
573        return apr_psprintf(p, "GnuTLS: Failed to initialize"
574                            ": (%d) %s", ret, gnutls_strerror(ret));
575    }
576
577#ifdef ENABLE_SRP
578    ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds);
579    if (ret < 0) {
580        return apr_psprintf(p, "GnuTLS: Failed to initialize"
581                            ": (%d) %s", ret, gnutls_strerror(ret));
582    }
583
584    sc->srp_tpasswd_conf_file = NULL;
585    sc->srp_tpasswd_file = NULL;
586#endif
587
588    sc->privkey_x509 = NULL;
589    memset( sc->certs_x509, 0, sizeof(sc->certs_x509));
590    sc->certs_x509_num = 0;
591    sc->cache_timeout = apr_time_from_sec(300);
592    sc->cache_type = mgs_cache_dbm;
593    sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache");
594
595    sc->client_verify_mode = GNUTLS_CERT_IGNORE;
596
597    return sc;
598}
599
600void *mgs_config_dir_merge(apr_pool_t * p, void *basev, void *addv)
601{
602    mgs_dirconf_rec *new;
603/*    mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */
604    mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv;
605
606    new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof(mgs_dirconf_rec));
607    new->lua_bytecode = apr_pstrmemdup(p, add->lua_bytecode,
608                                       add->lua_bytecode_len);
609    new->lua_bytecode_len = add->lua_bytecode_len;
610    new->client_verify_mode = add->client_verify_mode;
611    return new;
612}
613
614void *mgs_config_dir_create(apr_pool_t * p, char *dir)
615{
616    mgs_dirconf_rec *dc = apr_palloc(p, sizeof(*dc));
617
618    dc->client_verify_mode = -1;
619    dc->lua_bytecode = NULL;
620    dc->lua_bytecode_len = 0;
621    return dc;
622}
Note: See TracBrowser for help on using the repository browser.