Changeset 2b1118c in mod_gnutls for src/gnutls_hooks.c
- Timestamp:
- Jan 11, 2013, 12:58:31 AM (8 years ago)
- Branches:
- debian/master, debian/stretch-backports, jessie-backports
- Children:
- 819445c
- Parents:
- 619c6bf (diff), 180e49f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/gnutls_hooks.c
r619c6bf r2b1118c 41 41 static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt); 42 42 /* use side==0 for server and side==1 for client */ 43 static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert,44 int side,43 static void mgs_add_common_cert_vars(request_rec * r, 44 gnutls_x509_crt_t cert, int side, 45 45 int export_certificates_enabled); 46 static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, 47 int side, 48 int export_certificates_enabled); 46 static void mgs_add_common_pgpcert_vars(request_rec * r, 47 gnutls_openpgp_crt_t cert, 48 int side, 49 int export_certificates_enabled); 49 50 50 51 static apr_status_t mgs_cleanup_pre_config(void *data) 51 52 { 52 53 54 55 56 53 gnutls_free(session_ticket_key.data); 54 session_ticket_key.data = NULL; 55 session_ticket_key.size = 0; 56 gnutls_global_deinit(); 57 return APR_SUCCESS; 57 58 } 58 59 … … 60 61 static void gnutls_debug_log_all(int level, const char *str) 61 62 { 62 apr_file_printf(debug_log_fp, "<%d> %s\n", level, str); 63 } 63 apr_file_printf(debug_log_fp, "<%d> %s\n", level, str); 64 } 65 64 66 #define _gnutls_log apr_file_printf 65 67 #else 66 # define _gnutls_log(...) 68 # define _gnutls_log(...) 67 69 #endif 68 70 … … 71 73 apr_pool_t * plog, apr_pool_t * ptemp) 72 74 { 73 int ret;75 int ret; 74 76 75 77 #if MOD_GNUTLS_DEBUG 76 apr_file_open(&debug_log_fp, "/tmp/gnutls_debug", 77 APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, 78 pconf); 79 80 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 81 82 gnutls_global_set_log_level(9); 83 gnutls_global_set_log_function(gnutls_debug_log_all); 84 _gnutls_log(debug_log_fp, "gnutls: %s\n", gnutls_check_version(NULL)); 78 apr_file_open(&debug_log_fp, "/tmp/gnutls_debug", 79 APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, 80 pconf); 81 82 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 83 84 gnutls_global_set_log_level(9); 85 gnutls_global_set_log_function(gnutls_debug_log_all); 86 _gnutls_log(debug_log_fp, "gnutls: %s\n", 87 gnutls_check_version(NULL)); 85 88 #endif 86 89 87 90 #if APR_HAS_THREADS 88 91 ap_mpm_query(AP_MPMQ_IS_THREADED, &mpm_is_threaded); 89 92 #if (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR < 11) || GNUTLS_VERSION_MAJOR < 2 90 if (mpm_is_threaded) { 91 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); 92 } 93 if (mpm_is_threaded) { 94 gcry_control(GCRYCTL_SET_THREAD_CBS, 95 &gcry_threads_pthread); 96 } 93 97 #endif 94 98 #else 95 mpm_is_threaded = 0; 96 #endif 97 98 99 if (gnutls_check_version(LIBGNUTLS_VERSION)==NULL) { 100 _gnutls_log(debug_log_fp, "gnutls_check_version() failed. Required: gnutls-%s Found: gnutls-%s\n", 101 LIBGNUTLS_VERSION, gnutls_check_version(NULL)); 102 return -3; 103 } 104 105 ret = gnutls_global_init(); 106 if (ret < 0) { 107 _gnutls_log(debug_log_fp, "gnutls_global_init: %s\n", gnutls_strerror(ret)); 108 return -3; 109 } 110 111 ret = gnutls_session_ticket_key_generate( &session_ticket_key); 112 if (ret < 0) { 113 _gnutls_log(debug_log_fp, "gnutls_session_ticket_key_generate: %s\n", gnutls_strerror(ret)); 114 } 115 116 apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, 117 apr_pool_cleanup_null); 118 119 120 return OK; 99 mpm_is_threaded = 0; 100 #endif 101 102 103 if (gnutls_check_version(LIBGNUTLS_VERSION) == NULL) { 104 _gnutls_log(debug_log_fp, 105 "gnutls_check_version() failed. Required: gnutls-%s Found: gnutls-%s\n", 106 LIBGNUTLS_VERSION, gnutls_check_version(NULL)); 107 return -3; 108 } 109 110 ret = gnutls_global_init(); 111 if (ret < 0) { 112 _gnutls_log(debug_log_fp, "gnutls_global_init: %s\n", 113 gnutls_strerror(ret)); 114 return -3; 115 } 116 117 ret = gnutls_session_ticket_key_generate(&session_ticket_key); 118 if (ret < 0) { 119 _gnutls_log(debug_log_fp, 120 "gnutls_session_ticket_key_generate: %s\n", 121 gnutls_strerror(ret)); 122 } 123 124 apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, 125 apr_pool_cleanup_null); 126 127 128 return OK; 121 129 } 122 130 123 131 static int mgs_select_virtual_server_cb(gnutls_session_t session) 124 132 { 125 mgs_handle_t *ctxt; 126 mgs_srvconf_rec *tsc; 127 int ret; 128 int cprio[2]; 129 130 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 131 132 ctxt = gnutls_transport_get_ptr(session); 133 134 /* find the virtual server */ 135 tsc = mgs_find_sni_server(session); 136 137 if (tsc != NULL) 138 ctxt->sc = tsc; 139 140 gnutls_certificate_server_set_request(session, 141 ctxt->sc->client_verify_mode); 142 143 /* set the new server credentials 144 */ 145 146 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, 147 ctxt->sc->certs); 148 149 gnutls_credentials_set(session, GNUTLS_CRD_ANON, ctxt->sc->anon_creds); 133 mgs_handle_t *ctxt; 134 mgs_srvconf_rec *tsc; 135 int ret; 136 int cprio[2]; 137 138 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 139 140 ctxt = gnutls_transport_get_ptr(session); 141 142 /* find the virtual server */ 143 tsc = mgs_find_sni_server(session); 144 145 if (tsc != NULL) 146 ctxt->sc = tsc; 147 148 gnutls_certificate_server_set_request(session, 149 ctxt-> 150 sc->client_verify_mode); 151 152 /* set the new server credentials 153 */ 154 155 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, 156 ctxt->sc->certs); 157 158 gnutls_credentials_set(session, GNUTLS_CRD_ANON, 159 ctxt->sc->anon_creds); 150 160 151 161 #ifdef ENABLE_SRP 152 if (ctxt->sc->srp_tpasswd_conf_file != NULL 153 && ctxt->sc->srp_tpasswd_file != NULL) { 154 gnutls_credentials_set(session, GNUTLS_CRD_SRP, 155 ctxt->sc->srp_creds); 156 } 157 #endif 158 159 /* update the priorities - to avoid negotiating a ciphersuite that is not 160 * enabled on this virtual server. Note that here we ignore the version 161 * negotiation. 162 */ 163 ret = gnutls_priority_set(session, ctxt->sc->priorities); 164 /* actually it shouldn't fail since we have checked at startup */ 165 if (ret < 0) 166 return ret; 167 168 /* If both certificate types are not present disallow them from 169 * being negotiated. 170 */ 171 if (ctxt->sc->certs_x509[0] != NULL && ctxt->sc->cert_pgp == NULL) { 172 cprio[0] = GNUTLS_CRT_X509; 173 cprio[1] = 0; 174 gnutls_certificate_type_set_priority( session, cprio); 175 } else if (ctxt->sc->cert_pgp != NULL && ctxt->sc->certs_x509[0]==NULL) { 176 cprio[0] = GNUTLS_CRT_OPENPGP; 177 cprio[1] = 0; 178 gnutls_certificate_type_set_priority( session, cprio); 179 } 180 181 return 0; 162 if (ctxt->sc->srp_tpasswd_conf_file != NULL 163 && ctxt->sc->srp_tpasswd_file != NULL) { 164 gnutls_credentials_set(session, GNUTLS_CRD_SRP, 165 ctxt->sc->srp_creds); 166 } 167 #endif 168 169 /* update the priorities - to avoid negotiating a ciphersuite that is not 170 * enabled on this virtual server. Note that here we ignore the version 171 * negotiation. 172 */ 173 ret = gnutls_priority_set(session, ctxt->sc->priorities); 174 /* actually it shouldn't fail since we have checked at startup */ 175 if (ret < 0) 176 return ret; 177 178 /* If both certificate types are not present disallow them from 179 * being negotiated. 180 */ 181 if (ctxt->sc->certs_x509[0] != NULL && ctxt->sc->cert_pgp == NULL) { 182 cprio[0] = GNUTLS_CRT_X509; 183 cprio[1] = 0; 184 gnutls_certificate_type_set_priority(session, cprio); 185 } else if (ctxt->sc->cert_pgp != NULL 186 && ctxt->sc->certs_x509[0] == NULL) { 187 cprio[0] = GNUTLS_CRT_OPENPGP; 188 cprio[1] = 0; 189 gnutls_certificate_type_set_priority(session, cprio); 190 } 191 192 return 0; 182 193 } 183 194 184 195 static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st * ret) 185 196 { 186 mgs_handle_t *ctxt; 187 188 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 189 ctxt = gnutls_transport_get_ptr(session); 190 191 if (ctxt == NULL) 192 return GNUTLS_E_INTERNAL_ERROR; 193 194 if (gnutls_certificate_type_get( session) == GNUTLS_CRT_X509) { 195 ret->type = GNUTLS_CRT_X509; 196 ret->ncerts = ctxt->sc->certs_x509_num; 197 ret->deinit_all = 0; 198 199 ret->cert.x509 = ctxt->sc->certs_x509; 200 ret->key.x509 = ctxt->sc->privkey_x509; 201 202 return 0; 203 } else if (gnutls_certificate_type_get( session) == GNUTLS_CRT_OPENPGP) { 204 ret->type = GNUTLS_CRT_OPENPGP; 205 ret->ncerts = 1; 206 ret->deinit_all = 0; 207 208 ret->cert.pgp = ctxt->sc->cert_pgp; 209 ret->key.pgp = ctxt->sc->privkey_pgp; 210 211 return 0; 212 213 } 214 215 return GNUTLS_E_INTERNAL_ERROR; 197 mgs_handle_t *ctxt; 198 199 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 200 ctxt = gnutls_transport_get_ptr(session); 201 202 if (ctxt == NULL) 203 return GNUTLS_E_INTERNAL_ERROR; 204 205 if (gnutls_certificate_type_get(session) == GNUTLS_CRT_X509) { 206 ret->type = GNUTLS_CRT_X509; 207 ret->ncerts = ctxt->sc->certs_x509_num; 208 ret->deinit_all = 0; 209 210 ret->cert.x509 = ctxt->sc->certs_x509; 211 ret->key.x509 = ctxt->sc->privkey_x509; 212 213 return 0; 214 } else if (gnutls_certificate_type_get(session) == 215 GNUTLS_CRT_OPENPGP) { 216 ret->type = GNUTLS_CRT_OPENPGP; 217 ret->ncerts = 1; 218 ret->deinit_all = 0; 219 220 ret->cert.pgp = ctxt->sc->cert_pgp; 221 ret->key.pgp = ctxt->sc->privkey_pgp; 222 223 return 0; 224 225 } 226 227 return GNUTLS_E_INTERNAL_ERROR; 216 228 } 217 229 … … 234 246 gnutls_x509_crt_t cert, char **cert_cn) 235 247 { 236 int rv = 0, i; 237 size_t data_len; 238 239 240 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 241 *cert_cn = NULL; 242 243 data_len = 0; 244 rv = gnutls_x509_crt_get_dn_by_oid(cert, 245 GNUTLS_OID_X520_COMMON_NAME, 246 0, 0, NULL, &data_len); 247 248 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { 249 *cert_cn = apr_palloc(p, data_len); 248 int rv = 0, i; 249 size_t data_len; 250 251 252 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 253 *cert_cn = NULL; 254 255 data_len = 0; 250 256 rv = gnutls_x509_crt_get_dn_by_oid(cert, 251 GNUTLS_OID_X520_COMMON_NAME, 0, 252 0, *cert_cn, &data_len); 253 } else { /* No CN return subject alternative name */ 254 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, 255 "No common name found in certificate for '%s:%d'. Looking for subject alternative name...", 256 s->server_hostname, s->port); 257 rv = 0; 258 /* read subject alternative name */ 259 for (i = 0; !(rv < 0); i++) { 260 data_len = 0; 261 rv = gnutls_x509_crt_get_subject_alt_name(cert, i, 262 NULL, &data_len, 263 NULL); 264 265 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { 266 /* FIXME: not very efficient. What if we have several alt names 267 * before DNSName? 268 */ 269 *cert_cn = apr_palloc(p, data_len + 1); 270 271 rv = gnutls_x509_crt_get_subject_alt_name(cert, i, 272 *cert_cn, 273 &data_len, NULL); 274 (*cert_cn)[data_len] = 0; 275 276 if (rv == GNUTLS_SAN_DNSNAME) 277 break; 278 } 279 } 280 } 281 282 return rv; 257 GNUTLS_OID_X520_COMMON_NAME, 258 0, 0, NULL, &data_len); 259 260 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { 261 *cert_cn = apr_palloc(p, data_len); 262 rv = gnutls_x509_crt_get_dn_by_oid(cert, 263 GNUTLS_OID_X520_COMMON_NAME, 264 0, 0, *cert_cn, 265 &data_len); 266 } else { /* No CN return subject alternative name */ 267 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, 268 "No common name found in certificate for '%s:%d'. Looking for subject alternative name...", 269 s->server_hostname, s->port); 270 rv = 0; 271 /* read subject alternative name */ 272 for (i = 0; !(rv < 0); i++) { 273 data_len = 0; 274 rv = gnutls_x509_crt_get_subject_alt_name(cert, i, 275 NULL, 276 &data_len, 277 NULL); 278 279 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER 280 && data_len > 1) { 281 /* FIXME: not very efficient. What if we have several alt names 282 * before DNSName? 283 */ 284 *cert_cn = apr_palloc(p, data_len + 1); 285 286 rv = gnutls_x509_crt_get_subject_alt_name 287 (cert, i, *cert_cn, &data_len, NULL); 288 (*cert_cn)[data_len] = 0; 289 290 if (rv == GNUTLS_SAN_DNSNAME) 291 break; 292 } 293 } 294 } 295 296 return rv; 283 297 } 284 298 285 299 static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p, 286 gnutls_openpgp_crt_t cert, char **cert_cn) 287 { 288 int rv = 0; 289 size_t data_len; 290 291 292 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 293 *cert_cn = NULL; 294 295 data_len = 0; 296 rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len); 297 298 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { 299 *cert_cn = apr_palloc(p, data_len); 300 rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, &data_len); 301 } else { /* No CN return subject alternative name */ 302 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, 303 "No name found in PGP certificate for '%s:%d'.", 304 s->server_hostname, s->port); 305 } 306 307 return rv; 300 gnutls_openpgp_crt_t cert, char **cert_cn) 301 { 302 int rv = 0; 303 size_t data_len; 304 305 306 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 307 *cert_cn = NULL; 308 309 data_len = 0; 310 rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len); 311 312 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { 313 *cert_cn = apr_palloc(p, data_len); 314 rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, 315 &data_len); 316 } else { /* No CN return subject alternative name */ 317 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, 318 "No name found in PGP certificate for '%s:%d'.", 319 s->server_hostname, s->port); 320 } 321 322 return rv; 308 323 } 309 324 … … 313 328 apr_pool_t * ptemp, server_rec * base_server) 314 329 { 315 int rv; 316 server_rec *s; 317 gnutls_dh_params_t dh_params = NULL; 318 gnutls_rsa_params_t rsa_params = NULL; 319 mgs_srvconf_rec *sc; 320 mgs_srvconf_rec *sc_base; 321 void *data = NULL; 322 int first_run = 0; 323 const char *userdata_key = "mgs_init"; 324 325 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 326 apr_pool_userdata_get(&data, userdata_key, base_server->process->pool); 327 if (data == NULL) { 328 first_run = 1; 329 apr_pool_userdata_set((const void *) 1, userdata_key, 330 apr_pool_cleanup_null, 330 int rv; 331 server_rec *s; 332 gnutls_dh_params_t dh_params = NULL; 333 gnutls_rsa_params_t rsa_params = NULL; 334 mgs_srvconf_rec *sc; 335 mgs_srvconf_rec *sc_base; 336 void *data = NULL; 337 int first_run = 0; 338 const char *userdata_key = "mgs_init"; 339 340 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 341 apr_pool_userdata_get(&data, userdata_key, 331 342 base_server->process->pool); 332 } 333 334 335 { 343 if (data == NULL) { 344 first_run = 1; 345 apr_pool_userdata_set((const void *) 1, userdata_key, 346 apr_pool_cleanup_null, 347 base_server->process->pool); 348 } 349 350 336 351 s = base_server; 337 352 sc_base = … … 342 357 343 358 if (sc_base->dh_params == NULL) { 344 gnutls_datum pdata = { (void *) static_dh_params, sizeof(static_dh_params) }; 345 /* loading defaults */ 346 rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, 347 GNUTLS_X509_FMT_PEM); 348 349 if (rv < 0) { 350 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 351 "GnuTLS: Unable to load DH Params: (%d) %s", 352 rv, gnutls_strerror(rv)); 353 exit(rv); 354 } 355 } else dh_params = sc_base->dh_params; 356 357 if (sc_base->rsa_params != NULL) 358 rsa_params = sc_base->rsa_params; 359 gnutls_datum pdata = { 360 (void *) static_dh_params, 361 sizeof(static_dh_params) 362 }; 363 /* loading defaults */ 364 rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, 365 GNUTLS_X509_FMT_PEM); 366 367 if (rv < 0) { 368 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 369 "GnuTLS: Unable to load DH Params: (%d) %s", 370 rv, gnutls_strerror(rv)); 371 exit(rv); 372 } 373 } else 374 dh_params = sc_base->dh_params; 375 376 if (sc_base->rsa_params != NULL) 377 rsa_params = sc_base->rsa_params; 359 378 360 379 /* else not an error but RSA-EXPORT ciphersuites are not available … … 363 382 rv = mgs_cache_post_config(p, s, sc_base); 364 383 if (rv != 0) { 365 366 "GnuTLS: Post Config for GnuTLSCache Failed."367 " Shutting Down.");368 384 ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, 385 "GnuTLS: Post Config for GnuTLSCache Failed." 386 " Shutting Down."); 387 exit(-1); 369 388 } 370 389 371 390 for (s = base_server; s; s = s->next) { 372 void *load = NULL; 373 sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 374 &gnutls_module); 375 sc->cache_type = sc_base->cache_type; 376 sc->cache_config = sc_base->cache_config; 377 378 /* Check if the priorities have been set */ 379 if (sc->priorities == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) { 380 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 381 "GnuTLS: Host '%s:%d' is missing the GnuTLSPriorities directive!", 382 s->server_hostname, s->port); 383 exit(-1); 384 } 385 386 /* Check if DH or RSA params have been set per host */ 387 if (sc->rsa_params != NULL) 388 load = sc->rsa_params; 389 else if (rsa_params) load = rsa_params; 390 391 if (load != NULL) 392 gnutls_certificate_set_rsa_export_params(sc->certs, load); 393 394 395 load = NULL; 396 if (sc->dh_params != NULL) 397 load = sc->dh_params; 398 else if (dh_params) load = dh_params; 399 400 if (load != NULL) { /* not needed but anyway */ 401 gnutls_certificate_set_dh_params(sc->certs, load); 402 gnutls_anon_set_server_dh_params(sc->anon_creds, load); 403 } 404 405 gnutls_certificate_server_set_retrieve_function(sc->certs, 406 cert_retrieve_fn); 391 void *load = NULL; 392 sc = (mgs_srvconf_rec *) 393 ap_get_module_config(s->module_config, &gnutls_module); 394 sc->cache_type = sc_base->cache_type; 395 sc->cache_config = sc_base->cache_config; 396 397 /* Check if the priorities have been set */ 398 if (sc->priorities == NULL 399 && sc->enabled == GNUTLS_ENABLED_TRUE) { 400 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 401 "GnuTLS: Host '%s:%d' is missing the GnuTLSPriorities directive!", 402 s->server_hostname, s->port); 403 exit(-1); 404 } 405 406 /* Check if DH or RSA params have been set per host */ 407 if (sc->rsa_params != NULL) 408 load = sc->rsa_params; 409 else if (rsa_params) 410 load = rsa_params; 411 412 if (load != NULL) 413 gnutls_certificate_set_rsa_export_params(sc->certs, 414 load); 415 416 417 load = NULL; 418 if (sc->dh_params != NULL) 419 load = sc->dh_params; 420 else if (dh_params) 421 load = dh_params; 422 423 if (load != NULL) { /* not needed but anyway */ 424 gnutls_certificate_set_dh_params(sc->certs, load); 425 gnutls_anon_set_server_dh_params(sc->anon_creds, 426 load); 427 } 428 429 gnutls_certificate_server_set_retrieve_function(sc->certs, 430 cert_retrieve_fn); 407 431 408 432 #ifdef ENABLE_SRP 409 if (sc->srp_tpasswd_conf_file != NULL 410 && sc->srp_tpasswd_file != NULL) { 411 rv = gnutls_srp_set_server_credentials_file(sc->srp_creds, 412 sc-> 413 srp_tpasswd_file, 414 sc-> 415 srp_tpasswd_conf_file); 416 417 if (rv < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) { 418 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 419 "[GnuTLS] - Host '%s:%d' is missing a " 420 "SRP password or conf File!", 421 s->server_hostname, s->port); 422 exit(-1); 423 } 424 } 425 #endif 426 427 if (sc->certs_x509[0] == NULL && 428 sc->cert_pgp == NULL && 429 sc->enabled == GNUTLS_ENABLED_TRUE) { 430 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 431 "[GnuTLS] - Host '%s:%d' is missing a " 432 "Certificate File!", s->server_hostname, 433 s->port); 434 exit(-1); 435 } 436 437 if (sc->enabled == GNUTLS_ENABLED_TRUE && 438 ((sc->certs_x509[0] != NULL && sc->privkey_x509 == NULL) || 439 (sc->cert_pgp != NULL && sc->privkey_pgp == NULL))) { 440 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 441 "[GnuTLS] - Host '%s:%d' is missing a " 442 "Private Key File!", 443 s->server_hostname, s->port); 444 exit(-1); 445 } 446 447 if (sc->enabled == GNUTLS_ENABLED_TRUE) { 448 rv = read_crt_cn(s, p, sc->certs_x509[0], &sc->cert_cn); 449 if (rv < 0 && sc->cert_pgp != NULL) /* try openpgp certificate */ 450 rv = read_pgpcrt_cn(s, p, sc->cert_pgp, &sc->cert_cn); 451 452 if (rv < 0) { 453 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 454 "[GnuTLS] - Cannot find a certificate for host '%s:%d'!", 455 s->server_hostname, s->port); 456 sc->cert_cn = NULL; 457 continue; 458 } 459 } 460 } 461 } 462 463 ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION); 464 465 return OK; 433 if (sc->srp_tpasswd_conf_file != NULL 434 && sc->srp_tpasswd_file != NULL) { 435 rv = gnutls_srp_set_server_credentials_file 436 (sc->srp_creds, sc->srp_tpasswd_file, 437 sc->srp_tpasswd_conf_file); 438 439 if (rv < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) { 440 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, 441 s, 442 "[GnuTLS] - Host '%s:%d' is missing a " 443 "SRP password or conf File!", 444 s->server_hostname, s->port); 445 exit(-1); 446 } 447 } 448 #endif 449 450 if (sc->certs_x509[0] == NULL && 451 sc->cert_pgp == NULL && 452 sc->enabled == GNUTLS_ENABLED_TRUE) { 453 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 454 "[GnuTLS] - Host '%s:%d' is missing a " 455 "Certificate File!", 456 s->server_hostname, s->port); 457 exit(-1); 458 } 459 460 if (sc->enabled == GNUTLS_ENABLED_TRUE && 461 ((sc->certs_x509[0] != NULL 462 && sc->privkey_x509 == NULL) || (sc->cert_pgp != NULL 463 && sc->privkey_pgp 464 == NULL))) { 465 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 466 "[GnuTLS] - Host '%s:%d' is missing a " 467 "Private Key File!", 468 s->server_hostname, s->port); 469 exit(-1); 470 } 471 472 if (sc->enabled == GNUTLS_ENABLED_TRUE) { 473 rv = read_crt_cn(s, p, sc->certs_x509[0], 474 &sc->cert_cn); 475 if (rv < 0 && sc->cert_pgp != NULL) /* try openpgp certificate */ 476 rv = read_pgpcrt_cn(s, p, sc->cert_pgp, 477 &sc->cert_cn); 478 479 if (rv < 0) { 480 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, 481 s, 482 "[GnuTLS] - Cannot find a certificate for host '%s:%d'!", 483 s->server_hostname, s->port); 484 sc->cert_cn = NULL; 485 continue; 486 } 487 } 488 } 489 490 491 ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION); 492 493 return OK; 466 494 } 467 495 468 496 void mgs_hook_child_init(apr_pool_t * p, server_rec * s) 469 497 { 470 apr_status_t rv = APR_SUCCESS; 471 mgs_srvconf_rec *sc = ap_get_module_config(s->module_config, 472 &gnutls_module); 473 474 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 475 if (sc->cache_type != mgs_cache_none) { 476 rv = mgs_cache_child_init(p, s, sc); 477 if (rv != APR_SUCCESS) { 478 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, 479 "[GnuTLS] - Failed to run Cache Init"); 480 } 481 } else { 482 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, 483 "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache"); 484 } 498 apr_status_t rv = APR_SUCCESS; 499 mgs_srvconf_rec *sc = ap_get_module_config(s->module_config, 500 &gnutls_module); 501 502 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 503 if (sc->cache_type != mgs_cache_none) { 504 rv = mgs_cache_child_init(p, s, sc); 505 if (rv != APR_SUCCESS) { 506 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, 507 "[GnuTLS] - Failed to run Cache Init"); 508 } 509 } 485 510 } 486 511 487 512 const char *mgs_hook_http_scheme(const request_rec * r) 488 513 { 489 490 491 492 493 494 sc = 495 (mgs_srvconf_rec *) ap_get_module_config(r->server->module_config,496 &gnutls_module);497 498 _gnutls_log(debug_log_fp,"%s: %d\n", __func__, __LINE__);499 500 return NULL;501 502 503 514 mgs_srvconf_rec *sc; 515 516 if (r == NULL) 517 return NULL; 518 519 sc = (mgs_srvconf_rec *) ap_get_module_config(r-> 520 server->module_config, 521 &gnutls_module); 522 523 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 524 if (sc->enabled == GNUTLS_ENABLED_FALSE) { 525 return NULL; 526 } 527 528 return "https"; 504 529 } 505 530 506 531 apr_port_t mgs_hook_default_port(const request_rec * r) 507 532 { 508 509 510 511 512 513 sc = 514 (mgs_srvconf_rec *) ap_get_module_config(r->server->module_config,515 &gnutls_module);516 517 _gnutls_log(debug_log_fp,"%s: %d\n", __func__, __LINE__);518 519 return 0;520 521 522 533 mgs_srvconf_rec *sc; 534 535 if (r == NULL) 536 return 0; 537 538 sc = (mgs_srvconf_rec *) ap_get_module_config(r-> 539 server->module_config, 540 &gnutls_module); 541 542 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 543 if (sc->enabled == GNUTLS_ENABLED_FALSE) { 544 return 0; 545 } 546 547 return 443; 523 548 } 524 549 … … 527 552 #if USING_2_1_RECENT 528 553 typedef struct { 529 530 531 554 mgs_handle_t *ctxt; 555 mgs_srvconf_rec *sc; 556 const char *sni_name; 532 557 } vhost_cb_rec; 533 558 534 559 static int vhost_cb(void *baton, conn_rec * conn, server_rec * s) 535 560 { 536 mgs_srvconf_rec *tsc; 537 vhost_cb_rec *x = baton; 538 539 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 540 tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 541 &gnutls_module); 542 543 if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) { 561 mgs_srvconf_rec *tsc; 562 vhost_cb_rec *x = baton; 563 564 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 565 tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 566 &gnutls_module); 567 568 if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) { 569 return 0; 570 } 571 572 /* The CN can contain a * -- this will match those too. */ 573 if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) { 574 /* found a match */ 575 #if MOD_GNUTLS_DEBUG 576 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, 577 x->ctxt->c->base_server, 578 "GnuTLS: Virtual Host CB: " 579 "'%s' == '%s'", tsc->cert_cn, x->sni_name); 580 #endif 581 /* Because we actually change the server used here, we need to reset 582 * things like ClientVerify. 583 */ 584 x->sc = tsc; 585 /* Shit. Crap. Dammit. We *really* should rehandshake here, as our 586 * certificate structure *should* change when the server changes. 587 * acccckkkkkk. 588 */ 589 return 1; 590 } else { 591 #if MOD_GNUTLS_DEBUG 592 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, 593 x->ctxt->c->base_server, 594 "GnuTLS: Virtual Host CB: " 595 "'%s' != '%s'", tsc->cert_cn, x->sni_name); 596 #endif 597 598 } 544 599 return 0; 545 }546 547 /* The CN can contain a * -- this will match those too. */548 if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) {549 /* found a match */550 #if MOD_GNUTLS_DEBUG551 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,552 x->ctxt->c->base_server,553 "GnuTLS: Virtual Host CB: "554 "'%s' == '%s'", tsc->cert_cn, x->sni_name);555 #endif556 /* Because we actually change the server used here, we need to reset557 * things like ClientVerify.558 */559 x->sc = tsc;560 /* Shit. Crap. Dammit. We *really* should rehandshake here, as our561 * certificate structure *should* change when the server changes.562 * acccckkkkkk.563 */564 return 1;565 } else {566 #if MOD_GNUTLS_DEBUG567 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,568 x->ctxt->c->base_server,569 "GnuTLS: Virtual Host CB: "570 "'%s' != '%s'", tsc->cert_cn, x->sni_name);571 #endif572 573 }574 return 0;575 600 } 576 601 #endif … … 578 603 mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session) 579 604 { 580 581 582 583 584 605 int rv; 606 unsigned int sni_type; 607 size_t data_len = MAX_HOST_LEN; 608 char sni_name[MAX_HOST_LEN]; 609 mgs_handle_t *ctxt; 585 610 #if USING_2_1_RECENT 586 611 vhost_cb_rec cbx; 587 612 #else 588 589 590 #endif 591 592 593 594 595 _gnutls_log(debug_log_fp,"%s: %d\n", __func__, __LINE__);596 597 598 599 &data_len, &sni_type, 0);600 601 602 return NULL;603 604 605 606 ap_log_error(APLOG_MARK, APLOG_CRIT, 0,607 ctxt->c->base_server,608 "GnuTLS: Unknown type '%d' for SNI: "609 "'%s'", sni_type, sni_name);610 return NULL;611 613 server_rec *s; 614 mgs_srvconf_rec *tsc; 615 #endif 616 617 if (session == NULL) 618 return NULL; 619 620 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 621 ctxt = gnutls_transport_get_ptr(session); 622 623 rv = gnutls_server_name_get(ctxt->session, sni_name, 624 &data_len, &sni_type, 0); 625 626 if (rv != 0) { 627 return NULL; 628 } 629 630 if (sni_type != GNUTLS_NAME_DNS) { 631 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, 632 ctxt->c->base_server, 633 "GnuTLS: Unknown type '%d' for SNI: " 634 "'%s'", sni_type, sni_name); 635 return NULL; 636 } 612 637 613 638 /** … … 616 641 */ 617 642 #if USING_2_1_RECENT 618 619 620 621 622 623 624 return cbx.sc;625 643 cbx.ctxt = ctxt; 644 cbx.sc = NULL; 645 cbx.sni_name = sni_name; 646 647 rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx); 648 if (rv == 1) { 649 return cbx.sc; 650 } 626 651 #else 627 for (s = ap_server_conf; s; s = s->next) { 628 629 tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 630 &gnutls_module); 631 if (tsc->enabled != GNUTLS_ENABLED_TRUE) { 632 continue; 633 } 652 for (s = ap_server_conf; s; s = s->next) { 653 654 tsc = 655 (mgs_srvconf_rec *) 656 ap_get_module_config(s->module_config, &gnutls_module); 657 if (tsc->enabled != GNUTLS_ENABLED_TRUE) { 658 continue; 659 } 634 660 #if MOD_GNUTLS_DEBUG 635 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,636 ctxt->c->base_server,637 "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X",638 tsc->cert_cn, rv,639 gnutls_pk_algorithm_get_name640 (gnutls_x509_privkey_get_pk_algorithm641 (ctxt->sc->privkey_x509)), (unsigned int) s,642 (unsigned int) s->next, (unsigned int) tsc);643 #endif 644 /* The CN can contain a * -- this will match those too. */645 if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) {661 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, 662 ctxt->c->base_server, 663 "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X", 664 tsc->cert_cn, rv, 665 gnutls_pk_algorithm_get_name 666 (gnutls_x509_privkey_get_pk_algorithm 667 (ctxt->sc->privkey_x509)), (unsigned int) s, 668 (unsigned int) s->next, (unsigned int) tsc); 669 #endif 670 /* The CN can contain a * -- this will match those too. */ 671 if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) { 646 672 #if MOD_GNUTLS_DEBUG 647 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, 648 ctxt->c->base_server, 649 "GnuTLS: Virtual Host: " 650 "'%s' == '%s'", tsc->cert_cn, sni_name); 651 #endif 652 return tsc; 653 } 654 } 655 #endif 656 return NULL; 673 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, 674 ctxt->c->base_server, 675 "GnuTLS: Virtual Host: " 676 "'%s' == '%s'", tsc->cert_cn, 677 sni_name); 678 #endif 679 return tsc; 680 } 681 } 682 #endif 683 return NULL; 657 684 } 658 685 659 686 660 687 static const int protocol_priority[] = { 661 688 GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 662 689 }; 663 690 … … 665 692 static mgs_handle_t *create_gnutls_handle(apr_pool_t * pool, conn_rec * c) 666 693 { 667 mgs_handle_t *ctxt; 668 mgs_srvconf_rec *sc = 669 (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> 670 module_config, 671 &gnutls_module); 672 673 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 674 ctxt = apr_pcalloc(pool, sizeof(*ctxt)); 675 ctxt->c = c; 676 ctxt->sc = sc; 677 ctxt->status = 0; 678 679 ctxt->input_rc = APR_SUCCESS; 680 ctxt->input_bb = apr_brigade_create(c->pool, c->bucket_alloc); 681 ctxt->input_cbuf.length = 0; 682 683 ctxt->output_rc = APR_SUCCESS; 684 ctxt->output_bb = apr_brigade_create(c->pool, c->bucket_alloc); 685 ctxt->output_blen = 0; 686 ctxt->output_length = 0; 687 688 gnutls_init(&ctxt->session, GNUTLS_SERVER); 689 if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0) 690 gnutls_session_ticket_enable_server(ctxt->session, &session_ticket_key); 691 692 /* because we don't set any default priorities here (we set later at 693 * the user hello callback) we need to at least set this in order for 694 * gnutls to be able to read packets. 695 */ 696 gnutls_protocol_set_priority(ctxt->session, protocol_priority); 697 698 gnutls_handshake_set_post_client_hello_function(ctxt->session, 699 mgs_select_virtual_server_cb); 700 701 mgs_cache_session_init(ctxt); 702 703 return ctxt; 694 mgs_handle_t *ctxt; 695 mgs_srvconf_rec *sc = 696 (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> 697 module_config, 698 &gnutls_module); 699 700 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 701 ctxt = apr_pcalloc(pool, sizeof(*ctxt)); 702 ctxt->c = c; 703 ctxt->sc = sc; 704 ctxt->status = 0; 705 706 ctxt->input_rc = APR_SUCCESS; 707 ctxt->input_bb = apr_brigade_create(c->pool, c->bucket_alloc); 708 ctxt->input_cbuf.length = 0; 709 710 ctxt->output_rc = APR_SUCCESS; 711 ctxt->output_bb = apr_brigade_create(c->pool, c->bucket_alloc); 712 ctxt->output_blen = 0; 713 ctxt->output_length = 0; 714 715 gnutls_init(&ctxt->session, GNUTLS_SERVER); 716 if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0) 717 gnutls_session_ticket_enable_server(ctxt->session, 718 &session_ticket_key); 719 720 /* because we don't set any default priorities here (we set later at 721 * the user hello callback) we need to at least set this in order for 722 * gnutls to be able to read packets. 723 */ 724 gnutls_protocol_set_priority(ctxt->session, protocol_priority); 725 726 gnutls_handshake_set_post_client_hello_function(ctxt->session, 727 mgs_select_virtual_server_cb); 728 729 mgs_cache_session_init(ctxt); 730 731 return ctxt; 704 732 } 705 733 706 734 int mgs_hook_pre_connection(conn_rec * c, void *csd) 707 735 { 708 mgs_handle_t *ctxt; 709 mgs_srvconf_rec *sc; 710 711 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 712 713 if (c == NULL) 714 return DECLINED; 715 716 sc = 717 (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> 718 module_config, 719 &gnutls_module); 720 721 if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) { 736 mgs_handle_t *ctxt; 737 mgs_srvconf_rec *sc; 738 739 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 740 741 if (c == NULL) { 742 return DECLINED; 743 } 744 745 sc = (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> 746 module_config, 747 &gnutls_module); 748 749 if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) { 750 return DECLINED; 751 } 752 753 if (c->remote_addr->hostname || apr_strnatcmp(c->remote_ip,c->local_ip) == 0) { 754 /* Connection initiated by Apache (mod_proxy) => ignore */ 755 return OK; 756 } 757 758 ctxt = create_gnutls_handle(c->pool, c); 759 760 ap_set_module_config(c->conn_config, &gnutls_module, ctxt); 761 762 gnutls_transport_set_pull_function(ctxt->session, 763 mgs_transport_read); 764 gnutls_transport_set_push_function(ctxt->session, 765 mgs_transport_write); 766 gnutls_transport_set_ptr(ctxt->session, ctxt); 767 768 ctxt->input_filter = 769 ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c); 770 ctxt->output_filter = 771 ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c); 772 773 return OK; 774 } 775 776 int mgs_hook_fixups(request_rec * r) 777 { 778 unsigned char sbuf[GNUTLS_MAX_SESSION_ID]; 779 char buf[AP_IOBUFSIZE]; 780 const char *tmp; 781 size_t len; 782 mgs_handle_t *ctxt; 783 int rv = OK; 784 785 if (r == NULL) 786 return DECLINED; 787 788 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 789 apr_table_t *env = r->subprocess_env; 790 791 ctxt = 792 ap_get_module_config(r->connection->conn_config, 793 &gnutls_module); 794 795 if (!ctxt || ctxt->session == NULL) { 796 return DECLINED; 797 } 798 799 apr_table_setn(env, "HTTPS", "on"); 800 801 apr_table_setn(env, "SSL_VERSION_LIBRARY", 802 "GnuTLS/" LIBGNUTLS_VERSION); 803 apr_table_setn(env, "SSL_VERSION_INTERFACE", 804 "mod_gnutls/" MOD_GNUTLS_VERSION); 805 806 apr_table_setn(env, "SSL_PROTOCOL", 807 gnutls_protocol_get_name(gnutls_protocol_get_version 808 (ctxt->session))); 809 810 /* should have been called SSL_CIPHERSUITE instead */ 811 apr_table_setn(env, "SSL_CIPHER", 812 gnutls_cipher_suite_get_name(gnutls_kx_get 813 (ctxt->session), 814 gnutls_cipher_get 815 (ctxt->session), 816 gnutls_mac_get 817 (ctxt->session))); 818 819 apr_table_setn(env, "SSL_COMPRESS_METHOD", 820 gnutls_compression_get_name(gnutls_compression_get 821 (ctxt->session))); 822 823 #ifdef ENABLE_SRP 824 tmp = gnutls_srp_server_get_username(ctxt->session); 825 apr_table_setn(env, "SSL_SRP_USER", (tmp != NULL) ? tmp : ""); 826 #endif 827 828 if (apr_table_get(env, "SSL_CLIENT_VERIFY") == NULL) 829 apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE"); 830 831 unsigned int key_size = 832 8 * 833 gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session)); 834 tmp = apr_psprintf(r->pool, "%u", key_size); 835 836 apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp); 837 838 apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp); 839 840 apr_table_setn(env, "SSL_CIPHER_EXPORT", 841 (key_size <= 40) ? "true" : "false"); 842 843 len = sizeof(sbuf); 844 gnutls_session_get_id(ctxt->session, sbuf, &len); 845 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); 846 apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp)); 847 848 if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) 849 mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0, 850 ctxt-> 851 sc->export_certificates_enabled); 852 else if (gnutls_certificate_type_get(ctxt->session) == 853 GNUTLS_CRT_OPENPGP) 854 mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0, 855 ctxt-> 856 sc->export_certificates_enabled); 857 858 return rv; 859 } 860 861 int mgs_hook_authz(request_rec * r) 862 { 863 int rv; 864 mgs_handle_t *ctxt; 865 mgs_dirconf_rec *dc; 866 867 if (r == NULL) 868 return DECLINED; 869 870 dc = ap_get_module_config(r->per_dir_config, &gnutls_module); 871 872 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 873 ctxt = 874 ap_get_module_config(r->connection->conn_config, 875 &gnutls_module); 876 877 if (!ctxt || ctxt->session == NULL) { 878 return DECLINED; 879 } 880 881 if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) { 882 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 883 "GnuTLS: Directory set to Ignore Client Certificate!"); 884 } else { 885 if (ctxt->sc->client_verify_mode < dc->client_verify_mode) { 886 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 887 "GnuTLS: Attempting to rehandshake with peer. %d %d", 888 ctxt->sc->client_verify_mode, 889 dc->client_verify_mode); 890 891 /* If we already have a client certificate, there's no point in 892 * re-handshaking... */ 893 rv = mgs_cert_verify(r, ctxt); 894 if (rv != DECLINED && rv != HTTP_FORBIDDEN) 895 return rv; 896 897 gnutls_certificate_server_set_request 898 (ctxt->session, dc->client_verify_mode); 899 900 if (mgs_rehandshake(ctxt) != 0) { 901 return HTTP_FORBIDDEN; 902 } 903 } else if (ctxt->sc->client_verify_mode == 904 GNUTLS_CERT_IGNORE) { 905 #if MOD_GNUTLS_DEBUG 906 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 907 "GnuTLS: Peer is set to IGNORE"); 908 #endif 909 return DECLINED; 910 } 911 rv = mgs_cert_verify(r, ctxt); 912 if (rv != DECLINED && 913 (rv != HTTP_FORBIDDEN || 914 dc->client_verify_mode == GNUTLS_CERT_REQUIRE)) { 915 return rv; 916 } 917 } 918 722 919 return DECLINED; 723 }724 725 if(c->remote_addr->hostname)726 /* Connection initiated by Apache (mod_proxy) => ignore */727 return OK;728 729 ctxt = create_gnutls_handle(c->pool, c);730 731 ap_set_module_config(c->conn_config, &gnutls_module, ctxt);732 733 gnutls_transport_set_pull_function(ctxt->session, mgs_transport_read);734 gnutls_transport_set_push_function(ctxt->session, mgs_transport_write);735 gnutls_transport_set_ptr(ctxt->session, ctxt);736 737 ctxt->input_filter =738 ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c);739 ctxt->output_filter =740 ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c);741 742 return OK;743 }744 745 int mgs_hook_fixups(request_rec * r)746 {747 unsigned char sbuf[GNUTLS_MAX_SESSION_ID];748 char buf[AP_IOBUFSIZE];749 const char *tmp;750 size_t len;751 mgs_handle_t *ctxt;752 int rv = OK;753 754 if (r == NULL)755 return DECLINED;756 757 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);758 apr_table_t *env = r->subprocess_env;759 760 ctxt =761 ap_get_module_config(r->connection->conn_config, &gnutls_module);762 763 if (!ctxt || ctxt->session == NULL) {764 return DECLINED;765 }766 767 apr_table_setn(env, "HTTPS", "on");768 769 apr_table_setn(env, "SSL_VERSION_LIBRARY",770 "GnuTLS/" LIBGNUTLS_VERSION);771 apr_table_setn(env, "SSL_VERSION_INTERFACE",772 "mod_gnutls/" MOD_GNUTLS_VERSION);773 774 apr_table_setn(env, "SSL_PROTOCOL",775 gnutls_protocol_get_name(gnutls_protocol_get_version776 (ctxt->session)));777 778 /* should have been called SSL_CIPHERSUITE instead */779 apr_table_setn(env, "SSL_CIPHER",780 gnutls_cipher_suite_get_name(gnutls_kx_get781 (ctxt->session),782 gnutls_cipher_get(ctxt->783 session),784 gnutls_mac_get(ctxt->785 session)));786 787 apr_table_setn(env, "SSL_COMPRESS_METHOD",788 gnutls_compression_get_name(gnutls_compression_get789 (ctxt->session)));790 791 #ifdef ENABLE_SRP792 tmp = gnutls_srp_server_get_username(ctxt->session);793 apr_table_setn(env, "SSL_SRP_USER", (tmp!=NULL)?tmp:"");794 #endif795 796 if (apr_table_get(env, "SSL_CLIENT_VERIFY") == NULL)797 apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE");798 799 unsigned int key_size =800 8 * gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session));801 tmp = apr_psprintf(r->pool, "%u", key_size);802 803 apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp);804 805 apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp);806 807 apr_table_setn(env, "SSL_CIPHER_EXPORT",808 (key_size <= 40) ? "true" : "false");809 810 len = sizeof(sbuf);811 gnutls_session_get_id(ctxt->session, sbuf, &len);812 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf));813 apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp));814 815 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509)816 mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0,817 ctxt->sc->export_certificates_enabled);818 else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP)819 mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0,820 ctxt->sc->export_certificates_enabled);821 822 return rv;823 }824 825 int mgs_hook_authz(request_rec * r)826 {827 int rv;828 mgs_handle_t *ctxt;829 mgs_dirconf_rec *dc;830 831 if (r == NULL)832 return DECLINED;833 834 dc = ap_get_module_config(r->per_dir_config,835 &gnutls_module);836 837 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);838 ctxt =839 ap_get_module_config(r->connection->conn_config, &gnutls_module);840 841 if (!ctxt || ctxt->session == NULL) {842 return DECLINED;843 }844 845 if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) {846 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,847 "GnuTLS: Directory set to Ignore Client Certificate!");848 } else {849 if (ctxt->sc->client_verify_mode < dc->client_verify_mode) {850 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,851 "GnuTLS: Attempting to rehandshake with peer. %d %d",852 ctxt->sc->client_verify_mode,853 dc->client_verify_mode);854 855 /* If we already have a client certificate, there's no point in856 * re-handshaking... */857 rv = mgs_cert_verify(r, ctxt);858 if (rv != DECLINED && rv != HTTP_FORBIDDEN)859 return rv;860 861 gnutls_certificate_server_set_request(ctxt->session,862 dc->client_verify_mode);863 864 if (mgs_rehandshake(ctxt) != 0) {865 return HTTP_FORBIDDEN;866 }867 } else if (ctxt->sc->client_verify_mode == GNUTLS_CERT_IGNORE) {868 #if MOD_GNUTLS_DEBUG869 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,870 "GnuTLS: Peer is set to IGNORE");871 #endif872 return DECLINED;873 }874 rv = mgs_cert_verify(r, ctxt);875 if (rv != DECLINED &&876 (rv != HTTP_FORBIDDEN ||877 dc->client_verify_mode == GNUTLS_CERT_REQUIRE)) {878 return rv;879 }880 }881 882 return DECLINED;883 920 } 884 921 … … 896 933 int export_certificates_enabled) 897 934 { 898 unsigned char sbuf[64]; /* buffer to hold serials */ 899 char buf[AP_IOBUFSIZE]; 900 const char *tmp; 901 char *tmp2; 902 size_t len; 903 int ret, i; 904 905 if (r == NULL) 906 return; 907 908 apr_table_t *env = r->subprocess_env; 909 910 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 911 if (export_certificates_enabled != 0) { 912 char cert_buf[10 * 1024]; 913 len = sizeof(cert_buf); 914 915 if (gnutls_x509_crt_export 916 (cert, GNUTLS_X509_FMT_PEM, cert_buf, &len) >= 0) 917 apr_table_setn(env, 918 apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), 919 apr_pstrmemdup(r->pool, cert_buf, len)); 920 921 } 922 923 len = sizeof(buf); 924 gnutls_x509_crt_get_dn(cert, buf, &len); 925 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_S_DN", NULL), 926 apr_pstrmemdup(r->pool, buf, len)); 927 928 len = sizeof(buf); 929 gnutls_x509_crt_get_issuer_dn(cert, buf, &len); 930 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_I_DN", NULL), 931 apr_pstrmemdup(r->pool, buf, len)); 932 933 len = sizeof(sbuf); 934 gnutls_x509_crt_get_serial(cert, sbuf, &len); 935 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); 936 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_M_SERIAL", NULL), 937 apr_pstrdup(r->pool, tmp)); 938 939 ret = gnutls_x509_crt_get_version(cert); 940 if (ret > 0) 935 unsigned char sbuf[64]; /* buffer to hold serials */ 936 char buf[AP_IOBUFSIZE]; 937 const char *tmp; 938 char *tmp2; 939 size_t len; 940 int ret, i; 941 942 if (r == NULL) 943 return; 944 945 apr_table_t *env = r->subprocess_env; 946 947 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 948 if (export_certificates_enabled != 0) { 949 char cert_buf[10 * 1024]; 950 len = sizeof(cert_buf); 951 952 if (gnutls_x509_crt_export 953 (cert, GNUTLS_X509_FMT_PEM, cert_buf, &len) >= 0) 954 apr_table_setn(env, 955 apr_pstrcat(r->pool, MGS_SIDE, 956 "_CERT", NULL), 957 apr_pstrmemdup(r->pool, cert_buf, 958 len)); 959 960 } 961 962 len = sizeof(buf); 963 gnutls_x509_crt_get_dn(cert, buf, &len); 964 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_S_DN", NULL), 965 apr_pstrmemdup(r->pool, buf, len)); 966 967 len = sizeof(buf); 968 gnutls_x509_crt_get_issuer_dn(cert, buf, &len); 969 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_I_DN", NULL), 970 apr_pstrmemdup(r->pool, buf, len)); 971 972 len = sizeof(sbuf); 973 gnutls_x509_crt_get_serial(cert, sbuf, &len); 974 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); 941 975 apr_table_setn(env, 942 apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL), 943 apr_psprintf(r->pool, "%u", ret)); 944 945 apr_table_setn(env, 946 apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "X.509"); 947 948 tmp = 949 mgs_time2sz(gnutls_x509_crt_get_expiration_time 950 (cert), buf, sizeof(buf)); 951 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), 952 apr_pstrdup(r->pool, tmp)); 953 954 tmp = 955 mgs_time2sz(gnutls_x509_crt_get_activation_time 956 (cert), buf, sizeof(buf)); 957 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), 958 apr_pstrdup(r->pool, tmp)); 959 960 ret = gnutls_x509_crt_get_signature_algorithm(cert); 961 if (ret >= 0) { 962 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_SIG", NULL), 963 gnutls_sign_algorithm_get_name(ret)); 964 } 965 966 ret = gnutls_x509_crt_get_pk_algorithm(cert, NULL); 967 if (ret >= 0) { 968 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL), 969 gnutls_pk_algorithm_get_name(ret)); 970 } 971 972 /* export all the alternative names (DNS, RFC822 and URI) */ 973 for (i = 0; !(ret < 0); i++) { 974 len = 0; 975 ret = gnutls_x509_crt_get_subject_alt_name(cert, i, 976 NULL, &len, NULL); 977 978 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER && len > 1) { 979 tmp2 = apr_palloc(r->pool, len + 1); 980 981 ret = 982 gnutls_x509_crt_get_subject_alt_name(cert, i, tmp2, &len, 983 NULL); 984 tmp2[len] = 0; 985 986 if (ret == GNUTLS_SAN_DNSNAME) { 976 apr_pstrcat(r->pool, MGS_SIDE, "_M_SERIAL", NULL), 977 apr_pstrdup(r->pool, tmp)); 978 979 ret = gnutls_x509_crt_get_version(cert); 980 if (ret > 0) 987 981 apr_table_setn(env, 988 apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), 989 apr_psprintf(r->pool, "DNSNAME:%s", tmp2)); 990 } else if (ret == GNUTLS_SAN_RFC822NAME) { 982 apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", 983 NULL), apr_psprintf(r->pool, 984 "%u", ret)); 985 986 apr_table_setn(env, 987 apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), 988 "X.509"); 989 990 tmp = 991 mgs_time2sz(gnutls_x509_crt_get_expiration_time 992 (cert), buf, sizeof(buf)); 993 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), 994 apr_pstrdup(r->pool, tmp)); 995 996 tmp = 997 mgs_time2sz(gnutls_x509_crt_get_activation_time 998 (cert), buf, sizeof(buf)); 999 apr_table_setn(env, 1000 apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), 1001 apr_pstrdup(r->pool, tmp)); 1002 1003 ret = gnutls_x509_crt_get_signature_algorithm(cert); 1004 if (ret >= 0) { 991 1005 apr_table_setn(env, 992 apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), 993 apr_psprintf(r->pool, "RFC822NAME:%s", tmp2)); 994 } else if (ret == GNUTLS_SAN_URI) { 1006 apr_pstrcat(r->pool, MGS_SIDE, "_A_SIG", 1007 NULL), 1008 gnutls_sign_algorithm_get_name(ret)); 1009 } 1010 1011 ret = gnutls_x509_crt_get_pk_algorithm(cert, NULL); 1012 if (ret >= 0) { 995 1013 apr_table_setn(env, 996 apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), 997 apr_psprintf(r->pool, "URI:%s", tmp2)); 998 } else { 1014 apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", 1015 NULL), 1016 gnutls_pk_algorithm_get_name(ret)); 1017 } 1018 1019 /* export all the alternative names (DNS, RFC822 and URI) */ 1020 for (i = 0; !(ret < 0); i++) { 1021 len = 0; 1022 ret = gnutls_x509_crt_get_subject_alt_name(cert, i, 1023 NULL, &len, 1024 NULL); 1025 1026 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER && len > 1) { 1027 tmp2 = apr_palloc(r->pool, len + 1); 1028 1029 ret = 1030 gnutls_x509_crt_get_subject_alt_name(cert, i, 1031 tmp2, 1032 &len, 1033 NULL); 1034 tmp2[len] = 0; 1035 1036 if (ret == GNUTLS_SAN_DNSNAME) { 1037 apr_table_setn(env, 1038 apr_psprintf(r->pool, 1039 "%s_S_AN%u", 1040 MGS_SIDE, i), 1041 apr_psprintf(r->pool, 1042 "DNSNAME:%s", 1043 tmp2)); 1044 } else if (ret == GNUTLS_SAN_RFC822NAME) { 1045 apr_table_setn(env, 1046 apr_psprintf(r->pool, 1047 "%s_S_AN%u", 1048 MGS_SIDE, i), 1049 apr_psprintf(r->pool, 1050 "RFC822NAME:%s", 1051 tmp2)); 1052 } else if (ret == GNUTLS_SAN_URI) { 1053 apr_table_setn(env, 1054 apr_psprintf(r->pool, 1055 "%s_S_AN%u", 1056 MGS_SIDE, i), 1057 apr_psprintf(r->pool, 1058 "URI:%s", 1059 tmp2)); 1060 } else { 1061 apr_table_setn(env, 1062 apr_psprintf(r->pool, 1063 "%s_S_AN%u", 1064 MGS_SIDE, i), 1065 "UNSUPPORTED"); 1066 } 1067 } 1068 } 1069 } 1070 1071 static void 1072 mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, 1073 int side, int export_certificates_enabled) 1074 { 1075 unsigned char sbuf[64]; /* buffer to hold serials */ 1076 char buf[AP_IOBUFSIZE]; 1077 const char *tmp; 1078 size_t len; 1079 int ret; 1080 1081 if (r == NULL) 1082 return; 1083 1084 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 1085 apr_table_t *env = r->subprocess_env; 1086 1087 if (export_certificates_enabled != 0) { 1088 char cert_buf[10 * 1024]; 1089 len = sizeof(cert_buf); 1090 1091 if (gnutls_openpgp_crt_export 1092 (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0) 1093 apr_table_setn(env, 1094 apr_pstrcat(r->pool, MGS_SIDE, 1095 "_CERT", NULL), 1096 apr_pstrmemdup(r->pool, cert_buf, 1097 len)); 1098 1099 } 1100 1101 len = sizeof(buf); 1102 gnutls_openpgp_crt_get_name(cert, 0, buf, &len); 1103 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL), 1104 apr_pstrmemdup(r->pool, buf, len)); 1105 1106 len = sizeof(sbuf); 1107 gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len); 1108 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); 1109 apr_table_setn(env, 1110 apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", 1111 NULL), apr_pstrdup(r->pool, tmp)); 1112 1113 ret = gnutls_openpgp_crt_get_version(cert); 1114 if (ret > 0) 999 1115 apr_table_setn(env, 1000 apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), 1001 "UNSUPPORTED"); 1002 } 1003 } 1004 } 1005 } 1006 1007 static void 1008 mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side, 1009 int export_certificates_enabled) 1010 { 1011 unsigned char sbuf[64]; /* buffer to hold serials */ 1012 char buf[AP_IOBUFSIZE]; 1013 const char *tmp; 1014 size_t len; 1015 int ret; 1016 1017 if (r == NULL) 1018 return; 1019 1020 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 1021 apr_table_t *env = r->subprocess_env; 1022 1023 if (export_certificates_enabled != 0) { 1024 char cert_buf[10 * 1024]; 1025 len = sizeof(cert_buf); 1026 1027 if (gnutls_openpgp_crt_export 1028 (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0) 1029 apr_table_setn(env, 1030 apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), 1031 apr_pstrmemdup(r->pool, cert_buf, len)); 1032 1033 } 1034 1035 len = sizeof(buf); 1036 gnutls_openpgp_crt_get_name(cert, 0, buf, &len); 1037 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL), 1038 apr_pstrmemdup(r->pool, buf, len)); 1039 1040 len = sizeof(sbuf); 1041 gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len); 1042 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); 1043 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", NULL), 1044 apr_pstrdup(r->pool, tmp)); 1045 1046 ret = gnutls_openpgp_crt_get_version(cert); 1047 if (ret > 0) 1116 apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", 1117 NULL), apr_psprintf(r->pool, 1118 "%u", ret)); 1119 1048 1120 apr_table_setn(env, 1049 apr_pstrcat(r->pool, MGS_SIDE, "_ M_VERSION", NULL),1050 apr_psprintf(r->pool, "%u", ret));1051 1052 apr_table_setn(env, 1053 apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "OPENPGP"); 1054 1055 tmp = 1056 mgs_time2sz(gnutls_openpgp_crt_get_expiration_time1057 (cert), buf, sizeof(buf)); 1058 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), 1059 apr_pstrdup(r->pool, tmp));1060 1061 tmp = 1062 mgs_time2sz(gnutls_openpgp_crt_get_creation_time1063 (cert), buf, sizeof(buf));1064 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), 1065 apr_pstrdup(r->pool, tmp));1066 1067 ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL); 1068 if (ret >= 0) { 1069 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY",NULL),1070 gnutls_pk_algorithm_get_name(ret));1071 1121 apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), 1122 "OPENPGP"); 1123 1124 tmp = 1125 mgs_time2sz(gnutls_openpgp_crt_get_expiration_time 1126 (cert), buf, sizeof(buf)); 1127 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), 1128 apr_pstrdup(r->pool, tmp)); 1129 1130 tmp = 1131 mgs_time2sz(gnutls_openpgp_crt_get_creation_time 1132 (cert), buf, sizeof(buf)); 1133 apr_table_setn(env, 1134 apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), 1135 apr_pstrdup(r->pool, tmp)); 1136 1137 ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL); 1138 if (ret >= 0) { 1139 apr_table_setn(env, 1140 apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", 1141 NULL), 1142 gnutls_pk_algorithm_get_name(ret)); 1143 } 1072 1144 1073 1145 } … … 1076 1148 static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) 1077 1149 { 1078 const gnutls_datum_t *cert_list; 1079 unsigned int cert_list_size, status; 1080 int rv = GNUTLS_E_NO_CERTIFICATE_FOUND, ret; 1081 unsigned int ch_size = 0; 1082 union { 1083 gnutls_x509_crt_t x509[MAX_CHAIN_SIZE]; 1084 gnutls_openpgp_crt_t pgp; 1085 } cert; 1086 apr_time_t expiration_time, cur_time; 1087 1088 if (r == NULL || ctxt == NULL || ctxt->session == NULL) 1089 return HTTP_FORBIDDEN; 1090 1091 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 1092 cert_list = 1093 gnutls_certificate_get_peers(ctxt->session, &cert_list_size); 1094 1095 if (cert_list == NULL || cert_list_size == 0) { 1096 /* It is perfectly OK for a client not to send a certificate if on REQUEST mode 1150 const gnutls_datum_t *cert_list; 1151 unsigned int cert_list_size, status; 1152 int rv = GNUTLS_E_NO_CERTIFICATE_FOUND, ret; 1153 unsigned int ch_size = 0; 1154 union { 1155 gnutls_x509_crt_t x509[MAX_CHAIN_SIZE]; 1156 gnutls_openpgp_crt_t pgp; 1157 } cert; 1158 apr_time_t expiration_time, cur_time; 1159 1160 if (r == NULL || ctxt == NULL || ctxt->session == NULL) 1161 return HTTP_FORBIDDEN; 1162 1163 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 1164 cert_list = 1165 gnutls_certificate_get_peers(ctxt->session, &cert_list_size); 1166 1167 if (cert_list == NULL || cert_list_size == 0) { 1168 /* It is perfectly OK for a client not to send a certificate if on REQUEST mode 1169 */ 1170 if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) 1171 return OK; 1172 1173 /* no certificate provided by the client, but one was required. */ 1174 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1175 "GnuTLS: Failed to Verify Peer: " 1176 "Client did not submit a certificate"); 1177 return HTTP_FORBIDDEN; 1178 } 1179 1180 if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) { 1181 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 1182 "GnuTLS: A Chain of %d certificate(s) was provided for validation", 1183 cert_list_size); 1184 1185 for (ch_size = 0; ch_size < cert_list_size; ch_size++) { 1186 gnutls_x509_crt_init(&cert.x509[ch_size]); 1187 rv = gnutls_x509_crt_import(cert.x509[ch_size], 1188 &cert_list[ch_size], 1189 GNUTLS_X509_FMT_DER); 1190 // When failure to import, leave the loop 1191 if (rv != GNUTLS_E_SUCCESS) { 1192 if (ch_size < 1) { 1193 ap_log_rerror(APLOG_MARK, 1194 APLOG_INFO, 0, r, 1195 "GnuTLS: Failed to Verify Peer: " 1196 "Failed to import peer certificates."); 1197 ret = HTTP_FORBIDDEN; 1198 goto exit; 1199 } 1200 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1201 "GnuTLS: Failed to import some peer certificates. Using %d certificates", 1202 ch_size); 1203 rv = GNUTLS_E_SUCCESS; 1204 break; 1205 } 1206 } 1207 } else if (gnutls_certificate_type_get(ctxt->session) == 1208 GNUTLS_CRT_OPENPGP) { 1209 if (cert_list_size > 1) { 1210 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1211 "GnuTLS: Failed to Verify Peer: " 1212 "Chained Client Certificates are not supported."); 1213 return HTTP_FORBIDDEN; 1214 } 1215 1216 gnutls_openpgp_crt_init(&cert.pgp); 1217 rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], 1218 GNUTLS_OPENPGP_FMT_RAW); 1219 1220 } else 1221 return HTTP_FORBIDDEN; 1222 1223 if (rv < 0) { 1224 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1225 "GnuTLS: Failed to Verify Peer: " 1226 "Failed to import peer certificates."); 1227 ret = HTTP_FORBIDDEN; 1228 goto exit; 1229 } 1230 1231 if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) { 1232 apr_time_ansi_put(&expiration_time, 1233 gnutls_x509_crt_get_expiration_time 1234 (cert.x509[0])); 1235 1236 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 1237 "GnuTLS: Verifying list of %d certificate(s)", 1238 ch_size); 1239 rv = gnutls_x509_crt_list_verify(cert.x509, ch_size, 1240 ctxt->sc->ca_list, 1241 ctxt->sc->ca_list_size, 1242 NULL, 0, 0, &status); 1243 } else { 1244 apr_time_ansi_put(&expiration_time, 1245 gnutls_openpgp_crt_get_expiration_time 1246 (cert.pgp)); 1247 1248 rv = gnutls_openpgp_crt_verify_ring(cert.pgp, 1249 ctxt->sc->pgp_list, 0, 1250 &status); 1251 } 1252 1253 if (rv < 0) { 1254 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1255 "GnuTLS: Failed to Verify Peer certificate: (%d) %s", 1256 rv, gnutls_strerror(rv)); 1257 if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND) 1258 ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, r, 1259 "GnuTLS: No certificate was found for verification. Did you set the GnuTLSX509CAFile or GnuTLSPGPKeyringFile directives?"); 1260 ret = HTTP_FORBIDDEN; 1261 goto exit; 1262 } 1263 1264 /* TODO: X509 CRL Verification. */ 1265 /* May add later if anyone needs it. 1097 1266 */ 1098 if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) 1099 return OK; 1100 1101 /* no certificate provided by the client, but one was required. */ 1102 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1103 "GnuTLS: Failed to Verify Peer: " 1104 "Client did not submit a certificate"); 1105 return HTTP_FORBIDDEN; 1106 } 1107 1108 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { 1109 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 1110 "GnuTLS: A Chain of %d certificate(s) was provided for validation", cert_list_size); 1111 1112 for (ch_size = 0; ch_size<cert_list_size; ch_size++) { 1113 gnutls_x509_crt_init(&cert.x509[ch_size]); 1114 rv = gnutls_x509_crt_import(cert.x509[ch_size], &cert_list[ch_size], GNUTLS_X509_FMT_DER); 1115 // When failure to import, leave the loop 1116 if ( rv != GNUTLS_E_SUCCESS ) { 1117 if (ch_size < 1) { 1118 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1119 "GnuTLS: Failed to Verify Peer: " 1120 "Failed to import peer certificates."); 1121 ret = HTTP_FORBIDDEN; 1122 goto exit; 1123 } 1124 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1125 "GnuTLS: Failed to import some peer certificates. Using %d certificates", 1126 ch_size); 1127 rv = GNUTLS_E_SUCCESS; 1128 break; 1129 } 1130 } 1131 } else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) { 1132 if (cert_list_size > 1) { 1133 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1134 "GnuTLS: Failed to Verify Peer: " 1135 "Chained Client Certificates are not supported."); 1136 return HTTP_FORBIDDEN; 1137 } 1138 1139 gnutls_openpgp_crt_init(&cert.pgp); 1140 rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW); 1141 1142 } else return HTTP_FORBIDDEN; 1143 1144 if (rv < 0) { 1145 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1146 "GnuTLS: Failed to Verify Peer: " 1147 "Failed to import peer certificates."); 1148 ret = HTTP_FORBIDDEN; 1149 goto exit; 1150 } 1151 1152 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { 1153 apr_time_ansi_put(&expiration_time, 1154 gnutls_x509_crt_get_expiration_time(cert.x509[0])); 1155 1156 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 1157 "GnuTLS: Verifying list of %d certificate(s)", ch_size); 1158 rv = gnutls_x509_crt_list_verify(cert.x509, ch_size, 1159 ctxt->sc->ca_list, ctxt->sc->ca_list_size, 1160 NULL, 0, 0, &status); 1161 } else { 1162 apr_time_ansi_put(&expiration_time, 1163 gnutls_openpgp_crt_get_expiration_time(cert.pgp)); 1164 1165 rv = gnutls_openpgp_crt_verify_ring(cert.pgp, ctxt->sc->pgp_list, 1166 0, &status); 1167 } 1168 1169 if (rv < 0) { 1170 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1171 "GnuTLS: Failed to Verify Peer certificate: (%d) %s", 1172 rv, gnutls_strerror(rv)); 1173 if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND) 1174 ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, r, 1175 "GnuTLS: No certificate was found for verification. Did you set the GnuTLSX509CAFile or GnuTLSPGPKeyringFile directives?"); 1176 ret = HTTP_FORBIDDEN; 1177 goto exit; 1178 } 1179 1180 /* TODO: X509 CRL Verification. */ 1181 /* May add later if anyone needs it. 1182 */ 1183 /* ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); */ 1184 1185 cur_time = apr_time_now(); 1186 1187 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { 1188 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1189 "GnuTLS: Could not find Signer for Peer Certificate"); 1190 } 1191 1192 if (status & GNUTLS_CERT_SIGNER_NOT_CA) { 1193 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1194 "GnuTLS: Peer's Certificate signer is not a CA"); 1195 } 1196 1197 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { 1198 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1199 "GnuTLS: Peer's Certificate is using insecure algorithms"); 1200 } 1201 1202 if (status & GNUTLS_CERT_EXPIRED || status & GNUTLS_CERT_NOT_ACTIVATED) { 1203 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1204 "GnuTLS: Peer's Certificate signer is expired or not yet activated"); 1205 } 1206 1207 if (status & GNUTLS_CERT_INVALID) { 1208 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1209 "GnuTLS: Peer Certificate is invalid."); 1210 } else if (status & GNUTLS_CERT_REVOKED) { 1211 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1212 "GnuTLS: Peer Certificate is revoked."); 1213 } 1214 1215 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) 1216 mgs_add_common_cert_vars(r, cert.x509[0], 1, 1217 ctxt->sc->export_certificates_enabled); 1218 else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) 1219 mgs_add_common_pgpcert_vars(r, cert.pgp, 1, 1220 ctxt->sc->export_certificates_enabled); 1221 1222 { 1223 /* days remaining */ 1224 unsigned long remain = 1225 (apr_time_sec(expiration_time) - 1226 apr_time_sec(cur_time)) / 86400; 1227 apr_table_setn(r->subprocess_env, "SSL_CLIENT_V_REMAIN", 1228 apr_psprintf(r->pool, "%lu", remain)); 1229 } 1230 1231 if (status == 0) { 1232 apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", "SUCCESS"); 1233 ret = OK; 1234 } else { 1235 apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", "FAILED"); 1236 if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) 1237 ret = OK; 1238 else 1239 ret = HTTP_FORBIDDEN; 1240 } 1241 1242 exit: 1243 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { 1244 int i; 1245 for (i=0; i<ch_size; i++) { 1246 gnutls_x509_crt_deinit(cert.x509[i]); 1247 } 1248 } else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) 1249 gnutls_openpgp_crt_deinit(cert.pgp); 1250 return ret; 1251 1252 1253 } 1267 /* ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); */ 1268 1269 cur_time = apr_time_now(); 1270 1271 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { 1272 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1273 "GnuTLS: Could not find Signer for Peer Certificate"); 1274 } 1275 1276 if (status & GNUTLS_CERT_SIGNER_NOT_CA) { 1277 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1278 "GnuTLS: Peer's Certificate signer is not a CA"); 1279 } 1280 1281 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { 1282 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1283 "GnuTLS: Peer's Certificate is using insecure algorithms"); 1284 } 1285 1286 if (status & GNUTLS_CERT_EXPIRED 1287 || status & GNUTLS_CERT_NOT_ACTIVATED) { 1288 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1289 "GnuTLS: Peer's Certificate signer is expired or not yet activated"); 1290 } 1291 1292 if (status & GNUTLS_CERT_INVALID) { 1293 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1294 "GnuTLS: Peer Certificate is invalid."); 1295 } else if (status & GNUTLS_CERT_REVOKED) { 1296 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1297 "GnuTLS: Peer Certificate is revoked."); 1298 } 1299 1300 if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) 1301 mgs_add_common_cert_vars(r, cert.x509[0], 1, 1302 ctxt-> 1303 sc->export_certificates_enabled); 1304 else if (gnutls_certificate_type_get(ctxt->session) == 1305 GNUTLS_CRT_OPENPGP) 1306 mgs_add_common_pgpcert_vars(r, cert.pgp, 1, 1307 ctxt-> 1308 sc->export_certificates_enabled); 1309 1310 { 1311 /* days remaining */ 1312 unsigned long remain = 1313 (apr_time_sec(expiration_time) - 1314 apr_time_sec(cur_time)) / 86400; 1315 apr_table_setn(r->subprocess_env, "SSL_CLIENT_V_REMAIN", 1316 apr_psprintf(r->pool, "%lu", remain)); 1317 } 1318 1319 if (status == 0) { 1320 apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", 1321 "SUCCESS"); 1322 ret = OK; 1323 } else { 1324 apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", 1325 "FAILED"); 1326 if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) 1327 ret = OK; 1328 else 1329 ret = HTTP_FORBIDDEN; 1330 } 1331 1332 exit: 1333 if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) { 1334 int i; 1335 for (i = 0; i < ch_size; i++) { 1336 gnutls_x509_crt_deinit(cert.x509[i]); 1337 } 1338 } else if (gnutls_certificate_type_get(ctxt->session) == 1339 GNUTLS_CRT_OPENPGP) 1340 gnutls_openpgp_crt_deinit(cert.pgp); 1341 return ret; 1342 1343 1344 }
Note: See TracChangeset
for help on using the changeset viewer.