diff options
| -rw-r--r-- | include/mod_gnutls.h | 122 | ||||
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/gnutls_io.c | 307 | ||||
| -rw-r--r-- | src/mod_gnutls.c | 385 |
4 files changed, 460 insertions, 356 deletions
diff --git a/include/mod_gnutls.h b/include/mod_gnutls.h new file mode 100644 index 0000000..70e641f --- /dev/null +++ b/include/mod_gnutls.h | |||
| @@ -0,0 +1,122 @@ | |||
| 1 | /* ==================================================================== | ||
| 2 | * Copyright 2004 Paul Querna | ||
| 3 | * | ||
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | * you may not use this file except in compliance with the License. | ||
| 6 | * You may obtain a copy of the License at | ||
| 7 | * | ||
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | * | ||
| 10 | * Unless required by applicable law or agreed to in writing, software | ||
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | * See the License for the specific language governing permissions and | ||
| 14 | * limitations under the License. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef __mod_gnutls_h_inc | ||
| 19 | #define __mod_gnutls_h_inc | ||
| 20 | |||
| 21 | #include "httpd.h" | ||
| 22 | #include "http_config.h" | ||
| 23 | #include "http_protocol.h" | ||
| 24 | #include "http_connection.h" | ||
| 25 | #include "http_core.h" | ||
| 26 | #include "http_log.h" | ||
| 27 | #include "apr_buckets.h" | ||
| 28 | #include "apr_strings.h" | ||
| 29 | #include "apr_tables.h" | ||
| 30 | |||
| 31 | #include <gcrypt.h> | ||
| 32 | #include <gnutls/gnutls.h> | ||
| 33 | |||
| 34 | module AP_MODULE_DECLARE_DATA gnutls_module; | ||
| 35 | |||
| 36 | #define GNUTLS_OUTPUT_FILTER_NAME "gnutls_output_filter" | ||
| 37 | #define GNUTLS_INPUT_FILTER_NAME "gnutls_input_filter" | ||
| 38 | |||
| 39 | #define GNUTLS_ENABLED_FALSE 0 | ||
| 40 | #define GNUTLS_ENABLED_TRUE 1 | ||
| 41 | |||
| 42 | |||
| 43 | typedef struct | ||
| 44 | { | ||
| 45 | gnutls_certificate_credentials_t certs; | ||
| 46 | gnutls_anon_server_credentials_t anoncred; | ||
| 47 | char *key_file; | ||
| 48 | char *cert_file; | ||
| 49 | int enabled; | ||
| 50 | int ciphers[16]; | ||
| 51 | int key_exchange[16]; | ||
| 52 | int macs[16]; | ||
| 53 | int protocol[16]; | ||
| 54 | int compression[16]; | ||
| 55 | } gnutls_srvconf_rec; | ||
| 56 | |||
| 57 | typedef struct gnutls_handle_t gnutls_handle_t; | ||
| 58 | struct gnutls_handle_t | ||
| 59 | { | ||
| 60 | gnutls_srvconf_rec *sc; | ||
| 61 | gnutls_session_t session; | ||
| 62 | ap_filter_t *input_filter; | ||
| 63 | apr_bucket_brigade *input_bb; | ||
| 64 | apr_read_type_e input_block; | ||
| 65 | int status; | ||
| 66 | int non_https; | ||
| 67 | }; | ||
| 68 | |||
| 69 | /** Functions in gnutls_io.c **/ | ||
| 70 | |||
| 71 | /** | ||
| 72 | * mod_gnutls_filter_input will filter the input data | ||
| 73 | * by decrypting it using GnuTLS and passes it cleartext. | ||
| 74 | * | ||
| 75 | * @param f the filter info record | ||
| 76 | * @param bb the bucket brigade, where to store the result to | ||
| 77 | * @param mode what shall we read? | ||
| 78 | * @param block a block index we shall read from? | ||
| 79 | * @return result status | ||
| 80 | */ | ||
| 81 | apr_status_t mod_gnutls_filter_input(ap_filter_t * f, | ||
| 82 | apr_bucket_brigade * bb, | ||
| 83 | ap_input_mode_t mode, | ||
| 84 | apr_read_type_e block, apr_off_t readbytes); | ||
| 85 | |||
| 86 | /** | ||
| 87 | * mod_gnutls_filter_output will filter the encrypt | ||
| 88 | * the incoming bucket using GnuTLS and passes it onto the next filter. | ||
| 89 | * | ||
| 90 | * @param f the filter info record | ||
| 91 | * @param bb the bucket brigade, where to store the result to | ||
| 92 | * @return result status | ||
| 93 | */ | ||
| 94 | apr_status_t mod_gnutls_filter_output(ap_filter_t * f, apr_bucket_brigade * bb); | ||
| 95 | |||
| 96 | |||
| 97 | /** | ||
| 98 | * mod_gnutls_transport_read is called from GnuTLS to provide encrypted | ||
| 99 | * data from the client. | ||
| 100 | * | ||
| 101 | * @param ptr pointer to the filter context | ||
| 102 | * @param buffer place to put data | ||
| 103 | * @param len maximum size | ||
| 104 | * @return size length of the data stored in buffer | ||
| 105 | */ | ||
| 106 | ssize_t mod_gnutls_transport_read(gnutls_transport_ptr_t ptr, | ||
| 107 | void *buffer, size_t len); | ||
| 108 | |||
| 109 | /** | ||
| 110 | * mod_gnutls_transport_write is called from GnuTLS to | ||
| 111 | * write data to the client. | ||
| 112 | * | ||
| 113 | * @param ptr pointer to the filter context | ||
| 114 | * @param buffer buffer to write to the client | ||
| 115 | * @param len size of the buffer | ||
| 116 | * @return size length of the data written | ||
| 117 | */ | ||
| 118 | ssize_t mod_gnutls_transport_write(gnutls_transport_ptr_t ptr, | ||
| 119 | const void *buffer, size_t len); | ||
| 120 | |||
| 121 | |||
| 122 | #endif /* __mod_gnutls_h_inc */ | ||
diff --git a/src/Makefile.am b/src/Makefile.am index 00ef272..ebbe176 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | CLEANFILES = .libs/libmod_gnutls *~ | 1 | CLEANFILES = .libs/libmod_gnutls *~ |
| 2 | 2 | ||
| 3 | libmod_gnutls_la_SOURCES = mod_gnutls.c | 3 | libmod_gnutls_la_SOURCES = mod_gnutls.c gnutls_io.c |
| 4 | libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} | 4 | libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} |
| 5 | libmod_gnutls_la_LDFLAGS = ${MODULE_LIBS} | 5 | libmod_gnutls_la_LDFLAGS = ${MODULE_LIBS} |
| 6 | 6 | ||
diff --git a/src/gnutls_io.c b/src/gnutls_io.c new file mode 100644 index 0000000..6b0a15b --- /dev/null +++ b/src/gnutls_io.c | |||
| @@ -0,0 +1,307 @@ | |||
| 1 | /* ==================================================================== | ||
| 2 | * Copyright 2004 Paul Querna | ||
| 3 | * | ||
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | * you may not use this file except in compliance with the License. | ||
| 6 | * You may obtain a copy of the License at | ||
| 7 | * | ||
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | * | ||
| 10 | * Unless required by applicable law or agreed to in writing, software | ||
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | * See the License for the specific language governing permissions and | ||
| 14 | * limitations under the License. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include "mod_gnutls.h" | ||
| 19 | |||
| 20 | /** | ||
| 21 | * Describe how the GnuTLS Filter system works here | ||
| 22 | * - It is basicly the same as what mod_ssl uses in that respect. | ||
| 23 | */ | ||
| 24 | |||
| 25 | apr_status_t mod_gnutls_filter_input(ap_filter_t * f, | ||
| 26 | apr_bucket_brigade * bb, | ||
| 27 | ap_input_mode_t mode, | ||
| 28 | apr_read_type_e block, | ||
| 29 | apr_off_t readbytes) | ||
| 30 | { | ||
| 31 | apr_bucket* b; | ||
| 32 | apr_status_t status = APR_SUCCESS; | ||
| 33 | gnutls_handle_t *ctxt = (gnutls_handle_t *) f->ctx; | ||
| 34 | |||
| 35 | if (f->c->aborted) { | ||
| 36 | apr_bucket *bucket = apr_bucket_eos_create(f->c->bucket_alloc); | ||
| 37 | APR_BRIGADE_INSERT_TAIL(bb, bucket); | ||
| 38 | return APR_ECONNABORTED; | ||
| 39 | } | ||
| 40 | |||
| 41 | #if 0 | ||
| 42 | for (b = APR_BRIGADE_FIRST(bb); | ||
| 43 | b != APR_BRIGADE_SENTINEL(bb); b = APR_BUCKET_NEXT(b)) { | ||
| 44 | if (APR_BUCKET_IS_EOS(b)) { | ||
| 45 | /* end of connection */ | ||
| 46 | } | ||
| 47 | else if (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ) | ||
| 48 | == APR_SUCCESS) { | ||
| 49 | /* more data */ | ||
| 50 | } | ||
| 51 | } | ||
| 52 | #endif | ||
| 53 | return status; | ||
| 54 | } | ||
| 55 | |||
| 56 | #define GNUTLS_HANDSHAKE_ATTEMPTS 10 | ||
| 57 | |||
| 58 | apr_status_t mod_gnutls_filter_output(ap_filter_t * f, | ||
| 59 | apr_bucket_brigade * bb) | ||
| 60 | { | ||
| 61 | int ret, i; | ||
| 62 | const char *buf = 0; | ||
| 63 | apr_size_t bytes = 0; | ||
| 64 | gnutls_handle_t *ctxt = (gnutls_handle_t *) f->ctx; | ||
| 65 | apr_status_t status = APR_SUCCESS; | ||
| 66 | apr_read_type_e rblock = APR_NONBLOCK_READ; | ||
| 67 | |||
| 68 | if (f->c->aborted) { | ||
| 69 | apr_brigade_cleanup(bb); | ||
| 70 | return APR_ECONNABORTED; | ||
| 71 | } | ||
| 72 | |||
| 73 | if (ctxt->status == 0) { | ||
| 74 | for (i = GNUTLS_HANDSHAKE_ATTEMPTS; i > 0; i--) { | ||
| 75 | ret = gnutls_handshake(ctxt->session); | ||
| 76 | |||
| 77 | if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { | ||
| 78 | continue; | ||
| 79 | } | ||
| 80 | |||
| 81 | if (ret < 0) { | ||
| 82 | if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED | ||
| 83 | || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { | ||
| 84 | ret = gnutls_alert_get(ctxt->session); | ||
| 85 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, f->c->base_server, | ||
| 86 | "GnuTLS: Hanshake Alert (%d) '%s'.\n", ret, | ||
| 87 | gnutls_alert_get_name(ret)); | ||
| 88 | } | ||
| 89 | |||
| 90 | if (gnutls_error_is_fatal(ret) != 0) { | ||
| 91 | gnutls_deinit(ctxt->session); | ||
| 92 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, f->c->base_server, | ||
| 93 | "GnuTLS: Handshake Failed (%d) '%s'", ret, | ||
| 94 | gnutls_strerror(ret)); | ||
| 95 | ctxt->status = -1; | ||
| 96 | break; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | else { | ||
| 100 | ctxt->status = 1; | ||
| 101 | break; /* all done with the handshake */ | ||
| 102 | } | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | if (ctxt->status < 0) { | ||
| 107 | return ap_pass_brigade(f->next, bb); | ||
| 108 | } | ||
| 109 | |||
| 110 | while (!APR_BRIGADE_EMPTY(bb)) { | ||
| 111 | apr_bucket *bucket = APR_BRIGADE_FIRST(bb); | ||
| 112 | if (APR_BUCKET_IS_EOS(bucket) || APR_BUCKET_IS_FLUSH(bucket)) { | ||
| 113 | /** TODO: GnuTLS doesn't have a special flush method? **/ | ||
| 114 | if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { | ||
| 115 | return status; | ||
| 116 | } | ||
| 117 | break; | ||
| 118 | } | ||
| 119 | else if (AP_BUCKET_IS_EOC(bucket)) { | ||
| 120 | gnutls_bye(ctxt->session, GNUTLS_SHUT_WR); | ||
| 121 | |||
| 122 | if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { | ||
| 123 | return status; | ||
| 124 | } | ||
| 125 | break; | ||
| 126 | } | ||
| 127 | else { | ||
| 128 | /* filter output */ | ||
| 129 | const char *data; | ||
| 130 | apr_size_t len; | ||
| 131 | |||
| 132 | status = apr_bucket_read(bucket, &data, &len, rblock); | ||
| 133 | |||
| 134 | if (APR_STATUS_IS_EAGAIN(status)) { | ||
| 135 | rblock = APR_BLOCK_READ; | ||
| 136 | continue; /* and try again with a blocking read. */ | ||
| 137 | } | ||
| 138 | |||
| 139 | rblock = APR_NONBLOCK_READ; | ||
| 140 | |||
| 141 | if (!APR_STATUS_IS_EOF(status) && (status != APR_SUCCESS)) { | ||
| 142 | break; | ||
| 143 | } | ||
| 144 | |||
| 145 | ret = gnutls_record_send(ctxt->session, data, len); | ||
| 146 | if (ret < 0) { | ||
| 147 | /* error sending output */ | ||
| 148 | } | ||
| 149 | else if ((apr_size_t) ret != len) { | ||
| 150 | /* not all of the data was sent. */ | ||
| 151 | /* mod_ssl basicly errors out here.. this doesn't seem right? */ | ||
| 152 | } | ||
| 153 | else { | ||
| 154 | /* send complete */ | ||
| 155 | |||
| 156 | } | ||
| 157 | |||
| 158 | apr_bucket_delete(bucket); | ||
| 159 | |||
| 160 | if (status != APR_SUCCESS) { | ||
| 161 | break; | ||
| 162 | } | ||
| 163 | |||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | return status; | ||
| 168 | } | ||
| 169 | |||
| 170 | /** | ||
| 171 | * From mod_ssl / ssl_engine_io.c | ||
| 172 | * This function will read from a brigade and discard the read buckets as it | ||
| 173 | * proceeds. It will read at most *len bytes. | ||
| 174 | */ | ||
| 175 | static apr_status_t brigade_consume(apr_bucket_brigade * bb, | ||
| 176 | apr_read_type_e block, | ||
| 177 | char *c, apr_size_t * len) | ||
| 178 | { | ||
| 179 | apr_size_t actual = 0; | ||
| 180 | apr_status_t status = APR_SUCCESS; | ||
| 181 | |||
| 182 | while (!APR_BRIGADE_EMPTY(bb)) { | ||
| 183 | apr_bucket *b = APR_BRIGADE_FIRST(bb); | ||
| 184 | const char *str; | ||
| 185 | apr_size_t str_len; | ||
| 186 | apr_size_t consume; | ||
| 187 | |||
| 188 | /* Justin points out this is an http-ism that might | ||
| 189 | * not fit if brigade_consume is added to APR. Perhaps | ||
| 190 | * apr_bucket_read(eos_bucket) should return APR_EOF? | ||
| 191 | * Then this becomes mainline instead of a one-off. | ||
| 192 | */ | ||
| 193 | if (APR_BUCKET_IS_EOS(b)) { | ||
| 194 | status = APR_EOF; | ||
| 195 | break; | ||
| 196 | } | ||
| 197 | |||
| 198 | /* The reason I'm not offering brigade_consume yet | ||
| 199 | * across to apr-util is that the following call | ||
| 200 | * illustrates how borked that API really is. For | ||
| 201 | * this sort of case (caller provided buffer) it | ||
| 202 | * would be much more trivial for apr_bucket_consume | ||
| 203 | * to do all the work that follows, based on the | ||
| 204 | * particular characteristics of the bucket we are | ||
| 205 | * consuming here. | ||
| 206 | */ | ||
| 207 | status = apr_bucket_read(b, &str, &str_len, block); | ||
| 208 | |||
| 209 | if (status != APR_SUCCESS) { | ||
| 210 | if (APR_STATUS_IS_EOF(status)) { | ||
| 211 | /* This stream bucket was consumed */ | ||
| 212 | apr_bucket_delete(b); | ||
| 213 | continue; | ||
| 214 | } | ||
| 215 | break; | ||
| 216 | } | ||
| 217 | |||
| 218 | if (str_len > 0) { | ||
| 219 | /* Do not block once some data has been consumed */ | ||
| 220 | block = APR_NONBLOCK_READ; | ||
| 221 | |||
| 222 | /* Assure we don't overflow. */ | ||
| 223 | consume = (str_len + actual > *len) ? *len - actual : str_len; | ||
| 224 | |||
| 225 | memcpy(c, str, consume); | ||
| 226 | |||
| 227 | c += consume; | ||
| 228 | actual += consume; | ||
| 229 | |||
| 230 | if (consume >= b->length) { | ||
| 231 | /* This physical bucket was consumed */ | ||
| 232 | apr_bucket_delete(b); | ||
| 233 | } | ||
| 234 | else { | ||
| 235 | /* Only part of this physical bucket was consumed */ | ||
| 236 | b->start += consume; | ||
| 237 | b->length -= consume; | ||
| 238 | } | ||
| 239 | } | ||
| 240 | else if (b->length == 0) { | ||
| 241 | apr_bucket_delete(b); | ||
| 242 | } | ||
| 243 | |||
| 244 | /* This could probably be actual == *len, but be safe from stray | ||
| 245 | * photons. */ | ||
| 246 | if (actual >= *len) { | ||
| 247 | break; | ||
| 248 | } | ||
| 249 | } | ||
| 250 | |||
| 251 | *len = actual; | ||
| 252 | return status; | ||
| 253 | } | ||
| 254 | |||
| 255 | |||
| 256 | ssize_t mod_gnutls_transport_read(gnutls_transport_ptr_t ptr, | ||
| 257 | void *buffer, size_t len) | ||
| 258 | { | ||
| 259 | gnutls_handle_t *ctxt = ptr; | ||
| 260 | apr_status_t rc; | ||
| 261 | apr_size_t in = len; | ||
| 262 | /* If Len = 0, we don't do anything. */ | ||
| 263 | if (!len) | ||
| 264 | return 0; | ||
| 265 | |||
| 266 | if (APR_BRIGADE_EMPTY(ctxt->input_bb)) { | ||
| 267 | |||
| 268 | rc = ap_get_brigade(ctxt->input_filter->next, ctxt->input_bb, | ||
| 269 | AP_MODE_READBYTES, ctxt->input_block, in); | ||
| 270 | |||
| 271 | /* Not a problem, there was simply no data ready yet. | ||
| 272 | */ | ||
| 273 | if (APR_STATUS_IS_EAGAIN(rc) || APR_STATUS_IS_EINTR(rc) | ||
| 274 | || (rc == APR_SUCCESS && APR_BRIGADE_EMPTY(ctxt->input_bb))) { | ||
| 275 | return 0; | ||
| 276 | } | ||
| 277 | |||
| 278 | if (rc != APR_SUCCESS) { | ||
| 279 | /* Unexpected errors discard the brigade */ | ||
| 280 | apr_brigade_cleanup(ctxt->input_bb); | ||
| 281 | ctxt->input_bb = NULL; | ||
| 282 | return -1; | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | // brigade_consume(ctxt->input_bb, ctxt->input_block, buffer, &len); | ||
| 287 | |||
| 288 | |||
| 289 | ap_get_brigade(ctxt->input_filter->next, ctxt->input_bb, | ||
| 290 | AP_MODE_READBYTES, ctxt->input_block, len); | ||
| 291 | |||
| 292 | return len; | ||
| 293 | } | ||
| 294 | |||
| 295 | ssize_t mod_gnutls_transport_write(gnutls_transport_ptr_t ptr, | ||
| 296 | const void *buffer, size_t len) | ||
| 297 | { | ||
| 298 | gnutls_handle_t *ctxt = ptr; | ||
| 299 | |||
| 300 | // apr_bucket *bucket = apr_bucket_transient_create(in, inl, | ||
| 301 | // outctx->bb-> | ||
| 302 | // bucket_alloc); | ||
| 303 | |||
| 304 | // outctx->length += inl; | ||
| 305 | //APR_BRIGADE_INSERT_TAIL(outctx->bb, bucket); | ||
| 306 | return 0; | ||
| 307 | } | ||
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c index e696ec6..14bf319 100644 --- a/src/mod_gnutls.c +++ b/src/mod_gnutls.c | |||
| @@ -15,201 +15,12 @@ | |||
| 15 | * | 15 | * |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #include "httpd.h" | 18 | #include "mod_gnutls.h" |
| 19 | #include "http_config.h" | ||
| 20 | #include "http_protocol.h" | ||
| 21 | #include "http_connection.h" | ||
| 22 | #include "http_core.h" | ||
| 23 | #include "http_log.h" | ||
| 24 | #include "apr_buckets.h" | ||
| 25 | #include "apr_strings.h" | ||
| 26 | #include "apr_tables.h" | ||
| 27 | |||
| 28 | #include <gcrypt.h> | ||
| 29 | #include <gnutls/gnutls.h> | ||
| 30 | 19 | ||
| 31 | #if APR_HAS_THREADS | 20 | #if APR_HAS_THREADS |
| 32 | GCRY_THREAD_OPTION_PTHREAD_IMPL; | 21 | GCRY_THREAD_OPTION_PTHREAD_IMPL; |
| 33 | #endif | 22 | #endif |
| 34 | 23 | ||
| 35 | module AP_MODULE_DECLARE_DATA gnutls_module; | ||
| 36 | |||
| 37 | #ifdef GNUTLS_AS_FILTER | ||
| 38 | #define GNUTLS_OUTPUT_FILTER_NAME "GnuTLS Output Filter" | ||
| 39 | #define GNUTLS_INPUT_FILTER_NAME "GnuTLS Input Filter" | ||
| 40 | #endif | ||
| 41 | |||
| 42 | #define GNUTLS_ENABLED_FALSE 0 | ||
| 43 | #define GNUTLS_ENABLED_TRUE 1 | ||
| 44 | |||
| 45 | |||
| 46 | typedef struct { | ||
| 47 | gnutls_certificate_credentials_t certs; | ||
| 48 | gnutls_anon_server_credentials_t anoncred; | ||
| 49 | char *key_file; | ||
| 50 | char *cert_file; | ||
| 51 | int enabled; | ||
| 52 | int ciphers[16]; | ||
| 53 | int key_exchange[16]; | ||
| 54 | int macs[16]; | ||
| 55 | int protocol[16]; | ||
| 56 | int compression[16]; | ||
| 57 | } gnutls_srvconf_rec; | ||
| 58 | |||
| 59 | typedef struct gnutls_handle_t gnutls_handle_t; | ||
| 60 | struct gnutls_handle_t | ||
| 61 | { | ||
| 62 | gnutls_srvconf_rec *sc; | ||
| 63 | gnutls_session_t session; | ||
| 64 | ap_filter_t *input_filter; | ||
| 65 | apr_bucket_brigade *input_bb; | ||
| 66 | apr_read_type_e input_block; | ||
| 67 | int status; | ||
| 68 | int non_https; | ||
| 69 | }; | ||
| 70 | |||
| 71 | static apr_status_t gnutls_filter_input(ap_filter_t * f, | ||
| 72 | apr_bucket_brigade * bb, | ||
| 73 | ap_input_mode_t mode, | ||
| 74 | apr_read_type_e block, | ||
| 75 | apr_off_t readbytes) | ||
| 76 | { | ||
| 77 | apr_status_t status = APR_SUCCESS; | ||
| 78 | gnutls_handle_t *ctxt = (gnutls_handle_t *) f->ctx; | ||
| 79 | |||
| 80 | if (f->c->aborted) { | ||
| 81 | apr_bucket *bucket = apr_bucket_eos_create(f->c->bucket_alloc); | ||
| 82 | APR_BRIGADE_INSERT_TAIL(bb, bucket); | ||
| 83 | return APR_ECONNABORTED; | ||
| 84 | } | ||
| 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 | |||
| 98 | return status; | ||
| 99 | } | ||
| 100 | |||
| 101 | #define HANDSHAKE_ATTEMPTS 10 | ||
| 102 | |||
| 103 | static apr_status_t gnutls_filter_output(ap_filter_t * f, | ||
| 104 | apr_bucket_brigade * bb) | ||
| 105 | { | ||
| 106 | int ret, i; | ||
| 107 | const char *buf = 0; | ||
| 108 | apr_size_t bytes = 0; | ||
| 109 | gnutls_handle_t *ctxt = (gnutls_handle_t *) f->ctx; | ||
| 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 | } | ||
| 125 | |||
| 126 | if (ret < 0) { | ||
| 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 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | if (ctxt->status < 0) { | ||
| 149 | return ap_pass_brigade(f->next, bb); | ||
| 150 | } | ||
| 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; | ||
| 160 | } | ||
| 161 | else if(AP_BUCKET_IS_EOC(bucket)) { | ||
| 162 | gnutls_bye(ctxt->session, GNUTLS_SHUT_WR); | ||
| 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 | |||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | return status; | ||
| 211 | } | ||
| 212 | |||
| 213 | static apr_status_t gnutls_cleanup_pre_config(void *data) | 24 | static apr_status_t gnutls_cleanup_pre_config(void *data) |
| 214 | { | 25 | { |
| 215 | gnutls_global_deinit(); | 26 | gnutls_global_deinit(); |
| @@ -253,7 +64,7 @@ static int gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | |||
| 253 | 64 | ||
| 254 | for (s = base_server; s; s = s->next) { | 65 | for (s = base_server; s; s = s->next) { |
| 255 | sc = (gnutls_srvconf_rec *) ap_get_module_config(s->module_config, | 66 | sc = (gnutls_srvconf_rec *) ap_get_module_config(s->module_config, |
| 256 | &gnutls_module); | 67 | &gnutls_module); |
| 257 | if (sc->cert_file != NULL && sc->key_file != NULL) { | 68 | if (sc->cert_file != NULL && sc->key_file != NULL) { |
| 258 | gnutls_certificate_set_x509_key_file(sc->certs, sc->cert_file, | 69 | gnutls_certificate_set_x509_key_file(sc->certs, sc->cert_file, |
| 259 | sc->key_file, | 70 | sc->key_file, |
| @@ -261,7 +72,7 @@ static int gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | |||
| 261 | // gnutls_certificate_set_rsa_export_params(sc->certs, rsa_params); | 72 | // gnutls_certificate_set_rsa_export_params(sc->certs, rsa_params); |
| 262 | // gnutls_certificate_set_dh_params(sc->certs, dh_params); | 73 | // gnutls_certificate_set_dh_params(sc->certs, dh_params); |
| 263 | } | 74 | } |
| 264 | else if(sc->enabled == GNUTLS_ENABLED_TRUE ){ | 75 | else if (sc->enabled == GNUTLS_ENABLED_TRUE) { |
| 265 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, | 76 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, |
| 266 | "[GnuTLS] - Host '%s:%d' is missing a Cert and Key File!", | 77 | "[GnuTLS] - Host '%s:%d' is missing a Cert and Key File!", |
| 267 | s->server_hostname, s->port); | 78 | s->server_hostname, s->port); |
| @@ -277,7 +88,7 @@ static const char *gnutls_hook_http_method(const request_rec * r) | |||
| 277 | { | 88 | { |
| 278 | gnutls_srvconf_rec *sc = | 89 | gnutls_srvconf_rec *sc = |
| 279 | (gnutls_srvconf_rec *) ap_get_module_config(r->server->module_config, | 90 | (gnutls_srvconf_rec *) ap_get_module_config(r->server->module_config, |
| 280 | &gnutls_module); | 91 | &gnutls_module); |
| 281 | 92 | ||
| 282 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { | 93 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { |
| 283 | return NULL; | 94 | return NULL; |
| @@ -290,7 +101,7 @@ static apr_port_t gnutls_hook_default_port(const request_rec * r) | |||
| 290 | { | 101 | { |
| 291 | gnutls_srvconf_rec *sc = | 102 | gnutls_srvconf_rec *sc = |
| 292 | (gnutls_srvconf_rec *) ap_get_module_config(r->server->module_config, | 103 | (gnutls_srvconf_rec *) ap_get_module_config(r->server->module_config, |
| 293 | &gnutls_module); | 104 | &gnutls_module); |
| 294 | 105 | ||
| 295 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { | 106 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { |
| 296 | return 0; | 107 | return 0; |
| @@ -299,152 +110,13 @@ static apr_port_t gnutls_hook_default_port(const request_rec * r) | |||
| 299 | return 443; | 110 | return 443; |
| 300 | } | 111 | } |
| 301 | 112 | ||
| 302 | /** | ||
| 303 | * From mod_ssl / ssl_engine_io.c | ||
| 304 | * This function will read from a brigade and discard the read buckets as it | ||
| 305 | * proceeds. It will read at most *len bytes. | ||
| 306 | */ | ||
| 307 | static apr_status_t brigade_consume(apr_bucket_brigade * bb, | ||
| 308 | apr_read_type_e block, | ||
| 309 | char *c, apr_size_t * len) | ||
| 310 | { | ||
| 311 | apr_size_t actual = 0; | ||
| 312 | apr_status_t status = APR_SUCCESS; | ||
| 313 | |||
| 314 | while (!APR_BRIGADE_EMPTY(bb)) { | ||
| 315 | apr_bucket *b = APR_BRIGADE_FIRST(bb); | ||
| 316 | const char *str; | ||
| 317 | apr_size_t str_len; | ||
| 318 | apr_size_t consume; | ||
| 319 | |||
| 320 | /* Justin points out this is an http-ism that might | ||
| 321 | * not fit if brigade_consume is added to APR. Perhaps | ||
| 322 | * apr_bucket_read(eos_bucket) should return APR_EOF? | ||
| 323 | * Then this becomes mainline instead of a one-off. | ||
| 324 | */ | ||
| 325 | if (APR_BUCKET_IS_EOS(b)) { | ||
| 326 | status = APR_EOF; | ||
| 327 | break; | ||
| 328 | } | ||
| 329 | |||
| 330 | /* The reason I'm not offering brigade_consume yet | ||
| 331 | * across to apr-util is that the following call | ||
| 332 | * illustrates how borked that API really is. For | ||
| 333 | * this sort of case (caller provided buffer) it | ||
| 334 | * would be much more trivial for apr_bucket_consume | ||
| 335 | * to do all the work that follows, based on the | ||
| 336 | * particular characteristics of the bucket we are | ||
| 337 | * consuming here. | ||
| 338 | */ | ||
| 339 | status = apr_bucket_read(b, &str, &str_len, block); | ||
| 340 | |||
| 341 | if (status != APR_SUCCESS) { | ||
| 342 | if (APR_STATUS_IS_EOF(status)) { | ||
| 343 | /* This stream bucket was consumed */ | ||
| 344 | apr_bucket_delete(b); | ||
| 345 | continue; | ||
| 346 | } | ||
| 347 | break; | ||
| 348 | } | ||
| 349 | |||
| 350 | if (str_len > 0) { | ||
| 351 | /* Do not block once some data has been consumed */ | ||
| 352 | block = APR_NONBLOCK_READ; | ||
| 353 | |||
| 354 | /* Assure we don't overflow. */ | ||
| 355 | consume = (str_len + actual > *len) ? *len - actual : str_len; | ||
| 356 | |||
| 357 | memcpy(c, str, consume); | ||
| 358 | |||
| 359 | c += consume; | ||
| 360 | actual += consume; | ||
| 361 | |||
| 362 | if (consume >= b->length) { | ||
| 363 | /* This physical bucket was consumed */ | ||
| 364 | apr_bucket_delete(b); | ||
| 365 | } | ||
| 366 | else { | ||
| 367 | /* Only part of this physical bucket was consumed */ | ||
| 368 | b->start += consume; | ||
| 369 | b->length -= consume; | ||
| 370 | } | ||
| 371 | } | ||
| 372 | else if (b->length == 0) { | ||
| 373 | apr_bucket_delete(b); | ||
| 374 | } | ||
| 375 | |||
| 376 | /* This could probably be actual == *len, but be safe from stray | ||
| 377 | * photons. */ | ||
| 378 | if (actual >= *len) { | ||
| 379 | break; | ||
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | *len = actual; | ||
| 384 | return status; | ||
| 385 | } | ||
| 386 | |||
| 387 | |||
| 388 | static ssize_t gnutls_transport_read(gnutls_transport_ptr_t ptr, | ||
| 389 | void *buffer, size_t len) | ||
| 390 | { | ||
| 391 | gnutls_handle_t *ctxt = ptr; | ||
| 392 | apr_status_t rc; | ||
| 393 | apr_size_t in = len; | ||
| 394 | /* If Len = 0, we don't do anything. */ | ||
| 395 | if (!len) | ||
| 396 | return 0; | ||
| 397 | |||
| 398 | if (APR_BRIGADE_EMPTY(ctxt->input_bb)) { | ||
| 399 | |||
| 400 | rc = ap_get_brigade(ctxt->input_filter->next, ctxt->input_bb, | ||
| 401 | AP_MODE_READBYTES, ctxt->input_block, in); | ||
| 402 | |||
| 403 | /* Not a problem, there was simply no data ready yet. | ||
| 404 | */ | ||
| 405 | if (APR_STATUS_IS_EAGAIN(rc) || APR_STATUS_IS_EINTR(rc) | ||
| 406 | || (rc == APR_SUCCESS && APR_BRIGADE_EMPTY(ctxt->input_bb))) { | ||
| 407 | return 0; | ||
| 408 | } | ||
| 409 | |||
| 410 | if (rc != APR_SUCCESS) { | ||
| 411 | /* Unexpected errors discard the brigade */ | ||
| 412 | apr_brigade_cleanup(ctxt->input_bb); | ||
| 413 | ctxt->input_bb = NULL; | ||
| 414 | return -1; | ||
| 415 | } | ||
| 416 | } | ||
| 417 | |||
| 418 | // brigade_consume(ctxt->input_bb, ctxt->input_block, buffer, &len); | ||
| 419 | |||
| 420 | |||
| 421 | ap_get_brigade(ctxt->input_filter->next, ctxt->input_bb, | ||
| 422 | AP_MODE_READBYTES, ctxt->input_block, len); | ||
| 423 | |||
| 424 | return len; | ||
| 425 | } | ||
| 426 | |||
| 427 | static ssize_t gnutls_transport_write(gnutls_transport_ptr_t ptr, | ||
| 428 | const void *buffer, size_t len) | ||
| 429 | { | ||
| 430 | gnutls_handle_t *ctxt = ptr; | ||
| 431 | |||
| 432 | // apr_bucket *bucket = apr_bucket_transient_create(in, inl, | ||
| 433 | // outctx->bb-> | ||
| 434 | // bucket_alloc); | ||
| 435 | |||
| 436 | // outctx->length += inl; | ||
| 437 | //APR_BRIGADE_INSERT_TAIL(outctx->bb, bucket); | ||
| 438 | return 0; | ||
| 439 | } | ||
| 440 | |||
| 441 | static int gnutls_hook_pre_connection(conn_rec * c, void *csd) | 113 | static int gnutls_hook_pre_connection(conn_rec * c, void *csd) |
| 442 | { | 114 | { |
| 443 | gnutls_handle_t *ctxt; | 115 | gnutls_handle_t *ctxt; |
| 444 | gnutls_srvconf_rec *sc = | 116 | gnutls_srvconf_rec *sc = |
| 445 | (gnutls_srvconf_rec *) ap_get_module_config(c->base_server-> | 117 | (gnutls_srvconf_rec *) ap_get_module_config(c->base_server-> |
| 446 | module_config, | 118 | module_config, |
| 447 | &gnutls_module); | 119 | &gnutls_module); |
| 448 | 120 | ||
| 449 | if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) { | 121 | if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) { |
| 450 | return DECLINED; | 122 | return DECLINED; |
| @@ -470,12 +142,14 @@ static int gnutls_hook_pre_connection(conn_rec * c, void *csd) | |||
| 470 | gnutls_certificate_server_set_request(ctxt->session, GNUTLS_CERT_IGNORE); | 142 | gnutls_certificate_server_set_request(ctxt->session, GNUTLS_CERT_IGNORE); |
| 471 | 143 | ||
| 472 | // gnutls_dh_set_prime_bits(ctxt->session, DH_BITS); | 144 | // gnutls_dh_set_prime_bits(ctxt->session, DH_BITS); |
| 473 | 145 | ||
| 474 | 146 | ||
| 475 | ap_set_module_config(c->conn_config, &gnutls_module, ctxt); | 147 | ap_set_module_config(c->conn_config, &gnutls_module, ctxt); |
| 476 | 148 | ||
| 477 | gnutls_transport_set_pull_function(ctxt->session, gnutls_transport_read); | 149 | gnutls_transport_set_pull_function(ctxt->session, |
| 478 | gnutls_transport_set_push_function(ctxt->session, gnutls_transport_write); | 150 | mod_gnutls_transport_read); |
| 151 | gnutls_transport_set_push_function(ctxt->session, | ||
| 152 | mod_gnutls_transport_write); | ||
| 479 | gnutls_transport_set_ptr(ctxt->session, ctxt); | 153 | gnutls_transport_set_ptr(ctxt->session, ctxt); |
| 480 | ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c); | 154 | ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c); |
| 481 | ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c); | 155 | ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c); |
| @@ -484,24 +158,24 @@ static int gnutls_hook_pre_connection(conn_rec * c, void *csd) | |||
| 484 | } | 158 | } |
| 485 | 159 | ||
| 486 | static const char *gnutls_set_cert_file(cmd_parms * parms, void *dummy, | 160 | static const char *gnutls_set_cert_file(cmd_parms * parms, void *dummy, |
| 487 | const char *arg) | 161 | const char *arg) |
| 488 | { | 162 | { |
| 489 | gnutls_srvconf_rec *sc = | 163 | gnutls_srvconf_rec *sc = |
| 490 | (gnutls_srvconf_rec *) ap_get_module_config(parms->server-> | 164 | (gnutls_srvconf_rec *) ap_get_module_config(parms->server-> |
| 491 | module_config, | 165 | module_config, |
| 492 | &gnutls_module); | 166 | &gnutls_module); |
| 493 | sc->cert_file = apr_pstrdup(parms->pool, arg); | 167 | sc->cert_file = apr_pstrdup(parms->pool, arg); |
| 494 | return NULL; | 168 | return NULL; |
| 495 | } | 169 | } |
| 496 | 170 | ||
| 497 | static const char *gnutls_set_key_file(cmd_parms * parms, void *dummy, | 171 | static const char *gnutls_set_key_file(cmd_parms * parms, void *dummy, |
| 498 | const char *arg) | 172 | const char *arg) |
| 499 | { | 173 | { |
| 500 | gnutls_srvconf_rec *sc = | 174 | gnutls_srvconf_rec *sc = |
| 501 | (gnutls_srvconf_rec *) ap_get_module_config(parms->server-> | 175 | (gnutls_srvconf_rec *) ap_get_module_config(parms->server-> |
| 502 | module_config, | 176 | module_config, |
| 503 | &gnutls_module); | 177 | &gnutls_module); |
| 504 | sc->key_file = apr_pstrdup(parms->pool, arg); | 178 | sc->key_file = apr_pstrdup(parms->pool, arg); |
| 505 | return NULL; | 179 | return NULL; |
| 506 | } | 180 | } |
| 507 | 181 | ||
| @@ -510,8 +184,8 @@ static const char *gnutls_set_enabled(cmd_parms * parms, void *dummy, | |||
| 510 | { | 184 | { |
| 511 | gnutls_srvconf_rec *sc = | 185 | gnutls_srvconf_rec *sc = |
| 512 | (gnutls_srvconf_rec *) ap_get_module_config(parms->server-> | 186 | (gnutls_srvconf_rec *) ap_get_module_config(parms->server-> |
| 513 | module_config, | 187 | module_config, |
| 514 | &gnutls_module); | 188 | &gnutls_module); |
| 515 | if (!strcasecmp(arg, "On")) { | 189 | if (!strcasecmp(arg, "On")) { |
| 516 | sc->enabled = GNUTLS_ENABLED_TRUE; | 190 | sc->enabled = GNUTLS_ENABLED_TRUE; |
| 517 | } | 191 | } |
| @@ -535,8 +209,8 @@ static const command_rec gnutls_cmds[] = { | |||
| 535 | RSRC_CONF, | 209 | RSRC_CONF, |
| 536 | "SSL Server Certificate file"), | 210 | "SSL Server Certificate file"), |
| 537 | AP_INIT_TAKE1("GnuTLSEnable", gnutls_set_enabled, | 211 | AP_INIT_TAKE1("GnuTLSEnable", gnutls_set_enabled, |
| 538 | NULL, RSRC_CONF, | 212 | NULL, RSRC_CONF, |
| 539 | "Whether this server has GnuTLS Enabled. Default: Off"), | 213 | "Whether this server has GnuTLS Enabled. Default: Off"), |
| 540 | 214 | ||
| 541 | {NULL} | 215 | {NULL} |
| 542 | }; | 216 | }; |
| @@ -562,10 +236,12 @@ static void gnutls_hooks(apr_pool_t * p) | |||
| 562 | /* ap_register_output_filter ("UPGRADE_FILTER", | 236 | /* ap_register_output_filter ("UPGRADE_FILTER", |
| 563 | * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); | 237 | * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); |
| 564 | */ | 238 | */ |
| 565 | ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, gnutls_filter_input, | 239 | ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, |
| 566 | NULL, AP_FTYPE_CONNECTION + 5); | 240 | mod_gnutls_filter_input, NULL, |
| 567 | ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, gnutls_filter_output, | 241 | AP_FTYPE_CONNECTION + 5); |
| 568 | NULL, AP_FTYPE_CONNECTION + 5); | 242 | ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, |
| 243 | mod_gnutls_filter_output, NULL, | ||
| 244 | AP_FTYPE_CONNECTION + 5); | ||
| 569 | } | 245 | } |
| 570 | 246 | ||
| 571 | static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s) | 247 | static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s) |
| @@ -574,7 +250,6 @@ static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s) | |||
| 574 | gnutls_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc)); | 250 | gnutls_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc)); |
| 575 | 251 | ||
| 576 | sc->enabled = GNUTLS_ENABLED_FALSE; | 252 | sc->enabled = GNUTLS_ENABLED_FALSE; |
| 577 | sc->non_https = 0; | ||
| 578 | 253 | ||
| 579 | gnutls_certificate_allocate_credentials(&sc->certs); | 254 | gnutls_certificate_allocate_credentials(&sc->certs); |
| 580 | gnutls_anon_allocate_server_credentials(&sc->anoncred); | 255 | gnutls_anon_allocate_server_credentials(&sc->anoncred); |
| @@ -586,7 +261,7 @@ static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s) | |||
| 586 | sc->ciphers[i++] = GNUTLS_CIPHER_ARCFOUR_128; | 261 | sc->ciphers[i++] = GNUTLS_CIPHER_ARCFOUR_128; |
| 587 | sc->ciphers[i++] = GNUTLS_CIPHER_3DES_CBC; | 262 | sc->ciphers[i++] = GNUTLS_CIPHER_3DES_CBC; |
| 588 | sc->ciphers[i++] = GNUTLS_CIPHER_ARCFOUR_40; | 263 | sc->ciphers[i++] = GNUTLS_CIPHER_ARCFOUR_40; |
| 589 | sc->ciphers[i] = 0; | 264 | sc->ciphers[i] = 0; |
| 590 | 265 | ||
| 591 | i = 0; | 266 | i = 0; |
| 592 | sc->key_exchange[i++] = GNUTLS_KX_RSA; | 267 | sc->key_exchange[i++] = GNUTLS_KX_RSA; |
