diff options
author | Paul Querna | 2005-04-24 22:21:50 +0000 |
---|---|---|
committer | Paul Querna | 2005-04-24 22:21:50 +0000 |
commit | c301152dbbdf13c4bf212c7982b948c21149468d (patch) | |
tree | 311447345aca9ee56f930428843aef6a7e48569d | |
parent | 46b85d8e3634f34c0142823d92b037dd33b67898 (diff) |
- move hooks to gnutls_hooks.c
- use 'mgs_' as the prefix for all symbols, instead of mixed prefixes.
-rw-r--r-- | include/mod_gnutls.h.in | 75 | ||||
-rw-r--r-- | mod_gnutls.xcode/project.pbxproj | 10 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/gnutls_cache.c | 40 | ||||
-rw-r--r-- | src/gnutls_config.c | 42 | ||||
-rw-r--r-- | src/gnutls_hooks.c | 654 | ||||
-rw-r--r-- | src/gnutls_io.c | 32 | ||||
-rw-r--r-- | src/mod_gnutls.c | 665 |
8 files changed, 788 insertions, 732 deletions
diff --git a/include/mod_gnutls.h.in b/include/mod_gnutls.h.in index 61b0198..b5a84c0 100644 --- a/include/mod_gnutls.h.in +++ b/include/mod_gnutls.h.in | |||
@@ -62,17 +62,17 @@ module AP_MODULE_DECLARE_DATA gnutls_module; | |||
62 | 62 | ||
63 | typedef enum | 63 | typedef enum |
64 | { | 64 | { |
65 | mod_gnutls_cache_none, | 65 | mgs_cache_none, |
66 | mod_gnutls_cache_dbm, | 66 | mgs_cache_dbm, |
67 | #if HAVE_APR_MEMCACHE | 67 | #if HAVE_APR_MEMCACHE |
68 | mod_gnutls_cache_memcache | 68 | mgs_cache_memcache |
69 | #endif | 69 | #endif |
70 | } mod_gnutls_cache_e; | 70 | } mgs_cache_e; |
71 | 71 | ||
72 | typedef struct | 72 | typedef struct |
73 | { | 73 | { |
74 | int client_verify_mode; | 74 | int client_verify_mode; |
75 | } mod_gnutls_dirconf_rec; | 75 | } mgs_dirconf_rec; |
76 | 76 | ||
77 | typedef struct | 77 | typedef struct |
78 | { | 78 | { |
@@ -88,21 +88,21 @@ typedef struct | |||
88 | int compression[16]; | 88 | int compression[16]; |
89 | int cert_types[16]; | 89 | int cert_types[16]; |
90 | apr_time_t cache_timeout; | 90 | apr_time_t cache_timeout; |
91 | mod_gnutls_cache_e cache_type; | 91 | mgs_cache_e cache_type; |
92 | const char* cache_config; | 92 | const char* cache_config; |
93 | const char* rsa_params_file; | 93 | const char* rsa_params_file; |
94 | const char* dh_params_file; | 94 | const char* dh_params_file; |
95 | int client_verify_mode; | 95 | int client_verify_mode; |
96 | } mod_gnutls_srvconf_rec; | 96 | } mgs_srvconf_rec; |
97 | 97 | ||
98 | typedef struct { | 98 | typedef struct { |
99 | int length; | 99 | int length; |
100 | char *value; | 100 | char *value; |
101 | } mod_gnutls_char_buffer_t; | 101 | } mgs_char_buffer_t; |
102 | 102 | ||
103 | typedef struct | 103 | typedef struct |
104 | { | 104 | { |
105 | mod_gnutls_srvconf_rec *sc; | 105 | mgs_srvconf_rec *sc; |
106 | conn_rec* c; | 106 | conn_rec* c; |
107 | gnutls_session_t session; | 107 | gnutls_session_t session; |
108 | 108 | ||
@@ -111,7 +111,7 @@ typedef struct | |||
111 | apr_bucket_brigade *input_bb; | 111 | apr_bucket_brigade *input_bb; |
112 | apr_read_type_e input_block; | 112 | apr_read_type_e input_block; |
113 | ap_input_mode_t input_mode; | 113 | ap_input_mode_t input_mode; |
114 | mod_gnutls_char_buffer_t input_cbuf; | 114 | mgs_char_buffer_t input_cbuf; |
115 | char input_buffer[AP_IOBUFSIZE]; | 115 | char input_buffer[AP_IOBUFSIZE]; |
116 | 116 | ||
117 | apr_status_t output_rc; | 117 | apr_status_t output_rc; |
@@ -123,12 +123,12 @@ typedef struct | |||
123 | 123 | ||
124 | int status; | 124 | int status; |
125 | int non_https; | 125 | int non_https; |
126 | } mod_gnutls_handle_t; | 126 | } mgs_handle_t; |
127 | 127 | ||
128 | /** Functions in gnutls_io.c **/ | 128 | /** Functions in gnutls_io.c **/ |
129 | 129 | ||
130 | /** | 130 | /** |
131 | * mod_gnutls_filter_input will filter the input data | 131 | * mgs_filter_input will filter the input data |
132 | * by decrypting it using GnuTLS and passes it cleartext. | 132 | * by decrypting it using GnuTLS and passes it cleartext. |
133 | * | 133 | * |
134 | * @param f the filter info record | 134 | * @param f the filter info record |
@@ -137,26 +137,26 @@ typedef struct | |||
137 | * @param block a block index we shall read from? | 137 | * @param block a block index we shall read from? |
138 | * @return result status | 138 | * @return result status |
139 | */ | 139 | */ |
140 | apr_status_t mod_gnutls_filter_input(ap_filter_t * f, | 140 | apr_status_t mgs_filter_input(ap_filter_t * f, |
141 | apr_bucket_brigade * bb, | 141 | apr_bucket_brigade * bb, |
142 | ap_input_mode_t mode, | 142 | ap_input_mode_t mode, |
143 | apr_read_type_e block, | 143 | apr_read_type_e block, |
144 | apr_off_t readbytes); | 144 | apr_off_t readbytes); |
145 | 145 | ||
146 | /** | 146 | /** |
147 | * mod_gnutls_filter_output will filter the encrypt | 147 | * mgs_filter_output will filter the encrypt |
148 | * the incoming bucket using GnuTLS and passes it onto the next filter. | 148 | * the incoming bucket using GnuTLS and passes it onto the next filter. |
149 | * | 149 | * |
150 | * @param f the filter info record | 150 | * @param f the filter info record |
151 | * @param bb the bucket brigade, where to store the result to | 151 | * @param bb the bucket brigade, where to store the result to |
152 | * @return result status | 152 | * @return result status |
153 | */ | 153 | */ |
154 | apr_status_t mod_gnutls_filter_output(ap_filter_t * f, | 154 | apr_status_t mgs_filter_output(ap_filter_t * f, |
155 | apr_bucket_brigade * bb); | 155 | apr_bucket_brigade * bb); |
156 | 156 | ||
157 | 157 | ||
158 | /** | 158 | /** |
159 | * mod_gnutls_transport_read is called from GnuTLS to provide encrypted | 159 | * mgs_transport_read is called from GnuTLS to provide encrypted |
160 | * data from the client. | 160 | * data from the client. |
161 | * | 161 | * |
162 | * @param ptr pointer to the filter context | 162 | * @param ptr pointer to the filter context |
@@ -164,11 +164,11 @@ apr_status_t mod_gnutls_filter_output(ap_filter_t * f, | |||
164 | * @param len maximum size | 164 | * @param len maximum size |
165 | * @return size length of the data stored in buffer | 165 | * @return size length of the data stored in buffer |
166 | */ | 166 | */ |
167 | ssize_t mod_gnutls_transport_read(gnutls_transport_ptr_t ptr, | 167 | ssize_t mgs_transport_read(gnutls_transport_ptr_t ptr, |
168 | void *buffer, size_t len); | 168 | void *buffer, size_t len); |
169 | 169 | ||
170 | /** | 170 | /** |
171 | * mod_gnutls_transport_write is called from GnuTLS to | 171 | * mgs_transport_write is called from GnuTLS to |
172 | * write data to the client. | 172 | * write data to the client. |
173 | * | 173 | * |
174 | * @param ptr pointer to the filter context | 174 | * @param ptr pointer to the filter context |
@@ -176,28 +176,28 @@ ssize_t mod_gnutls_transport_read(gnutls_transport_ptr_t ptr, | |||
176 | * @param len size of the buffer | 176 | * @param len size of the buffer |
177 | * @return size length of the data written | 177 | * @return size length of the data written |
178 | */ | 178 | */ |
179 | ssize_t mod_gnutls_transport_write(gnutls_transport_ptr_t ptr, | 179 | ssize_t mgs_transport_write(gnutls_transport_ptr_t ptr, |
180 | const void *buffer, size_t len); | 180 | const void *buffer, size_t len); |
181 | 181 | ||
182 | 182 | ||
183 | int mod_gnutls_rehandshake(mod_gnutls_handle_t * ctxt); | 183 | int mgs_rehandshake(mgs_handle_t * ctxt); |
184 | 184 | ||
185 | 185 | ||
186 | 186 | ||
187 | /** | 187 | /** |
188 | * Init the Cache after Configuration is done | 188 | * Init the Cache after Configuration is done |
189 | */ | 189 | */ |
190 | int mod_gnutls_cache_post_config(apr_pool_t *p, server_rec *s, | 190 | int mgs_cache_post_config(apr_pool_t *p, server_rec *s, |
191 | mod_gnutls_srvconf_rec *sc); | 191 | mgs_srvconf_rec *sc); |
192 | /** | 192 | /** |
193 | * Init the Cache inside each Process | 193 | * Init the Cache inside each Process |
194 | */ | 194 | */ |
195 | int mod_gnutls_cache_child_init(apr_pool_t *p, server_rec *s, | 195 | int mgs_cache_child_init(apr_pool_t *p, server_rec *s, |
196 | mod_gnutls_srvconf_rec *sc); | 196 | mgs_srvconf_rec *sc); |
197 | /** | 197 | /** |
198 | * Setup the Session Caching | 198 | * Setup the Session Caching |
199 | */ | 199 | */ |
200 | int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt); | 200 | int mgs_cache_session_init(mgs_handle_t *ctxt); |
201 | 201 | ||
202 | #define GNUTLS_SESSION_ID_STRING_LEN \ | 202 | #define GNUTLS_SESSION_ID_STRING_LEN \ |
203 | ((GNUTLS_MAX_SESSION_ID + 1) * 2) | 203 | ((GNUTLS_MAX_SESSION_ID + 1) * 2) |
@@ -209,9 +209,10 @@ int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt); | |||
209 | * @param str Location to store the Hex Encoded String | 209 | * @param str Location to store the Hex Encoded String |
210 | * @param strsize The Maximum Length that can be stored in str | 210 | * @param strsize The Maximum Length that can be stored in str |
211 | */ | 211 | */ |
212 | char *mod_gnutls_session_id2sz(unsigned char *id, int idlen, | 212 | char *mgs_session_id2sz(unsigned char *id, int idlen, |
213 | char *str, int strsize); | 213 | char *str, int strsize); |
214 | 214 | ||
215 | |||
215 | /* Configuration Functions */ | 216 | /* Configuration Functions */ |
216 | 217 | ||
217 | const char *mgs_set_cert_file(cmd_parms * parms, void *dummy, | 218 | const char *mgs_set_cert_file(cmd_parms * parms, void *dummy, |
@@ -239,4 +240,26 @@ void *mgs_config_server_create(apr_pool_t * p, server_rec * s); | |||
239 | 240 | ||
240 | void *mgs_config_dir_create(apr_pool_t *p, char *dir); | 241 | void *mgs_config_dir_create(apr_pool_t *p, char *dir); |
241 | 242 | ||
243 | |||
244 | /* mod_gnutls Hooks. */ | ||
245 | |||
246 | int mgs_hook_pre_config(apr_pool_t * pconf, | ||
247 | apr_pool_t * plog, apr_pool_t * ptemp); | ||
248 | |||
249 | int mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | ||
250 | apr_pool_t * ptemp, | ||
251 | server_rec * base_server); | ||
252 | |||
253 | void mgs_hook_child_init(apr_pool_t *p, server_rec *s); | ||
254 | |||
255 | const char *mgs_hook_http_scheme(const request_rec * r); | ||
256 | |||
257 | apr_port_t mgs_hook_default_port(const request_rec * r); | ||
258 | |||
259 | int mgs_hook_pre_connection(conn_rec * c, void *csd); | ||
260 | |||
261 | int mgs_hook_fixups(request_rec *r); | ||
262 | |||
263 | int mgs_hook_authz(request_rec *r); | ||
264 | |||
242 | #endif /* __mod_gnutls_h_inc */ | 265 | #endif /* __mod_gnutls_h_inc */ |
diff --git a/mod_gnutls.xcode/project.pbxproj b/mod_gnutls.xcode/project.pbxproj index fd24bb2..08b50e1 100644 --- a/mod_gnutls.xcode/project.pbxproj +++ b/mod_gnutls.xcode/project.pbxproj | |||
@@ -14,9 +14,19 @@ | |||
14 | refType = 2; | 14 | refType = 2; |
15 | sourceTree = SOURCE_ROOT; | 15 | sourceTree = SOURCE_ROOT; |
16 | }; | 16 | }; |
17 | 4541F3C5081C4F2B007457C1 = { | ||
18 | fileEncoding = 30; | ||
19 | isa = PBXFileReference; | ||
20 | lastKnownFileType = sourcecode.c.c; | ||
21 | name = gnutls_hooks.c; | ||
22 | path = src/gnutls_hooks.c; | ||
23 | refType = 2; | ||
24 | sourceTree = SOURCE_ROOT; | ||
25 | }; | ||
17 | 45B624630802F1E200CBFD9A = { | 26 | 45B624630802F1E200CBFD9A = { |
18 | children = ( | 27 | children = ( |
19 | 4541F3BA081C4B1A007457C1, | 28 | 4541F3BA081C4B1A007457C1, |
29 | 4541F3C5081C4F2B007457C1, | ||
20 | 45B6246D0802F20D00CBFD9A, | 30 | 45B6246D0802F20D00CBFD9A, |
21 | 45B6247D0802F85B00CBFD9A, | 31 | 45B6247D0802F85B00CBFD9A, |
22 | 45B6247A0802F84500CBFD9A, | 32 | 45B6247A0802F84500CBFD9A, |
diff --git a/src/Makefile.am b/src/Makefile.am index a15fc57..c6d42c9 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 gnutls_io.c gnutls_cache.c gnutls_config.c | 3 | libmod_gnutls_la_SOURCES = mod_gnutls.c gnutls_io.c gnutls_cache.c gnutls_config.c gnutls_hooks.c |
4 | libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} | 4 | libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} |
5 | libmod_gnutls_la_LDFLAGS = -rpath ${AP_LIBEXECDIR} -module -avoid-version ${MODULE_LIBS} | 5 | libmod_gnutls_la_LDFLAGS = -rpath ${AP_LIBEXECDIR} -module -avoid-version ${MODULE_LIBS} |
6 | 6 | ||
diff --git a/src/gnutls_cache.c b/src/gnutls_cache.c index 8499b84..4c094fa 100644 --- a/src/gnutls_cache.c +++ b/src/gnutls_cache.c | |||
@@ -53,7 +53,7 @@ static char *gnutls_session_id2sz(unsigned char *id, int idlen, | |||
53 | return str; | 53 | return str; |
54 | } | 54 | } |
55 | 55 | ||
56 | char *mod_gnutls_session_id2sz(unsigned char *id, int idlen, | 56 | char *mgs_session_id2sz(unsigned char *id, int idlen, |
57 | char *str, int strsize) | 57 | char *str, int strsize) |
58 | { | 58 | { |
59 | char *cp; | 59 | char *cp; |
@@ -80,7 +80,7 @@ char *mod_gnutls_session_id2sz(unsigned char *id, int idlen, | |||
80 | static apr_memcache_t* mc; | 80 | static apr_memcache_t* mc; |
81 | 81 | ||
82 | static int mc_cache_child_init(apr_pool_t *p, server_rec *s, | 82 | static int mc_cache_child_init(apr_pool_t *p, server_rec *s, |
83 | mod_gnutls_srvconf_rec *sc) | 83 | mgs_srvconf_rec *sc) |
84 | { | 84 | { |
85 | apr_status_t rv = APR_SUCCESS; | 85 | apr_status_t rv = APR_SUCCESS; |
86 | int thread_limit = 0; | 86 | int thread_limit = 0; |
@@ -166,7 +166,7 @@ static int mc_cache_store(void* baton, gnutls_datum_t key, | |||
166 | gnutls_datum_t data) | 166 | gnutls_datum_t data) |
167 | { | 167 | { |
168 | apr_status_t rv = APR_SUCCESS; | 168 | apr_status_t rv = APR_SUCCESS; |
169 | mod_gnutls_handle_t *ctxt = baton; | 169 | mgs_handle_t *ctxt = baton; |
170 | char buf[STR_SESSION_LEN]; | 170 | char buf[STR_SESSION_LEN]; |
171 | char* strkey = NULL; | 171 | char* strkey = NULL; |
172 | apr_uint32_t timeout; | 172 | apr_uint32_t timeout; |
@@ -193,7 +193,7 @@ static int mc_cache_store(void* baton, gnutls_datum_t key, | |||
193 | static gnutls_datum_t mc_cache_fetch(void* baton, gnutls_datum_t key) | 193 | static gnutls_datum_t mc_cache_fetch(void* baton, gnutls_datum_t key) |
194 | { | 194 | { |
195 | apr_status_t rv = APR_SUCCESS; | 195 | apr_status_t rv = APR_SUCCESS; |
196 | mod_gnutls_handle_t *ctxt = baton; | 196 | mgs_handle_t *ctxt = baton; |
197 | char buf[STR_SESSION_LEN]; | 197 | char buf[STR_SESSION_LEN]; |
198 | char* strkey = NULL; | 198 | char* strkey = NULL; |
199 | char* value; | 199 | char* value; |
@@ -234,7 +234,7 @@ static gnutls_datum_t mc_cache_fetch(void* baton, gnutls_datum_t key) | |||
234 | static int mc_cache_delete(void* baton, gnutls_datum_t key) | 234 | static int mc_cache_delete(void* baton, gnutls_datum_t key) |
235 | { | 235 | { |
236 | apr_status_t rv = APR_SUCCESS; | 236 | apr_status_t rv = APR_SUCCESS; |
237 | mod_gnutls_handle_t *ctxt = baton; | 237 | mgs_handle_t *ctxt = baton; |
238 | char buf[STR_SESSION_LEN]; | 238 | char buf[STR_SESSION_LEN]; |
239 | char* strkey = NULL; | 239 | char* strkey = NULL; |
240 | 240 | ||
@@ -259,7 +259,7 @@ static int mc_cache_delete(void* baton, gnutls_datum_t key) | |||
259 | 259 | ||
260 | #define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD ) | 260 | #define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD ) |
261 | 261 | ||
262 | static int dbm_cache_expire(mod_gnutls_handle_t *ctxt) | 262 | static int dbm_cache_expire(mgs_handle_t *ctxt) |
263 | { | 263 | { |
264 | apr_status_t rv; | 264 | apr_status_t rv; |
265 | apr_dbm_t *dbm; | 265 | apr_dbm_t *dbm; |
@@ -346,7 +346,7 @@ static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key) | |||
346 | apr_dbm_t *dbm; | 346 | apr_dbm_t *dbm; |
347 | apr_datum_t dbmkey; | 347 | apr_datum_t dbmkey; |
348 | apr_datum_t dbmval; | 348 | apr_datum_t dbmval; |
349 | mod_gnutls_handle_t *ctxt = baton; | 349 | mgs_handle_t *ctxt = baton; |
350 | apr_status_t rv; | 350 | apr_status_t rv; |
351 | 351 | ||
352 | dbmkey.dptr = key.data; | 352 | dbmkey.dptr = key.data; |
@@ -395,7 +395,7 @@ static int dbm_cache_store(void* baton, gnutls_datum_t key, | |||
395 | apr_dbm_t *dbm; | 395 | apr_dbm_t *dbm; |
396 | apr_datum_t dbmkey; | 396 | apr_datum_t dbmkey; |
397 | apr_datum_t dbmval; | 397 | apr_datum_t dbmval; |
398 | mod_gnutls_handle_t *ctxt = baton; | 398 | mgs_handle_t *ctxt = baton; |
399 | apr_status_t rv; | 399 | apr_status_t rv; |
400 | apr_time_t expiry; | 400 | apr_time_t expiry; |
401 | 401 | ||
@@ -448,7 +448,7 @@ static int dbm_cache_delete(void* baton, gnutls_datum_t key) | |||
448 | { | 448 | { |
449 | apr_dbm_t *dbm; | 449 | apr_dbm_t *dbm; |
450 | apr_datum_t dbmkey; | 450 | apr_datum_t dbmkey; |
451 | mod_gnutls_handle_t *ctxt = baton; | 451 | mgs_handle_t *ctxt = baton; |
452 | apr_status_t rv; | 452 | apr_status_t rv; |
453 | 453 | ||
454 | dbmkey.dptr = (char *)key.data; | 454 | dbmkey.dptr = (char *)key.data; |
@@ -483,7 +483,7 @@ static int dbm_cache_delete(void* baton, gnutls_datum_t key) | |||
483 | } | 483 | } |
484 | 484 | ||
485 | static int dbm_cache_post_config(apr_pool_t *p, server_rec *s, | 485 | static int dbm_cache_post_config(apr_pool_t *p, server_rec *s, |
486 | mod_gnutls_srvconf_rec *sc) | 486 | mgs_srvconf_rec *sc) |
487 | { | 487 | { |
488 | apr_status_t rv; | 488 | apr_status_t rv; |
489 | apr_dbm_t *dbm; | 489 | apr_dbm_t *dbm; |
@@ -518,23 +518,23 @@ static int dbm_cache_post_config(apr_pool_t *p, server_rec *s, | |||
518 | return rv; | 518 | return rv; |
519 | } | 519 | } |
520 | 520 | ||
521 | int mod_gnutls_cache_post_config(apr_pool_t *p, server_rec *s, | 521 | int mgs_cache_post_config(apr_pool_t *p, server_rec *s, |
522 | mod_gnutls_srvconf_rec *sc) | 522 | mgs_srvconf_rec *sc) |
523 | { | 523 | { |
524 | if (sc->cache_type == mod_gnutls_cache_dbm) { | 524 | if (sc->cache_type == mgs_cache_dbm) { |
525 | return dbm_cache_post_config(p, s, sc); | 525 | return dbm_cache_post_config(p, s, sc); |
526 | } | 526 | } |
527 | return 0; | 527 | return 0; |
528 | } | 528 | } |
529 | 529 | ||
530 | int mod_gnutls_cache_child_init(apr_pool_t *p, server_rec *s, | 530 | int mgs_cache_child_init(apr_pool_t *p, server_rec *s, |
531 | mod_gnutls_srvconf_rec *sc) | 531 | mgs_srvconf_rec *sc) |
532 | { | 532 | { |
533 | if (sc->cache_type == mod_gnutls_cache_dbm) { | 533 | if (sc->cache_type == mgs_cache_dbm) { |
534 | return 0; | 534 | return 0; |
535 | } | 535 | } |
536 | #if HAVE_APR_MEMCACHE | 536 | #if HAVE_APR_MEMCACHE |
537 | else if (sc->cache_type == mod_gnutls_cache_memcache) { | 537 | else if (sc->cache_type == mgs_cache_memcache) { |
538 | return mc_cache_child_init(p, s, sc); | 538 | return mc_cache_child_init(p, s, sc); |
539 | } | 539 | } |
540 | #endif | 540 | #endif |
@@ -543,16 +543,16 @@ int mod_gnutls_cache_child_init(apr_pool_t *p, server_rec *s, | |||
543 | 543 | ||
544 | #include <assert.h> | 544 | #include <assert.h> |
545 | 545 | ||
546 | int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt) | 546 | int mgs_cache_session_init(mgs_handle_t *ctxt) |
547 | { | 547 | { |
548 | if (ctxt->sc->cache_type == mod_gnutls_cache_dbm) { | 548 | if (ctxt->sc->cache_type == mgs_cache_dbm) { |
549 | gnutls_db_set_retrieve_function(ctxt->session, dbm_cache_fetch); | 549 | gnutls_db_set_retrieve_function(ctxt->session, dbm_cache_fetch); |
550 | gnutls_db_set_remove_function(ctxt->session, dbm_cache_delete); | 550 | gnutls_db_set_remove_function(ctxt->session, dbm_cache_delete); |
551 | gnutls_db_set_store_function(ctxt->session, dbm_cache_store); | 551 | gnutls_db_set_store_function(ctxt->session, dbm_cache_store); |
552 | gnutls_db_set_ptr(ctxt->session, ctxt); | 552 | gnutls_db_set_ptr(ctxt->session, ctxt); |
553 | } | 553 | } |
554 | #if HAVE_APR_MEMCACHE | 554 | #if HAVE_APR_MEMCACHE |
555 | else if (ctxt->sc->cache_type == mod_gnutls_cache_memcache) { | 555 | else if (ctxt->sc->cache_type == mgs_cache_memcache) { |
556 | gnutls_db_set_retrieve_function(ctxt->session, mc_cache_fetch); | 556 | gnutls_db_set_retrieve_function(ctxt->session, mc_cache_fetch); |
557 | gnutls_db_set_remove_function(ctxt->session, mc_cache_delete); | 557 | gnutls_db_set_remove_function(ctxt->session, mc_cache_delete); |
558 | gnutls_db_set_store_function(ctxt->session, mc_cache_store); | 558 | gnutls_db_set_store_function(ctxt->session, mc_cache_store); |
diff --git a/src/gnutls_config.c b/src/gnutls_config.c index 2c29ccb..f9a315c 100644 --- a/src/gnutls_config.c +++ b/src/gnutls_config.c | |||
@@ -59,8 +59,8 @@ const char *mgs_set_cert_file(cmd_parms * parms, void *dummy, | |||
59 | gnutls_datum_t data; | 59 | gnutls_datum_t data; |
60 | const char* file; | 60 | const char* file; |
61 | apr_pool_t* spool; | 61 | apr_pool_t* spool; |
62 | mod_gnutls_srvconf_rec *sc = | 62 | mgs_srvconf_rec *sc = |
63 | (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server-> | 63 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
64 | module_config, | 64 | module_config, |
65 | &gnutls_module); | 65 | &gnutls_module); |
66 | apr_pool_create(&spool, parms->pool); | 66 | apr_pool_create(&spool, parms->pool); |
@@ -91,8 +91,8 @@ const char *mgs_set_key_file(cmd_parms * parms, void *dummy, | |||
91 | gnutls_datum_t data; | 91 | gnutls_datum_t data; |
92 | const char* file; | 92 | const char* file; |
93 | apr_pool_t* spool; | 93 | apr_pool_t* spool; |
94 | mod_gnutls_srvconf_rec *sc = | 94 | mgs_srvconf_rec *sc = |
95 | (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server-> | 95 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
96 | module_config, | 96 | module_config, |
97 | &gnutls_module); | 97 | &gnutls_module); |
98 | apr_pool_create(&spool, parms->pool); | 98 | apr_pool_create(&spool, parms->pool); |
@@ -119,7 +119,7 @@ const char *mgs_set_cache(cmd_parms * parms, void *dummy, | |||
119 | const char *type, const char* arg) | 119 | const char *type, const char* arg) |
120 | { | 120 | { |
121 | const char* err; | 121 | const char* err; |
122 | mod_gnutls_srvconf_rec *sc = ap_get_module_config(parms->server-> | 122 | mgs_srvconf_rec *sc = ap_get_module_config(parms->server-> |
123 | module_config, | 123 | module_config, |
124 | &gnutls_module); | 124 | &gnutls_module); |
125 | if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) { | 125 | if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) { |
@@ -127,21 +127,21 @@ const char *mgs_set_cache(cmd_parms * parms, void *dummy, | |||
127 | } | 127 | } |
128 | 128 | ||
129 | if (strcasecmp("none", type) == 0) { | 129 | if (strcasecmp("none", type) == 0) { |
130 | sc->cache_type = mod_gnutls_cache_none; | 130 | sc->cache_type = mgs_cache_none; |
131 | } | 131 | } |
132 | else if (strcasecmp("dbm", type) == 0) { | 132 | else if (strcasecmp("dbm", type) == 0) { |
133 | sc->cache_type = mod_gnutls_cache_dbm; | 133 | sc->cache_type = mgs_cache_dbm; |
134 | } | 134 | } |
135 | #if HAVE_APR_MEMCACHE | 135 | #if HAVE_APR_MEMCACHE |
136 | else if (strcasecmp("memcache", type) == 0) { | 136 | else if (strcasecmp("memcache", type) == 0) { |
137 | sc->cache_type = mod_gnutls_cache_memcache; | 137 | sc->cache_type = mgs_cache_memcache; |
138 | } | 138 | } |
139 | #endif | 139 | #endif |
140 | else { | 140 | else { |
141 | return "Invalid Type for GnuTLSCache!"; | 141 | return "Invalid Type for GnuTLSCache!"; |
142 | } | 142 | } |
143 | 143 | ||
144 | if (sc->cache_type == mod_gnutls_cache_dbm) { | 144 | if (sc->cache_type == mgs_cache_dbm) { |
145 | sc->cache_config = ap_server_root_relative(parms->pool, arg); | 145 | sc->cache_config = ap_server_root_relative(parms->pool, arg); |
146 | } | 146 | } |
147 | else { | 147 | else { |
@@ -155,8 +155,8 @@ const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy, | |||
155 | const char *arg) | 155 | const char *arg) |
156 | { | 156 | { |
157 | int argint; | 157 | int argint; |
158 | mod_gnutls_srvconf_rec *sc = | 158 | mgs_srvconf_rec *sc = |
159 | (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server-> | 159 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
160 | module_config, | 160 | module_config, |
161 | &gnutls_module); | 161 | &gnutls_module); |
162 | 162 | ||
@@ -195,12 +195,12 @@ const char *mgs_set_client_verify(cmd_parms * parms, void *dummy, | |||
195 | 195 | ||
196 | /* This was set from a directory context */ | 196 | /* This was set from a directory context */ |
197 | if (parms->path) { | 197 | if (parms->path) { |
198 | mod_gnutls_dirconf_rec *dc = (mod_gnutls_dirconf_rec *)dummy; | 198 | mgs_dirconf_rec *dc = (mgs_dirconf_rec *)dummy; |
199 | dc->client_verify_mode = mode; | 199 | dc->client_verify_mode = mode; |
200 | } | 200 | } |
201 | else { | 201 | else { |
202 | mod_gnutls_srvconf_rec *sc = | 202 | mgs_srvconf_rec *sc = |
203 | (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server-> | 203 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
204 | module_config, | 204 | module_config, |
205 | &gnutls_module); | 205 | &gnutls_module); |
206 | sc->client_verify_mode = mode; | 206 | sc->client_verify_mode = mode; |
@@ -214,8 +214,8 @@ const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy, | |||
214 | { | 214 | { |
215 | int rv; | 215 | int rv; |
216 | const char* file; | 216 | const char* file; |
217 | mod_gnutls_srvconf_rec *sc = | 217 | mgs_srvconf_rec *sc = |
218 | (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server-> | 218 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
219 | module_config, | 219 | module_config, |
220 | &gnutls_module); | 220 | &gnutls_module); |
221 | file = ap_server_root_relative(parms->pool, arg); | 221 | file = ap_server_root_relative(parms->pool, arg); |
@@ -233,8 +233,8 @@ const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy, | |||
233 | const char *mgs_set_enabled(cmd_parms * parms, void *dummy, | 233 | const char *mgs_set_enabled(cmd_parms * parms, void *dummy, |
234 | const char *arg) | 234 | const char *arg) |
235 | { | 235 | { |
236 | mod_gnutls_srvconf_rec *sc = | 236 | mgs_srvconf_rec *sc = |
237 | (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server-> | 237 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
238 | module_config, | 238 | module_config, |
239 | &gnutls_module); | 239 | &gnutls_module); |
240 | if (!strcasecmp(arg, "On")) { | 240 | if (!strcasecmp(arg, "On")) { |
@@ -253,7 +253,7 @@ const char *mgs_set_enabled(cmd_parms * parms, void *dummy, | |||
253 | void *mgs_config_server_create(apr_pool_t * p, server_rec * s) | 253 | void *mgs_config_server_create(apr_pool_t * p, server_rec * s) |
254 | { | 254 | { |
255 | int i; | 255 | int i; |
256 | mod_gnutls_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc)); | 256 | mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc)); |
257 | 257 | ||
258 | sc->enabled = GNUTLS_ENABLED_FALSE; | 258 | sc->enabled = GNUTLS_ENABLED_FALSE; |
259 | 259 | ||
@@ -261,7 +261,7 @@ void *mgs_config_server_create(apr_pool_t * p, server_rec * s) | |||
261 | sc->privkey_x509 = NULL; | 261 | sc->privkey_x509 = NULL; |
262 | sc->cert_x509 = NULL; | 262 | sc->cert_x509 = NULL; |
263 | sc->cache_timeout = apr_time_from_sec(300); | 263 | sc->cache_timeout = apr_time_from_sec(300); |
264 | sc->cache_type = mod_gnutls_cache_dbm; | 264 | sc->cache_type = mgs_cache_dbm; |
265 | sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache"); | 265 | sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache"); |
266 | 266 | ||
267 | /* TODO: Make this Configurable. But it isn't configurable in mod_ssl? */ | 267 | /* TODO: Make this Configurable. But it isn't configurable in mod_ssl? */ |
@@ -319,7 +319,7 @@ void *mgs_config_server_create(apr_pool_t * p, server_rec * s) | |||
319 | 319 | ||
320 | void *mgs_config_dir_create(apr_pool_t *p, char *dir) | 320 | void *mgs_config_dir_create(apr_pool_t *p, char *dir) |
321 | { | 321 | { |
322 | mod_gnutls_dirconf_rec *dc = apr_palloc(p, sizeof(*dc)); | 322 | mgs_dirconf_rec *dc = apr_palloc(p, sizeof(*dc)); |
323 | 323 | ||
324 | dc->client_verify_mode = -1; | 324 | dc->client_verify_mode = -1; |
325 | 325 | ||
diff --git a/src/gnutls_hooks.c b/src/gnutls_hooks.c new file mode 100644 index 0000000..5429d66 --- /dev/null +++ b/src/gnutls_hooks.c | |||
@@ -0,0 +1,654 @@ | |||
1 | /** | ||
2 | * Copyright 2004-2005 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 | #include "http_vhost.h" | ||
20 | |||
21 | #if !USING_2_1_RECENT | ||
22 | extern server_rec *ap_server_conf; | ||
23 | #endif | ||
24 | |||
25 | #if APR_HAS_THREADS | ||
26 | GCRY_THREAD_OPTION_PTHREAD_IMPL; | ||
27 | #endif | ||
28 | |||
29 | #if MOD_GNUTLS_DEBUG | ||
30 | static apr_file_t* debug_log_fp; | ||
31 | #endif | ||
32 | |||
33 | static apr_status_t mgs_cleanup_pre_config(void *data) | ||
34 | { | ||
35 | gnutls_global_deinit(); | ||
36 | return APR_SUCCESS; | ||
37 | } | ||
38 | |||
39 | #if MOD_GNUTLS_DEBUG | ||
40 | static void gnutls_debug_log_all( int level, const char* str) | ||
41 | { | ||
42 | apr_file_printf(debug_log_fp, "<%d> %s\n", level, str); | ||
43 | } | ||
44 | #endif | ||
45 | |||
46 | int mgs_hook_pre_config(apr_pool_t * pconf, | ||
47 | apr_pool_t * plog, apr_pool_t * ptemp) | ||
48 | { | ||
49 | |||
50 | #if APR_HAS_THREADS | ||
51 | /* TODO: Check MPM Type here */ | ||
52 | gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); | ||
53 | #endif | ||
54 | |||
55 | gnutls_global_init(); | ||
56 | |||
57 | apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, | ||
58 | apr_pool_cleanup_null); | ||
59 | |||
60 | #if MOD_GNUTLS_DEBUG | ||
61 | apr_file_open(&debug_log_fp, "/tmp/gnutls_debug", | ||
62 | APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT, pconf); | ||
63 | |||
64 | gnutls_global_set_log_level(9); | ||
65 | gnutls_global_set_log_function(gnutls_debug_log_all); | ||
66 | #endif | ||
67 | |||
68 | return OK; | ||
69 | } | ||
70 | |||
71 | |||
72 | static gnutls_datum load_params(const char* file, server_rec* s, | ||
73 | apr_pool_t* pool) | ||
74 | { | ||
75 | gnutls_datum ret = { NULL, 0 }; | ||
76 | apr_file_t* fp; | ||
77 | apr_finfo_t finfo; | ||
78 | apr_status_t rv; | ||
79 | apr_size_t br = 0; | ||
80 | |||
81 | rv = apr_file_open(&fp, file, APR_READ|APR_BINARY, APR_OS_DEFAULT, | ||
82 | pool); | ||
83 | if (rv != APR_SUCCESS) { | ||
84 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, | ||
85 | "GnuTLS failed to load params file at: %s", file); | ||
86 | return ret; | ||
87 | } | ||
88 | |||
89 | rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp); | ||
90 | |||
91 | if (rv != APR_SUCCESS) { | ||
92 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, | ||
93 | "GnuTLS failed to stat params file at: %s", file); | ||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | ret.data = apr_palloc(pool, finfo.size+1); | ||
98 | rv = apr_file_read_full(fp, ret.data, finfo.size, &br); | ||
99 | |||
100 | if (rv != APR_SUCCESS) { | ||
101 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, | ||
102 | "GnuTLS failed to read params file at: %s", file); | ||
103 | return ret; | ||
104 | } | ||
105 | apr_file_close(fp); | ||
106 | ret.data[br] = '\0'; | ||
107 | ret.size = br; | ||
108 | |||
109 | return ret; | ||
110 | } | ||
111 | |||
112 | int mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | ||
113 | apr_pool_t * ptemp, | ||
114 | server_rec * base_server) | ||
115 | { | ||
116 | int rv; | ||
117 | int data_len; | ||
118 | server_rec *s; | ||
119 | gnutls_dh_params_t dh_params; | ||
120 | gnutls_rsa_params_t rsa_params; | ||
121 | mgs_srvconf_rec *sc; | ||
122 | mgs_srvconf_rec *sc_base; | ||
123 | void *data = NULL; | ||
124 | int first_run = 0; | ||
125 | const char *userdata_key = "mgs_init"; | ||
126 | |||
127 | apr_pool_userdata_get(&data, userdata_key, base_server->process->pool); | ||
128 | if (data == NULL) { | ||
129 | first_run = 1; | ||
130 | apr_pool_userdata_set((const void *)1, userdata_key, | ||
131 | apr_pool_cleanup_null, | ||
132 | base_server->process->pool); | ||
133 | } | ||
134 | |||
135 | |||
136 | { | ||
137 | gnutls_datum pdata; | ||
138 | apr_pool_t* tpool; | ||
139 | s = base_server; | ||
140 | sc_base = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, | ||
141 | &gnutls_module); | ||
142 | |||
143 | apr_pool_create(&tpool, p); | ||
144 | |||
145 | gnutls_dh_params_init(&dh_params); | ||
146 | |||
147 | pdata = load_params(sc_base->dh_params_file, s, tpool); | ||
148 | |||
149 | if (pdata.size != 0) { | ||
150 | rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, | ||
151 | GNUTLS_X509_FMT_PEM); | ||
152 | if (rv != 0) { | ||
153 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
154 | "GnuTLS: Unable to load DH Params: (%d) %s", | ||
155 | rv, gnutls_strerror(rv)); | ||
156 | exit(rv); | ||
157 | } | ||
158 | } | ||
159 | else { | ||
160 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
161 | "GnuTLS: Unable to load DH Params." | ||
162 | " Shutting Down."); | ||
163 | exit(-1); | ||
164 | } | ||
165 | apr_pool_clear(tpool); | ||
166 | |||
167 | gnutls_rsa_params_init(&rsa_params); | ||
168 | |||
169 | pdata = load_params(sc_base->rsa_params_file, s, tpool); | ||
170 | |||
171 | if (pdata.size != 0) { | ||
172 | rv = gnutls_rsa_params_import_pkcs1(rsa_params, &pdata, | ||
173 | GNUTLS_X509_FMT_PEM); | ||
174 | if (rv != 0) { | ||
175 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
176 | "GnuTLS: Unable to load RSA Params: (%d) %s", | ||
177 | rv, gnutls_strerror(rv)); | ||
178 | exit(rv); | ||
179 | } | ||
180 | } | ||
181 | else { | ||
182 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
183 | "GnuTLS: Unable to load RSA Params." | ||
184 | " Shutting Down."); | ||
185 | exit(-1); | ||
186 | } | ||
187 | |||
188 | apr_pool_destroy(tpool); | ||
189 | rv = mgs_cache_post_config(p, s, sc_base); | ||
190 | if (rv != 0) { | ||
191 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, | ||
192 | "GnuTLS: Post Config for GnuTLSCache Failed." | ||
193 | " Shutting Down."); | ||
194 | exit(-1); | ||
195 | } | ||
196 | |||
197 | for (s = base_server; s; s = s->next) { | ||
198 | sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, | ||
199 | &gnutls_module); | ||
200 | sc->cache_type = sc_base->cache_type; | ||
201 | sc->cache_config = sc_base->cache_config; | ||
202 | |||
203 | gnutls_certificate_set_rsa_export_params(sc->certs, | ||
204 | rsa_params); | ||
205 | gnutls_certificate_set_dh_params(sc->certs, dh_params); | ||
206 | |||
207 | if (sc->cert_x509 == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) { | ||
208 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, | ||
209 | "[GnuTLS] - Host '%s:%d' is missing a " | ||
210 | "Certificate File!", | ||
211 | s->server_hostname, s->port); | ||
212 | exit(-1); | ||
213 | } | ||
214 | |||
215 | if (sc->privkey_x509 == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) { | ||
216 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, | ||
217 | "[GnuTLS] - Host '%s:%d' is missing a " | ||
218 | "Private Key File!", | ||
219 | s->server_hostname, s->port); | ||
220 | exit(-1); | ||
221 | } | ||
222 | |||
223 | rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509, | ||
224 | GNUTLS_OID_X520_COMMON_NAME, 0, 0, | ||
225 | NULL, &data_len); | ||
226 | |||
227 | if (data_len < 1) { | ||
228 | sc->enabled = GNUTLS_ENABLED_FALSE; | ||
229 | sc->cert_cn = NULL; | ||
230 | continue; | ||
231 | } | ||
232 | |||
233 | sc->cert_cn = apr_palloc(p, data_len); | ||
234 | rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509, | ||
235 | GNUTLS_OID_X520_COMMON_NAME, 0, 0, | ||
236 | sc->cert_cn, &data_len); | ||
237 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | ||
238 | s, | ||
239 | "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X sc: 0x%08X", sc->cert_cn, rv, | ||
240 | gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(sc->privkey_x509)), | ||
241 | (unsigned int)s, (unsigned int)sc); | ||
242 | } | ||
243 | } | ||
244 | |||
245 | ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION); | ||
246 | |||
247 | return OK; | ||
248 | } | ||
249 | |||
250 | void mgs_hook_child_init(apr_pool_t *p, server_rec *s) | ||
251 | { | ||
252 | apr_status_t rv = APR_SUCCESS; | ||
253 | mgs_srvconf_rec *sc = ap_get_module_config(s->module_config, | ||
254 | &gnutls_module); | ||
255 | |||
256 | if (sc->cache_type != mgs_cache_none) { | ||
257 | rv = mgs_cache_child_init(p, s, sc); | ||
258 | if(rv != APR_SUCCESS) { | ||
259 | ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, | ||
260 | "[GnuTLS] - Failed to run Cache Init"); | ||
261 | } | ||
262 | } | ||
263 | else { | ||
264 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, | ||
265 | "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache"); | ||
266 | } | ||
267 | } | ||
268 | |||
269 | const char *mgs_hook_http_scheme(const request_rec * r) | ||
270 | { | ||
271 | mgs_srvconf_rec *sc = | ||
272 | (mgs_srvconf_rec *) ap_get_module_config(r->server-> | ||
273 | module_config, | ||
274 | &gnutls_module); | ||
275 | |||
276 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { | ||
277 | return NULL; | ||
278 | } | ||
279 | |||
280 | return "https"; | ||
281 | } | ||
282 | |||
283 | apr_port_t mgs_hook_default_port(const request_rec * r) | ||
284 | { | ||
285 | mgs_srvconf_rec *sc = | ||
286 | (mgs_srvconf_rec *) ap_get_module_config(r->server-> | ||
287 | module_config, | ||
288 | &gnutls_module); | ||
289 | |||
290 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | return 443; | ||
295 | } | ||
296 | |||
297 | #define MAX_HOST_LEN 255 | ||
298 | |||
299 | #if USING_2_1_RECENT | ||
300 | typedef struct | ||
301 | { | ||
302 | mgs_handle_t *ctxt; | ||
303 | gnutls_retr_st* ret; | ||
304 | const char* sni_name; | ||
305 | } vhost_cb_rec; | ||
306 | |||
307 | static int vhost_cb (void* baton, conn_rec* conn, server_rec* s) | ||
308 | { | ||
309 | mgs_srvconf_rec *tsc; | ||
310 | vhost_cb_rec* x = baton; | ||
311 | |||
312 | tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, | ||
313 | &gnutls_module); | ||
314 | |||
315 | if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) { | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | /* The CN can contain a * -- this will match those too. */ | ||
320 | if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) { | ||
321 | /* found a match */ | ||
322 | x->ret->cert.x509 = &tsc->cert_x509; | ||
323 | x->ret->key.x509 = tsc->privkey_x509; | ||
324 | #if MOD_GNUTLS_DEBUG | ||
325 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | ||
326 | x->ctxt->c->base_server, | ||
327 | "GnuTLS: Virtual Host CB: " | ||
328 | "'%s' == '%s'", tsc->cert_cn, x->sni_name); | ||
329 | #endif | ||
330 | /* Because we actually change the server used here, we need to reset | ||
331 | * things like ClientVerify. | ||
332 | */ | ||
333 | x->ctxt->sc = tsc; | ||
334 | /* Shit. Crap. Dammit. We *really* should rehandshake here, as our | ||
335 | * certificate structure *should* change when the server changes. | ||
336 | * acccckkkkkk. | ||
337 | */ | ||
338 | gnutls_certificate_server_set_request(x->ctxt->session, x->ctxt->sc->client_verify_mode); | ||
339 | return 1; | ||
340 | } | ||
341 | return 0; | ||
342 | } | ||
343 | #endif | ||
344 | |||
345 | static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st* ret) | ||
346 | { | ||
347 | int rv; | ||
348 | int sni_type; | ||
349 | int data_len = MAX_HOST_LEN; | ||
350 | char sni_name[MAX_HOST_LEN]; | ||
351 | mgs_handle_t *ctxt; | ||
352 | #if USING_2_1_RECENT | ||
353 | vhost_cb_rec cbx; | ||
354 | #else | ||
355 | server_rec* s; | ||
356 | mgs_srvconf_rec *tsc; | ||
357 | #endif | ||
358 | |||
359 | ctxt = gnutls_transport_get_ptr(session); | ||
360 | |||
361 | sni_type = gnutls_certificate_type_get(session); | ||
362 | if (sni_type != GNUTLS_CRT_X509) { | ||
363 | /* In theory, we could support OpenPGP Certificates. Theory != code. */ | ||
364 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, | ||
365 | ctxt->c->base_server, | ||
366 | "GnuTLS: Only x509 Certificates are currently supported."); | ||
367 | return -1; | ||
368 | } | ||
369 | |||
370 | ret->type = GNUTLS_CRT_X509; | ||
371 | ret->ncerts = 1; | ||
372 | ret->deinit_all = 0; | ||
373 | |||
374 | rv = gnutls_server_name_get(ctxt->session, sni_name, | ||
375 | &data_len, &sni_type, 0); | ||
376 | |||
377 | if (rv != 0) { | ||
378 | goto use_default_crt; | ||
379 | } | ||
380 | |||
381 | if (sni_type != GNUTLS_NAME_DNS) { | ||
382 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, | ||
383 | ctxt->c->base_server, | ||
384 | "GnuTLS: Unknown type '%d' for SNI: " | ||
385 | "'%s'", sni_type, sni_name); | ||
386 | goto use_default_crt; | ||
387 | } | ||
388 | |||
389 | /** | ||
390 | * Code in the Core already sets up the c->base_server as the base | ||
391 | * for this IP/Port combo. Trust that the core did the 'right' thing. | ||
392 | */ | ||
393 | #if USING_2_1_RECENT | ||
394 | cbx.ctxt = ctxt; | ||
395 | cbx.ret = ret; | ||
396 | cbx.sni_name = sni_name; | ||
397 | |||
398 | rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx); | ||
399 | if (rv == 1) { | ||
400 | return 0; | ||
401 | } | ||
402 | #else | ||
403 | for (s = ap_server_conf; s; s = s->next) { | ||
404 | |||
405 | tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, | ||
406 | &gnutls_module); | ||
407 | if (tsc->enabled != GNUTLS_ENABLED_TRUE) { | ||
408 | continue; | ||
409 | } | ||
410 | #if MOD_GNUTLS_DEBUG | ||
411 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | ||
412 | ctxt->c->base_server, | ||
413 | "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X", tsc->cert_cn, rv, | ||
414 | gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(ctxt->sc->privkey_x509)), | ||
415 | (unsigned int)s, (unsigned int)s->next, (unsigned int)tsc); | ||
416 | #endif | ||
417 | /* The CN can contain a * -- this will match those too. */ | ||
418 | if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) { | ||
419 | /* found a match */ | ||
420 | ret->cert.x509 = &tsc->cert_x509; | ||
421 | ret->key.x509 = tsc->privkey_x509; | ||
422 | #if MOD_GNUTLS_DEBUG | ||
423 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | ||
424 | ctxt->c->base_server, | ||
425 | "GnuTLS: Virtual Host: " | ||
426 | "'%s' == '%s'", tsc->cert_cn, sni_name); | ||
427 | #endif | ||
428 | ctxt->sc = tsc; | ||
429 | gnutls_certificate_server_set_request(ctxt->session, ctxt->sc->client_verify_mode); | ||
430 | return 0; | ||
431 | } | ||
432 | } | ||
433 | #endif | ||
434 | |||
435 | /** | ||
436 | * If the client does not support the Server Name Indication, give the default | ||
437 | * certificate for this server. | ||
438 | */ | ||
439 | use_default_crt: | ||
440 | ret->cert.x509 = &ctxt->sc->cert_x509; | ||
441 | ret->key.x509 = ctxt->sc->privkey_x509; | ||
442 | #if MOD_GNUTLS_DEBUG | ||
443 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | ||
444 | ctxt->c->base_server, | ||
445 | "GnuTLS: Using Default Certificate."); | ||
446 | #endif | ||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | static mgs_handle_t* create_gnutls_handle(apr_pool_t* pool, conn_rec * c) | ||
451 | { | ||
452 | mgs_handle_t *ctxt; | ||
453 | mgs_srvconf_rec *sc = | ||
454 | (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> | ||
455 | module_config, | ||
456 | &gnutls_module); | ||
457 | |||
458 | ctxt = apr_pcalloc(pool, sizeof(*ctxt)); | ||
459 | ctxt->c = c; | ||
460 | ctxt->sc = sc; | ||
461 | ctxt->status = 0; | ||
462 | |||
463 | ctxt->input_rc = APR_SUCCESS; | ||
464 | ctxt->input_bb = apr_brigade_create(c->pool, c->bucket_alloc); | ||
465 | ctxt->input_cbuf.length = 0; | ||
466 | |||
467 | ctxt->output_rc = APR_SUCCESS; | ||
468 | ctxt->output_bb = apr_brigade_create(c->pool, c->bucket_alloc); | ||
469 | ctxt->output_blen = 0; | ||
470 | ctxt->output_length = 0; | ||
471 | |||
472 | gnutls_init(&ctxt->session, GNUTLS_SERVER); | ||
473 | |||
474 | gnutls_protocol_set_priority(ctxt->session, sc->protocol); | ||
475 | gnutls_cipher_set_priority(ctxt->session, sc->ciphers); | ||
476 | gnutls_compression_set_priority(ctxt->session, sc->compression); | ||
477 | gnutls_kx_set_priority(ctxt->session, sc->key_exchange); | ||
478 | gnutls_mac_set_priority(ctxt->session, sc->macs); | ||
479 | gnutls_certificate_type_set_priority(ctxt->session, sc->cert_types); | ||
480 | |||
481 | mgs_cache_session_init(ctxt); | ||
482 | |||
483 | gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, ctxt->sc->certs); | ||
484 | |||
485 | gnutls_certificate_server_set_retrieve_function(sc->certs, cert_retrieve_fn); | ||
486 | gnutls_certificate_server_set_request(ctxt->session, ctxt->sc->client_verify_mode); | ||
487 | return ctxt; | ||
488 | } | ||
489 | |||
490 | int mgs_hook_pre_connection(conn_rec * c, void *csd) | ||
491 | { | ||
492 | mgs_handle_t *ctxt; | ||
493 | mgs_srvconf_rec *sc = | ||
494 | (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> | ||
495 | module_config, | ||
496 | &gnutls_module); | ||
497 | |||
498 | if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) { | ||
499 | return DECLINED; | ||
500 | } | ||
501 | |||
502 | ctxt = create_gnutls_handle(c->pool, c); | ||
503 | |||
504 | ap_set_module_config(c->conn_config, &gnutls_module, ctxt); | ||
505 | |||
506 | gnutls_transport_set_pull_function(ctxt->session, | ||
507 | mgs_transport_read); | ||
508 | gnutls_transport_set_push_function(ctxt->session, | ||
509 | mgs_transport_write); | ||
510 | gnutls_transport_set_ptr(ctxt->session, ctxt); | ||
511 | |||
512 | ctxt->input_filter = ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, | ||
513 | NULL, c); | ||
514 | ctxt->output_filter = ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, | ||
515 | NULL, c); | ||
516 | |||
517 | return OK; | ||
518 | } | ||
519 | |||
520 | int mgs_hook_fixups(request_rec *r) | ||
521 | { | ||
522 | unsigned char sbuf[GNUTLS_MAX_SESSION_ID]; | ||
523 | char buf[GNUTLS_SESSION_ID_STRING_LEN]; | ||
524 | const char* tmp; | ||
525 | int len; | ||
526 | mgs_handle_t *ctxt; | ||
527 | apr_table_t *env = r->subprocess_env; | ||
528 | |||
529 | ctxt = ap_get_module_config(r->connection->conn_config, &gnutls_module); | ||
530 | |||
531 | if(!ctxt) { | ||
532 | return DECLINED; | ||
533 | } | ||
534 | |||
535 | apr_table_setn(env, "HTTPS", "on"); | ||
536 | |||
537 | apr_table_setn(env, "GNUTLS_VERSION_INTERFACE", MOD_GNUTLS_VERSION); | ||
538 | apr_table_setn(env, "GNUTLS_VERSION_LIBRARY", LIBGNUTLS_VERSION); | ||
539 | |||
540 | apr_table_setn(env, "SSL_PROTOCOL", | ||
541 | gnutls_protocol_get_name(gnutls_protocol_get_version(ctxt->session))); | ||
542 | |||
543 | apr_table_setn(env, "SSL_CIPHER", | ||
544 | gnutls_cipher_get_name(gnutls_cipher_get(ctxt->session))); | ||
545 | |||
546 | apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE"); | ||
547 | |||
548 | tmp = apr_psprintf(r->pool, "%d", | ||
549 | 8 * gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session))); | ||
550 | |||
551 | apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp); | ||
552 | |||
553 | apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp); | ||
554 | |||
555 | len = sizeof(sbuf); | ||
556 | gnutls_session_get_id(ctxt->session, sbuf, &len); | ||
557 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); | ||
558 | apr_table_setn(env, "SSL_SESSION_ID", tmp); | ||
559 | |||
560 | return OK; | ||
561 | } | ||
562 | |||
563 | int mgs_hook_authz(request_rec *r) | ||
564 | { | ||
565 | int rv; | ||
566 | int status; | ||
567 | mgs_handle_t *ctxt; | ||
568 | mgs_dirconf_rec *dc = ap_get_module_config(r->per_dir_config, | ||
569 | &gnutls_module); | ||
570 | |||
571 | ctxt = ap_get_module_config(r->connection->conn_config, &gnutls_module); | ||
572 | |||
573 | if (!ctxt) { | ||
574 | return DECLINED; | ||
575 | } | ||
576 | |||
577 | if (!dc) { | ||
578 | dc = mgs_config_dir_create(r->pool, NULL); | ||
579 | } | ||
580 | |||
581 | if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) { | ||
582 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | ||
583 | "GnuTLS: Directory set to Ignore Client Certificate!"); | ||
584 | return DECLINED; | ||
585 | } | ||
586 | |||
587 | if (ctxt->sc->client_verify_mode < dc->client_verify_mode) { | ||
588 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | ||
589 | "GnuTLS: Attempting to rehandshake with peer. %d %d", | ||
590 | ctxt->sc->client_verify_mode, dc->client_verify_mode); | ||
591 | |||
592 | gnutls_certificate_server_set_request(ctxt->session, | ||
593 | dc->client_verify_mode); | ||
594 | |||
595 | if (mgs_rehandshake(ctxt) != 0) { | ||
596 | return HTTP_FORBIDDEN; | ||
597 | } | ||
598 | } | ||
599 | else if (ctxt->sc->client_verify_mode == GNUTLS_CERT_IGNORE) { | ||
600 | #if MOD_GNUTLS_DEBUG | ||
601 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
602 | "GnuTLS: Peer is set to IGNORE"); | ||
603 | #endif | ||
604 | return DECLINED; | ||
605 | } | ||
606 | |||
607 | rv = gnutls_certificate_verify_peers2(ctxt->session, &status); | ||
608 | |||
609 | if (rv < 0) { | ||
610 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
611 | "GnuTLS: Failed to Verify Peer: (%d) %s", | ||
612 | rv, gnutls_strerror(rv)); | ||
613 | return HTTP_FORBIDDEN; | ||
614 | } | ||
615 | |||
616 | if (status < 0) { | ||
617 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
618 | "GnuTLS: Peer Status is invalid."); | ||
619 | return HTTP_FORBIDDEN; | ||
620 | } | ||
621 | |||
622 | if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { | ||
623 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
624 | "GnuTLS: Could not find Signer for Peer Certificate"); | ||
625 | } | ||
626 | |||
627 | if (status & GNUTLS_CERT_SIGNER_NOT_CA) { | ||
628 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
629 | "GnuTLS: Could not find CA for Peer Certificate"); | ||
630 | } | ||
631 | |||
632 | if (status & GNUTLS_CERT_INVALID) { | ||
633 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
634 | "GnuTLS: Peer Certificate is invalid."); | ||
635 | return HTTP_FORBIDDEN; | ||
636 | } | ||
637 | else if (status & GNUTLS_CERT_REVOKED) { | ||
638 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
639 | "GnuTLS: Peer Certificate is revoked."); | ||
640 | return HTTP_FORBIDDEN; | ||
641 | } | ||
642 | |||
643 | /* TODO: OpenPGP Certificates */ | ||
644 | if (gnutls_certificate_type_get(ctxt->session) != GNUTLS_CRT_X509) { | ||
645 | ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, | ||
646 | "GnuTLS: Only x509 is supported for client certificates"); | ||
647 | return HTTP_FORBIDDEN; | ||
648 | } | ||
649 | /* TODO: Further Verification. */ | ||
650 | ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, | ||
651 | "GnuTLS: Verified Peer."); | ||
652 | return OK; | ||
653 | } | ||
654 | |||
diff --git a/src/gnutls_io.c b/src/gnutls_io.c index dee2c4f..acb6095 100644 --- a/src/gnutls_io.c +++ b/src/gnutls_io.c | |||
@@ -35,7 +35,7 @@ static apr_status_t gnutls_io_filter_error(ap_filter_t * f, | |||
35 | apr_bucket_brigade * bb, | 35 | apr_bucket_brigade * bb, |
36 | apr_status_t status) | 36 | apr_status_t status) |
37 | { | 37 | { |
38 | mod_gnutls_handle_t *ctxt = (mod_gnutls_handle_t *) f->ctx; | 38 | mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; |
39 | apr_bucket *bucket; | 39 | apr_bucket *bucket; |
40 | 40 | ||
41 | switch (status) { | 41 | switch (status) { |
@@ -63,7 +63,7 @@ static apr_status_t gnutls_io_filter_error(ap_filter_t * f, | |||
63 | return APR_SUCCESS; | 63 | return APR_SUCCESS; |
64 | } | 64 | } |
65 | 65 | ||
66 | static int char_buffer_read(mod_gnutls_char_buffer_t * buffer, char *in, | 66 | static int char_buffer_read(mgs_char_buffer_t * buffer, char *in, |
67 | int inl) | 67 | int inl) |
68 | { | 68 | { |
69 | if (!buffer->length) { | 69 | if (!buffer->length) { |
@@ -87,7 +87,7 @@ static int char_buffer_read(mod_gnutls_char_buffer_t * buffer, char *in, | |||
87 | return inl; | 87 | return inl; |
88 | } | 88 | } |
89 | 89 | ||
90 | static int char_buffer_write(mod_gnutls_char_buffer_t * buffer, char *in, | 90 | static int char_buffer_write(mgs_char_buffer_t * buffer, char *in, |
91 | int inl) | 91 | int inl) |
92 | { | 92 | { |
93 | buffer->value = in; | 93 | buffer->value = in; |
@@ -181,7 +181,7 @@ static apr_status_t brigade_consume(apr_bucket_brigade * bb, | |||
181 | } | 181 | } |
182 | 182 | ||
183 | 183 | ||
184 | static apr_status_t gnutls_io_input_read(mod_gnutls_handle_t * ctxt, | 184 | static apr_status_t gnutls_io_input_read(mgs_handle_t * ctxt, |
185 | char *buf, apr_size_t * len) | 185 | char *buf, apr_size_t * len) |
186 | { | 186 | { |
187 | apr_size_t wanted = *len; | 187 | apr_size_t wanted = *len; |
@@ -310,7 +310,7 @@ static apr_status_t gnutls_io_input_read(mod_gnutls_handle_t * ctxt, | |||
310 | return ctxt->input_rc; | 310 | return ctxt->input_rc; |
311 | } | 311 | } |
312 | 312 | ||
313 | static apr_status_t gnutls_io_input_getline(mod_gnutls_handle_t * ctxt, | 313 | static apr_status_t gnutls_io_input_getline(mgs_handle_t * ctxt, |
314 | char *buf, apr_size_t * len) | 314 | char *buf, apr_size_t * len) |
315 | { | 315 | { |
316 | const char *pos = NULL; | 316 | const char *pos = NULL; |
@@ -353,7 +353,7 @@ static apr_status_t gnutls_io_input_getline(mod_gnutls_handle_t * ctxt, | |||
353 | return APR_SUCCESS; | 353 | return APR_SUCCESS; |
354 | } | 354 | } |
355 | 355 | ||
356 | static int gnutls_do_handshake(mod_gnutls_handle_t * ctxt) | 356 | static int gnutls_do_handshake(mgs_handle_t * ctxt) |
357 | { | 357 | { |
358 | int ret; | 358 | int ret; |
359 | int errcode; | 359 | int errcode; |
@@ -403,7 +403,7 @@ tryagain: | |||
403 | } | 403 | } |
404 | } | 404 | } |
405 | 405 | ||
406 | int mod_gnutls_rehandshake(mod_gnutls_handle_t * ctxt) | 406 | int mgs_rehandshake(mgs_handle_t * ctxt) |
407 | { | 407 | { |
408 | int rv; | 408 | int rv; |
409 | 409 | ||
@@ -424,14 +424,14 @@ int mod_gnutls_rehandshake(mod_gnutls_handle_t * ctxt) | |||
424 | } | 424 | } |
425 | 425 | ||
426 | 426 | ||
427 | apr_status_t mod_gnutls_filter_input(ap_filter_t* f, | 427 | apr_status_t mgs_filter_input(ap_filter_t* f, |
428 | apr_bucket_brigade * bb, | 428 | apr_bucket_brigade * bb, |
429 | ap_input_mode_t mode, | 429 | ap_input_mode_t mode, |
430 | apr_read_type_e block, | 430 | apr_read_type_e block, |
431 | apr_off_t readbytes) | 431 | apr_off_t readbytes) |
432 | { | 432 | { |
433 | apr_status_t status = APR_SUCCESS; | 433 | apr_status_t status = APR_SUCCESS; |
434 | mod_gnutls_handle_t *ctxt = (mod_gnutls_handle_t *) f->ctx; | 434 | mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; |
435 | apr_size_t len = sizeof(ctxt->input_buffer); | 435 | apr_size_t len = sizeof(ctxt->input_buffer); |
436 | 436 | ||
437 | if (f->c->aborted) { | 437 | if (f->c->aborted) { |
@@ -488,12 +488,12 @@ apr_status_t mod_gnutls_filter_input(ap_filter_t* f, | |||
488 | return status; | 488 | return status; |
489 | } | 489 | } |
490 | 490 | ||
491 | apr_status_t mod_gnutls_filter_output(ap_filter_t * f, | 491 | apr_status_t mgs_filter_output(ap_filter_t * f, |
492 | apr_bucket_brigade * bb) | 492 | apr_bucket_brigade * bb) |
493 | { | 493 | { |
494 | apr_size_t ret; | 494 | apr_size_t ret; |
495 | apr_bucket* e; | 495 | apr_bucket* e; |
496 | mod_gnutls_handle_t *ctxt = (mod_gnutls_handle_t *) f->ctx; | 496 | mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; |
497 | apr_status_t status = APR_SUCCESS; | 497 | apr_status_t status = APR_SUCCESS; |
498 | apr_read_type_e rblock = APR_NONBLOCK_READ; | 498 | apr_read_type_e rblock = APR_NONBLOCK_READ; |
499 | 499 | ||
@@ -592,10 +592,10 @@ apr_status_t mod_gnutls_filter_output(ap_filter_t * f, | |||
592 | return status; | 592 | return status; |
593 | } | 593 | } |
594 | 594 | ||
595 | ssize_t mod_gnutls_transport_read(gnutls_transport_ptr_t ptr, | 595 | ssize_t mgs_transport_read(gnutls_transport_ptr_t ptr, |
596 | void *buffer, size_t len) | 596 | void *buffer, size_t len) |
597 | { | 597 | { |
598 | mod_gnutls_handle_t *ctxt = ptr; | 598 | mgs_handle_t *ctxt = ptr; |
599 | apr_status_t rc; | 599 | apr_status_t rc; |
600 | apr_size_t in = len; | 600 | apr_size_t in = len; |
601 | apr_read_type_e block = ctxt->input_block; | 601 | apr_read_type_e block = ctxt->input_block; |
@@ -659,7 +659,7 @@ ssize_t mod_gnutls_transport_read(gnutls_transport_ptr_t ptr, | |||
659 | } | 659 | } |
660 | 660 | ||
661 | 661 | ||
662 | static ssize_t write_flush(mod_gnutls_handle_t * ctxt) | 662 | static ssize_t write_flush(mgs_handle_t * ctxt) |
663 | { | 663 | { |
664 | apr_bucket *e; | 664 | apr_bucket *e; |
665 | 665 | ||
@@ -691,10 +691,10 @@ static ssize_t write_flush(mod_gnutls_handle_t * ctxt) | |||
691 | return (ctxt->output_rc == APR_SUCCESS) ? 1 : -1; | 691 | return (ctxt->output_rc == APR_SUCCESS) ? 1 : -1; |
692 | } | 692 | } |
693 | 693 | ||
694 | ssize_t mod_gnutls_transport_write(gnutls_transport_ptr_t ptr, | 694 | ssize_t mgs_transport_write(gnutls_transport_ptr_t ptr, |
695 | const void *buffer, size_t len) | 695 | const void *buffer, size_t len) |
696 | { | 696 | { |
697 | mod_gnutls_handle_t *ctxt = ptr; | 697 | mgs_handle_t *ctxt = ptr; |
698 | 698 | ||
699 | /* pass along the encrypted data | 699 | /* pass along the encrypted data |
700 | * need to flush since we're using SSL's malloc-ed buffer | 700 | * need to flush since we're using SSL's malloc-ed buffer |
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c index fbcbc52..a2c36ee 100644 --- a/src/mod_gnutls.c +++ b/src/mod_gnutls.c | |||
@@ -16,676 +16,45 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "mod_gnutls.h" | 18 | #include "mod_gnutls.h" |
19 | #include "http_vhost.h" | ||
20 | 19 | ||
21 | extern server_rec *ap_server_conf; | ||
22 | |||
23 | #if APR_HAS_THREADS | ||
24 | GCRY_THREAD_OPTION_PTHREAD_IMPL; | ||
25 | #endif | ||
26 | |||
27 | #if MOD_GNUTLS_DEBUG | ||
28 | static apr_file_t* debug_log_fp; | ||
29 | #endif | ||
30 | |||
31 | static apr_status_t mod_gnutls_cleanup_pre_config(void *data) | ||
32 | { | ||
33 | gnutls_global_deinit(); | ||
34 | return APR_SUCCESS; | ||
35 | } | ||
36 | |||
37 | #if MOD_GNUTLS_DEBUG | ||
38 | static void gnutls_debug_log_all( int level, const char* str) | ||
39 | { | ||
40 | apr_file_printf(debug_log_fp, "<%d> %s\n", level, str); | ||
41 | } | ||
42 | #endif | ||
43 | |||
44 | static int mod_gnutls_hook_pre_config(apr_pool_t * pconf, | ||
45 | apr_pool_t * plog, apr_pool_t * ptemp) | ||
46 | { | ||
47 | |||
48 | #if APR_HAS_THREADS | ||
49 | /* TODO: Check MPM Type here */ | ||
50 | gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); | ||
51 | #endif | ||
52 | |||
53 | gnutls_global_init(); | ||
54 | |||
55 | apr_pool_cleanup_register(pconf, NULL, mod_gnutls_cleanup_pre_config, | ||
56 | apr_pool_cleanup_null); | ||
57 | |||
58 | #if MOD_GNUTLS_DEBUG | ||
59 | apr_file_open(&debug_log_fp, "/tmp/gnutls_debug", | ||
60 | APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT, pconf); | ||
61 | |||
62 | gnutls_global_set_log_level(9); | ||
63 | gnutls_global_set_log_function(gnutls_debug_log_all); | ||
64 | #endif | ||
65 | |||
66 | return OK; | ||
67 | } | ||
68 | |||
69 | |||
70 | static gnutls_datum load_params(const char* file, server_rec* s, | ||
71 | apr_pool_t* pool) | ||
72 | { | ||
73 | gnutls_datum ret = { NULL, 0 }; | ||
74 | apr_file_t* fp; | ||
75 | apr_finfo_t finfo; | ||
76 | apr_status_t rv; | ||
77 | apr_size_t br = 0; | ||
78 | |||
79 | rv = apr_file_open(&fp, file, APR_READ|APR_BINARY, APR_OS_DEFAULT, | ||
80 | pool); | ||
81 | if (rv != APR_SUCCESS) { | ||
82 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, | ||
83 | "GnuTLS failed to load params file at: %s", file); | ||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp); | ||
88 | |||
89 | if (rv != APR_SUCCESS) { | ||
90 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, | ||
91 | "GnuTLS failed to stat params file at: %s", file); | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | ret.data = apr_palloc(pool, finfo.size+1); | ||
96 | rv = apr_file_read_full(fp, ret.data, finfo.size, &br); | ||
97 | |||
98 | if (rv != APR_SUCCESS) { | ||
99 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, | ||
100 | "GnuTLS failed to read params file at: %s", file); | ||
101 | return ret; | ||
102 | } | ||
103 | apr_file_close(fp); | ||
104 | ret.data[br] = '\0'; | ||
105 | ret.size = br; | ||
106 | |||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | static int mod_gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | ||
111 | apr_pool_t * ptemp, | ||
112 | server_rec * base_server) | ||
113 | { | ||
114 | int rv; | ||
115 | int data_len; | ||
116 | server_rec *s; | ||
117 | gnutls_dh_params_t dh_params; | ||
118 | gnutls_rsa_params_t rsa_params; | ||
119 | mod_gnutls_srvconf_rec *sc; | ||
120 | mod_gnutls_srvconf_rec *sc_base; | ||
121 | void *data = NULL; | ||
122 | int first_run = 0; | ||
123 | const char *userdata_key = "mod_gnutls_init"; | ||
124 | |||
125 | apr_pool_userdata_get(&data, userdata_key, base_server->process->pool); | ||
126 | if (data == NULL) { | ||
127 | first_run = 1; | ||
128 | apr_pool_userdata_set((const void *)1, userdata_key, | ||
129 | apr_pool_cleanup_null, | ||
130 | base_server->process->pool); | ||
131 | } | ||
132 | |||
133 | |||
134 | { | ||
135 | gnutls_datum pdata; | ||
136 | apr_pool_t* tpool; | ||
137 | s = base_server; | ||
138 | sc_base = (mod_gnutls_srvconf_rec *) ap_get_module_config(s->module_config, | ||
139 | &gnutls_module); | ||
140 | |||
141 | apr_pool_create(&tpool, p); | ||
142 | |||
143 | gnutls_dh_params_init(&dh_params); | ||
144 | |||
145 | pdata = load_params(sc_base->dh_params_file, s, tpool); | ||
146 | |||
147 | if (pdata.size != 0) { | ||
148 | rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, | ||
149 | GNUTLS_X509_FMT_PEM); | ||
150 | if (rv != 0) { | ||
151 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
152 | "GnuTLS: Unable to load DH Params: (%d) %s", | ||
153 | rv, gnutls_strerror(rv)); | ||
154 | exit(rv); | ||
155 | } | ||
156 | } | ||
157 | else { | ||
158 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
159 | "GnuTLS: Unable to load DH Params." | ||
160 | " Shutting Down."); | ||
161 | exit(-1); | ||
162 | } | ||
163 | apr_pool_clear(tpool); | ||
164 | |||
165 | gnutls_rsa_params_init(&rsa_params); | ||
166 | |||
167 | pdata = load_params(sc_base->rsa_params_file, s, tpool); | ||
168 | |||
169 | if (pdata.size != 0) { | ||
170 | rv = gnutls_rsa_params_import_pkcs1(rsa_params, &pdata, | ||
171 | GNUTLS_X509_FMT_PEM); | ||
172 | if (rv != 0) { | ||
173 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
174 | "GnuTLS: Unable to load RSA Params: (%d) %s", | ||
175 | rv, gnutls_strerror(rv)); | ||
176 | exit(rv); | ||
177 | } | ||
178 | } | ||
179 | else { | ||
180 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
181 | "GnuTLS: Unable to load RSA Params." | ||
182 | " Shutting Down."); | ||
183 | exit(-1); | ||
184 | } | ||
185 | |||
186 | apr_pool_destroy(tpool); | ||
187 | rv = mod_gnutls_cache_post_config(p, s, sc_base); | ||
188 | if (rv != 0) { | ||
189 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, | ||
190 | "GnuTLS: Post Config for GnuTLSCache Failed." | ||
191 | " Shutting Down."); | ||
192 | exit(-1); | ||
193 | } | ||
194 | |||
195 | for (s = base_server; s; s = s->next) { | ||
196 | sc = (mod_gnutls_srvconf_rec *) ap_get_module_config(s->module_config, | ||
197 | &gnutls_module); | ||
198 | sc->cache_type = sc_base->cache_type; | ||
199 | sc->cache_config = sc_base->cache_config; | ||
200 | |||
201 | gnutls_certificate_set_rsa_export_params(sc->certs, | ||
202 | rsa_params); | ||
203 | gnutls_certificate_set_dh_params(sc->certs, dh_params); | ||
204 | |||
205 | if (sc->cert_x509 == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) { | ||
206 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, | ||
207 | "[GnuTLS] - Host '%s:%d' is missing a " | ||
208 | "Certificate File!", | ||
209 | s->server_hostname, s->port); | ||
210 | exit(-1); | ||
211 | } | ||
212 | |||
213 | if (sc->privkey_x509 == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) { | ||
214 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, | ||
215 | "[GnuTLS] - Host '%s:%d' is missing a " | ||
216 | "Private Key File!", | ||
217 | s->server_hostname, s->port); | ||
218 | exit(-1); | ||
219 | } | ||
220 | |||
221 | rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509, | ||
222 | GNUTLS_OID_X520_COMMON_NAME, 0, 0, | ||
223 | NULL, &data_len); | ||
224 | |||
225 | if (data_len < 1) { | ||
226 | sc->enabled = GNUTLS_ENABLED_FALSE; | ||
227 | sc->cert_cn = NULL; | ||
228 | continue; | ||
229 | } | ||
230 | |||
231 | sc->cert_cn = apr_palloc(p, data_len); | ||
232 | rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509, | ||
233 | GNUTLS_OID_X520_COMMON_NAME, 0, 0, | ||
234 | sc->cert_cn, &data_len); | ||
235 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | ||
236 | s, | ||
237 | "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X sc: 0x%08X", sc->cert_cn, rv, | ||
238 | gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(sc->privkey_x509)), | ||
239 | (unsigned int)s, (unsigned int)sc); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION); | ||
244 | |||
245 | return OK; | ||
246 | } | ||
247 | |||
248 | static void mod_gnutls_hook_child_init(apr_pool_t *p, server_rec *s) | ||
249 | { | ||
250 | apr_status_t rv = APR_SUCCESS; | ||
251 | mod_gnutls_srvconf_rec *sc = ap_get_module_config(s->module_config, | ||
252 | &gnutls_module); | ||
253 | |||
254 | if (sc->cache_type != mod_gnutls_cache_none) { | ||
255 | rv = mod_gnutls_cache_child_init(p, s, sc); | ||
256 | if(rv != APR_SUCCESS) { | ||
257 | ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, | ||
258 | "[GnuTLS] - Failed to run Cache Init"); | ||
259 | } | ||
260 | } | ||
261 | else { | ||
262 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, | ||
263 | "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache"); | ||
264 | } | ||
265 | } | ||
266 | |||
267 | static const char *mod_gnutls_hook_http_scheme(const request_rec * r) | ||
268 | { | ||
269 | mod_gnutls_srvconf_rec *sc = | ||
270 | (mod_gnutls_srvconf_rec *) ap_get_module_config(r->server-> | ||
271 | module_config, | ||
272 | &gnutls_module); | ||
273 | |||
274 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { | ||
275 | return NULL; | ||
276 | } | ||
277 | |||
278 | return "https"; | ||
279 | } | ||
280 | |||
281 | static apr_port_t mod_gnutls_hook_default_port(const request_rec * r) | ||
282 | { | ||
283 | mod_gnutls_srvconf_rec *sc = | ||
284 | (mod_gnutls_srvconf_rec *) ap_get_module_config(r->server-> | ||
285 | module_config, | ||
286 | &gnutls_module); | ||
287 | |||
288 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | return 443; | ||
293 | } | ||
294 | |||
295 | #define MAX_HOST_LEN 255 | ||
296 | |||
297 | #if USING_2_1_RECENT | ||
298 | typedef struct | ||
299 | { | ||
300 | mod_gnutls_handle_t *ctxt; | ||
301 | gnutls_retr_st* ret; | ||
302 | const char* sni_name; | ||
303 | } vhost_cb_rec; | ||
304 | |||
305 | int vhost_cb (void* baton, conn_rec* conn, server_rec* s) | ||
306 | { | ||
307 | mod_gnutls_srvconf_rec *tsc; | ||
308 | vhost_cb_rec* x = baton; | ||
309 | |||
310 | tsc = (mod_gnutls_srvconf_rec *) ap_get_module_config(s->module_config, | ||
311 | &gnutls_module); | ||
312 | |||
313 | if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) { | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | /* The CN can contain a * -- this will match those too. */ | ||
318 | if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) { | ||
319 | /* found a match */ | ||
320 | x->ret->cert.x509 = &tsc->cert_x509; | ||
321 | x->ret->key.x509 = tsc->privkey_x509; | ||
322 | #if MOD_GNUTLS_DEBUG | ||
323 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | ||
324 | x->ctxt->c->base_server, | ||
325 | "GnuTLS: Virtual Host CB: " | ||
326 | "'%s' == '%s'", tsc->cert_cn, x->sni_name); | ||
327 | #endif | ||
328 | /* Because we actually change the server used here, we need to reset | ||
329 | * things like ClientVerify. | ||
330 | */ | ||
331 | x->ctxt->sc = tsc; | ||
332 | /* Shit. Crap. Dammit. We *really* should rehandshake here, as our | ||
333 | * certificate structure *should* change when the server changes. | ||
334 | * acccckkkkkk. | ||
335 | */ | ||
336 | gnutls_certificate_server_set_request(x->ctxt->session, x->ctxt->sc->client_verify_mode); | ||
337 | return 1; | ||
338 | } | ||
339 | return 0; | ||
340 | } | ||
341 | #endif | ||
342 | |||
343 | static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st* ret) | ||
344 | { | ||
345 | int rv; | ||
346 | int sni_type; | ||
347 | int data_len = MAX_HOST_LEN; | ||
348 | char sni_name[MAX_HOST_LEN]; | ||
349 | mod_gnutls_handle_t *ctxt; | ||
350 | #if USING_2_1_RECENT | ||
351 | vhost_cb_rec cbx; | ||
352 | #else | ||
353 | server_rec* s; | ||
354 | mod_gnutls_srvconf_rec *tsc; | ||
355 | #endif | ||
356 | |||
357 | ctxt = gnutls_transport_get_ptr(session); | ||
358 | |||
359 | sni_type = gnutls_certificate_type_get(session); | ||
360 | if (sni_type != GNUTLS_CRT_X509) { | ||
361 | /* In theory, we could support OpenPGP Certificates. Theory != code. */ | ||
362 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, | ||
363 | ctxt->c->base_server, | ||
364 | "GnuTLS: Only x509 Certificates are currently supported."); | ||
365 | return -1; | ||
366 | } | ||
367 | |||
368 | ret->type = GNUTLS_CRT_X509; | ||
369 | ret->ncerts = 1; | ||
370 | ret->deinit_all = 0; | ||
371 | |||
372 | rv = gnutls_server_name_get(ctxt->session, sni_name, | ||
373 | &data_len, &sni_type, 0); | ||
374 | |||
375 | if (rv != 0) { | ||
376 | goto use_default_crt; | ||
377 | } | ||
378 | |||
379 | if (sni_type != GNUTLS_NAME_DNS) { | ||
380 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, | ||
381 | ctxt->c->base_server, | ||
382 | "GnuTLS: Unknown type '%d' for SNI: " | ||
383 | "'%s'", sni_type, sni_name); | ||
384 | goto use_default_crt; | ||
385 | } | ||
386 | |||
387 | /** | ||
388 | * Code in the Core already sets up the c->base_server as the base | ||
389 | * for this IP/Port combo. Trust that the core did the 'right' thing. | ||
390 | */ | ||
391 | #if USING_2_1_RECENT | ||
392 | cbx.ctxt = ctxt; | ||
393 | cbx.ret = ret; | ||
394 | cbx.sni_name = sni_name; | ||
395 | |||
396 | rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx); | ||
397 | if (rv == 1) { | ||
398 | return 0; | ||
399 | } | ||
400 | #else | ||
401 | for (s = ap_server_conf; s; s = s->next) { | ||
402 | |||
403 | tsc = (mod_gnutls_srvconf_rec *) ap_get_module_config(s->module_config, | ||
404 | &gnutls_module); | ||
405 | if (tsc->enabled != GNUTLS_ENABLED_TRUE) { | ||
406 | continue; | ||
407 | } | ||
408 | #if MOD_GNUTLS_DEBUG | ||
409 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | ||
410 | ctxt->c->base_server, | ||
411 | "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X", tsc->cert_cn, rv, | ||
412 | gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(ctxt->sc->privkey_x509)), | ||
413 | (unsigned int)s, (unsigned int)s->next, (unsigned int)tsc); | ||
414 | #endif | ||
415 | /* The CN can contain a * -- this will match those too. */ | ||
416 | if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) { | ||
417 | /* found a match */ | ||
418 | ret->cert.x509 = &tsc->cert_x509; | ||
419 | ret->key.x509 = tsc->privkey_x509; | ||
420 | #if MOD_GNUTLS_DEBUG | ||
421 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | ||
422 | ctxt->c->base_server, | ||
423 | "GnuTLS: Virtual Host: " | ||
424 | "'%s' == '%s'", tsc->cert_cn, sni_name); | ||
425 | #endif | ||
426 | ctxt->sc = tsc; | ||
427 | gnutls_certificate_server_set_request(ctxt->session, ctxt->sc->client_verify_mode); | ||
428 | return 0; | ||
429 | } | ||
430 | } | ||
431 | #endif | ||
432 | |||
433 | /** | ||
434 | * If the client does not support the Server Name Indication, give the default | ||
435 | * certificate for this server. | ||
436 | */ | ||
437 | use_default_crt: | ||
438 | ret->cert.x509 = &ctxt->sc->cert_x509; | ||
439 | ret->key.x509 = ctxt->sc->privkey_x509; | ||
440 | #if MOD_GNUTLS_DEBUG | ||
441 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | ||
442 | ctxt->c->base_server, | ||
443 | "GnuTLS: Using Default Certificate."); | ||
444 | #endif | ||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | static mod_gnutls_handle_t* create_gnutls_handle(apr_pool_t* pool, conn_rec * c) | ||
449 | { | ||
450 | mod_gnutls_handle_t *ctxt; | ||
451 | mod_gnutls_srvconf_rec *sc = | ||
452 | (mod_gnutls_srvconf_rec *) ap_get_module_config(c->base_server-> | ||
453 | module_config, | ||
454 | &gnutls_module); | ||
455 | |||
456 | ctxt = apr_pcalloc(pool, sizeof(*ctxt)); | ||
457 | ctxt->c = c; | ||
458 | ctxt->sc = sc; | ||
459 | ctxt->status = 0; | ||
460 | |||
461 | ctxt->input_rc = APR_SUCCESS; | ||
462 | ctxt->input_bb = apr_brigade_create(c->pool, c->bucket_alloc); | ||
463 | ctxt->input_cbuf.length = 0; | ||
464 | |||
465 | ctxt->output_rc = APR_SUCCESS; | ||
466 | ctxt->output_bb = apr_brigade_create(c->pool, c->bucket_alloc); | ||
467 | ctxt->output_blen = 0; | ||
468 | ctxt->output_length = 0; | ||
469 | |||
470 | gnutls_init(&ctxt->session, GNUTLS_SERVER); | ||
471 | |||
472 | gnutls_protocol_set_priority(ctxt->session, sc->protocol); | ||
473 | gnutls_cipher_set_priority(ctxt->session, sc->ciphers); | ||
474 | gnutls_compression_set_priority(ctxt->session, sc->compression); | ||
475 | gnutls_kx_set_priority(ctxt->session, sc->key_exchange); | ||
476 | gnutls_mac_set_priority(ctxt->session, sc->macs); | ||
477 | gnutls_certificate_type_set_priority(ctxt->session, sc->cert_types); | ||
478 | |||
479 | mod_gnutls_cache_session_init(ctxt); | ||
480 | |||
481 | gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, ctxt->sc->certs); | ||
482 | |||
483 | gnutls_certificate_server_set_retrieve_function(sc->certs, cert_retrieve_fn); | ||
484 | gnutls_certificate_server_set_request(ctxt->session, ctxt->sc->client_verify_mode); | ||
485 | return ctxt; | ||
486 | } | ||
487 | |||
488 | static int mod_gnutls_hook_pre_connection(conn_rec * c, void *csd) | ||
489 | { | ||
490 | mod_gnutls_handle_t *ctxt; | ||
491 | mod_gnutls_srvconf_rec *sc = | ||
492 | (mod_gnutls_srvconf_rec *) ap_get_module_config(c->base_server-> | ||
493 | module_config, | ||
494 | &gnutls_module); | ||
495 | |||
496 | if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) { | ||
497 | return DECLINED; | ||
498 | } | ||
499 | |||
500 | ctxt = create_gnutls_handle(c->pool, c); | ||
501 | |||
502 | ap_set_module_config(c->conn_config, &gnutls_module, ctxt); | ||
503 | |||
504 | gnutls_transport_set_pull_function(ctxt->session, | ||
505 | mod_gnutls_transport_read); | ||
506 | gnutls_transport_set_push_function(ctxt->session, | ||
507 | mod_gnutls_transport_write); | ||
508 | gnutls_transport_set_ptr(ctxt->session, ctxt); | ||
509 | |||
510 | ctxt->input_filter = ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, | ||
511 | NULL, c); | ||
512 | ctxt->output_filter = ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, | ||
513 | NULL, c); | ||
514 | |||
515 | return OK; | ||
516 | } | ||
517 | |||
518 | static int mod_gnutls_hook_fixups(request_rec *r) | ||
519 | { | ||
520 | unsigned char sbuf[GNUTLS_MAX_SESSION_ID]; | ||
521 | char buf[GNUTLS_SESSION_ID_STRING_LEN]; | ||
522 | const char* tmp; | ||
523 | int len; | ||
524 | mod_gnutls_handle_t *ctxt; | ||
525 | apr_table_t *env = r->subprocess_env; | ||
526 | |||
527 | ctxt = ap_get_module_config(r->connection->conn_config, &gnutls_module); | ||
528 | |||
529 | if(!ctxt) { | ||
530 | return DECLINED; | ||
531 | } | ||
532 | |||
533 | apr_table_setn(env, "HTTPS", "on"); | ||
534 | |||
535 | apr_table_setn(env, "GNUTLS_VERSION_INTERFACE", MOD_GNUTLS_VERSION); | ||
536 | apr_table_setn(env, "GNUTLS_VERSION_LIBRARY", LIBGNUTLS_VERSION); | ||
537 | |||
538 | apr_table_setn(env, "SSL_PROTOCOL", | ||
539 | gnutls_protocol_get_name(gnutls_protocol_get_version(ctxt->session))); | ||
540 | |||
541 | apr_table_setn(env, "SSL_CIPHER", | ||
542 | gnutls_cipher_get_name(gnutls_cipher_get(ctxt->session))); | ||
543 | |||
544 | apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE"); | ||
545 | |||
546 | tmp = apr_psprintf(r->pool, "%d", | ||
547 | 8 * gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session))); | ||
548 | |||
549 | apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp); | ||
550 | |||
551 | apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp); | ||
552 | |||
553 | len = sizeof(sbuf); | ||
554 | gnutls_session_get_id(ctxt->session, sbuf, &len); | ||
555 | tmp = mod_gnutls_session_id2sz(sbuf, len, buf, sizeof(buf)); | ||
556 | apr_table_setn(env, "SSL_SESSION_ID", tmp); | ||
557 | |||
558 | return OK; | ||
559 | } | ||
560 | |||
561 | int mod_gnutls_hook_authz(request_rec *r) | ||
562 | { | ||
563 | int rv; | ||
564 | int status; | ||
565 | mod_gnutls_handle_t *ctxt; | ||
566 | mod_gnutls_dirconf_rec *dc = ap_get_module_config(r->per_dir_config, | ||
567 | &gnutls_module); | ||
568 | |||
569 | ctxt = ap_get_module_config(r->connection->conn_config, &gnutls_module); | ||
570 | |||
571 | if (!ctxt) { | ||
572 | return DECLINED; | ||
573 | } | ||
574 | |||
575 | if (!dc) { | ||
576 | dc = mgs_config_dir_create(r->pool, NULL); | ||
577 | } | ||
578 | |||
579 | if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) { | ||
580 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | ||
581 | "GnuTLS: Directory set to Ignore Client Certificate!"); | ||
582 | return DECLINED; | ||
583 | } | ||
584 | |||
585 | if (ctxt->sc->client_verify_mode < dc->client_verify_mode) { | ||
586 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | ||
587 | "GnuTLS: Attempting to rehandshake with peer. %d %d", | ||
588 | ctxt->sc->client_verify_mode, dc->client_verify_mode); | ||
589 | |||
590 | gnutls_certificate_server_set_request(ctxt->session, | ||
591 | dc->client_verify_mode); | ||
592 | |||
593 | if (mod_gnutls_rehandshake(ctxt) != 0) { | ||
594 | return HTTP_FORBIDDEN; | ||
595 | } | ||
596 | } | ||
597 | else if (ctxt->sc->client_verify_mode == GNUTLS_CERT_IGNORE) { | ||
598 | #if MOD_GNUTLS_DEBUG | ||
599 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
600 | "GnuTLS: Peer is set to IGNORE"); | ||
601 | #endif | ||
602 | return DECLINED; | ||
603 | } | ||
604 | |||
605 | rv = gnutls_certificate_verify_peers2(ctxt->session, &status); | ||
606 | |||
607 | if (rv < 0) { | ||
608 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
609 | "GnuTLS: Failed to Verify Peer: (%d) %s", | ||
610 | rv, gnutls_strerror(rv)); | ||
611 | return HTTP_FORBIDDEN; | ||
612 | } | ||
613 | |||
614 | if (status < 0) { | ||
615 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
616 | "GnuTLS: Peer Status is invalid."); | ||
617 | return HTTP_FORBIDDEN; | ||
618 | } | ||
619 | |||
620 | if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { | ||
621 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
622 | "GnuTLS: Could not find Signer for Peer Certificate"); | ||
623 | } | ||
624 | |||
625 | if (status & GNUTLS_CERT_SIGNER_NOT_CA) { | ||
626 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
627 | "GnuTLS: Could not find CA for Peer Certificate"); | ||
628 | } | ||
629 | |||
630 | if (status & GNUTLS_CERT_INVALID) { | ||
631 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
632 | "GnuTLS: Peer Certificate is invalid."); | ||
633 | return HTTP_FORBIDDEN; | ||
634 | } | ||
635 | else if (status & GNUTLS_CERT_REVOKED) { | ||
636 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
637 | "GnuTLS: Peer Certificate is revoked."); | ||
638 | return HTTP_FORBIDDEN; | ||
639 | } | ||
640 | |||
641 | /* TODO: OpenPGP Certificates */ | ||
642 | if (gnutls_certificate_type_get(ctxt->session) != GNUTLS_CRT_X509) { | ||
643 | ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, | ||
644 | "GnuTLS: Only x509 is supported for client certificates"); | ||
645 | return HTTP_FORBIDDEN; | ||
646 | } | ||
647 | /* TODO: Further Verification. */ | ||
648 | ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, | ||
649 | "GnuTLS: Verified Peer."); | ||
650 | return OK; | ||
651 | } | ||
652 | 20 | ||
653 | static void gnutls_hooks(apr_pool_t * p) | 21 | static void gnutls_hooks(apr_pool_t * p) |
654 | { | 22 | { |
655 | ap_hook_pre_connection(mod_gnutls_hook_pre_connection, NULL, NULL, | 23 | ap_hook_pre_connection(mgs_hook_pre_connection, NULL, NULL, |
656 | APR_HOOK_MIDDLE); | 24 | APR_HOOK_MIDDLE); |
657 | ap_hook_post_config(mod_gnutls_hook_post_config, NULL, NULL, | 25 | ap_hook_post_config(mgs_hook_post_config, NULL, NULL, |
658 | APR_HOOK_MIDDLE); | ||
659 | ap_hook_child_init(mod_gnutls_hook_child_init, NULL, NULL, | ||
660 | APR_HOOK_MIDDLE); | 26 | APR_HOOK_MIDDLE); |
27 | ap_hook_child_init(mgs_hook_child_init, NULL, NULL, | ||
28 | APR_HOOK_MIDDLE); | ||
661 | #if USING_2_1_RECENT | 29 | #if USING_2_1_RECENT |
662 | ap_hook_http_scheme(mod_gnutls_hook_http_scheme, NULL, NULL, | 30 | ap_hook_http_scheme(mgs_hook_http_scheme, NULL, NULL, |
663 | APR_HOOK_MIDDLE); | 31 | APR_HOOK_MIDDLE); |
664 | #else | 32 | #else |
665 | ap_hook_http_method(mod_gnutls_hook_http_scheme, NULL, NULL, | 33 | ap_hook_http_method(mgs_hook_http_scheme, NULL, NULL, |
666 | APR_HOOK_MIDDLE); | 34 | APR_HOOK_MIDDLE); |
667 | #endif | 35 | #endif |
668 | ap_hook_default_port(mod_gnutls_hook_default_port, NULL, NULL, | 36 | ap_hook_default_port(mgs_hook_default_port, NULL, NULL, |
669 | APR_HOOK_MIDDLE); | 37 | APR_HOOK_MIDDLE); |
670 | ap_hook_pre_config(mod_gnutls_hook_pre_config, NULL, NULL, | 38 | ap_hook_pre_config(mgs_hook_pre_config, NULL, NULL, |
671 | APR_HOOK_MIDDLE); | 39 | APR_HOOK_MIDDLE); |
672 | 40 | ||
673 | ap_hook_access_checker(mod_gnutls_hook_authz, NULL, NULL, APR_HOOK_REALLY_FIRST); | 41 | ap_hook_access_checker(mgs_hook_authz, NULL, NULL, APR_HOOK_REALLY_FIRST); |
674 | 42 | ||
675 | ap_hook_fixups(mod_gnutls_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST); | 43 | ap_hook_fixups(mgs_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST); |
676 | 44 | ||
677 | /* TODO: HTTP Upgrade Filter */ | 45 | /* TODO: HTTP Upgrade Filter */ |
678 | /* ap_register_output_filter ("UPGRADE_FILTER", | 46 | /* ap_register_output_filter ("UPGRADE_FILTER", |
679 | * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); | 47 | * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); |
680 | */ | 48 | */ |
681 | ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, | 49 | ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, |
682 | mod_gnutls_filter_input, NULL, | 50 | mgs_filter_input, NULL, |
683 | AP_FTYPE_CONNECTION + 5); | 51 | AP_FTYPE_CONNECTION + 5); |
684 | ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, | 52 | ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, |
685 | mod_gnutls_filter_output, NULL, | 53 | mgs_filter_output, NULL, |
686 | AP_FTYPE_CONNECTION + 5); | 54 | AP_FTYPE_CONNECTION + 5); |
687 | } | 55 | } |
688 | 56 | ||
57 | |||
689 | static const command_rec mgs_config_cmds[] = { | 58 | static const command_rec mgs_config_cmds[] = { |
690 | AP_INIT_TAKE1("GnuTLSClientVerify", mgs_set_client_verify, | 59 | AP_INIT_TAKE1("GnuTLSClientVerify", mgs_set_client_verify, |
691 | NULL, | 60 | NULL, |