aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikos Mavrogiannopoulos 2007-12-15 13:26:01 +0000
committerGravatar Nokis Mavrogiannopoulos 2007-12-15 13:26:01 +0000
commite5bbda4df989848cbcd92263dd4b11a99b019b4f (patch)
tree721754cdff0987366b835feb26b4b48e89ec0542
parentd2439b92fc87095f0288d9bc1aa5cf2621f0eac3 (diff)
Initial support for openpgp keys
-rw-r--r--NEWS5
-rw-r--r--include/mod_gnutls.h.in14
-rw-r--r--src/gnutls_config.c111
-rw-r--r--src/gnutls_hooks.c220
-rw-r--r--src/mod_gnutls.c16
5 files changed, 326 insertions, 40 deletions
diff --git a/NEWS b/NEWS
index 49abeda..b3a4cd9 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
1** Version 0.5.0
2
3- Added support for OpenPGP keys.
4
1** Version 0.4.2 (2007-12-10) 5** Version 0.4.2 (2007-12-10)
2 6
3- Added support for sending a certificate chain. 7- Added support for sending a certificate chain.
@@ -23,3 +27,4 @@ to David Hrbáč.
23- Better handling of GnuTLSDHFile and GnuTLSRSAFile. 27- Better handling of GnuTLSDHFile and GnuTLSRSAFile.
24 28
25- No longer default paths for RSA and DH parameter files. 29- No longer default paths for RSA and DH parameter files.
30[5~ \ No newline at end of file
diff --git a/include/mod_gnutls.h.in b/include/mod_gnutls.h.in
index a0f6581..db7e7dd 100644
--- a/include/mod_gnutls.h.in
+++ b/include/mod_gnutls.h.in
@@ -29,6 +29,8 @@
29 29
30#include <gcrypt.h> 30#include <gcrypt.h>
31#include <gnutls/gnutls.h> 31#include <gnutls/gnutls.h>
32#include <gnutls/extra.h>
33#include <gnutls/openpgp.h>
32#include <gnutls/x509.h> 34#include <gnutls/x509.h>
33 35
34#ifndef __mod_gnutls_h_inc 36#ifndef __mod_gnutls_h_inc
@@ -94,6 +96,8 @@ typedef struct
94 gnutls_x509_crt_t certs_x509[MAX_CHAIN_SIZE]; /* A certificate chain */ 96 gnutls_x509_crt_t certs_x509[MAX_CHAIN_SIZE]; /* A certificate chain */
95 unsigned int certs_x509_num; 97 unsigned int certs_x509_num;
96 gnutls_x509_privkey_t privkey_x509; 98 gnutls_x509_privkey_t privkey_x509;
99 gnutls_openpgp_crt_t cert_pgp; /* A certificate chain */
100 gnutls_openpgp_privkey_t privkey_pgp;
97 int enabled; 101 int enabled;
98 /* whether to send the PEM encoded certificates 102 /* whether to send the PEM encoded certificates
99 * to CGIs 103 * to CGIs
@@ -108,6 +112,7 @@ typedef struct
108 const char* srp_tpasswd_file; 112 const char* srp_tpasswd_file;
109 const char* srp_tpasswd_conf_file; 113 const char* srp_tpasswd_conf_file;
110 gnutls_x509_crt_t ca_list[MAX_CA_CRTS]; 114 gnutls_x509_crt_t ca_list[MAX_CA_CRTS];
115 gnutls_openpgp_keyring_t pgp_list;
111 unsigned int ca_list_size; 116 unsigned int ca_list_size;
112 int client_verify_mode; 117 int client_verify_mode;
113} mgs_srvconf_rec; 118} mgs_srvconf_rec;
@@ -254,6 +259,12 @@ const char *mgs_set_cert_file(cmd_parms * parms, void *dummy,
254const char *mgs_set_key_file(cmd_parms * parms, void *dummy, 259const char *mgs_set_key_file(cmd_parms * parms, void *dummy,
255 const char *arg); 260 const char *arg);
256 261
262const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy,
263 const char *arg);
264
265const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy,
266 const char *arg);
267
257const char *mgs_set_cache(cmd_parms * parms, void *dummy, 268const char *mgs_set_cache(cmd_parms * parms, void *dummy,
258 const char *type, const char* arg); 269 const char *type, const char* arg);
259 270
@@ -266,6 +277,9 @@ const char *mgs_set_client_verify(cmd_parms * parms, void *dummy,
266const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy, 277const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy,
267 const char *arg); 278 const char *arg);
268 279
280const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy,
281 const char *arg);
282
269const char *mgs_set_enabled(cmd_parms * parms, void *dummy, 283const char *mgs_set_enabled(cmd_parms * parms, void *dummy,
270 const char *arg); 284 const char *arg);
271const char *mgs_set_export_certificates_enabled(cmd_parms * parms, void *dummy, 285const char *mgs_set_export_certificates_enabled(cmd_parms * parms, void *dummy,
diff --git a/src/gnutls_config.c b/src/gnutls_config.c
index 8d6308a..4dccd08 100644
--- a/src/gnutls_config.c
+++ b/src/gnutls_config.c
@@ -202,6 +202,85 @@ const char *mgs_set_key_file(cmd_parms * parms, void *dummy,
202 return NULL; 202 return NULL;
203} 203}
204 204
205const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy,
206 const char *arg)
207{
208 int ret;
209 gnutls_datum_t data;
210 const char *file;
211 apr_pool_t *spool;
212 mgs_srvconf_rec *sc =
213 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
214 module_config,
215 &gnutls_module);
216 apr_pool_create(&spool, parms->pool);
217
218 file = ap_server_root_relative(spool, arg);
219
220 if (load_datum_from_file(spool, file, &data) != 0) {
221 return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
222 "Certificate '%s'", file);
223 }
224
225 ret = gnutls_openpgp_crt_init( &sc->cert_pgp);
226 if (ret < 0) {
227 return apr_psprintf(parms->pool, "GnuTLS: Failed to Init "
228 "PGP Certificate: (%d) %s", ret,
229 gnutls_strerror(ret));
230 }
231
232
233 ret =
234 gnutls_openpgp_crt_import(sc->cert_pgp, &data, GNUTLS_OPENPGP_FMT_BASE64);
235 if (ret < 0) {
236 return apr_psprintf(parms->pool, "GnuTLS: Failed to Import "
237 "PGP Certificate '%s': (%d) %s", file, ret,
238 gnutls_strerror(ret));
239 }
240
241 apr_pool_destroy(spool);
242 return NULL;
243}
244
245const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy,
246 const char *arg)
247{
248 int ret;
249 gnutls_datum_t data;
250 const char *file;
251 apr_pool_t *spool;
252 mgs_srvconf_rec *sc =
253 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
254 module_config,
255 &gnutls_module);
256 apr_pool_create(&spool, parms->pool);
257
258 file = ap_server_root_relative(spool, arg);
259
260 if (load_datum_from_file(spool, file, &data) != 0) {
261 return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
262 "Private Key '%s'", file);
263 }
264
265 ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp);
266 if (ret < 0) {
267 return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize"
268 ": (%d) %s", ret, gnutls_strerror(ret));
269 }
270
271 ret =
272 gnutls_openpgp_privkey_import(sc->privkey_pgp, &data,
273 GNUTLS_OPENPGP_FMT_BASE64, NULL, 0);
274 if (ret != 0) {
275 return apr_psprintf(parms->pool, "GnuTLS: Failed to Import "
276 "PGP Private Key '%s': (%d) %s", file, ret,
277 gnutls_strerror(ret));
278 }
279 apr_pool_destroy(spool);
280 return NULL;
281}
282
283
205const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy, 284const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy,
206 const char *arg) 285 const char *arg)
207{ 286{
@@ -350,6 +429,38 @@ const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy,
350 return NULL; 429 return NULL;
351} 430}
352 431
432const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy,
433 const char *arg)
434{
435 int rv;
436 const char *file;
437 apr_pool_t *spool;
438 gnutls_datum_t data;
439
440 mgs_srvconf_rec *sc =
441 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
442 module_config,
443 &gnutls_module);
444 apr_pool_create(&spool, parms->pool);
445
446 file = ap_server_root_relative(spool, arg);
447
448 if (load_datum_from_file(spool, file, &data) != 0) {
449 return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
450 "Keyring File '%s'", file);
451 }
452
453 rv = gnutls_openpgp_keyring_import(sc->pgp_list, &data, GNUTLS_OPENPGP_FMT_BASE64);
454 if (rv < 0) {
455 return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
456 "Keyring File '%s': (%d) %s", file, rv,
457 gnutls_strerror(rv));
458 }
459
460 apr_pool_destroy(spool);
461 return NULL;
462}
463
353const char *mgs_set_enabled(cmd_parms * parms, void *dummy, 464const char *mgs_set_enabled(cmd_parms * parms, void *dummy,
354 const char *arg) 465 const char *arg)
355{ 466{
diff --git a/src/gnutls_hooks.c b/src/gnutls_hooks.c
index 55a1120..39fcd2b 100644
--- a/src/gnutls_hooks.c
+++ b/src/gnutls_hooks.c
@@ -36,7 +36,10 @@ static int mpm_is_threaded;
36 36
37static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt); 37static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt);
38/* use side==0 for server and side==1 for client */ 38/* use side==0 for server and side==1 for client */
39static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt cert, 39static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert,
40 int side,
41 int export_certificates_enabled);
42static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert,
40 int side, 43 int side,
41 int export_certificates_enabled); 44 int export_certificates_enabled);
42 45
@@ -71,6 +74,10 @@ int ret;
71 ret = gnutls_global_init(); 74 ret = gnutls_global_init();
72 if (ret < 0) /* FIXME: can we print here? */ 75 if (ret < 0) /* FIXME: can we print here? */
73 exit(ret); 76 exit(ret);
77
78 ret = gnutls_global_init_extra();
79 if (ret < 0) /* FIXME: can we print here? */
80 exit(ret);
74 81
75 apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, 82 apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config,
76 apr_pool_cleanup_null); 83 apr_pool_cleanup_null);
@@ -87,14 +94,12 @@ int ret;
87 return OK; 94 return OK;
88} 95}
89 96
90/* We don't support openpgp certificates, yet */
91const static int cert_type_prio[2] = { GNUTLS_CRT_X509, 0 };
92
93static int mgs_select_virtual_server_cb(gnutls_session_t session) 97static int mgs_select_virtual_server_cb(gnutls_session_t session)
94{ 98{
95 mgs_handle_t *ctxt; 99 mgs_handle_t *ctxt;
96 mgs_srvconf_rec *tsc; 100 mgs_srvconf_rec *tsc;
97 int ret; 101 int ret;
102 int cprio[3] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 };
98 103
99 ctxt = gnutls_transport_get_ptr(session); 104 ctxt = gnutls_transport_get_ptr(session);
100 105
@@ -126,8 +131,20 @@ static int mgs_select_virtual_server_cb(gnutls_session_t session)
126 * negotiation. 131 * negotiation.
127 */ 132 */
128 ret = gnutls_priority_set(session, ctxt->sc->priorities); 133 ret = gnutls_priority_set(session, ctxt->sc->priorities);
129 gnutls_certificate_type_set_priority(session, cert_type_prio);
130 134
135 /* Do not allow the user to override certificate priorities. We know
136 * better if the certificate of certain type is enabled. */
137 if (ctxt->sc->cert_pgp != NULL && ctxt->sc->certs_x509[0] != NULL) {
138 gnutls_certificate_type_set_priority( session, cprio);
139 } else if (ctxt->sc->certs_x509[0] != NULL) {
140 cprio[0] = GNUTLS_CRT_X509;
141 cprio[1] = 0;
142 gnutls_certificate_type_set_priority( session, cprio);
143 } else if (ctxt->sc->cert_pgp != NULL) {
144 cprio[0] = GNUTLS_CRT_OPENPGP;
145 cprio[1] = 0;
146 gnutls_certificate_type_set_priority( session, cprio);
147 }
131 148
132 /* actually it shouldn't fail since we have checked at startup */ 149 /* actually it shouldn't fail since we have checked at startup */
133 if (ret < 0) 150 if (ret < 0)
@@ -143,13 +160,28 @@ static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st * ret)
143 160
144 ctxt = gnutls_transport_get_ptr(session); 161 ctxt = gnutls_transport_get_ptr(session);
145 162
146 ret->type = GNUTLS_CRT_X509; 163 if (gnutls_certificate_type_get( session) == GNUTLS_CRT_X509) {
147 ret->ncerts = ctxt->sc->certs_x509_num; 164 ret->type = GNUTLS_CRT_X509;
148 ret->deinit_all = 0; 165 ret->ncerts = ctxt->sc->certs_x509_num;
166 ret->deinit_all = 0;
167
168 ret->cert.x509 = ctxt->sc->certs_x509;
169 ret->key.x509 = ctxt->sc->privkey_x509;
170
171 return 0;
172 } else if (gnutls_certificate_type_get( session) == GNUTLS_CRT_OPENPGP) {
173 ret->type = GNUTLS_CRT_OPENPGP;
174 ret->ncerts = 1;
175 ret->deinit_all = 0;
176
177 ret->cert.pgp = ctxt->sc->cert_pgp;
178 ret->key.pgp = ctxt->sc->privkey_pgp;
179
180 return 0;
181
182 }
149 183
150 ret->cert.x509 = ctxt->sc->certs_x509; 184 return GNUTLS_E_INTERNAL_ERROR;
151 ret->key.x509 = ctxt->sc->privkey_x509;
152 return 0;
153} 185}
154 186
155const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n" 187const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n"
@@ -167,7 +199,7 @@ const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n"
167 * Returns negative on error. 199 * Returns negative on error.
168 */ 200 */
169static int read_crt_cn(server_rec * s, apr_pool_t * p, 201static int read_crt_cn(server_rec * s, apr_pool_t * p,
170 gnutls_x509_crt cert, char **cert_cn) 202 gnutls_x509_crt_t cert, char **cert_cn)
171{ 203{
172 int rv = 0, i; 204 int rv = 0, i;
173 size_t data_len; 205 size_t data_len;
@@ -175,6 +207,7 @@ static int read_crt_cn(server_rec * s, apr_pool_t * p,
175 207
176 *cert_cn = NULL; 208 *cert_cn = NULL;
177 209
210 data_len = 0;
178 rv = gnutls_x509_crt_get_dn_by_oid(cert, 211 rv = gnutls_x509_crt_get_dn_by_oid(cert,
179 GNUTLS_OID_X520_COMMON_NAME, 212 GNUTLS_OID_X520_COMMON_NAME,
180 0, 0, NULL, &data_len); 213 0, 0, NULL, &data_len);
@@ -186,7 +219,7 @@ static int read_crt_cn(server_rec * s, apr_pool_t * p,
186 0, *cert_cn, &data_len); 219 0, *cert_cn, &data_len);
187 } else { /* No CN return subject alternative name */ 220 } else { /* No CN return subject alternative name */
188 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, 221 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
189 "No common name found in certificate for '%s:%d'. Looking for subject alternative name.", 222 "No common name found in certificate for '%s:%d'. Looking for subject alternative name...",
190 s->server_hostname, s->port); 223 s->server_hostname, s->port);
191 rv = 0; 224 rv = 0;
192 /* read subject alternative name */ 225 /* read subject alternative name */
@@ -214,9 +247,33 @@ static int read_crt_cn(server_rec * s, apr_pool_t * p,
214 } 247 }
215 248
216 return rv; 249 return rv;
250}
251
252static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p,
253 gnutls_openpgp_crt_t cert, char **cert_cn)
254{
255 int rv = 0;
256 size_t data_len;
257
258
259 *cert_cn = NULL;
260
261 data_len = 0;
262 rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len);
263
264 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) {
265 *cert_cn = apr_palloc(p, data_len);
266 rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, &data_len);
267 } else { /* No CN return subject alternative name */
268 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
269 "No name found in PGP certificate for '%s:%d'.",
270 s->server_hostname, s->port);
271 }
217 272
273 return rv;
218} 274}
219 275
276
220int 277int
221mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, 278mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog,
222 apr_pool_t * ptemp, server_rec * base_server) 279 apr_pool_t * ptemp, server_rec * base_server)
@@ -350,6 +407,9 @@ mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog,
350 407
351 if (sc->enabled == GNUTLS_ENABLED_TRUE) { 408 if (sc->enabled == GNUTLS_ENABLED_TRUE) {
352 rv = read_crt_cn(s, p, sc->certs_x509[0], &sc->cert_cn); 409 rv = read_crt_cn(s, p, sc->certs_x509[0], &sc->cert_cn);
410 if (rv < 0) /* try openpgp certificate */
411 rv = read_pgpcrt_cn(s, p, sc->cert_pgp, &sc->cert_cn);
412
353 if (rv < 0) { 413 if (rv < 0) {
354 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, 414 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
355 "[GnuTLS] - Cannot find a certificate for host '%s:%d'!", 415 "[GnuTLS] - Cannot find a certificate for host '%s:%d'!",
@@ -478,15 +538,6 @@ mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session)
478 538
479 ctxt = gnutls_transport_get_ptr(session); 539 ctxt = gnutls_transport_get_ptr(session);
480 540
481 sni_type = gnutls_certificate_type_get(session);
482 if (sni_type != GNUTLS_CRT_X509) {
483 /* In theory, we could support OpenPGP Certificates. Theory != code. */
484 ap_log_error(APLOG_MARK, APLOG_CRIT, 0,
485 ctxt->c->base_server,
486 "GnuTLS: Only x509 Certificates are currently supported.");
487 return NULL;
488 }
489
490 rv = gnutls_server_name_get(ctxt->session, sni_name, 541 rv = gnutls_server_name_get(ctxt->session, sni_name,
491 &data_len, &sni_type, 0); 542 &data_len, &sni_type, 0);
492 543
@@ -684,7 +735,11 @@ int mgs_hook_fixups(request_rec * r)
684 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); 735 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf));
685 apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp)); 736 apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp));
686 737
687 mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0, 738 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509)
739 mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0,
740 ctxt->sc->export_certificates_enabled);
741 else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP)
742 mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0,
688 ctxt->sc->export_certificates_enabled); 743 ctxt->sc->export_certificates_enabled);
689 744
690 return rv; 745 return rv;
@@ -746,7 +801,7 @@ int mgs_hook_authz(request_rec * r)
746 */ 801 */
747#define MGS_SIDE ((side==0)?"SSL_SERVER":"SSL_CLIENT") 802#define MGS_SIDE ((side==0)?"SSL_SERVER":"SSL_CLIENT")
748static void 803static void
749mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt cert, int side, 804mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side,
750 int export_certificates_enabled) 805 int export_certificates_enabled)
751{ 806{
752 unsigned char sbuf[64]; /* buffer to hold serials */ 807 unsigned char sbuf[64]; /* buffer to hold serials */
@@ -852,17 +907,82 @@ mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt cert, int side,
852 } 907 }
853 } 908 }
854 } 909 }
910}
855 911
912static void
913mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side,
914 int export_certificates_enabled)
915{
916 unsigned char sbuf[64]; /* buffer to hold serials */
917 char buf[AP_IOBUFSIZE];
918 const char *tmp;
919 size_t len;
920 int ret;
856 921
857} 922 apr_table_t *env = r->subprocess_env;
923
924 if (export_certificates_enabled != 0) {
925 char cert_buf[10 * 1024];
926 len = sizeof(cert_buf);
927
928 if (gnutls_openpgp_crt_export
929 (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0)
930 apr_table_setn(env,
931 apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL),
932 apr_pstrmemdup(r->pool, cert_buf, len));
933
934 }
935
936 len = sizeof(buf);
937 gnutls_openpgp_crt_get_name(cert, 0, buf, &len);
938 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL),
939 apr_pstrmemdup(r->pool, buf, len));
940
941 len = sizeof(sbuf);
942 gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len);
943 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf));
944 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", NULL),
945 apr_pstrdup(r->pool, tmp));
946
947 ret = gnutls_openpgp_crt_get_version(cert);
948 if (ret > 0)
949 apr_table_setn(env,
950 apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL),
951 apr_psprintf(r->pool, "%u", ret));
952
953 apr_table_setn(env,
954 apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "OPENPGP");
955
956 tmp =
957 mgs_time2sz(gnutls_openpgp_crt_get_expiration_time
958 (cert), buf, sizeof(buf));
959 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL),
960 apr_pstrdup(r->pool, tmp));
858 961
962 tmp =
963 mgs_time2sz(gnutls_openpgp_crt_get_creation_time
964 (cert), buf, sizeof(buf));
965 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL),
966 apr_pstrdup(r->pool, tmp));
859 967
968 ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL);
969 if (ret >= 0) {
970 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL),
971 gnutls_pk_algorithm_get_name(ret));
972 }
973
974}
975
976/* FIXME: Allow client sending a certificate chain */
860static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) 977static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt)
861{ 978{
862 const gnutls_datum_t *cert_list; 979 const gnutls_datum_t *cert_list;
863 unsigned int cert_list_size, status, expired; 980 unsigned int cert_list_size, status, expired;
864 int rv, ret; 981 int rv, ret;
865 gnutls_x509_crt_t cert; 982 union {
983 gnutls_x509_crt_t x509;
984 gnutls_openpgp_crt_t pgp;
985 } cert;
866 apr_time_t activation_time, expiration_time, cur_time; 986 apr_time_t activation_time, expiration_time, cur_time;
867 987
868 cert_list = 988 cert_list =
@@ -888,23 +1008,40 @@ static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt)
888 return HTTP_FORBIDDEN; 1008 return HTTP_FORBIDDEN;
889 } 1009 }
890 1010
891 gnutls_x509_crt_init(&cert); 1011 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) {
892 rv = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER); 1012 gnutls_x509_crt_init(&cert.x509);
1013 rv = gnutls_x509_crt_import(cert.x509, &cert_list[0], GNUTLS_X509_FMT_DER);
1014 } else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) {
1015 gnutls_openpgp_crt_init(&cert.pgp);
1016 rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW);
1017 } else return HTTP_FORBIDDEN;
1018
893 if (rv < 0) { 1019 if (rv < 0) {
894 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1020 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
895 "GnuTLS: Failed to Verify Peer: " 1021 "GnuTLS: Failed to Verify Peer: "
896 "Failed to import peer certificates."); 1022 "Failed to import peer certificates.");
897 ret = HTTP_FORBIDDEN; 1023 ret = HTTP_FORBIDDEN;
898 goto exit; 1024 goto exit;
899 } 1025 }
900 1026
901 apr_time_ansi_put(&expiration_time, 1027 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) {
902 gnutls_x509_crt_get_expiration_time(cert)); 1028 apr_time_ansi_put(&expiration_time,
903 apr_time_ansi_put(&activation_time, 1029 gnutls_x509_crt_get_expiration_time(cert.x509));
904 gnutls_x509_crt_get_activation_time(cert)); 1030 apr_time_ansi_put(&activation_time,
1031 gnutls_x509_crt_get_activation_time(cert.x509));
905 1032
906 rv = gnutls_x509_crt_verify(cert, ctxt->sc->ca_list, 1033 rv = gnutls_x509_crt_verify(cert.x509, ctxt->sc->ca_list,
907 ctxt->sc->ca_list_size, 0, &status); 1034 ctxt->sc->ca_list_size, 0, &status);
1035 } else {
1036 apr_time_ansi_put(&expiration_time,
1037 gnutls_openpgp_crt_get_expiration_time(cert.pgp));
1038 apr_time_ansi_put(&activation_time,
1039 gnutls_openpgp_crt_get_creation_time(cert.pgp));
1040
1041 rv = gnutls_openpgp_crt_verify_ring(cert.pgp, ctxt->sc->pgp_list,
1042 0, &status);
1043 }
1044
908 1045
909 if (rv < 0) { 1046 if (rv < 0) {
910 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1047 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
@@ -957,7 +1094,11 @@ static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt)
957// mgs_hook_fixups(r); 1094// mgs_hook_fixups(r);
958// rv = mgs_authz_lua(r); 1095// rv = mgs_authz_lua(r);
959 1096
960 mgs_add_common_cert_vars(r, cert, 1, 1097 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509)
1098 mgs_add_common_cert_vars(r, cert.x509, 1,
1099 ctxt->sc->export_certificates_enabled);
1100 else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP)
1101 mgs_add_common_pgpcert_vars(r, cert.pgp, 1,
961 ctxt->sc->export_certificates_enabled); 1102 ctxt->sc->export_certificates_enabled);
962 1103
963 { 1104 {
@@ -981,7 +1122,10 @@ static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt)
981 } 1122 }
982 1123
983 exit: 1124 exit:
984 gnutls_x509_crt_deinit(cert); 1125 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509)
1126 gnutls_x509_crt_deinit(cert.x509);
1127 else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP)
1128 gnutls_openpgp_crt_deinit(cert.pgp);
985 return ret; 1129 return ret;
986 1130
987 1131
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c
index a6e5528..4d70fbd 100644
--- a/src/mod_gnutls.c
+++ b/src/mod_gnutls.c
@@ -64,6 +64,10 @@ static const command_rec mgs_config_cmds[] = {
64 NULL, 64 NULL,
65 RSRC_CONF, 65 RSRC_CONF,
66 "Set the CA File to verify Client Certificates"), 66 "Set the CA File to verify Client Certificates"),
67 AP_INIT_TAKE1("GnuTLSPGPKeyringFile", mgs_set_keyring_file,
68 NULL,
69 RSRC_CONF,
70 "Set the Keyring File to verify Client Certificates"),
67 AP_INIT_TAKE1("GnuTLSDHFile", mgs_set_dh_file, 71 AP_INIT_TAKE1("GnuTLSDHFile", mgs_set_dh_file,
68 NULL, 72 NULL,
69 RSRC_CONF, 73 RSRC_CONF,
@@ -75,11 +79,19 @@ static const command_rec mgs_config_cmds[] = {
75 AP_INIT_TAKE1("GnuTLSCertificateFile", mgs_set_cert_file, 79 AP_INIT_TAKE1("GnuTLSCertificateFile", mgs_set_cert_file,
76 NULL, 80 NULL,
77 RSRC_CONF, 81 RSRC_CONF,
78 "SSL Server Key file"), 82 "SSL Server Certificate file"),
79 AP_INIT_TAKE1("GnuTLSKeyFile", mgs_set_key_file, 83 AP_INIT_TAKE1("GnuTLSKeyFile", mgs_set_key_file,
80 NULL, 84 NULL,
81 RSRC_CONF, 85 RSRC_CONF,
82 "SSL Server SRP Password file"), 86 "SSL Server Private Key file"),
87 AP_INIT_TAKE1("GnuTLSPGPCertificateFile", mgs_set_pgpcert_file,
88 NULL,
89 RSRC_CONF,
90 "SSL Server PGP Certificate file"),
91 AP_INIT_TAKE1("GnuTLSPGPKeyFile", mgs_set_pgpkey_file,
92 NULL,
93 RSRC_CONF,
94 "SSL Server PGP Private key file"),
83 AP_INIT_TAKE1("GnuTLSSRPPasswdFile", mgs_set_srp_tpasswd_file, 95 AP_INIT_TAKE1("GnuTLSSRPPasswdFile", mgs_set_srp_tpasswd_file,
84 NULL, 96 NULL,
85 RSRC_CONF, 97 RSRC_CONF,