diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gnutls_config.c | 111 | ||||
-rw-r--r-- | src/gnutls_hooks.c | 220 | ||||
-rw-r--r-- | src/mod_gnutls.c | 16 |
3 files changed, 307 insertions, 40 deletions
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 | ||
205 | const 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 | |||
245 | const 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 | |||
205 | const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy, | 284 | const 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 | ||
432 | const 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 | |||
353 | const char *mgs_set_enabled(cmd_parms * parms, void *dummy, | 464 | const 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 | ||
37 | static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt); | 37 | static 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 */ |
39 | static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt cert, | 39 | static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, |
40 | int side, | ||
41 | int export_certificates_enabled); | ||
42 | static 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 */ | ||
91 | const static int cert_type_prio[2] = { GNUTLS_CRT_X509, 0 }; | ||
92 | |||
93 | static int mgs_select_virtual_server_cb(gnutls_session_t session) | 97 | static 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 | ||
155 | const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n" | 187 | const 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 | */ |
169 | static int read_crt_cn(server_rec * s, apr_pool_t * p, | 201 | static 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 | |||
252 | static 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 | |||
220 | int | 277 | int |
221 | mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | 278 | mgs_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") |
748 | static void | 803 | static void |
749 | mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt cert, int side, | 804 | mgs_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 | ||
912 | static void | ||
913 | mgs_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 */ | ||
860 | static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) | 977 | static 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, |