diff options
author | Paul Querna | 2004-09-27 19:21:52 +0000 |
---|---|---|
committer | Paul Querna | 2004-09-27 19:21:52 +0000 |
commit | aa99b132ccd5d20f01ad8e20f1b3807883d86024 (patch) | |
tree | 599e1bc0d25f0cb0e321eeb2c8a6bc6e7d4abf44 /src | |
parent | 6a8a8396ceed9fb87a6586ebcb144b5f4b62a39a (diff) |
commit before i move everything around
Diffstat (limited to 'src')
-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) |