diff options
| author | 2004-09-27 19:21:52 +0000 | |
|---|---|---|
| committer | 2004-09-27 19:21:52 +0000 | |
| commit | aa99b132ccd5d20f01ad8e20f1b3807883d86024 (patch) | |
| tree | 599e1bc0d25f0cb0e321eeb2c8a6bc6e7d4abf44 | |
| parent | 6a8a8396ceed9fb87a6586ebcb144b5f4b62a39a (diff) | |
commit before i move everything around
| -rw-r--r-- | src/mod_gnutls.c | 169 |
1 files changed, 114 insertions, 55 deletions
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c index e9ad89c..e696ec6 100644 --- a/src/mod_gnutls.c +++ b/src/mod_gnutls.c | |||
| @@ -49,7 +49,6 @@ typedef struct { | |||
| 49 | char *key_file; | 49 | char *key_file; |
| 50 | char *cert_file; | 50 | char *cert_file; |
| 51 | int enabled; | 51 | int enabled; |
| 52 | int non_https; | ||
| 53 | int ciphers[16]; | 52 | int ciphers[16]; |
| 54 | int key_exchange[16]; | 53 | int key_exchange[16]; |
| 55 | int macs[16]; | 54 | int macs[16]; |
| @@ -62,14 +61,13 @@ struct gnutls_handle_t | |||
| 62 | { | 61 | { |
| 63 | gnutls_srvconf_rec *sc; | 62 | gnutls_srvconf_rec *sc; |
| 64 | gnutls_session_t session; | 63 | gnutls_session_t session; |
| 65 | #ifdef GNUTLS_AS_FILTER | ||
| 66 | ap_filter_t *input_filter; | 64 | ap_filter_t *input_filter; |
| 67 | apr_bucket_brigade *input_bb; | 65 | apr_bucket_brigade *input_bb; |
| 68 | apr_read_type_e input_block; | 66 | apr_read_type_e input_block; |
| 69 | #endif | 67 | int status; |
| 68 | int non_https; | ||
| 70 | }; | 69 | }; |
| 71 | 70 | ||
| 72 | #ifdef GNUTLS_AS_FILTER | ||
| 73 | static apr_status_t gnutls_filter_input(ap_filter_t * f, | 71 | static apr_status_t gnutls_filter_input(ap_filter_t * f, |
| 74 | apr_bucket_brigade * bb, | 72 | apr_bucket_brigade * bb, |
| 75 | ap_input_mode_t mode, | 73 | ap_input_mode_t mode, |
| @@ -85,38 +83,133 @@ static apr_status_t gnutls_filter_input(ap_filter_t * f, | |||
| 85 | return APR_ECONNABORTED; | 83 | return APR_ECONNABORTED; |
| 86 | } | 84 | } |
| 87 | 85 | ||
| 86 | |||
| 87 | for (b = APR_BRIGADE_FIRST(bb); | ||
| 88 | b != APR_BRIGADE_SENTINEL(bb); b = APR_BUCKET_NEXT(b)) { | ||
| 89 | if (APR_BUCKET_IS_EOS(b)) { | ||
| 90 | /* end of connection */ | ||
| 91 | } | ||
| 92 | else if (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ) | ||
| 93 | == APR_SUCCESS) { | ||
| 94 | /* more data */ | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 88 | return status; | 98 | return status; |
| 89 | } | 99 | } |
| 90 | 100 | ||
| 101 | #define HANDSHAKE_ATTEMPTS 10 | ||
| 102 | |||
| 91 | static apr_status_t gnutls_filter_output(ap_filter_t * f, | 103 | static apr_status_t gnutls_filter_output(ap_filter_t * f, |
| 92 | apr_bucket_brigade * bb) | 104 | apr_bucket_brigade * bb) |
| 93 | { | 105 | { |
| 94 | apr_bucket *b; | 106 | int ret, i; |
| 95 | const char *buf = 0; | 107 | const char *buf = 0; |
| 96 | apr_size_t bytes = 0; | 108 | apr_size_t bytes = 0; |
| 97 | gnutls_handle_t *ctxt = (gnutls_handle_t *) f->ctx; | 109 | gnutls_handle_t *ctxt = (gnutls_handle_t *) f->ctx; |
| 98 | apr_status_t status = APR_SUCCESS; | 110 | apr_status_t status = APR_SUCCESS; |
| 111 | apr_read_type_e rblock = APR_NONBLOCK_READ; | ||
| 112 | |||
| 113 | if (f->c->aborted) { | ||
| 114 | apr_brigade_cleanup(bb); | ||
| 115 | return APR_ECONNABORTED; | ||
| 116 | } | ||
| 117 | |||
| 118 | if(ctxt->status == 0) { | ||
| 119 | for (i=HANDSHAKE_ATTEMPTS; i>0; i--){ | ||
| 120 | ret = gnutls_handshake(ctxt->session); | ||
| 121 | |||
| 122 | if(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN){ | ||
| 123 | continue; | ||
| 124 | } | ||
| 99 | 125 | ||
| 100 | if (!ctxt) { | 126 | if (ret < 0) { |
| 101 | /* first run. */ | 127 | if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { |
| 128 | ret = gnutls_alert_get(ctxt->session); | ||
| 129 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, f->c->base_server, | ||
| 130 | "GnuTLS: Hanshake Alert (%d) '%s'.\n", ret, gnutls_alert_get_name(ret)); | ||
| 131 | } | ||
| 132 | |||
| 133 | if (gnutls_error_is_fatal(ret) != 0) { | ||
| 134 | gnutls_deinit(ctxt->session); | ||
| 135 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, f->c->base_server, | ||
| 136 | "GnuTLS: Handshake Failed (%d) '%s'",ret, gnutls_strerror(ret)); | ||
| 137 | ctxt->status = -1; | ||
| 138 | break; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | else { | ||
| 142 | ctxt->status = 1; | ||
| 143 | break; /* all done with the handshake */ | ||
| 144 | } | ||
| 145 | } | ||
| 102 | } | 146 | } |
| 103 | 147 | ||
| 104 | for (b = APR_BRIGADE_FIRST(bb); | 148 | if (ctxt->status < 0) { |
| 105 | b != APR_BRIGADE_SENTINEL(bb); b = APR_BUCKET_NEXT(b)) { | 149 | return ap_pass_brigade(f->next, bb); |
| 106 | if (APR_BUCKET_IS_EOS(b)) { | 150 | } |
| 107 | /* end of connection */ | 151 | |
| 152 | while (!APR_BRIGADE_EMPTY(bb)) { | ||
| 153 | apr_bucket *bucket = APR_BRIGADE_FIRST(bb); | ||
| 154 | if (APR_BUCKET_IS_EOS(bucket) || APR_BUCKET_IS_FLUSH(bucket)) { | ||
| 155 | /** TODO: GnuTLS doesn't have a special flush method? **/ | ||
| 156 | if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { | ||
| 157 | return status; | ||
| 158 | } | ||
| 159 | break; | ||
| 108 | } | 160 | } |
| 109 | else if (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ) | 161 | else if(AP_BUCKET_IS_EOC(bucket)) { |
| 110 | == APR_SUCCESS) { | 162 | gnutls_bye(ctxt->session, GNUTLS_SHUT_WR); |
| 111 | /* more data */ | 163 | |
| 164 | if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { | ||
| 165 | return status; | ||
| 166 | } | ||
| 167 | break; | ||
| 168 | } | ||
| 169 | else { | ||
| 170 | /* filter output */ | ||
| 171 | const char *data; | ||
| 172 | apr_size_t len; | ||
| 173 | |||
| 174 | status = apr_bucket_read(bucket, &data, &len, rblock); | ||
| 175 | |||
| 176 | if (APR_STATUS_IS_EAGAIN(status)) { | ||
| 177 | rblock = APR_BLOCK_READ; | ||
| 178 | continue; /* and try again with a blocking read. */ | ||
| 179 | } | ||
| 180 | |||
| 181 | rblock = APR_NONBLOCK_READ; | ||
| 182 | |||
| 183 | if (!APR_STATUS_IS_EOF(status) && (status != APR_SUCCESS)) { | ||
| 184 | break; | ||
| 185 | } | ||
| 186 | |||
| 187 | ret = gnutls_record_send(ctxt->session, data, len); | ||
| 188 | status = ssl_filter_write(f, data, len); | ||
| 189 | if(ret < 0) { | ||
| 190 | /* error sending output */ | ||
| 191 | } | ||
| 192 | else if ((apr_size_t)res != len) { | ||
| 193 | /* not all of the data was sent. */ | ||
| 194 | /* mod_ssl basicly errors out here.. this doesn't seem right? */ | ||
| 195 | } | ||
| 196 | else { | ||
| 197 | /* send complete */ | ||
| 198 | |||
| 199 | } | ||
| 200 | |||
| 201 | apr_bucket_delete(bucket); | ||
| 202 | |||
| 203 | if (status != APR_SUCCESS) { | ||
| 204 | break; | ||
| 205 | } | ||
| 206 | |||
| 112 | } | 207 | } |
| 113 | } | 208 | } |
| 114 | 209 | ||
| 115 | return status; | 210 | return status; |
| 116 | } | 211 | } |
| 117 | 212 | ||
| 118 | #endif /* GNUTLS_AS_FILTER */ | ||
| 119 | |||
| 120 | static apr_status_t gnutls_cleanup_pre_config(void *data) | 213 | static apr_status_t gnutls_cleanup_pre_config(void *data) |
| 121 | { | 214 | { |
| 122 | gnutls_global_deinit(); | 215 | gnutls_global_deinit(); |
| @@ -206,7 +299,6 @@ static apr_port_t gnutls_hook_default_port(const request_rec * r) | |||
| 206 | return 443; | 299 | return 443; |
| 207 | } | 300 | } |
| 208 | 301 | ||
| 209 | #ifdef GNUTLS_AS_FILTER | ||
| 210 | /** | 302 | /** |
| 211 | * From mod_ssl / ssl_engine_io.c | 303 | * From mod_ssl / ssl_engine_io.c |
| 212 | * This function will read from a brigade and discard the read buckets as it | 304 | * This function will read from a brigade and discard the read buckets as it |
| @@ -345,14 +437,9 @@ static ssize_t gnutls_transport_write(gnutls_transport_ptr_t ptr, | |||
| 345 | //APR_BRIGADE_INSERT_TAIL(outctx->bb, bucket); | 437 | //APR_BRIGADE_INSERT_TAIL(outctx->bb, bucket); |
| 346 | return 0; | 438 | return 0; |
| 347 | } | 439 | } |
| 348 | #endif /* GNUTLS_AS_FILTER */ | ||
| 349 | 440 | ||
| 350 | static int gnutls_hook_pre_connection(conn_rec * c, void *csd) | 441 | static int gnutls_hook_pre_connection(conn_rec * c, void *csd) |
| 351 | { | 442 | { |
| 352 | #ifndef GNUTLS_AS_FILTER | ||
| 353 | int cfd; | ||
| 354 | int ret; | ||
| 355 | #endif | ||
| 356 | gnutls_handle_t *ctxt; | 443 | gnutls_handle_t *ctxt; |
| 357 | gnutls_srvconf_rec *sc = | 444 | gnutls_srvconf_rec *sc = |
| 358 | (gnutls_srvconf_rec *) ap_get_module_config(c->base_server-> | 445 | (gnutls_srvconf_rec *) ap_get_module_config(c->base_server-> |
| @@ -366,6 +453,7 @@ static int gnutls_hook_pre_connection(conn_rec * c, void *csd) | |||
| 366 | ctxt = apr_pcalloc(c->pool, sizeof(*ctxt)); | 453 | ctxt = apr_pcalloc(c->pool, sizeof(*ctxt)); |
| 367 | 454 | ||
| 368 | ctxt->sc = sc; | 455 | ctxt->sc = sc; |
| 456 | ctxt->status = 0; | ||
| 369 | gnutls_init(&ctxt->session, GNUTLS_SERVER); | 457 | gnutls_init(&ctxt->session, GNUTLS_SERVER); |
| 370 | 458 | ||
| 371 | gnutls_cipher_set_priority(ctxt->session, sc->ciphers); | 459 | gnutls_cipher_set_priority(ctxt->session, sc->ciphers); |
| @@ -375,6 +463,10 @@ static int gnutls_hook_pre_connection(conn_rec * c, void *csd) | |||
| 375 | gnutls_mac_set_priority(ctxt->session, sc->macs); | 463 | gnutls_mac_set_priority(ctxt->session, sc->macs); |
| 376 | 464 | ||
| 377 | gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, sc->certs); | 465 | gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, sc->certs); |
| 466 | // if(anon) { | ||
| 467 | // gnutls_credentials_set(ctxt->session, GNUTLS_CRD_ANON, sc->anoncred); | ||
| 468 | // } | ||
| 469 | |||
| 378 | gnutls_certificate_server_set_request(ctxt->session, GNUTLS_CERT_IGNORE); | 470 | gnutls_certificate_server_set_request(ctxt->session, GNUTLS_CERT_IGNORE); |
| 379 | 471 | ||
| 380 | // gnutls_dh_set_prime_bits(ctxt->session, DH_BITS); | 472 | // gnutls_dh_set_prime_bits(ctxt->session, DH_BITS); |
| @@ -382,43 +474,12 @@ static int gnutls_hook_pre_connection(conn_rec * c, void *csd) | |||
| 382 | 474 | ||
| 383 | ap_set_module_config(c->conn_config, &gnutls_module, ctxt); | 475 | ap_set_module_config(c->conn_config, &gnutls_module, ctxt); |
| 384 | 476 | ||
| 385 | #ifdef GNUTLS_AS_FILTER | ||
| 386 | gnutls_transport_set_pull_function(ctxt->session, gnutls_transport_read); | 477 | gnutls_transport_set_pull_function(ctxt->session, gnutls_transport_read); |
| 387 | gnutls_transport_set_push_function(ctxt->session, gnutls_transport_write); | 478 | gnutls_transport_set_push_function(ctxt->session, gnutls_transport_write); |
| 388 | gnutls_transport_set_ptr(ctxt->session, ctxt); | 479 | gnutls_transport_set_ptr(ctxt->session, ctxt); |
| 389 | |||
| 390 | ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c); | 480 | ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c); |
| 391 | ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c); | 481 | ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c); |
| 392 | #else | ||
| 393 | apr_os_sock_get(&cfd, csd); | ||
| 394 | gnutls_transport_set_ptr(ctxt->session, (gnutls_transport_ptr)cfd); | ||
| 395 | gnutls_credentials_set(ctxt->session, GNUTLS_CRD_ANON, sc->anoncred); | ||
| 396 | 482 | ||
| 397 | do{ | ||
| 398 | ret = gnutls_handshake(ctxt->session); | ||
| 399 | |||
| 400 | if(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN){ | ||
| 401 | continue; | ||
| 402 | } | ||
| 403 | |||
| 404 | if (ret < 0) { | ||
| 405 | if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { | ||
| 406 | ret = gnutls_alert_get(ctxt->session); | ||
| 407 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server, | ||
| 408 | "GnuTLS: Hanshake Alert (%d) '%s'.\n", ret, gnutls_alert_get_name(ret)); | ||
| 409 | } | ||
| 410 | |||
| 411 | if (gnutls_error_is_fatal(ret) != 0) { | ||
| 412 | gnutls_deinit(ctxt->session); | ||
| 413 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server, | ||
| 414 | "GnuTLS: Handshake Failed (%d) '%s'",ret, gnutls_strerror(ret)); | ||
| 415 | sc->non_https = 1; | ||
| 416 | break; | ||
| 417 | } | ||
| 418 | } | ||
| 419 | break; /* all done with the handshake */ | ||
| 420 | } while(1); | ||
| 421 | #endif | ||
| 422 | return OK; | 483 | return OK; |
| 423 | } | 484 | } |
| 424 | 485 | ||
| @@ -501,12 +562,10 @@ static void gnutls_hooks(apr_pool_t * p) | |||
| 501 | /* ap_register_output_filter ("UPGRADE_FILTER", | 562 | /* ap_register_output_filter ("UPGRADE_FILTER", |
| 502 | * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); | 563 | * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); |
| 503 | */ | 564 | */ |
| 504 | #ifdef GNUTLS_AS_FILTER | ||
| 505 | ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, gnutls_filter_input, | 565 | ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, gnutls_filter_input, |
| 506 | NULL, AP_FTYPE_CONNECTION + 5); | 566 | NULL, AP_FTYPE_CONNECTION + 5); |
| 507 | ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, gnutls_filter_output, | 567 | ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, gnutls_filter_output, |
| 508 | NULL, AP_FTYPE_CONNECTION + 5); | 568 | NULL, AP_FTYPE_CONNECTION + 5); |
| 509 | #endif | ||
| 510 | } | 569 | } |
| 511 | 570 | ||
| 512 | static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s) | 571 | static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s) |
