diff options
-rw-r--r-- | src/gnutls_cache.c | 925 | ||||
-rw-r--r-- | src/gnutls_config.c | 1039 | ||||
-rw-r--r-- | src/gnutls_hooks.c | 1944 | ||||
-rw-r--r-- | src/gnutls_io.c | 1367 | ||||
-rw-r--r-- | src/gnutls_lua.c | 465 | ||||
-rw-r--r-- | src/mod_gnutls.c | 253 |
6 files changed, 3101 insertions, 2892 deletions
diff --git a/src/gnutls_cache.c b/src/gnutls_cache.c index 90ea440..cbf879c 100644 --- a/src/gnutls_cache.c +++ b/src/gnutls_cache.c | |||
@@ -44,18 +44,18 @@ | |||
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | char *mgs_session_id2sz(unsigned char *id, int idlen, | 46 | char *mgs_session_id2sz(unsigned char *id, int idlen, |
47 | char *str, int strsize) | 47 | char *str, int strsize) |
48 | { | 48 | { |
49 | char *cp; | 49 | char *cp; |
50 | int n; | 50 | int n; |
51 | 51 | ||
52 | cp = str; | 52 | cp = str; |
53 | for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) { | 53 | for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) { |
54 | apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]); | 54 | apr_snprintf(cp, strsize - (cp - str), "%02X", id[n]); |
55 | cp += 2; | 55 | cp += 2; |
56 | } | 56 | } |
57 | *cp = '\0'; | 57 | *cp = '\0'; |
58 | return str; | 58 | return str; |
59 | } | 59 | } |
60 | 60 | ||
61 | 61 | ||
@@ -63,35 +63,38 @@ char *mgs_session_id2sz(unsigned char *id, int idlen, | |||
63 | * server:port.SessionID | 63 | * server:port.SessionID |
64 | * to disallow resuming sessions on different servers | 64 | * to disallow resuming sessions on different servers |
65 | */ | 65 | */ |
66 | static int mgs_session_id2dbm(conn_rec* c, unsigned char *id, int idlen, | 66 | static int mgs_session_id2dbm(conn_rec * c, unsigned char *id, int idlen, |
67 | apr_datum_t* dbmkey) | 67 | apr_datum_t * dbmkey) |
68 | { | 68 | { |
69 | char buf[STR_SESSION_LEN]; | 69 | char buf[STR_SESSION_LEN]; |
70 | char *sz; | 70 | char *sz; |
71 | 71 | ||
72 | sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf)); | 72 | sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf)); |
73 | if (sz == NULL) | 73 | if (sz == NULL) |
74 | return -1; | 74 | return -1; |
75 | 75 | ||
76 | dbmkey->dptr = apr_psprintf(c->pool, "%s:%d.%s", c->base_server->server_hostname, c->base_server->port, sz); | 76 | dbmkey->dptr = |
77 | dbmkey->dsize = strlen( dbmkey->dptr); | 77 | apr_psprintf(c->pool, "%s:%d.%s", |
78 | 78 | c->base_server->server_hostname, | |
79 | return 0; | 79 | c->base_server->port, sz); |
80 | dbmkey->dsize = strlen(dbmkey->dptr); | ||
81 | |||
82 | return 0; | ||
80 | } | 83 | } |
81 | 84 | ||
82 | #define CTIME "%b %d %k:%M:%S %Y %Z" | 85 | #define CTIME "%b %d %k:%M:%S %Y %Z" |
83 | char *mgs_time2sz(time_t in_time, char *str, int strsize) | 86 | char *mgs_time2sz(time_t in_time, char *str, int strsize) |
84 | { | 87 | { |
85 | apr_time_exp_t vtm; | 88 | apr_time_exp_t vtm; |
86 | apr_size_t ret_size; | 89 | apr_size_t ret_size; |
87 | apr_time_t t; | 90 | apr_time_t t; |
88 | 91 | ||
89 | 92 | ||
90 | apr_time_ansi_put (&t, in_time); | 93 | apr_time_ansi_put(&t, in_time); |
91 | apr_time_exp_gmt (&vtm, t); | 94 | apr_time_exp_gmt(&vtm, t); |
92 | apr_strftime(str, &ret_size, strsize-1, CTIME, &vtm); | 95 | apr_strftime(str, &ret_size, strsize - 1, CTIME, &vtm); |
93 | 96 | ||
94 | return str; | 97 | return str; |
95 | } | 98 | } |
96 | 99 | ||
97 | #if HAVE_APR_MEMCACHE | 100 | #if HAVE_APR_MEMCACHE |
@@ -99,16 +102,18 @@ char *mgs_time2sz(time_t in_time, char *str, int strsize) | |||
99 | * server:port.SessionID | 102 | * server:port.SessionID |
100 | * to disallow resuming sessions on different servers | 103 | * to disallow resuming sessions on different servers |
101 | */ | 104 | */ |
102 | static char* mgs_session_id2mc(conn_rec* c, unsigned char *id, int idlen) | 105 | static char *mgs_session_id2mc(conn_rec * c, unsigned char *id, int idlen) |
103 | { | 106 | { |
104 | char buf[STR_SESSION_LEN]; | 107 | char buf[STR_SESSION_LEN]; |
105 | char *sz; | 108 | char *sz; |
106 | 109 | ||
107 | sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf)); | 110 | sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf)); |
108 | if (sz == NULL) | 111 | if (sz == NULL) |
109 | return NULL; | 112 | return NULL; |
110 | 113 | ||
111 | return apr_psprintf(c->pool, MC_TAG"%s:%d.%s", c->base_server->server_hostname, c->base_server->port, sz); | 114 | return apr_psprintf(c->pool, MC_TAG "%s:%d.%s", |
115 | c->base_server->server_hostname, | ||
116 | c->base_server->port, sz); | ||
112 | } | 117 | } |
113 | 118 | ||
114 | /** | 119 | /** |
@@ -117,482 +122,498 @@ char *sz; | |||
117 | */ | 122 | */ |
118 | 123 | ||
119 | /* The underlying apr_memcache system is thread safe... woohoo */ | 124 | /* The underlying apr_memcache system is thread safe... woohoo */ |
120 | static apr_memcache_t* mc; | 125 | static apr_memcache_t *mc; |
121 | 126 | ||
122 | static int mc_cache_child_init(apr_pool_t *p, server_rec *s, | 127 | static int mc_cache_child_init(apr_pool_t * p, server_rec * s, |
123 | mgs_srvconf_rec *sc) | 128 | mgs_srvconf_rec * sc) |
124 | { | 129 | { |
125 | apr_status_t rv = APR_SUCCESS; | 130 | apr_status_t rv = APR_SUCCESS; |
126 | int thread_limit = 0; | 131 | int thread_limit = 0; |
127 | int nservers = 0; | 132 | int nservers = 0; |
128 | char* cache_config; | 133 | char *cache_config; |
129 | char* split; | 134 | char *split; |
130 | char* tok; | 135 | char *tok; |
131 | 136 | ||
132 | ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit); | 137 | ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit); |
133 | 138 | ||
134 | /* Find all the servers in the first run to get a total count */ | 139 | /* Find all the servers in the first run to get a total count */ |
135 | cache_config = apr_pstrdup(p, sc->cache_config); | 140 | cache_config = apr_pstrdup(p, sc->cache_config); |
136 | split = apr_strtok(cache_config, " ", &tok); | 141 | split = apr_strtok(cache_config, " ", &tok); |
137 | while (split) { | 142 | while (split) { |
138 | nservers++; | 143 | nservers++; |
139 | split = apr_strtok(NULL," ", &tok); | 144 | split = apr_strtok(NULL, " ", &tok); |
140 | } | 145 | } |
141 | 146 | ||
142 | rv = apr_memcache_create(p, nservers, 0, &mc); | 147 | rv = apr_memcache_create(p, nservers, 0, &mc); |
143 | if (rv != APR_SUCCESS) { | 148 | if (rv != APR_SUCCESS) { |
144 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, | 149 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, |
145 | "[gnutls_cache] Failed to create Memcache Object of '%d' size.", | 150 | "[gnutls_cache] Failed to create Memcache Object of '%d' size.", |
146 | nservers); | 151 | nservers); |
147 | return rv; | 152 | return rv; |
148 | } | 153 | } |
149 | 154 | ||
150 | /* Now add each server to the memcache */ | 155 | /* Now add each server to the memcache */ |
151 | cache_config = apr_pstrdup(p, sc->cache_config); | 156 | cache_config = apr_pstrdup(p, sc->cache_config); |
152 | split = apr_strtok(cache_config, " ", &tok); | 157 | split = apr_strtok(cache_config, " ", &tok); |
153 | while (split) { | 158 | while (split) { |
154 | apr_memcache_server_t* st; | 159 | apr_memcache_server_t *st; |
155 | char* host_str; | 160 | char *host_str; |
156 | char* scope_id; | 161 | char *scope_id; |
157 | apr_port_t port; | 162 | apr_port_t port; |
158 | 163 | ||
159 | rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p); | 164 | rv = apr_parse_addr_port(&host_str, &scope_id, &port, |
160 | if (rv != APR_SUCCESS) { | 165 | split, p); |
161 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, | 166 | if (rv != APR_SUCCESS) { |
162 | "[gnutls_cache] Failed to Parse Server: '%s'", split); | 167 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, |
163 | return rv; | 168 | "[gnutls_cache] Failed to Parse Server: '%s'", |
164 | } | 169 | split); |
165 | 170 | return rv; | |
166 | if (host_str == NULL) { | 171 | } |
167 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, | 172 | |
168 | "[gnutls_cache] Failed to Parse Server, " | 173 | if (host_str == NULL) { |
169 | "no hostname specified: '%s'", split); | 174 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, |
170 | return rv; | 175 | "[gnutls_cache] Failed to Parse Server, " |
171 | } | 176 | "no hostname specified: '%s'", split); |
172 | 177 | return rv; | |
173 | if (port == 0) { | 178 | } |
174 | port = 11211; /* default port */ | 179 | |
175 | } | 180 | if (port == 0) { |
176 | 181 | port = 11211; /* default port */ | |
177 | /* Should Max Conns be (thread_limit / nservers) ? */ | 182 | } |
178 | rv = apr_memcache_server_create(p, | 183 | |
179 | host_str, port, | 184 | /* Should Max Conns be (thread_limit / nservers) ? */ |
180 | 0, | 185 | rv = apr_memcache_server_create(p, |
181 | 1, | 186 | host_str, port, |
182 | thread_limit, | 187 | 0, |
183 | 600, | 188 | 1, thread_limit, 600, &st); |
184 | &st); | 189 | if (rv != APR_SUCCESS) { |
185 | if (rv != APR_SUCCESS) { | 190 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, |
186 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, | 191 | "[gnutls_cache] Failed to Create Server: %s:%d", |
187 | "[gnutls_cache] Failed to Create Server: %s:%d", | 192 | host_str, port); |
188 | host_str, port); | 193 | return rv; |
189 | return rv; | 194 | } |
190 | } | 195 | |
191 | 196 | rv = apr_memcache_add_server(mc, st); | |
192 | rv = apr_memcache_add_server(mc, st); | 197 | if (rv != APR_SUCCESS) { |
193 | if (rv != APR_SUCCESS) { | 198 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, |
194 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, | 199 | "[gnutls_cache] Failed to Add Server: %s:%d", |
195 | "[gnutls_cache] Failed to Add Server: %s:%d", | 200 | host_str, port); |
196 | host_str, port); | 201 | return rv; |
197 | return rv; | 202 | } |
198 | } | 203 | |
199 | 204 | split = apr_strtok(NULL, " ", &tok); | |
200 | split = apr_strtok(NULL," ", &tok); | 205 | } |
201 | } | 206 | return rv; |
202 | return rv; | ||
203 | } | 207 | } |
204 | 208 | ||
205 | static int mc_cache_store(void* baton, gnutls_datum_t key, | 209 | static int mc_cache_store(void *baton, gnutls_datum_t key, |
206 | gnutls_datum_t data) | 210 | gnutls_datum_t data) |
207 | { | 211 | { |
208 | apr_status_t rv = APR_SUCCESS; | 212 | apr_status_t rv = APR_SUCCESS; |
209 | mgs_handle_t *ctxt = baton; | 213 | mgs_handle_t *ctxt = baton; |
210 | char* strkey = NULL; | 214 | char *strkey = NULL; |
211 | apr_uint32_t timeout; | 215 | apr_uint32_t timeout; |
212 | 216 | ||
213 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); | 217 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); |
214 | if(!strkey) | 218 | if (!strkey) |
215 | return -1; | 219 | return -1; |
216 | 220 | ||
217 | timeout = apr_time_sec(ctxt->sc->cache_timeout); | 221 | timeout = apr_time_sec(ctxt->sc->cache_timeout); |
218 | 222 | ||
219 | rv = apr_memcache_set(mc, strkey, data.data, data.size, timeout, 0); | 223 | rv = apr_memcache_set(mc, strkey, data.data, data.size, timeout, |
224 | 0); | ||
220 | 225 | ||
221 | if (rv != APR_SUCCESS) { | 226 | if (rv != APR_SUCCESS) { |
222 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, | 227 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, |
223 | ctxt->c->base_server, | 228 | ctxt->c->base_server, |
224 | "[gnutls_cache] error setting key '%s' " | 229 | "[gnutls_cache] error setting key '%s' " |
225 | "with %d bytes of data", strkey, data.size); | 230 | "with %d bytes of data", strkey, data.size); |
226 | return -1; | 231 | return -1; |
227 | } | 232 | } |
228 | 233 | ||
229 | return 0; | 234 | return 0; |
230 | } | 235 | } |
231 | 236 | ||
232 | static gnutls_datum_t mc_cache_fetch(void* baton, gnutls_datum_t key) | 237 | static gnutls_datum_t mc_cache_fetch(void *baton, gnutls_datum_t key) |
233 | { | 238 | { |
234 | apr_status_t rv = APR_SUCCESS; | 239 | apr_status_t rv = APR_SUCCESS; |
235 | mgs_handle_t *ctxt = baton; | 240 | mgs_handle_t *ctxt = baton; |
236 | char* strkey = NULL; | 241 | char *strkey = NULL; |
237 | char* value; | 242 | char *value; |
238 | apr_size_t value_len; | 243 | apr_size_t value_len; |
239 | gnutls_datum_t data = { NULL, 0 }; | 244 | gnutls_datum_t data = { NULL, 0 }; |
240 | 245 | ||
241 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); | 246 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); |
242 | if (!strkey) { | 247 | if (!strkey) { |
243 | return data; | 248 | return data; |
244 | } | 249 | } |
245 | 250 | ||
246 | rv = apr_memcache_getp(mc, ctxt->c->pool, strkey, | 251 | rv = apr_memcache_getp(mc, ctxt->c->pool, strkey, |
247 | &value, &value_len, NULL); | 252 | &value, &value_len, NULL); |
248 | 253 | ||
249 | if (rv != APR_SUCCESS) { | 254 | if (rv != APR_SUCCESS) { |
250 | #if MOD_GNUTLS_DEBUG | 255 | #if MOD_GNUTLS_DEBUG |
251 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, | 256 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, |
252 | ctxt->c->base_server, | 257 | ctxt->c->base_server, |
253 | "[gnutls_cache] error fetching key '%s' ", | 258 | "[gnutls_cache] error fetching key '%s' ", |
254 | strkey); | 259 | strkey); |
255 | #endif | 260 | #endif |
256 | data.size = 0; | 261 | data.size = 0; |
257 | data.data = NULL; | 262 | data.data = NULL; |
258 | return data; | 263 | return data; |
259 | } | 264 | } |
260 | 265 | ||
261 | /* TODO: Eliminate this memcpy. gnutls-- */ | 266 | /* TODO: Eliminate this memcpy. gnutls-- */ |
262 | data.data = gnutls_malloc(value_len); | 267 | data.data = gnutls_malloc(value_len); |
263 | if (data.data == NULL) | 268 | if (data.data == NULL) |
264 | return data; | 269 | return data; |
265 | 270 | ||
266 | data.size = value_len; | 271 | data.size = value_len; |
267 | memcpy(data.data, value, value_len); | 272 | memcpy(data.data, value, value_len); |
268 | 273 | ||
269 | return data; | 274 | return data; |
270 | } | 275 | } |
271 | 276 | ||
272 | static int mc_cache_delete(void* baton, gnutls_datum_t key) | 277 | static int mc_cache_delete(void *baton, gnutls_datum_t key) |
273 | { | 278 | { |
274 | apr_status_t rv = APR_SUCCESS; | 279 | apr_status_t rv = APR_SUCCESS; |
275 | mgs_handle_t *ctxt = baton; | 280 | mgs_handle_t *ctxt = baton; |
276 | char* strkey = NULL; | 281 | char *strkey = NULL; |
277 | 282 | ||
278 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); | 283 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); |
279 | if(!strkey) | 284 | if (!strkey) |
280 | return -1; | 285 | return -1; |
281 | 286 | ||
282 | rv = apr_memcache_delete(mc, strkey, 0); | 287 | rv = apr_memcache_delete(mc, strkey, 0); |
283 | 288 | ||
284 | if (rv != APR_SUCCESS) { | 289 | if (rv != APR_SUCCESS) { |
285 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, | 290 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, |
286 | ctxt->c->base_server, | 291 | ctxt->c->base_server, |
287 | "[gnutls_cache] error deleting key '%s' ", | 292 | "[gnutls_cache] error deleting key '%s' ", |
288 | strkey); | 293 | strkey); |
289 | return -1; | 294 | return -1; |
290 | } | 295 | } |
291 | 296 | ||
292 | return 0; | 297 | return 0; |
293 | } | 298 | } |
294 | 299 | ||
295 | #endif /* have_apr_memcache */ | 300 | #endif /* have_apr_memcache */ |
296 | 301 | ||
297 | const char* db_type(mgs_srvconf_rec * sc) | 302 | const char *db_type(mgs_srvconf_rec * sc) |
298 | { | 303 | { |
299 | if (sc->cache_type == mgs_cache_gdbm) | 304 | if (sc->cache_type == mgs_cache_gdbm) |
300 | return "gdbm"; | 305 | return "gdbm"; |
301 | else | 306 | else |
302 | return "db"; | 307 | return "db"; |
303 | } | 308 | } |
304 | 309 | ||
305 | #define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD ) | 310 | #define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD ) |
306 | 311 | ||
307 | static void dbm_cache_expire(mgs_handle_t *ctxt) | 312 | static void dbm_cache_expire(mgs_handle_t * ctxt) |
308 | { | 313 | { |
309 | apr_status_t rv; | 314 | apr_status_t rv; |
310 | apr_dbm_t *dbm; | 315 | apr_dbm_t *dbm; |
311 | apr_datum_t dbmkey; | 316 | apr_datum_t dbmkey; |
312 | apr_datum_t dbmval; | 317 | apr_datum_t dbmval; |
313 | apr_time_t now; | 318 | apr_time_t now; |
314 | apr_time_t dtime; | 319 | apr_time_t dtime; |
315 | apr_pool_t* spool; | 320 | apr_pool_t *spool; |
316 | int total, deleted; | 321 | int total, deleted; |
317 | 322 | ||
318 | now = apr_time_now(); | 323 | now = apr_time_now(); |
319 | 324 | ||
320 | if (now - ctxt->sc->last_cache_check < (ctxt->sc->cache_timeout)/2) | 325 | if (now - ctxt->sc->last_cache_check < |
321 | return; | 326 | (ctxt->sc->cache_timeout) / 2) |
322 | 327 | return; | |
323 | ctxt->sc->last_cache_check = now; | 328 | |
324 | 329 | ctxt->sc->last_cache_check = now; | |
325 | apr_pool_create(&spool, ctxt->c->pool); | 330 | |
326 | 331 | apr_pool_create(&spool, ctxt->c->pool); | |
327 | total = 0; | 332 | |
328 | deleted = 0; | 333 | total = 0; |
329 | 334 | deleted = 0; | |
330 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config, APR_DBM_RWCREATE, | 335 | |
331 | SSL_DBM_FILE_MODE, spool); | 336 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), |
332 | if (rv != APR_SUCCESS) { | 337 | ctxt->sc->cache_config, APR_DBM_RWCREATE, |
333 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | 338 | SSL_DBM_FILE_MODE, spool); |
334 | ctxt->c->base_server, | 339 | if (rv != APR_SUCCESS) { |
335 | "[gnutls_cache] error opening cache searcher '%s'", | 340 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, |
336 | ctxt->sc->cache_config); | 341 | ctxt->c->base_server, |
337 | apr_pool_destroy(spool); | 342 | "[gnutls_cache] error opening cache searcher '%s'", |
338 | return; | 343 | ctxt->sc->cache_config); |
339 | } | 344 | apr_pool_destroy(spool); |
340 | 345 | return; | |
341 | apr_dbm_firstkey(dbm, &dbmkey); | 346 | } |
342 | while (dbmkey.dptr != NULL) { | 347 | |
343 | apr_dbm_fetch(dbm, dbmkey, &dbmval); | 348 | apr_dbm_firstkey(dbm, &dbmkey); |
344 | if (dbmval.dptr != NULL && dbmval.dsize >= sizeof(apr_time_t)) { | 349 | while (dbmkey.dptr != NULL) { |
345 | memcpy(&dtime, dbmval.dptr, sizeof(apr_time_t)); | 350 | apr_dbm_fetch(dbm, dbmkey, &dbmval); |
346 | 351 | if (dbmval.dptr != NULL | |
347 | if (now >= dtime) { | 352 | && dbmval.dsize >= sizeof(apr_time_t)) { |
348 | apr_dbm_delete(dbm, dbmkey); | 353 | memcpy(&dtime, dbmval.dptr, sizeof(apr_time_t)); |
349 | deleted++; | 354 | |
350 | } | 355 | if (now >= dtime) { |
351 | apr_dbm_freedatum( dbm, dbmval); | 356 | apr_dbm_delete(dbm, dbmkey); |
352 | } else { | 357 | deleted++; |
353 | apr_dbm_delete(dbm, dbmkey); | 358 | } |
354 | deleted++; | 359 | apr_dbm_freedatum(dbm, dbmval); |
355 | } | 360 | } else { |
356 | total++; | 361 | apr_dbm_delete(dbm, dbmkey); |
357 | apr_dbm_nextkey(dbm, &dbmkey); | 362 | deleted++; |
358 | } | 363 | } |
359 | apr_dbm_close(dbm); | 364 | total++; |
360 | 365 | apr_dbm_nextkey(dbm, &dbmkey); | |
361 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, | 366 | } |
362 | ctxt->c->base_server, | 367 | apr_dbm_close(dbm); |
363 | "[gnutls_cache] Cleaned up cache '%s'. Deleted %d and left %d", | 368 | |
364 | ctxt->sc->cache_config, deleted, total-deleted); | 369 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, |
365 | 370 | ctxt->c->base_server, | |
366 | apr_pool_destroy(spool); | 371 | "[gnutls_cache] Cleaned up cache '%s'. Deleted %d and left %d", |
367 | 372 | ctxt->sc->cache_config, deleted, total - deleted); | |
368 | return; | 373 | |
374 | apr_pool_destroy(spool); | ||
375 | |||
376 | return; | ||
369 | } | 377 | } |
370 | 378 | ||
371 | static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key) | 379 | static gnutls_datum_t dbm_cache_fetch(void *baton, gnutls_datum_t key) |
372 | { | 380 | { |
373 | gnutls_datum_t data = { NULL, 0 }; | 381 | gnutls_datum_t data = { NULL, 0 }; |
374 | apr_dbm_t *dbm; | 382 | apr_dbm_t *dbm; |
375 | apr_datum_t dbmkey; | 383 | apr_datum_t dbmkey; |
376 | apr_datum_t dbmval; | 384 | apr_datum_t dbmval; |
377 | mgs_handle_t *ctxt = baton; | 385 | mgs_handle_t *ctxt = baton; |
378 | apr_status_t rv; | 386 | apr_status_t rv; |
379 | 387 | ||
380 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) | 388 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) |
381 | return data; | 389 | return data; |
382 | 390 | ||
383 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config, | 391 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), |
384 | APR_DBM_READONLY, SSL_DBM_FILE_MODE, ctxt->c->pool); | 392 | ctxt->sc->cache_config, APR_DBM_READONLY, |
385 | if (rv != APR_SUCCESS) { | 393 | SSL_DBM_FILE_MODE, ctxt->c->pool); |
386 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | 394 | if (rv != APR_SUCCESS) { |
387 | ctxt->c->base_server, | 395 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, |
388 | "[gnutls_cache] error opening cache '%s'", | 396 | ctxt->c->base_server, |
389 | ctxt->sc->cache_config); | 397 | "[gnutls_cache] error opening cache '%s'", |
390 | return data; | 398 | ctxt->sc->cache_config); |
391 | } | 399 | return data; |
392 | 400 | } | |
393 | rv = apr_dbm_fetch(dbm, dbmkey, &dbmval); | 401 | |
394 | 402 | rv = apr_dbm_fetch(dbm, dbmkey, &dbmval); | |
395 | if (rv != APR_SUCCESS) { | 403 | |
396 | apr_dbm_close(dbm); | 404 | if (rv != APR_SUCCESS) { |
397 | return data; | 405 | apr_dbm_close(dbm); |
398 | } | 406 | return data; |
399 | 407 | } | |
400 | if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(apr_time_t)) { | 408 | |
401 | apr_dbm_freedatum( dbm, dbmval); | 409 | if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(apr_time_t)) { |
402 | apr_dbm_close(dbm); | 410 | apr_dbm_freedatum(dbm, dbmval); |
403 | return data; | 411 | apr_dbm_close(dbm); |
404 | } | 412 | return data; |
405 | 413 | } | |
406 | data.size = dbmval.dsize - sizeof(apr_time_t); | 414 | |
407 | 415 | data.size = dbmval.dsize - sizeof(apr_time_t); | |
408 | data.data = gnutls_malloc(data.size); | 416 | |
409 | if (data.data == NULL) { | 417 | data.data = gnutls_malloc(data.size); |
410 | apr_dbm_freedatum( dbm, dbmval); | 418 | if (data.data == NULL) { |
411 | apr_dbm_close(dbm); | 419 | apr_dbm_freedatum(dbm, dbmval); |
412 | return data; | 420 | apr_dbm_close(dbm); |
413 | } | 421 | return data; |
414 | 422 | } | |
415 | memcpy(data.data, dbmval.dptr+sizeof(apr_time_t), data.size); | 423 | |
416 | 424 | memcpy(data.data, dbmval.dptr + sizeof(apr_time_t), data.size); | |
417 | apr_dbm_freedatum( dbm, dbmval); | 425 | |
418 | apr_dbm_close(dbm); | 426 | apr_dbm_freedatum(dbm, dbmval); |
419 | 427 | apr_dbm_close(dbm); | |
420 | return data; | 428 | |
429 | return data; | ||
421 | } | 430 | } |
422 | 431 | ||
423 | static int dbm_cache_store(void* baton, gnutls_datum_t key, | 432 | static int dbm_cache_store(void *baton, gnutls_datum_t key, |
424 | gnutls_datum_t data) | 433 | gnutls_datum_t data) |
425 | { | 434 | { |
426 | apr_dbm_t *dbm; | 435 | apr_dbm_t *dbm; |
427 | apr_datum_t dbmkey; | 436 | apr_datum_t dbmkey; |
428 | apr_datum_t dbmval; | 437 | apr_datum_t dbmval; |
429 | mgs_handle_t *ctxt = baton; | 438 | mgs_handle_t *ctxt = baton; |
430 | apr_status_t rv; | 439 | apr_status_t rv; |
431 | apr_time_t expiry; | 440 | apr_time_t expiry; |
432 | apr_pool_t* spool; | 441 | apr_pool_t *spool; |
433 | 442 | ||
434 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) | 443 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) |
435 | return -1; | 444 | return -1; |
436 | 445 | ||
437 | /* we expire dbm only on every store | 446 | /* we expire dbm only on every store |
438 | */ | 447 | */ |
439 | dbm_cache_expire(ctxt); | 448 | dbm_cache_expire(ctxt); |
440 | 449 | ||
441 | apr_pool_create(&spool, ctxt->c->pool); | 450 | apr_pool_create(&spool, ctxt->c->pool); |
442 | 451 | ||
443 | /* create DBM value */ | 452 | /* create DBM value */ |
444 | dbmval.dsize = data.size + sizeof(apr_time_t); | 453 | dbmval.dsize = data.size + sizeof(apr_time_t); |
445 | dbmval.dptr = (char *)apr_palloc(spool, dbmval.dsize); | 454 | dbmval.dptr = (char *) apr_palloc(spool, dbmval.dsize); |
446 | 455 | ||
447 | expiry = apr_time_now() + ctxt->sc->cache_timeout; | 456 | expiry = apr_time_now() + ctxt->sc->cache_timeout; |
448 | 457 | ||
449 | memcpy((char *)dbmval.dptr, &expiry, sizeof(apr_time_t)); | 458 | memcpy((char *) dbmval.dptr, &expiry, sizeof(apr_time_t)); |
450 | memcpy((char *)dbmval.dptr+sizeof(apr_time_t), | 459 | memcpy((char *) dbmval.dptr + sizeof(apr_time_t), |
451 | data.data, data.size); | 460 | data.data, data.size); |
452 | 461 | ||
453 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config, | 462 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), |
454 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); | 463 | ctxt->sc->cache_config, APR_DBM_RWCREATE, |
455 | if (rv != APR_SUCCESS) { | 464 | SSL_DBM_FILE_MODE, ctxt->c->pool); |
456 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | 465 | if (rv != APR_SUCCESS) { |
457 | ctxt->c->base_server, | 466 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, |
458 | "[gnutls_cache] error opening cache '%s'", | 467 | ctxt->c->base_server, |
459 | ctxt->sc->cache_config); | 468 | "[gnutls_cache] error opening cache '%s'", |
460 | apr_pool_destroy(spool); | 469 | ctxt->sc->cache_config); |
461 | return -1; | 470 | apr_pool_destroy(spool); |
462 | } | 471 | return -1; |
463 | 472 | } | |
464 | rv = apr_dbm_store(dbm, dbmkey, dbmval); | 473 | |
465 | 474 | rv = apr_dbm_store(dbm, dbmkey, dbmval); | |
466 | if (rv != APR_SUCCESS) { | 475 | |
467 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, | 476 | if (rv != APR_SUCCESS) { |
468 | ctxt->c->base_server, | 477 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, |
469 | "[gnutls_cache] error storing in cache '%s'", | 478 | ctxt->c->base_server, |
470 | ctxt->sc->cache_config); | 479 | "[gnutls_cache] error storing in cache '%s'", |
471 | apr_dbm_close(dbm); | 480 | ctxt->sc->cache_config); |
472 | apr_pool_destroy(spool); | 481 | apr_dbm_close(dbm); |
473 | return -1; | 482 | apr_pool_destroy(spool); |
474 | } | 483 | return -1; |
475 | 484 | } | |
476 | apr_dbm_close(dbm); | 485 | |
477 | 486 | apr_dbm_close(dbm); | |
478 | apr_pool_destroy(spool); | 487 | |
479 | 488 | apr_pool_destroy(spool); | |
480 | return 0; | 489 | |
490 | return 0; | ||
481 | } | 491 | } |
482 | 492 | ||
483 | static int dbm_cache_delete(void* baton, gnutls_datum_t key) | 493 | static int dbm_cache_delete(void *baton, gnutls_datum_t key) |
484 | { | 494 | { |
485 | apr_dbm_t *dbm; | 495 | apr_dbm_t *dbm; |
486 | apr_datum_t dbmkey; | 496 | apr_datum_t dbmkey; |
487 | mgs_handle_t *ctxt = baton; | 497 | mgs_handle_t *ctxt = baton; |
488 | apr_status_t rv; | 498 | apr_status_t rv; |
489 | 499 | ||
490 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) | 500 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) |
491 | return -1; | 501 | return -1; |
492 | 502 | ||
493 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config, | 503 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), |
494 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); | 504 | ctxt->sc->cache_config, APR_DBM_RWCREATE, |
495 | if (rv != APR_SUCCESS) { | 505 | SSL_DBM_FILE_MODE, ctxt->c->pool); |
496 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | 506 | if (rv != APR_SUCCESS) { |
497 | ctxt->c->base_server, | 507 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, |
498 | "[gnutls_cache] error opening cache '%s'", | 508 | ctxt->c->base_server, |
499 | ctxt->sc->cache_config); | 509 | "[gnutls_cache] error opening cache '%s'", |
500 | return -1; | 510 | ctxt->sc->cache_config); |
501 | } | 511 | return -1; |
502 | 512 | } | |
503 | rv = apr_dbm_delete(dbm, dbmkey); | 513 | |
504 | 514 | rv = apr_dbm_delete(dbm, dbmkey); | |
505 | if (rv != APR_SUCCESS) { | 515 | |
506 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | 516 | if (rv != APR_SUCCESS) { |
507 | ctxt->c->base_server, | 517 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, |
508 | "[gnutls_cache] error deleting from cache '%s'", | 518 | ctxt->c->base_server, |
509 | ctxt->sc->cache_config); | 519 | "[gnutls_cache] error deleting from cache '%s'", |
510 | apr_dbm_close(dbm); | 520 | ctxt->sc->cache_config); |
511 | return -1; | 521 | apr_dbm_close(dbm); |
512 | } | 522 | return -1; |
513 | 523 | } | |
514 | apr_dbm_close(dbm); | 524 | |
515 | 525 | apr_dbm_close(dbm); | |
516 | return 0; | 526 | |
527 | return 0; | ||
517 | } | 528 | } |
518 | 529 | ||
519 | static int dbm_cache_post_config(apr_pool_t *p, server_rec *s, | 530 | static int dbm_cache_post_config(apr_pool_t * p, server_rec * s, |
520 | mgs_srvconf_rec *sc) | 531 | mgs_srvconf_rec * sc) |
521 | { | 532 | { |
522 | apr_status_t rv; | 533 | apr_status_t rv; |
523 | apr_dbm_t *dbm; | 534 | apr_dbm_t *dbm; |
524 | const char* path1; | 535 | const char *path1; |
525 | const char* path2; | 536 | const char *path2; |
526 | 537 | ||
527 | rv = apr_dbm_open_ex(&dbm, db_type(sc), sc->cache_config, APR_DBM_RWCREATE, | 538 | rv = apr_dbm_open_ex(&dbm, db_type(sc), sc->cache_config, |
528 | SSL_DBM_FILE_MODE, p); | 539 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, p); |
529 | 540 | ||
530 | if (rv != APR_SUCCESS) { | 541 | if (rv != APR_SUCCESS) { |
531 | ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, | 542 | ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, |
532 | "GnuTLS: Cannot create DBM Cache at `%s'", | 543 | "GnuTLS: Cannot create DBM Cache at `%s'", |
533 | sc->cache_config); | 544 | sc->cache_config); |
534 | return rv; | 545 | return rv; |
535 | } | 546 | } |
536 | 547 | ||
537 | apr_dbm_close(dbm); | 548 | apr_dbm_close(dbm); |
538 | 549 | ||
539 | apr_dbm_get_usednames_ex(p, db_type(sc), sc->cache_config, &path1, &path2); | 550 | apr_dbm_get_usednames_ex(p, db_type(sc), sc->cache_config, &path1, |
551 | &path2); | ||
540 | 552 | ||
541 | /* The Following Code takes logic directly from mod_ssl's DBM Cache */ | 553 | /* The Following Code takes logic directly from mod_ssl's DBM Cache */ |
542 | #if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE) | 554 | #if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE) |
543 | /* Running as Root */ | 555 | /* Running as Root */ |
544 | if (path1 && geteuid() == 0) { | 556 | if (path1 && geteuid() == 0) { |
545 | chown(path1, ap_unixd_config.user_id, -1); | 557 | chown(path1, ap_unixd_config.user_id, -1); |
546 | if (path2 != NULL) { | 558 | if (path2 != NULL) { |
547 | chown(path2, ap_unixd_config.user_id, -1); | 559 | chown(path2, ap_unixd_config.user_id, -1); |
548 | } | 560 | } |
549 | } | 561 | } |
550 | #endif | 562 | #endif |
551 | 563 | ||
552 | return rv; | 564 | return rv; |
553 | } | 565 | } |
554 | 566 | ||
555 | int mgs_cache_post_config(apr_pool_t *p, server_rec *s, | 567 | int mgs_cache_post_config(apr_pool_t * p, server_rec * s, |
556 | mgs_srvconf_rec *sc) | 568 | mgs_srvconf_rec * sc) |
557 | { | 569 | { |
558 | if (sc->cache_type == mgs_cache_dbm || sc->cache_type == mgs_cache_gdbm) { | 570 | if (sc->cache_type == mgs_cache_dbm |
559 | return dbm_cache_post_config(p, s, sc); | 571 | || sc->cache_type == mgs_cache_gdbm) { |
560 | } | 572 | return dbm_cache_post_config(p, s, sc); |
561 | return 0; | 573 | } |
574 | return 0; | ||
562 | } | 575 | } |
563 | 576 | ||
564 | int mgs_cache_child_init(apr_pool_t *p, server_rec *s, | 577 | int mgs_cache_child_init(apr_pool_t * p, server_rec * s, |
565 | mgs_srvconf_rec *sc) | 578 | mgs_srvconf_rec * sc) |
566 | { | 579 | { |
567 | if (sc->cache_type == mgs_cache_dbm || sc->cache_type == mgs_cache_gdbm) { | 580 | if (sc->cache_type == mgs_cache_dbm |
568 | return 0; | 581 | || sc->cache_type == mgs_cache_gdbm) { |
569 | } | 582 | return 0; |
583 | } | ||
570 | #if HAVE_APR_MEMCACHE | 584 | #if HAVE_APR_MEMCACHE |
571 | else if (sc->cache_type == mgs_cache_memcache) { | 585 | else if (sc->cache_type == mgs_cache_memcache) { |
572 | return mc_cache_child_init(p, s, sc); | 586 | return mc_cache_child_init(p, s, sc); |
573 | } | 587 | } |
574 | #endif | 588 | #endif |
575 | return 0; | 589 | return 0; |
576 | } | 590 | } |
577 | 591 | ||
578 | #include <assert.h> | 592 | #include <assert.h> |
579 | 593 | ||
580 | int mgs_cache_session_init(mgs_handle_t *ctxt) | 594 | int mgs_cache_session_init(mgs_handle_t * ctxt) |
581 | { | 595 | { |
582 | if (ctxt->sc->cache_type == mgs_cache_dbm || ctxt->sc->cache_type == mgs_cache_gdbm) { | 596 | if (ctxt->sc->cache_type == mgs_cache_dbm |
583 | gnutls_db_set_retrieve_function(ctxt->session, dbm_cache_fetch); | 597 | || ctxt->sc->cache_type == mgs_cache_gdbm) { |
584 | gnutls_db_set_remove_function(ctxt->session, dbm_cache_delete); | 598 | gnutls_db_set_retrieve_function(ctxt->session, |
585 | gnutls_db_set_store_function(ctxt->session, dbm_cache_store); | 599 | dbm_cache_fetch); |
586 | gnutls_db_set_ptr(ctxt->session, ctxt); | 600 | gnutls_db_set_remove_function(ctxt->session, |
587 | } | 601 | dbm_cache_delete); |
602 | gnutls_db_set_store_function(ctxt->session, | ||
603 | dbm_cache_store); | ||
604 | gnutls_db_set_ptr(ctxt->session, ctxt); | ||
605 | } | ||
588 | #if HAVE_APR_MEMCACHE | 606 | #if HAVE_APR_MEMCACHE |
589 | else if (ctxt->sc->cache_type == mgs_cache_memcache) { | 607 | else if (ctxt->sc->cache_type == mgs_cache_memcache) { |
590 | gnutls_db_set_retrieve_function(ctxt->session, mc_cache_fetch); | 608 | gnutls_db_set_retrieve_function(ctxt->session, |
591 | gnutls_db_set_remove_function(ctxt->session, mc_cache_delete); | 609 | mc_cache_fetch); |
592 | gnutls_db_set_store_function(ctxt->session, mc_cache_store); | 610 | gnutls_db_set_remove_function(ctxt->session, |
593 | gnutls_db_set_ptr(ctxt->session, ctxt); | 611 | mc_cache_delete); |
594 | } | 612 | gnutls_db_set_store_function(ctxt->session, |
613 | mc_cache_store); | ||
614 | gnutls_db_set_ptr(ctxt->session, ctxt); | ||
615 | } | ||
595 | #endif | 616 | #endif |
596 | 617 | ||
597 | return 0; | 618 | return 0; |
598 | } | 619 | } |
diff --git a/src/gnutls_config.c b/src/gnutls_config.c index ff8ec33..fc3e166 100644 --- a/src/gnutls_config.c +++ b/src/gnutls_config.c | |||
@@ -21,284 +21,308 @@ | |||
21 | static int load_datum_from_file(apr_pool_t * pool, | 21 | static int load_datum_from_file(apr_pool_t * pool, |
22 | const char *file, gnutls_datum_t * data) | 22 | const char *file, gnutls_datum_t * data) |
23 | { | 23 | { |
24 | apr_file_t *fp; | 24 | apr_file_t *fp; |
25 | apr_finfo_t finfo; | 25 | apr_finfo_t finfo; |
26 | apr_status_t rv; | 26 | apr_status_t rv; |
27 | apr_size_t br = 0; | 27 | apr_size_t br = 0; |
28 | 28 | ||
29 | rv = apr_file_open(&fp, file, APR_READ | APR_BINARY, APR_OS_DEFAULT, | 29 | rv = apr_file_open(&fp, file, APR_READ | APR_BINARY, |
30 | pool); | 30 | APR_OS_DEFAULT, pool); |
31 | if (rv != APR_SUCCESS) { | 31 | if (rv != APR_SUCCESS) { |
32 | return rv; | 32 | return rv; |
33 | } | 33 | } |
34 | 34 | ||
35 | rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp); | 35 | rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp); |
36 | 36 | ||
37 | if (rv != APR_SUCCESS) { | 37 | if (rv != APR_SUCCESS) { |
38 | return rv; | 38 | return rv; |
39 | } | 39 | } |
40 | 40 | ||
41 | data->data = apr_palloc(pool, finfo.size + 1); | 41 | data->data = apr_palloc(pool, finfo.size + 1); |
42 | rv = apr_file_read_full(fp, data->data, finfo.size, &br); | 42 | rv = apr_file_read_full(fp, data->data, finfo.size, &br); |
43 | 43 | ||
44 | if (rv != APR_SUCCESS) { | 44 | if (rv != APR_SUCCESS) { |
45 | return rv; | 45 | return rv; |
46 | } | 46 | } |
47 | apr_file_close(fp); | 47 | apr_file_close(fp); |
48 | 48 | ||
49 | data->data[br] = '\0'; | 49 | data->data[br] = '\0'; |
50 | data->size = br; | 50 | data->size = br; |
51 | 51 | ||
52 | return 0; | 52 | return 0; |
53 | } | 53 | } |
54 | 54 | ||
55 | const char *mgs_set_dh_file(cmd_parms * parms, void *dummy, | 55 | const char *mgs_set_dh_file(cmd_parms * parms, void *dummy, |
56 | const char *arg) | 56 | const char *arg) |
57 | { | 57 | { |
58 | int ret; | 58 | int ret; |
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 | mgs_srvconf_rec *sc = | 62 | mgs_srvconf_rec *sc = |
63 | (mgs_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 | 66 | ||
67 | apr_pool_create(&spool, parms->pool); | 67 | apr_pool_create(&spool, parms->pool); |
68 | 68 | ||
69 | file = ap_server_root_relative(spool, arg); | 69 | file = ap_server_root_relative(spool, arg); |
70 | 70 | ||
71 | if (load_datum_from_file(spool, file, &data) != 0) { | 71 | if (load_datum_from_file(spool, file, &data) != 0) { |
72 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 72 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
73 | "DH params '%s'", file); | 73 | "DH params '%s'", file); |
74 | } | 74 | } |
75 | 75 | ||
76 | ret = gnutls_dh_params_init(&sc->dh_params); | 76 | ret = gnutls_dh_params_init(&sc->dh_params); |
77 | if (ret < 0) { | 77 | if (ret < 0) { |
78 | return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" | 78 | return apr_psprintf(parms->pool, |
79 | ": (%d) %s", ret, gnutls_strerror(ret)); | 79 | "GnuTLS: Failed to initialize" |
80 | } | 80 | ": (%d) %s", ret, |
81 | 81 | gnutls_strerror(ret)); | |
82 | ret = | 82 | } |
83 | gnutls_dh_params_import_pkcs3(sc->dh_params, &data, GNUTLS_X509_FMT_PEM); | 83 | |
84 | if (ret < 0) { | 84 | ret = |
85 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | 85 | gnutls_dh_params_import_pkcs3(sc->dh_params, &data, |
86 | "DH params '%s': (%d) %s", file, ret, | 86 | GNUTLS_X509_FMT_PEM); |
87 | gnutls_strerror(ret)); | 87 | if (ret < 0) { |
88 | } | 88 | return apr_psprintf(parms->pool, |
89 | 89 | "GnuTLS: Failed to Import " | |
90 | apr_pool_destroy(spool); | 90 | "DH params '%s': (%d) %s", file, ret, |
91 | 91 | gnutls_strerror(ret)); | |
92 | return NULL; | 92 | } |
93 | |||
94 | apr_pool_destroy(spool); | ||
95 | |||
96 | return NULL; | ||
93 | } | 97 | } |
94 | 98 | ||
95 | const char *mgs_set_rsa_export_file(cmd_parms * parms, void *dummy, | 99 | const char *mgs_set_rsa_export_file(cmd_parms * parms, void *dummy, |
96 | const char *arg) | 100 | const char *arg) |
97 | { | 101 | { |
98 | int ret; | 102 | int ret; |
99 | gnutls_datum_t data; | 103 | gnutls_datum_t data; |
100 | const char *file; | 104 | const char *file; |
101 | apr_pool_t *spool; | 105 | apr_pool_t *spool; |
102 | mgs_srvconf_rec *sc = | 106 | mgs_srvconf_rec *sc = |
103 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 107 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
104 | module_config, | 108 | module_config, |
105 | &gnutls_module); | 109 | &gnutls_module); |
106 | 110 | ||
107 | apr_pool_create(&spool, parms->pool); | 111 | apr_pool_create(&spool, parms->pool); |
108 | 112 | ||
109 | file = ap_server_root_relative(spool, arg); | 113 | file = ap_server_root_relative(spool, arg); |
110 | 114 | ||
111 | if (load_datum_from_file(spool, file, &data) != 0) { | 115 | if (load_datum_from_file(spool, file, &data) != 0) { |
112 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 116 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
113 | "RSA params '%s'", file); | 117 | "RSA params '%s'", file); |
114 | } | 118 | } |
115 | 119 | ||
116 | ret = gnutls_rsa_params_init(&sc->rsa_params); | 120 | ret = gnutls_rsa_params_init(&sc->rsa_params); |
117 | if (ret < 0) { | 121 | if (ret < 0) { |
118 | return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" | 122 | return apr_psprintf(parms->pool, |
119 | ": (%d) %s", ret, gnutls_strerror(ret)); | 123 | "GnuTLS: Failed to initialize" |
120 | } | 124 | ": (%d) %s", ret, |
121 | 125 | gnutls_strerror(ret)); | |
122 | ret = | 126 | } |
123 | gnutls_rsa_params_import_pkcs1(sc->rsa_params, &data, GNUTLS_X509_FMT_PEM); | 127 | |
124 | if (ret != 0) { | 128 | ret = |
125 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | 129 | gnutls_rsa_params_import_pkcs1(sc->rsa_params, &data, |
126 | "RSA params '%s': (%d) %s", file, ret, | 130 | GNUTLS_X509_FMT_PEM); |
127 | gnutls_strerror(ret)); | 131 | if (ret != 0) { |
128 | } | 132 | return apr_psprintf(parms->pool, |
129 | 133 | "GnuTLS: Failed to Import " | |
130 | apr_pool_destroy(spool); | 134 | "RSA params '%s': (%d) %s", file, ret, |
131 | return NULL; | 135 | gnutls_strerror(ret)); |
136 | } | ||
137 | |||
138 | apr_pool_destroy(spool); | ||
139 | return NULL; | ||
132 | } | 140 | } |
133 | 141 | ||
134 | 142 | ||
135 | const char *mgs_set_cert_file(cmd_parms * parms, void *dummy, | 143 | const char *mgs_set_cert_file(cmd_parms * parms, void *dummy, |
136 | const char *arg) | 144 | const char *arg) |
137 | { | 145 | { |
138 | int ret; | 146 | int ret; |
139 | gnutls_datum_t data; | 147 | gnutls_datum_t data; |
140 | const char *file; | 148 | const char *file; |
141 | apr_pool_t *spool; | 149 | apr_pool_t *spool; |
142 | mgs_srvconf_rec *sc = | 150 | mgs_srvconf_rec *sc = |
143 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 151 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
144 | module_config, | 152 | module_config, |
145 | &gnutls_module); | 153 | &gnutls_module); |
146 | apr_pool_create(&spool, parms->pool); | 154 | apr_pool_create(&spool, parms->pool); |
147 | 155 | ||
148 | file = ap_server_root_relative(spool, arg); | 156 | file = ap_server_root_relative(spool, arg); |
149 | 157 | ||
150 | if (load_datum_from_file(spool, file, &data) != 0) { | 158 | if (load_datum_from_file(spool, file, &data) != 0) { |
151 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 159 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
152 | "Certificate '%s'", file); | 160 | "Certificate '%s'", file); |
153 | } | 161 | } |
154 | 162 | ||
155 | sc->certs_x509_num = MAX_CHAIN_SIZE; | 163 | sc->certs_x509_num = MAX_CHAIN_SIZE; |
156 | ret = | 164 | ret = |
157 | gnutls_x509_crt_list_import(sc->certs_x509, &sc->certs_x509_num, &data, GNUTLS_X509_FMT_PEM, 0); | 165 | gnutls_x509_crt_list_import(sc->certs_x509, |
158 | if (ret < 0) { | 166 | &sc->certs_x509_num, &data, |
159 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | 167 | GNUTLS_X509_FMT_PEM, 0); |
160 | "Certificate '%s': (%d) %s", file, ret, | 168 | if (ret < 0) { |
161 | gnutls_strerror(ret)); | 169 | return apr_psprintf(parms->pool, |
162 | } | 170 | "GnuTLS: Failed to Import " |
163 | 171 | "Certificate '%s': (%d) %s", file, ret, | |
164 | apr_pool_destroy(spool); | 172 | gnutls_strerror(ret)); |
165 | return NULL; | 173 | } |
174 | |||
175 | apr_pool_destroy(spool); | ||
176 | return NULL; | ||
166 | } | 177 | } |
167 | 178 | ||
168 | const char *mgs_set_key_file(cmd_parms * parms, void *dummy, | 179 | const char *mgs_set_key_file(cmd_parms * parms, void *dummy, |
169 | const char *arg) | 180 | const char *arg) |
170 | { | 181 | { |
171 | int ret; | 182 | int ret; |
172 | gnutls_datum_t data; | 183 | gnutls_datum_t data; |
173 | const char *file; | 184 | const char *file; |
174 | apr_pool_t *spool; | 185 | apr_pool_t *spool; |
175 | mgs_srvconf_rec *sc = | 186 | mgs_srvconf_rec *sc = |
176 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 187 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
177 | module_config, | 188 | module_config, |
178 | &gnutls_module); | 189 | &gnutls_module); |
179 | apr_pool_create(&spool, parms->pool); | 190 | apr_pool_create(&spool, parms->pool); |
180 | 191 | ||
181 | file = ap_server_root_relative(spool, arg); | 192 | file = ap_server_root_relative(spool, arg); |
182 | 193 | ||
183 | if (load_datum_from_file(spool, file, &data) != 0) { | 194 | if (load_datum_from_file(spool, file, &data) != 0) { |
184 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 195 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
185 | "Private Key '%s'", file); | 196 | "Private Key '%s'", file); |
186 | } | 197 | } |
187 | 198 | ||
188 | ret = gnutls_x509_privkey_init(&sc->privkey_x509); | 199 | ret = gnutls_x509_privkey_init(&sc->privkey_x509); |
189 | if (ret < 0) { | 200 | if (ret < 0) { |
190 | return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" | 201 | return apr_psprintf(parms->pool, |
191 | ": (%d) %s", ret, gnutls_strerror(ret)); | 202 | "GnuTLS: Failed to initialize" |
192 | } | 203 | ": (%d) %s", ret, |
193 | 204 | gnutls_strerror(ret)); | |
194 | ret = | 205 | } |
195 | gnutls_x509_privkey_import(sc->privkey_x509, &data, | 206 | |
196 | GNUTLS_X509_FMT_PEM); | 207 | ret = |
197 | 208 | gnutls_x509_privkey_import(sc->privkey_x509, &data, | |
198 | if (ret < 0) | 209 | GNUTLS_X509_FMT_PEM); |
199 | ret = gnutls_x509_privkey_import_pkcs8 (sc->privkey_x509, &data, GNUTLS_X509_FMT_PEM, | 210 | |
200 | NULL, GNUTLS_PKCS_PLAIN); | 211 | if (ret < 0) |
201 | 212 | ret = | |
202 | if (ret < 0) { | 213 | gnutls_x509_privkey_import_pkcs8(sc->privkey_x509, |
203 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | 214 | &data, |
204 | "Private Key '%s': (%d) %s", file, ret, | 215 | GNUTLS_X509_FMT_PEM, |
205 | gnutls_strerror(ret)); | 216 | NULL, |
206 | } | 217 | GNUTLS_PKCS_PLAIN); |
207 | apr_pool_destroy(spool); | 218 | |
208 | return NULL; | 219 | if (ret < 0) { |
220 | return apr_psprintf(parms->pool, | ||
221 | "GnuTLS: Failed to Import " | ||
222 | "Private Key '%s': (%d) %s", file, ret, | ||
223 | gnutls_strerror(ret)); | ||
224 | } | ||
225 | apr_pool_destroy(spool); | ||
226 | return NULL; | ||
209 | } | 227 | } |
210 | 228 | ||
211 | const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy, | 229 | const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy, |
212 | const char *arg) | 230 | const char *arg) |
213 | { | 231 | { |
214 | int ret; | 232 | int ret; |
215 | gnutls_datum_t data; | 233 | gnutls_datum_t data; |
216 | const char *file; | 234 | const char *file; |
217 | apr_pool_t *spool; | 235 | apr_pool_t *spool; |
218 | mgs_srvconf_rec *sc = | 236 | mgs_srvconf_rec *sc = |
219 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 237 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
220 | module_config, | 238 | module_config, |
221 | &gnutls_module); | 239 | &gnutls_module); |
222 | apr_pool_create(&spool, parms->pool); | 240 | apr_pool_create(&spool, parms->pool); |
223 | 241 | ||
224 | file = ap_server_root_relative(spool, arg); | 242 | file = ap_server_root_relative(spool, arg); |
225 | 243 | ||
226 | if (load_datum_from_file(spool, file, &data) != 0) { | 244 | if (load_datum_from_file(spool, file, &data) != 0) { |
227 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 245 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
228 | "Certificate '%s'", file); | 246 | "Certificate '%s'", file); |
229 | } | 247 | } |
230 | 248 | ||
231 | ret = gnutls_openpgp_crt_init( &sc->cert_pgp); | 249 | ret = gnutls_openpgp_crt_init(&sc->cert_pgp); |
232 | if (ret < 0) { | 250 | if (ret < 0) { |
233 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Init " | 251 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Init " |
234 | "PGP Certificate: (%d) %s", ret, | 252 | "PGP Certificate: (%d) %s", ret, |
235 | gnutls_strerror(ret)); | 253 | gnutls_strerror(ret)); |
236 | } | 254 | } |
237 | 255 | ||
238 | ret = | 256 | ret = |
239 | gnutls_openpgp_crt_import(sc->cert_pgp, &data, GNUTLS_OPENPGP_FMT_BASE64); | 257 | gnutls_openpgp_crt_import(sc->cert_pgp, &data, |
240 | if (ret < 0) { | 258 | GNUTLS_OPENPGP_FMT_BASE64); |
241 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | 259 | if (ret < 0) { |
242 | "PGP Certificate '%s': (%d) %s", file, ret, | 260 | return apr_psprintf(parms->pool, |
243 | gnutls_strerror(ret)); | 261 | "GnuTLS: Failed to Import " |
244 | } | 262 | "PGP Certificate '%s': (%d) %s", file, |
245 | 263 | ret, gnutls_strerror(ret)); | |
246 | apr_pool_destroy(spool); | 264 | } |
247 | return NULL; | 265 | |
266 | apr_pool_destroy(spool); | ||
267 | return NULL; | ||
248 | } | 268 | } |
249 | 269 | ||
250 | const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy, | 270 | const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy, |
251 | const char *arg) | 271 | const char *arg) |
252 | { | 272 | { |
253 | int ret; | 273 | int ret; |
254 | gnutls_datum_t data; | 274 | gnutls_datum_t data; |
255 | const char *file; | 275 | const char *file; |
256 | apr_pool_t *spool; | 276 | apr_pool_t *spool; |
257 | mgs_srvconf_rec *sc = | 277 | mgs_srvconf_rec *sc = |
258 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 278 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
259 | module_config, | 279 | module_config, |
260 | &gnutls_module); | 280 | &gnutls_module); |
261 | apr_pool_create(&spool, parms->pool); | 281 | apr_pool_create(&spool, parms->pool); |
262 | 282 | ||
263 | file = ap_server_root_relative(spool, arg); | 283 | file = ap_server_root_relative(spool, arg); |
264 | 284 | ||
265 | if (load_datum_from_file(spool, file, &data) != 0) { | 285 | if (load_datum_from_file(spool, file, &data) != 0) { |
266 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 286 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
267 | "Private Key '%s'", file); | 287 | "Private Key '%s'", file); |
268 | } | 288 | } |
269 | 289 | ||
270 | ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp); | 290 | ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp); |
271 | if (ret < 0) { | 291 | if (ret < 0) { |
272 | return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" | 292 | return apr_psprintf(parms->pool, |
273 | ": (%d) %s", ret, gnutls_strerror(ret)); | 293 | "GnuTLS: Failed to initialize" |
274 | } | 294 | ": (%d) %s", ret, |
275 | 295 | gnutls_strerror(ret)); | |
276 | ret = | 296 | } |
277 | gnutls_openpgp_privkey_import(sc->privkey_pgp, &data, | 297 | |
278 | GNUTLS_OPENPGP_FMT_BASE64, NULL, 0); | 298 | ret = |
279 | if (ret != 0) { | 299 | gnutls_openpgp_privkey_import(sc->privkey_pgp, &data, |
280 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | 300 | GNUTLS_OPENPGP_FMT_BASE64, NULL, |
281 | "PGP Private Key '%s': (%d) %s", file, ret, | 301 | 0); |
282 | gnutls_strerror(ret)); | 302 | if (ret != 0) { |
283 | } | 303 | return apr_psprintf(parms->pool, |
284 | apr_pool_destroy(spool); | 304 | "GnuTLS: Failed to Import " |
285 | return NULL; | 305 | "PGP Private Key '%s': (%d) %s", file, |
306 | ret, gnutls_strerror(ret)); | ||
307 | } | ||
308 | apr_pool_destroy(spool); | ||
309 | return NULL; | ||
286 | } | 310 | } |
287 | 311 | ||
288 | const char *mgs_set_tickets(cmd_parms * parms, void *dummy, | 312 | const char *mgs_set_tickets(cmd_parms * parms, void *dummy, |
289 | const char *arg) | 313 | const char *arg) |
290 | { | 314 | { |
291 | mgs_srvconf_rec *sc = | 315 | mgs_srvconf_rec *sc = |
292 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 316 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
293 | module_config, | 317 | module_config, |
294 | &gnutls_module); | 318 | &gnutls_module); |
295 | 319 | ||
296 | sc->tickets = 0; | 320 | sc->tickets = 0; |
297 | if (strcasecmp("on", arg) == 0) { | 321 | if (strcasecmp("on", arg) == 0) { |
298 | sc->tickets = 1; | 322 | sc->tickets = 1; |
299 | } | 323 | } |
300 | 324 | ||
301 | return NULL; | 325 | return NULL; |
302 | } | 326 | } |
303 | 327 | ||
304 | 328 | ||
@@ -307,27 +331,28 @@ const char *mgs_set_tickets(cmd_parms * parms, void *dummy, | |||
307 | const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy, | 331 | const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy, |
308 | const char *arg) | 332 | const char *arg) |
309 | { | 333 | { |
310 | mgs_srvconf_rec *sc = | 334 | mgs_srvconf_rec *sc = |
311 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 335 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
312 | module_config, | 336 | module_config, |
313 | &gnutls_module); | 337 | &gnutls_module); |
314 | 338 | ||
315 | sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg); | 339 | sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg); |
316 | 340 | ||
317 | return NULL; | 341 | return NULL; |
318 | } | 342 | } |
319 | 343 | ||
320 | const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy, | 344 | const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy, |
321 | const char *arg) | 345 | const char *arg) |
322 | { | 346 | { |
323 | mgs_srvconf_rec *sc = | 347 | mgs_srvconf_rec *sc = |
324 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 348 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
325 | module_config, | 349 | module_config, |
326 | &gnutls_module); | 350 | &gnutls_module); |
327 | 351 | ||
328 | sc->srp_tpasswd_conf_file = ap_server_root_relative(parms->pool, arg); | 352 | sc->srp_tpasswd_conf_file = |
353 | ap_server_root_relative(parms->pool, arg); | ||
329 | 354 | ||
330 | return NULL; | 355 | return NULL; |
331 | } | 356 | } |
332 | 357 | ||
333 | #endif | 358 | #endif |
@@ -335,308 +360,326 @@ const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy, | |||
335 | const char *mgs_set_cache(cmd_parms * parms, void *dummy, | 360 | const char *mgs_set_cache(cmd_parms * parms, void *dummy, |
336 | const char *type, const char *arg) | 361 | const char *type, const char *arg) |
337 | { | 362 | { |
338 | const char *err; | 363 | const char *err; |
339 | mgs_srvconf_rec *sc = ap_get_module_config(parms->server-> | 364 | mgs_srvconf_rec *sc = |
340 | module_config, | 365 | ap_get_module_config(parms->server->module_config, |
341 | &gnutls_module); | 366 | &gnutls_module); |
342 | if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) { | 367 | if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) { |
343 | return err; | 368 | return err; |
344 | } | 369 | } |
345 | 370 | ||
346 | if (strcasecmp("none", type) == 0) { | 371 | if (strcasecmp("none", type) == 0) { |
347 | sc->cache_type = mgs_cache_none; | 372 | sc->cache_type = mgs_cache_none; |
348 | } else if (strcasecmp("dbm", type) == 0) { | 373 | } else if (strcasecmp("dbm", type) == 0) { |
349 | sc->cache_type = mgs_cache_dbm; | 374 | sc->cache_type = mgs_cache_dbm; |
350 | } | 375 | } else if (strcasecmp("gdbm", type) == 0) { |
351 | else if (strcasecmp("gdbm", type) == 0) { | 376 | sc->cache_type = mgs_cache_gdbm; |
352 | sc->cache_type = mgs_cache_gdbm; | 377 | } |
353 | } | ||
354 | #if HAVE_APR_MEMCACHE | 378 | #if HAVE_APR_MEMCACHE |
355 | else if (strcasecmp("memcache", type) == 0) { | 379 | else if (strcasecmp("memcache", type) == 0) { |
356 | sc->cache_type = mgs_cache_memcache; | 380 | sc->cache_type = mgs_cache_memcache; |
357 | } | 381 | } |
358 | #endif | 382 | #endif |
359 | else { | 383 | else { |
360 | return "Invalid Type for GnuTLSCache!"; | 384 | return "Invalid Type for GnuTLSCache!"; |
361 | } | 385 | } |
362 | 386 | ||
363 | if (sc->cache_type == mgs_cache_dbm || sc->cache_type == mgs_cache_gdbm) { | 387 | if (sc->cache_type == mgs_cache_dbm |
364 | sc->cache_config = ap_server_root_relative(parms->pool, arg); | 388 | || sc->cache_type == mgs_cache_gdbm) { |
365 | } else { | 389 | sc->cache_config = |
366 | sc->cache_config = apr_pstrdup(parms->pool, arg); | 390 | ap_server_root_relative(parms->pool, arg); |
367 | } | 391 | } else { |
368 | 392 | sc->cache_config = apr_pstrdup(parms->pool, arg); | |
369 | return NULL; | 393 | } |
394 | |||
395 | return NULL; | ||
370 | } | 396 | } |
371 | 397 | ||
372 | const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy, | 398 | const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy, |
373 | const char *arg) | 399 | const char *arg) |
374 | { | 400 | { |
375 | int argint; | 401 | int argint; |
376 | mgs_srvconf_rec *sc = | ||
377 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | ||
378 | module_config, | ||
379 | &gnutls_module); | ||
380 | |||
381 | argint = atoi(arg); | ||
382 | |||
383 | if (argint < 0) { | ||
384 | return "GnuTLSCacheTimeout: Invalid argument"; | ||
385 | } else if (argint == 0) { | ||
386 | sc->cache_timeout = 0; | ||
387 | } else { | ||
388 | sc->cache_timeout = apr_time_from_sec(argint); | ||
389 | } | ||
390 | |||
391 | return NULL; | ||
392 | } | ||
393 | |||
394 | const char *mgs_set_client_verify(cmd_parms * parms, void *dummy, | ||
395 | const char *arg) | ||
396 | { | ||
397 | int mode; | ||
398 | |||
399 | if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) { | ||
400 | mode = GNUTLS_CERT_IGNORE; | ||
401 | } else if (strcasecmp("optional", arg) == 0 | ||
402 | || strcasecmp("request", arg) == 0) { | ||
403 | mode = GNUTLS_CERT_REQUEST; | ||
404 | } else if (strcasecmp("require", arg) == 0) { | ||
405 | mode = GNUTLS_CERT_REQUIRE; | ||
406 | } else { | ||
407 | return "GnuTLSClientVerify: Invalid argument"; | ||
408 | } | ||
409 | |||
410 | /* This was set from a directory context */ | ||
411 | if (parms->path) { | ||
412 | mgs_dirconf_rec *dc = (mgs_dirconf_rec *) dummy; | ||
413 | dc->client_verify_mode = mode; | ||
414 | } else { | ||
415 | mgs_srvconf_rec *sc = | 402 | mgs_srvconf_rec *sc = |
416 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 403 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
417 | module_config, | 404 | module_config, |
418 | &gnutls_module); | 405 | &gnutls_module); |
419 | sc->client_verify_mode = mode; | ||
420 | } | ||
421 | 406 | ||
422 | return NULL; | 407 | argint = atoi(arg); |
408 | |||
409 | if (argint < 0) { | ||
410 | return "GnuTLSCacheTimeout: Invalid argument"; | ||
411 | } else if (argint == 0) { | ||
412 | sc->cache_timeout = 0; | ||
413 | } else { | ||
414 | sc->cache_timeout = apr_time_from_sec(argint); | ||
415 | } | ||
416 | |||
417 | return NULL; | ||
418 | } | ||
419 | |||
420 | const char *mgs_set_client_verify(cmd_parms * parms, void *dummy, | ||
421 | const char *arg) | ||
422 | { | ||
423 | int mode; | ||
424 | |||
425 | if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) { | ||
426 | mode = GNUTLS_CERT_IGNORE; | ||
427 | } else if (strcasecmp("optional", arg) == 0 | ||
428 | || strcasecmp("request", arg) == 0) { | ||
429 | mode = GNUTLS_CERT_REQUEST; | ||
430 | } else if (strcasecmp("require", arg) == 0) { | ||
431 | mode = GNUTLS_CERT_REQUIRE; | ||
432 | } else { | ||
433 | return "GnuTLSClientVerify: Invalid argument"; | ||
434 | } | ||
435 | |||
436 | /* This was set from a directory context */ | ||
437 | if (parms->path) { | ||
438 | mgs_dirconf_rec *dc = (mgs_dirconf_rec *) dummy; | ||
439 | dc->client_verify_mode = mode; | ||
440 | } else { | ||
441 | mgs_srvconf_rec *sc = | ||
442 | (mgs_srvconf_rec *) | ||
443 | ap_get_module_config(parms->server->module_config, | ||
444 | &gnutls_module); | ||
445 | sc->client_verify_mode = mode; | ||
446 | } | ||
447 | |||
448 | return NULL; | ||
423 | } | 449 | } |
424 | 450 | ||
425 | #define INIT_CA_SIZE 128 | 451 | #define INIT_CA_SIZE 128 |
426 | const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy, | 452 | const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy, |
427 | const char *arg) | 453 | const char *arg) |
428 | { | 454 | { |
429 | int rv; | 455 | int rv; |
430 | const char *file; | 456 | const char *file; |
431 | apr_pool_t *spool; | 457 | apr_pool_t *spool; |
432 | gnutls_datum_t data; | 458 | gnutls_datum_t data; |
433 | 459 | ||
434 | mgs_srvconf_rec *sc = | 460 | mgs_srvconf_rec *sc = |
435 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 461 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
436 | module_config, | 462 | module_config, |
437 | &gnutls_module); | 463 | &gnutls_module); |
438 | apr_pool_create(&spool, parms->pool); | 464 | apr_pool_create(&spool, parms->pool); |
439 | 465 | ||
440 | file = ap_server_root_relative(spool, arg); | 466 | file = ap_server_root_relative(spool, arg); |
441 | 467 | ||
442 | if (load_datum_from_file(spool, file, &data) != 0) { | 468 | if (load_datum_from_file(spool, file, &data) != 0) { |
443 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 469 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
444 | "Client CA File '%s'", file); | 470 | "Client CA File '%s'", file); |
445 | } | 471 | } |
446 | 472 | ||
447 | sc->ca_list_size = INIT_CA_SIZE; | 473 | sc->ca_list_size = INIT_CA_SIZE; |
448 | sc->ca_list = malloc(sc->ca_list_size * sizeof(*sc->ca_list)); | 474 | sc->ca_list = malloc(sc->ca_list_size * sizeof(*sc->ca_list)); |
449 | if (sc->ca_list == NULL) { | 475 | if (sc->ca_list == NULL) { |
450 | return apr_psprintf(parms->pool, "mod_gnutls: Memory allocation error"); | 476 | return apr_psprintf(parms->pool, |
451 | } | 477 | "mod_gnutls: Memory allocation error"); |
452 | 478 | } | |
453 | rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size, | 479 | |
454 | &data, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED); | 480 | rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size, |
455 | if (rv < 0 && rv != GNUTLS_E_SHORT_MEMORY_BUFFER) { | 481 | &data, GNUTLS_X509_FMT_PEM, |
456 | return apr_psprintf(parms->pool, "GnuTLS: Failed to load " | 482 | GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED); |
457 | "Client CA File '%s': (%d) %s", file, rv, | 483 | if (rv < 0 && rv != GNUTLS_E_SHORT_MEMORY_BUFFER) { |
458 | gnutls_strerror(rv)); | 484 | return apr_psprintf(parms->pool, "GnuTLS: Failed to load " |
459 | } | 485 | "Client CA File '%s': (%d) %s", file, |
460 | 486 | rv, gnutls_strerror(rv)); | |
461 | if (INIT_CA_SIZE < sc->ca_list_size) { | 487 | } |
462 | sc->ca_list = realloc(sc->ca_list, sc->ca_list_size*sizeof(*sc->ca_list)); | 488 | |
463 | if (sc->ca_list == NULL) { | 489 | if (INIT_CA_SIZE < sc->ca_list_size) { |
464 | return apr_psprintf(parms->pool, "mod_gnutls: Memory allocation error"); | 490 | sc->ca_list = |
465 | } | 491 | realloc(sc->ca_list, |
466 | 492 | sc->ca_list_size * sizeof(*sc->ca_list)); | |
467 | /* re-read */ | 493 | if (sc->ca_list == NULL) { |
468 | rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size, | 494 | return apr_psprintf(parms->pool, |
469 | &data, GNUTLS_X509_FMT_PEM, 0); | 495 | "mod_gnutls: Memory allocation error"); |
470 | 496 | } | |
471 | if (rv < 0) { | 497 | |
472 | return apr_psprintf(parms->pool, "GnuTLS: Failed to load " | 498 | /* re-read */ |
473 | "Client CA File '%s': (%d) %s", file, rv, | 499 | rv = gnutls_x509_crt_list_import(sc->ca_list, |
474 | gnutls_strerror(rv)); | 500 | &sc->ca_list_size, &data, |
475 | } | 501 | GNUTLS_X509_FMT_PEM, 0); |
476 | } | 502 | |
477 | 503 | if (rv < 0) { | |
478 | apr_pool_destroy(spool); | 504 | return apr_psprintf(parms->pool, |
479 | return NULL; | 505 | "GnuTLS: Failed to load " |
506 | "Client CA File '%s': (%d) %s", | ||
507 | file, rv, gnutls_strerror(rv)); | ||
508 | } | ||
509 | } | ||
510 | |||
511 | apr_pool_destroy(spool); | ||
512 | return NULL; | ||
480 | } | 513 | } |
481 | 514 | ||
482 | const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy, | 515 | const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy, |
483 | const char *arg) | 516 | const char *arg) |
484 | { | 517 | { |
485 | int rv; | 518 | int rv; |
486 | const char *file; | 519 | const char *file; |
487 | apr_pool_t *spool; | 520 | apr_pool_t *spool; |
488 | gnutls_datum_t data; | 521 | gnutls_datum_t data; |
489 | 522 | ||
490 | mgs_srvconf_rec *sc = | 523 | mgs_srvconf_rec *sc = |
491 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 524 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
492 | module_config, | 525 | module_config, |
493 | &gnutls_module); | 526 | &gnutls_module); |
494 | apr_pool_create(&spool, parms->pool); | 527 | apr_pool_create(&spool, parms->pool); |
495 | 528 | ||
496 | file = ap_server_root_relative(spool, arg); | 529 | file = ap_server_root_relative(spool, arg); |
497 | 530 | ||
498 | if (load_datum_from_file(spool, file, &data) != 0) { | 531 | if (load_datum_from_file(spool, file, &data) != 0) { |
499 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 532 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
500 | "Keyring File '%s'", file); | 533 | "Keyring File '%s'", file); |
501 | } | 534 | } |
502 | 535 | ||
503 | rv = gnutls_openpgp_keyring_init(&sc->pgp_list); | 536 | rv = gnutls_openpgp_keyring_init(&sc->pgp_list); |
504 | if (rv < 0) { | 537 | if (rv < 0) { |
505 | return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" | 538 | return apr_psprintf(parms->pool, |
506 | "keyring: (%d) %s", rv, gnutls_strerror(rv)); | 539 | "GnuTLS: Failed to initialize" |
507 | } | 540 | "keyring: (%d) %s", rv, |
508 | 541 | gnutls_strerror(rv)); | |
509 | rv = gnutls_openpgp_keyring_import(sc->pgp_list, &data, GNUTLS_OPENPGP_FMT_BASE64); | 542 | } |
510 | if (rv < 0) { | 543 | |
511 | return apr_psprintf(parms->pool, "GnuTLS: Failed to load " | 544 | rv = gnutls_openpgp_keyring_import(sc->pgp_list, &data, |
512 | "Keyring File '%s': (%d) %s", file, rv, | 545 | GNUTLS_OPENPGP_FMT_BASE64); |
513 | gnutls_strerror(rv)); | 546 | if (rv < 0) { |
514 | } | 547 | return apr_psprintf(parms->pool, "GnuTLS: Failed to load " |
515 | 548 | "Keyring File '%s': (%d) %s", file, rv, | |
516 | apr_pool_destroy(spool); | 549 | gnutls_strerror(rv)); |
517 | return NULL; | 550 | } |
551 | |||
552 | apr_pool_destroy(spool); | ||
553 | return NULL; | ||
518 | } | 554 | } |
519 | 555 | ||
520 | const char *mgs_set_enabled(cmd_parms * parms, void *dummy, | 556 | const char *mgs_set_enabled(cmd_parms * parms, void *dummy, |
521 | const char *arg) | 557 | const char *arg) |
522 | { | 558 | { |
523 | mgs_srvconf_rec *sc = | 559 | mgs_srvconf_rec *sc = |
524 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 560 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
525 | module_config, | 561 | module_config, |
526 | &gnutls_module); | 562 | &gnutls_module); |
527 | if (!strcasecmp(arg, "On")) { | 563 | if (!strcasecmp(arg, "On")) { |
528 | sc->enabled = GNUTLS_ENABLED_TRUE; | 564 | sc->enabled = GNUTLS_ENABLED_TRUE; |
529 | } else if (!strcasecmp(arg, "Off")) { | 565 | } else if (!strcasecmp(arg, "Off")) { |
530 | sc->enabled = GNUTLS_ENABLED_FALSE; | 566 | sc->enabled = GNUTLS_ENABLED_FALSE; |
531 | } else { | 567 | } else { |
532 | return "GnuTLSEnable must be set to 'On' or 'Off'"; | 568 | return "GnuTLSEnable must be set to 'On' or 'Off'"; |
533 | } | 569 | } |
534 | 570 | ||
535 | return NULL; | 571 | return NULL; |
536 | } | 572 | } |
537 | 573 | ||
538 | const char *mgs_set_export_certificates_enabled(cmd_parms * parms, void *dummy, | 574 | const char *mgs_set_export_certificates_enabled(cmd_parms * parms, |
539 | const char *arg) | 575 | void *dummy, |
576 | const char *arg) | ||
540 | { | 577 | { |
541 | mgs_srvconf_rec *sc = | 578 | mgs_srvconf_rec *sc = |
542 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 579 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
543 | module_config, | 580 | module_config, |
544 | &gnutls_module); | 581 | &gnutls_module); |
545 | if (!strcasecmp(arg, "On")) { | 582 | if (!strcasecmp(arg, "On")) { |
546 | sc->export_certificates_enabled = GNUTLS_ENABLED_TRUE; | 583 | sc->export_certificates_enabled = GNUTLS_ENABLED_TRUE; |
547 | } else if (!strcasecmp(arg, "Off")) { | 584 | } else if (!strcasecmp(arg, "Off")) { |
548 | sc->export_certificates_enabled = GNUTLS_ENABLED_FALSE; | 585 | sc->export_certificates_enabled = GNUTLS_ENABLED_FALSE; |
549 | } else { | 586 | } else { |
550 | return "GnuTLSExportCertificates must be set to 'On' or 'Off'"; | 587 | return |
551 | } | 588 | "GnuTLSExportCertificates must be set to 'On' or 'Off'"; |
552 | 589 | } | |
553 | return NULL; | 590 | |
591 | return NULL; | ||
554 | } | 592 | } |
555 | 593 | ||
556 | 594 | ||
557 | const char *mgs_set_priorities(cmd_parms * parms, void *dummy, const char *arg) | 595 | const char *mgs_set_priorities(cmd_parms * parms, void *dummy, |
596 | const char *arg) | ||
558 | { | 597 | { |
559 | int ret; | 598 | int ret; |
560 | const char *err; | 599 | const char *err; |
561 | mgs_srvconf_rec *sc = | 600 | mgs_srvconf_rec *sc = |
562 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 601 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
563 | module_config, | 602 | module_config, |
564 | &gnutls_module); | 603 | &gnutls_module); |
565 | 604 | ||
566 | 605 | ||
567 | ret = gnutls_priority_init( &sc->priorities, arg, &err); | 606 | ret = gnutls_priority_init(&sc->priorities, arg, &err); |
568 | if (ret < 0) { | 607 | if (ret < 0) { |
569 | if (ret == GNUTLS_E_INVALID_REQUEST) | 608 | if (ret == GNUTLS_E_INVALID_REQUEST) |
570 | return apr_psprintf(parms->pool, "GnuTLS: Syntax error parsing priorities string at: %s", err); | 609 | return apr_psprintf(parms->pool, |
571 | return "Error setting priorities"; | 610 | "GnuTLS: Syntax error parsing priorities string at: %s", |
572 | } | 611 | err); |
573 | 612 | return "Error setting priorities"; | |
574 | return NULL; | 613 | } |
614 | |||
615 | return NULL; | ||
575 | } | 616 | } |
576 | 617 | ||
577 | void *mgs_config_server_create(apr_pool_t * p, server_rec * s) | 618 | void *mgs_config_server_create(apr_pool_t * p, server_rec * s) |
578 | { | 619 | { |
579 | mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc)); | 620 | mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc)); |
580 | int ret; | 621 | int ret; |
581 | |||
582 | sc->enabled = GNUTLS_ENABLED_FALSE; | ||
583 | |||
584 | ret = gnutls_certificate_allocate_credentials(&sc->certs); | ||
585 | if (ret < 0) { | ||
586 | return apr_psprintf(p, "GnuTLS: Failed to initialize" | ||
587 | ": (%d) %s", ret, gnutls_strerror(ret)); | ||
588 | } | ||
589 | |||
590 | ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds); | ||
591 | if (ret < 0) { | ||
592 | return apr_psprintf(p, "GnuTLS: Failed to initialize" | ||
593 | ": (%d) %s", ret, gnutls_strerror(ret)); | ||
594 | } | ||
595 | 622 | ||
623 | sc->enabled = GNUTLS_ENABLED_FALSE; | ||
624 | |||
625 | ret = gnutls_certificate_allocate_credentials(&sc->certs); | ||
626 | if (ret < 0) { | ||
627 | return apr_psprintf(p, "GnuTLS: Failed to initialize" | ||
628 | ": (%d) %s", ret, | ||
629 | gnutls_strerror(ret)); | ||
630 | } | ||
631 | |||
632 | ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds); | ||
633 | if (ret < 0) { | ||
634 | return apr_psprintf(p, "GnuTLS: Failed to initialize" | ||
635 | ": (%d) %s", ret, | ||
636 | gnutls_strerror(ret)); | ||
637 | } | ||
596 | #ifdef ENABLE_SRP | 638 | #ifdef ENABLE_SRP |
597 | ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds); | 639 | ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds); |
598 | if (ret < 0) { | 640 | if (ret < 0) { |
599 | return apr_psprintf(p, "GnuTLS: Failed to initialize" | 641 | return apr_psprintf(p, "GnuTLS: Failed to initialize" |
600 | ": (%d) %s", ret, gnutls_strerror(ret)); | 642 | ": (%d) %s", ret, |
601 | } | 643 | gnutls_strerror(ret)); |
602 | 644 | } | |
603 | sc->srp_tpasswd_conf_file = NULL; | 645 | |
604 | sc->srp_tpasswd_file = NULL; | 646 | sc->srp_tpasswd_conf_file = NULL; |
647 | sc->srp_tpasswd_file = NULL; | ||
605 | #endif | 648 | #endif |
606 | 649 | ||
607 | sc->privkey_x509 = NULL; | 650 | sc->privkey_x509 = NULL; |
608 | memset( sc->certs_x509, 0, sizeof(sc->certs_x509)); | 651 | memset(sc->certs_x509, 0, sizeof(sc->certs_x509)); |
609 | sc->certs_x509_num = 0; | 652 | sc->certs_x509_num = 0; |
610 | sc->cache_timeout = apr_time_from_sec(300); | 653 | sc->cache_timeout = apr_time_from_sec(300); |
611 | sc->cache_type = mgs_cache_none; | 654 | sc->cache_type = mgs_cache_none; |
612 | sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache"); | 655 | sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache"); |
613 | sc->tickets = 1; /* by default enable session tickets */ | 656 | sc->tickets = 1; /* by default enable session tickets */ |
614 | 657 | ||
615 | sc->client_verify_mode = GNUTLS_CERT_IGNORE; | 658 | sc->client_verify_mode = GNUTLS_CERT_IGNORE; |
616 | 659 | ||
617 | return sc; | 660 | return sc; |
618 | } | 661 | } |
619 | 662 | ||
620 | void *mgs_config_dir_merge(apr_pool_t * p, void *basev, void *addv) | 663 | void *mgs_config_dir_merge(apr_pool_t * p, void *basev, void *addv) |
621 | { | 664 | { |
622 | mgs_dirconf_rec *new; | 665 | mgs_dirconf_rec *new; |
623 | /* mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */ | 666 | /* mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */ |
624 | mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv; | 667 | mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv; |
625 | 668 | ||
626 | new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof(mgs_dirconf_rec)); | 669 | new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof(mgs_dirconf_rec)); |
627 | new->lua_bytecode = apr_pstrmemdup(p, add->lua_bytecode, | 670 | new->lua_bytecode = apr_pstrmemdup(p, add->lua_bytecode, |
628 | add->lua_bytecode_len); | 671 | add->lua_bytecode_len); |
629 | new->lua_bytecode_len = add->lua_bytecode_len; | 672 | new->lua_bytecode_len = add->lua_bytecode_len; |
630 | new->client_verify_mode = add->client_verify_mode; | 673 | new->client_verify_mode = add->client_verify_mode; |
631 | return new; | 674 | return new; |
632 | } | 675 | } |
633 | 676 | ||
634 | void *mgs_config_dir_create(apr_pool_t * p, char *dir) | 677 | void *mgs_config_dir_create(apr_pool_t * p, char *dir) |
635 | { | 678 | { |
636 | mgs_dirconf_rec *dc = apr_palloc(p, sizeof(*dc)); | 679 | mgs_dirconf_rec *dc = apr_palloc(p, sizeof(*dc)); |
637 | 680 | ||
638 | dc->client_verify_mode = -1; | 681 | dc->client_verify_mode = -1; |
639 | dc->lua_bytecode = NULL; | 682 | dc->lua_bytecode = NULL; |
640 | dc->lua_bytecode_len = 0; | 683 | dc->lua_bytecode_len = 0; |
641 | return dc; | 684 | return dc; |
642 | } | 685 | } |
diff --git a/src/gnutls_hooks.c b/src/gnutls_hooks.c index 7c638fb..34c3585 100644 --- a/src/gnutls_hooks.c +++ b/src/gnutls_hooks.c | |||
@@ -40,179 +40,191 @@ static gnutls_datum session_ticket_key = { NULL, 0 }; | |||
40 | 40 | ||
41 | static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt); | 41 | static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt); |
42 | /* use side==0 for server and side==1 for client */ | 42 | /* use side==0 for server and side==1 for client */ |
43 | static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, | 43 | static void mgs_add_common_cert_vars(request_rec * r, |
44 | int side, | 44 | gnutls_x509_crt_t cert, int side, |
45 | int export_certificates_enabled); | ||
46 | static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, | ||
47 | int side, | ||
48 | int export_certificates_enabled); | 45 | int export_certificates_enabled); |
46 | static void mgs_add_common_pgpcert_vars(request_rec * r, | ||
47 | gnutls_openpgp_crt_t cert, | ||
48 | int side, | ||
49 | int export_certificates_enabled); | ||
49 | 50 | ||
50 | static apr_status_t mgs_cleanup_pre_config(void *data) | 51 | static apr_status_t mgs_cleanup_pre_config(void *data) |
51 | { | 52 | { |
52 | gnutls_free(session_ticket_key.data); | 53 | gnutls_free(session_ticket_key.data); |
53 | session_ticket_key.data = NULL; | 54 | session_ticket_key.data = NULL; |
54 | session_ticket_key.size = 0; | 55 | session_ticket_key.size = 0; |
55 | gnutls_global_deinit(); | 56 | gnutls_global_deinit(); |
56 | return APR_SUCCESS; | 57 | return APR_SUCCESS; |
57 | } | 58 | } |
58 | 59 | ||
59 | #if MOD_GNUTLS_DEBUG | 60 | #if MOD_GNUTLS_DEBUG |
60 | static void gnutls_debug_log_all(int level, const char *str) | 61 | static void gnutls_debug_log_all(int level, const char *str) |
61 | { | 62 | { |
62 | apr_file_printf(debug_log_fp, "<%d> %s\n", level, str); | 63 | apr_file_printf(debug_log_fp, "<%d> %s\n", level, str); |
63 | } | 64 | } |
65 | |||
64 | #define _gnutls_log apr_file_printf | 66 | #define _gnutls_log apr_file_printf |
65 | #else | 67 | #else |
66 | # define _gnutls_log(...) | 68 | # define _gnutls_log(...) |
67 | #endif | 69 | #endif |
68 | 70 | ||
69 | int | 71 | int |
70 | mgs_hook_pre_config(apr_pool_t * pconf, | 72 | mgs_hook_pre_config(apr_pool_t * pconf, |
71 | apr_pool_t * plog, apr_pool_t * ptemp) | 73 | apr_pool_t * plog, apr_pool_t * ptemp) |
72 | { | 74 | { |
73 | int ret; | 75 | int ret; |
74 | 76 | ||
75 | #if MOD_GNUTLS_DEBUG | 77 | #if MOD_GNUTLS_DEBUG |
76 | apr_file_open(&debug_log_fp, "/tmp/gnutls_debug", | 78 | apr_file_open(&debug_log_fp, "/tmp/gnutls_debug", |
77 | APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, | 79 | APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, |
78 | pconf); | 80 | pconf); |
79 | 81 | ||
80 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 82 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
81 | 83 | ||
82 | gnutls_global_set_log_level(9); | 84 | gnutls_global_set_log_level(9); |
83 | gnutls_global_set_log_function(gnutls_debug_log_all); | 85 | gnutls_global_set_log_function(gnutls_debug_log_all); |
84 | _gnutls_log(debug_log_fp, "gnutls: %s\n", gnutls_check_version(NULL)); | 86 | _gnutls_log(debug_log_fp, "gnutls: %s\n", |
87 | gnutls_check_version(NULL)); | ||
85 | #endif | 88 | #endif |
86 | 89 | ||
87 | #if APR_HAS_THREADS | 90 | #if APR_HAS_THREADS |
88 | ap_mpm_query(AP_MPMQ_IS_THREADED, &mpm_is_threaded); | 91 | ap_mpm_query(AP_MPMQ_IS_THREADED, &mpm_is_threaded); |
89 | #if (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR < 11) || GNUTLS_VERSION_MAJOR < 2 | 92 | #if (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR < 11) || GNUTLS_VERSION_MAJOR < 2 |
90 | if (mpm_is_threaded) { | 93 | if (mpm_is_threaded) { |
91 | gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); | 94 | gcry_control(GCRYCTL_SET_THREAD_CBS, |
92 | } | 95 | &gcry_threads_pthread); |
96 | } | ||
93 | #endif | 97 | #endif |
94 | #else | 98 | #else |
95 | mpm_is_threaded = 0; | 99 | mpm_is_threaded = 0; |
96 | #endif | 100 | #endif |
97 | 101 | ||
98 | 102 | ||
99 | if (gnutls_check_version(LIBGNUTLS_VERSION)==NULL) { | 103 | if (gnutls_check_version(LIBGNUTLS_VERSION) == NULL) { |
100 | _gnutls_log(debug_log_fp, "gnutls_check_version() failed. Required: gnutls-%s Found: gnutls-%s\n", | 104 | _gnutls_log(debug_log_fp, |
101 | LIBGNUTLS_VERSION, gnutls_check_version(NULL)); | 105 | "gnutls_check_version() failed. Required: gnutls-%s Found: gnutls-%s\n", |
102 | return -3; | 106 | LIBGNUTLS_VERSION, gnutls_check_version(NULL)); |
103 | } | 107 | return -3; |
108 | } | ||
109 | |||
110 | ret = gnutls_global_init(); | ||
111 | if (ret < 0) { | ||
112 | _gnutls_log(debug_log_fp, "gnutls_global_init: %s\n", | ||
113 | gnutls_strerror(ret)); | ||
114 | return -3; | ||
115 | } | ||
104 | 116 | ||
105 | ret = gnutls_global_init(); | 117 | ret = gnutls_session_ticket_key_generate(&session_ticket_key); |
106 | if (ret < 0) { | 118 | if (ret < 0) { |
107 | _gnutls_log(debug_log_fp, "gnutls_global_init: %s\n", gnutls_strerror(ret)); | 119 | _gnutls_log(debug_log_fp, |
108 | return -3; | 120 | "gnutls_session_ticket_key_generate: %s\n", |
109 | } | 121 | gnutls_strerror(ret)); |
110 | 122 | } | |
111 | ret = gnutls_session_ticket_key_generate( &session_ticket_key); | ||
112 | if (ret < 0) { | ||
113 | _gnutls_log(debug_log_fp, "gnutls_session_ticket_key_generate: %s\n", gnutls_strerror(ret)); | ||
114 | } | ||
115 | 123 | ||
116 | apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, | 124 | apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, |
117 | apr_pool_cleanup_null); | 125 | apr_pool_cleanup_null); |
118 | 126 | ||
119 | 127 | ||
120 | return OK; | 128 | return OK; |
121 | } | 129 | } |
122 | 130 | ||
123 | static int mgs_select_virtual_server_cb(gnutls_session_t session) | 131 | static int mgs_select_virtual_server_cb(gnutls_session_t session) |
124 | { | 132 | { |
125 | mgs_handle_t *ctxt; | 133 | mgs_handle_t *ctxt; |
126 | mgs_srvconf_rec *tsc; | 134 | mgs_srvconf_rec *tsc; |
127 | int ret; | 135 | int ret; |
128 | int cprio[2]; | 136 | int cprio[2]; |
129 | 137 | ||
130 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 138 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
131 | 139 | ||
132 | ctxt = gnutls_transport_get_ptr(session); | 140 | ctxt = gnutls_transport_get_ptr(session); |
133 | 141 | ||
134 | /* find the virtual server */ | 142 | /* find the virtual server */ |
135 | tsc = mgs_find_sni_server(session); | 143 | tsc = mgs_find_sni_server(session); |
136 | 144 | ||
137 | if (tsc != NULL) | 145 | if (tsc != NULL) |
138 | ctxt->sc = tsc; | 146 | ctxt->sc = tsc; |
139 | 147 | ||
140 | gnutls_certificate_server_set_request(session, | 148 | gnutls_certificate_server_set_request(session, |
141 | ctxt->sc->client_verify_mode); | 149 | ctxt-> |
150 | sc->client_verify_mode); | ||
142 | 151 | ||
143 | /* set the new server credentials | 152 | /* set the new server credentials |
144 | */ | 153 | */ |
145 | 154 | ||
146 | gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, | 155 | gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, |
147 | ctxt->sc->certs); | 156 | ctxt->sc->certs); |
148 | 157 | ||
149 | gnutls_credentials_set(session, GNUTLS_CRD_ANON, ctxt->sc->anon_creds); | 158 | gnutls_credentials_set(session, GNUTLS_CRD_ANON, |
159 | ctxt->sc->anon_creds); | ||
150 | 160 | ||
151 | #ifdef ENABLE_SRP | 161 | #ifdef ENABLE_SRP |
152 | if (ctxt->sc->srp_tpasswd_conf_file != NULL | 162 | if (ctxt->sc->srp_tpasswd_conf_file != NULL |
153 | && ctxt->sc->srp_tpasswd_file != NULL) { | 163 | && ctxt->sc->srp_tpasswd_file != NULL) { |
154 | gnutls_credentials_set(session, GNUTLS_CRD_SRP, | 164 | gnutls_credentials_set(session, GNUTLS_CRD_SRP, |
155 | ctxt->sc->srp_creds); | 165 | ctxt->sc->srp_creds); |
156 | } | 166 | } |
157 | #endif | 167 | #endif |
158 | 168 | ||
159 | /* update the priorities - to avoid negotiating a ciphersuite that is not | 169 | /* update the priorities - to avoid negotiating a ciphersuite that is not |
160 | * enabled on this virtual server. Note that here we ignore the version | 170 | * enabled on this virtual server. Note that here we ignore the version |
161 | * negotiation. | 171 | * negotiation. |
162 | */ | 172 | */ |
163 | ret = gnutls_priority_set(session, ctxt->sc->priorities); | 173 | ret = gnutls_priority_set(session, ctxt->sc->priorities); |
164 | /* actually it shouldn't fail since we have checked at startup */ | 174 | /* actually it shouldn't fail since we have checked at startup */ |
165 | if (ret < 0) | 175 | if (ret < 0) |
166 | return ret; | 176 | return ret; |
167 | 177 | ||
168 | /* If both certificate types are not present disallow them from | 178 | /* If both certificate types are not present disallow them from |
169 | * being negotiated. | 179 | * being negotiated. |
170 | */ | 180 | */ |
171 | if (ctxt->sc->certs_x509[0] != NULL && ctxt->sc->cert_pgp == NULL) { | 181 | if (ctxt->sc->certs_x509[0] != NULL && ctxt->sc->cert_pgp == NULL) { |
172 | cprio[0] = GNUTLS_CRT_X509; | 182 | cprio[0] = GNUTLS_CRT_X509; |
173 | cprio[1] = 0; | 183 | cprio[1] = 0; |
174 | gnutls_certificate_type_set_priority( session, cprio); | 184 | gnutls_certificate_type_set_priority(session, cprio); |
175 | } else if (ctxt->sc->cert_pgp != NULL && ctxt->sc->certs_x509[0]==NULL) { | 185 | } else if (ctxt->sc->cert_pgp != NULL |
176 | cprio[0] = GNUTLS_CRT_OPENPGP; | 186 | && ctxt->sc->certs_x509[0] == NULL) { |
177 | cprio[1] = 0; | 187 | cprio[0] = GNUTLS_CRT_OPENPGP; |
178 | gnutls_certificate_type_set_priority( session, cprio); | 188 | cprio[1] = 0; |
179 | } | 189 | gnutls_certificate_type_set_priority(session, cprio); |
180 | 190 | } | |
181 | return 0; | 191 | |
192 | return 0; | ||
182 | } | 193 | } |
183 | 194 | ||
184 | static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st * ret) | 195 | static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st * ret) |
185 | { | 196 | { |
186 | mgs_handle_t *ctxt; | 197 | mgs_handle_t *ctxt; |
198 | |||
199 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | ||
200 | ctxt = gnutls_transport_get_ptr(session); | ||
187 | 201 | ||
188 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 202 | if (ctxt == NULL) |
189 | ctxt = gnutls_transport_get_ptr(session); | 203 | return GNUTLS_E_INTERNAL_ERROR; |
190 | 204 | ||
191 | if (ctxt == NULL) | 205 | if (gnutls_certificate_type_get(session) == GNUTLS_CRT_X509) { |
192 | return GNUTLS_E_INTERNAL_ERROR; | 206 | ret->type = GNUTLS_CRT_X509; |
207 | ret->ncerts = ctxt->sc->certs_x509_num; | ||
208 | ret->deinit_all = 0; | ||
193 | 209 | ||
194 | if (gnutls_certificate_type_get( session) == GNUTLS_CRT_X509) { | 210 | ret->cert.x509 = ctxt->sc->certs_x509; |
195 | ret->type = GNUTLS_CRT_X509; | 211 | ret->key.x509 = ctxt->sc->privkey_x509; |
196 | ret->ncerts = ctxt->sc->certs_x509_num; | ||
197 | ret->deinit_all = 0; | ||
198 | 212 | ||
199 | ret->cert.x509 = ctxt->sc->certs_x509; | 213 | return 0; |
200 | ret->key.x509 = ctxt->sc->privkey_x509; | 214 | } else if (gnutls_certificate_type_get(session) == |
201 | 215 | GNUTLS_CRT_OPENPGP) { | |
202 | return 0; | 216 | ret->type = GNUTLS_CRT_OPENPGP; |
203 | } else if (gnutls_certificate_type_get( session) == GNUTLS_CRT_OPENPGP) { | 217 | ret->ncerts = 1; |
204 | ret->type = GNUTLS_CRT_OPENPGP; | 218 | ret->deinit_all = 0; |
205 | ret->ncerts = 1; | ||
206 | ret->deinit_all = 0; | ||
207 | 219 | ||
208 | ret->cert.pgp = ctxt->sc->cert_pgp; | 220 | ret->cert.pgp = ctxt->sc->cert_pgp; |
209 | ret->key.pgp = ctxt->sc->privkey_pgp; | 221 | ret->key.pgp = ctxt->sc->privkey_pgp; |
210 | 222 | ||
211 | return 0; | 223 | return 0; |
212 | |||
213 | } | ||
214 | 224 | ||
215 | return GNUTLS_E_INTERNAL_ERROR; | 225 | } |
226 | |||
227 | return GNUTLS_E_INTERNAL_ERROR; | ||
216 | } | 228 | } |
217 | 229 | ||
218 | /* 2048-bit group parameters from SRP specification */ | 230 | /* 2048-bit group parameters from SRP specification */ |
@@ -233,78 +245,81 @@ const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n" | |||
233 | static int read_crt_cn(server_rec * s, apr_pool_t * p, | 245 | static int read_crt_cn(server_rec * s, apr_pool_t * p, |
234 | gnutls_x509_crt_t cert, char **cert_cn) | 246 | gnutls_x509_crt_t cert, char **cert_cn) |
235 | { | 247 | { |
236 | int rv = 0, i; | 248 | int rv = 0, i; |
237 | size_t data_len; | 249 | size_t data_len; |
238 | |||
239 | 250 | ||
240 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | ||
241 | *cert_cn = NULL; | ||
242 | 251 | ||
243 | data_len = 0; | 252 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
244 | rv = gnutls_x509_crt_get_dn_by_oid(cert, | 253 | *cert_cn = NULL; |
245 | GNUTLS_OID_X520_COMMON_NAME, | ||
246 | 0, 0, NULL, &data_len); | ||
247 | 254 | ||
248 | if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { | 255 | data_len = 0; |
249 | *cert_cn = apr_palloc(p, data_len); | ||
250 | rv = gnutls_x509_crt_get_dn_by_oid(cert, | 256 | rv = gnutls_x509_crt_get_dn_by_oid(cert, |
251 | GNUTLS_OID_X520_COMMON_NAME, 0, | 257 | GNUTLS_OID_X520_COMMON_NAME, |
252 | 0, *cert_cn, &data_len); | 258 | 0, 0, NULL, &data_len); |
253 | } else { /* No CN return subject alternative name */ | 259 | |
254 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, | 260 | if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { |
255 | "No common name found in certificate for '%s:%d'. Looking for subject alternative name...", | 261 | *cert_cn = apr_palloc(p, data_len); |
256 | s->server_hostname, s->port); | 262 | rv = gnutls_x509_crt_get_dn_by_oid(cert, |
257 | rv = 0; | 263 | GNUTLS_OID_X520_COMMON_NAME, |
258 | /* read subject alternative name */ | 264 | 0, 0, *cert_cn, |
259 | for (i = 0; !(rv < 0); i++) { | 265 | &data_len); |
260 | data_len = 0; | 266 | } else { /* No CN return subject alternative name */ |
261 | rv = gnutls_x509_crt_get_subject_alt_name(cert, i, | 267 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, |
262 | NULL, &data_len, | 268 | "No common name found in certificate for '%s:%d'. Looking for subject alternative name...", |
263 | NULL); | 269 | s->server_hostname, s->port); |
264 | 270 | rv = 0; | |
265 | if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { | 271 | /* read subject alternative name */ |
266 | /* FIXME: not very efficient. What if we have several alt names | 272 | for (i = 0; !(rv < 0); i++) { |
267 | * before DNSName? | 273 | data_len = 0; |
268 | */ | 274 | rv = gnutls_x509_crt_get_subject_alt_name(cert, i, |
269 | *cert_cn = apr_palloc(p, data_len + 1); | 275 | NULL, |
270 | 276 | &data_len, | |
271 | rv = gnutls_x509_crt_get_subject_alt_name(cert, i, | 277 | NULL); |
272 | *cert_cn, | 278 | |
273 | &data_len, NULL); | 279 | if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER |
274 | (*cert_cn)[data_len] = 0; | 280 | && data_len > 1) { |
275 | 281 | /* FIXME: not very efficient. What if we have several alt names | |
276 | if (rv == GNUTLS_SAN_DNSNAME) | 282 | * before DNSName? |
277 | break; | 283 | */ |
278 | } | 284 | *cert_cn = apr_palloc(p, data_len + 1); |
285 | |||
286 | rv = gnutls_x509_crt_get_subject_alt_name | ||
287 | (cert, i, *cert_cn, &data_len, NULL); | ||
288 | (*cert_cn)[data_len] = 0; | ||
289 | |||
290 | if (rv == GNUTLS_SAN_DNSNAME) | ||
291 | break; | ||
292 | } | ||
293 | } | ||
279 | } | 294 | } |
280 | } | ||
281 | 295 | ||
282 | return rv; | 296 | return rv; |
283 | } | 297 | } |
284 | 298 | ||
285 | static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p, | 299 | static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p, |
286 | gnutls_openpgp_crt_t cert, char **cert_cn) | 300 | gnutls_openpgp_crt_t cert, char **cert_cn) |
287 | { | 301 | { |
288 | int rv = 0; | 302 | int rv = 0; |
289 | size_t data_len; | 303 | size_t data_len; |
290 | 304 | ||
291 | 305 | ||
292 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 306 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
293 | *cert_cn = NULL; | 307 | *cert_cn = NULL; |
294 | 308 | ||
295 | data_len = 0; | 309 | data_len = 0; |
296 | rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len); | 310 | rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len); |
297 | 311 | ||
298 | if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { | 312 | if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { |
299 | *cert_cn = apr_palloc(p, data_len); | 313 | *cert_cn = apr_palloc(p, data_len); |
300 | rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, &data_len); | 314 | rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, |
301 | } else { /* No CN return subject alternative name */ | 315 | &data_len); |
302 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, | 316 | } else { /* No CN return subject alternative name */ |
303 | "No name found in PGP certificate for '%s:%d'.", | 317 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, |
304 | s->server_hostname, s->port); | 318 | "No name found in PGP certificate for '%s:%d'.", |
305 | } | 319 | s->server_hostname, s->port); |
320 | } | ||
306 | 321 | ||
307 | return rv; | 322 | return rv; |
308 | } | 323 | } |
309 | 324 | ||
310 | 325 | ||
@@ -312,27 +327,27 @@ int | |||
312 | mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | 327 | mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, |
313 | apr_pool_t * ptemp, server_rec * base_server) | 328 | apr_pool_t * ptemp, server_rec * base_server) |
314 | { | 329 | { |
315 | int rv; | 330 | int rv; |
316 | server_rec *s; | 331 | server_rec *s; |
317 | gnutls_dh_params_t dh_params = NULL; | 332 | gnutls_dh_params_t dh_params = NULL; |
318 | gnutls_rsa_params_t rsa_params = NULL; | 333 | gnutls_rsa_params_t rsa_params = NULL; |
319 | mgs_srvconf_rec *sc; | 334 | mgs_srvconf_rec *sc; |
320 | mgs_srvconf_rec *sc_base; | 335 | mgs_srvconf_rec *sc_base; |
321 | void *data = NULL; | 336 | void *data = NULL; |
322 | int first_run = 0; | 337 | int first_run = 0; |
323 | const char *userdata_key = "mgs_init"; | 338 | const char *userdata_key = "mgs_init"; |
324 | 339 | ||
325 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 340 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
326 | apr_pool_userdata_get(&data, userdata_key, base_server->process->pool); | 341 | apr_pool_userdata_get(&data, userdata_key, |
327 | if (data == NULL) { | ||
328 | first_run = 1; | ||
329 | apr_pool_userdata_set((const void *) 1, userdata_key, | ||
330 | apr_pool_cleanup_null, | ||
331 | base_server->process->pool); | 342 | base_server->process->pool); |
332 | } | 343 | if (data == NULL) { |
344 | first_run = 1; | ||
345 | apr_pool_userdata_set((const void *) 1, userdata_key, | ||
346 | apr_pool_cleanup_null, | ||
347 | base_server->process->pool); | ||
348 | } | ||
333 | 349 | ||
334 | 350 | ||
335 | { | ||
336 | s = base_server; | 351 | s = base_server; |
337 | sc_base = | 352 | sc_base = |
338 | (mgs_srvconf_rec *) ap_get_module_config(s->module_config, | 353 | (mgs_srvconf_rec *) ap_get_module_config(s->module_config, |
@@ -341,545 +356,568 @@ mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | |||
341 | gnutls_dh_params_init(&dh_params); | 356 | gnutls_dh_params_init(&dh_params); |
342 | 357 | ||
343 | if (sc_base->dh_params == NULL) { | 358 | if (sc_base->dh_params == NULL) { |
344 | gnutls_datum pdata = { (void *) static_dh_params, sizeof(static_dh_params) }; | 359 | gnutls_datum pdata = { |
345 | /* loading defaults */ | 360 | (void *) static_dh_params, |
346 | rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, | 361 | sizeof(static_dh_params) |
347 | GNUTLS_X509_FMT_PEM); | 362 | }; |
348 | 363 | /* loading defaults */ | |
349 | if (rv < 0) { | 364 | rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, |
350 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | 365 | GNUTLS_X509_FMT_PEM); |
351 | "GnuTLS: Unable to load DH Params: (%d) %s", | 366 | |
352 | rv, gnutls_strerror(rv)); | 367 | if (rv < 0) { |
353 | exit(rv); | 368 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, |
354 | } | 369 | "GnuTLS: Unable to load DH Params: (%d) %s", |
355 | } else dh_params = sc_base->dh_params; | 370 | rv, gnutls_strerror(rv)); |
356 | 371 | exit(rv); | |
357 | if (sc_base->rsa_params != NULL) | 372 | } |
358 | rsa_params = sc_base->rsa_params; | 373 | } else |
374 | dh_params = sc_base->dh_params; | ||
375 | |||
376 | if (sc_base->rsa_params != NULL) | ||
377 | rsa_params = sc_base->rsa_params; | ||
359 | 378 | ||
360 | /* else not an error but RSA-EXPORT ciphersuites are not available | 379 | /* else not an error but RSA-EXPORT ciphersuites are not available |
361 | */ | 380 | */ |
362 | 381 | ||
363 | rv = mgs_cache_post_config(p, s, sc_base); | 382 | rv = mgs_cache_post_config(p, s, sc_base); |
364 | if (rv != 0) { | 383 | if (rv != 0) { |
365 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, | 384 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, |
366 | "GnuTLS: Post Config for GnuTLSCache Failed." | 385 | "GnuTLS: Post Config for GnuTLSCache Failed." |
367 | " Shutting Down."); | 386 | " Shutting Down."); |
368 | exit(-1); | 387 | exit(-1); |
369 | } | 388 | } |
370 | 389 | ||
371 | for (s = base_server; s; s = s->next) { | 390 | for (s = base_server; s; s = s->next) { |
372 | void *load = NULL; | 391 | void *load = NULL; |
373 | sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, | 392 | sc = (mgs_srvconf_rec *) |
374 | &gnutls_module); | 393 | ap_get_module_config(s->module_config, &gnutls_module); |
375 | sc->cache_type = sc_base->cache_type; | 394 | sc->cache_type = sc_base->cache_type; |
376 | sc->cache_config = sc_base->cache_config; | 395 | sc->cache_config = sc_base->cache_config; |
377 | 396 | ||
378 | /* Check if the priorities have been set */ | 397 | /* Check if the priorities have been set */ |
379 | if (sc->priorities == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) { | 398 | if (sc->priorities == NULL |
380 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | 399 | && sc->enabled == GNUTLS_ENABLED_TRUE) { |
381 | "GnuTLS: Host '%s:%d' is missing the GnuTLSPriorities directive!", | 400 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, |
382 | s->server_hostname, s->port); | 401 | "GnuTLS: Host '%s:%d' is missing the GnuTLSPriorities directive!", |
383 | exit(-1); | 402 | s->server_hostname, s->port); |
384 | } | 403 | exit(-1); |
385 | 404 | } | |
386 | /* Check if DH or RSA params have been set per host */ | 405 | |
387 | if (sc->rsa_params != NULL) | 406 | /* Check if DH or RSA params have been set per host */ |
388 | load = sc->rsa_params; | 407 | if (sc->rsa_params != NULL) |
389 | else if (rsa_params) load = rsa_params; | 408 | load = sc->rsa_params; |
390 | 409 | else if (rsa_params) | |
391 | if (load != NULL) | 410 | load = rsa_params; |
392 | gnutls_certificate_set_rsa_export_params(sc->certs, load); | 411 | |
393 | 412 | if (load != NULL) | |
394 | 413 | gnutls_certificate_set_rsa_export_params(sc->certs, | |
395 | load = NULL; | 414 | load); |
396 | if (sc->dh_params != NULL) | 415 | |
397 | load = sc->dh_params; | 416 | |
398 | else if (dh_params) load = dh_params; | 417 | load = NULL; |
399 | 418 | if (sc->dh_params != NULL) | |
400 | if (load != NULL) { /* not needed but anyway */ | 419 | load = sc->dh_params; |
401 | gnutls_certificate_set_dh_params(sc->certs, load); | 420 | else if (dh_params) |
402 | gnutls_anon_set_server_dh_params(sc->anon_creds, load); | 421 | load = dh_params; |
403 | } | 422 | |
404 | 423 | if (load != NULL) { /* not needed but anyway */ | |
405 | gnutls_certificate_server_set_retrieve_function(sc->certs, | 424 | gnutls_certificate_set_dh_params(sc->certs, load); |
406 | cert_retrieve_fn); | 425 | gnutls_anon_set_server_dh_params(sc->anon_creds, |
426 | load); | ||
427 | } | ||
428 | |||
429 | gnutls_certificate_server_set_retrieve_function(sc->certs, | ||
430 | cert_retrieve_fn); | ||
407 | 431 | ||
408 | #ifdef ENABLE_SRP | 432 | #ifdef ENABLE_SRP |
409 | if (sc->srp_tpasswd_conf_file != NULL | 433 | if (sc->srp_tpasswd_conf_file != NULL |
410 | && sc->srp_tpasswd_file != NULL) { | 434 | && sc->srp_tpasswd_file != NULL) { |
411 | rv = gnutls_srp_set_server_credentials_file(sc->srp_creds, | 435 | rv = gnutls_srp_set_server_credentials_file |
412 | sc-> | 436 | (sc->srp_creds, sc->srp_tpasswd_file, |
413 | srp_tpasswd_file, | 437 | sc->srp_tpasswd_conf_file); |
414 | sc-> | 438 | |
415 | srp_tpasswd_conf_file); | 439 | if (rv < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) { |
416 | 440 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, | |
417 | if (rv < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) { | 441 | s, |
418 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | 442 | "[GnuTLS] - Host '%s:%d' is missing a " |
419 | "[GnuTLS] - Host '%s:%d' is missing a " | 443 | "SRP password or conf File!", |
420 | "SRP password or conf File!", | 444 | s->server_hostname, s->port); |
421 | s->server_hostname, s->port); | 445 | exit(-1); |
422 | exit(-1); | 446 | } |
423 | } | 447 | } |
424 | } | ||
425 | #endif | 448 | #endif |
426 | 449 | ||
427 | if (sc->certs_x509[0] == NULL && | 450 | if (sc->certs_x509[0] == NULL && |
428 | sc->cert_pgp == NULL && | 451 | sc->cert_pgp == NULL && |
429 | sc->enabled == GNUTLS_ENABLED_TRUE) { | 452 | sc->enabled == GNUTLS_ENABLED_TRUE) { |
430 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | 453 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, |
431 | "[GnuTLS] - Host '%s:%d' is missing a " | 454 | "[GnuTLS] - Host '%s:%d' is missing a " |
432 | "Certificate File!", s->server_hostname, | 455 | "Certificate File!", |
433 | s->port); | 456 | s->server_hostname, s->port); |
434 | exit(-1); | 457 | exit(-1); |
435 | } | 458 | } |
436 | |||
437 | if (sc->enabled == GNUTLS_ENABLED_TRUE && | ||
438 | ((sc->certs_x509[0] != NULL && sc->privkey_x509 == NULL) || | ||
439 | (sc->cert_pgp != NULL && sc->privkey_pgp == NULL))) { | ||
440 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
441 | "[GnuTLS] - Host '%s:%d' is missing a " | ||
442 | "Private Key File!", | ||
443 | s->server_hostname, s->port); | ||
444 | exit(-1); | ||
445 | } | ||
446 | 459 | ||
447 | if (sc->enabled == GNUTLS_ENABLED_TRUE) { | 460 | if (sc->enabled == GNUTLS_ENABLED_TRUE && |
448 | rv = read_crt_cn(s, p, sc->certs_x509[0], &sc->cert_cn); | 461 | ((sc->certs_x509[0] != NULL |
449 | if (rv < 0 && sc->cert_pgp != NULL) /* try openpgp certificate */ | 462 | && sc->privkey_x509 == NULL) || (sc->cert_pgp != NULL |
450 | rv = read_pgpcrt_cn(s, p, sc->cert_pgp, &sc->cert_cn); | 463 | && sc->privkey_pgp |
464 | == NULL))) { | ||
465 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
466 | "[GnuTLS] - Host '%s:%d' is missing a " | ||
467 | "Private Key File!", | ||
468 | s->server_hostname, s->port); | ||
469 | exit(-1); | ||
470 | } | ||
451 | 471 | ||
452 | if (rv < 0) { | 472 | if (sc->enabled == GNUTLS_ENABLED_TRUE) { |
453 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | 473 | rv = read_crt_cn(s, p, sc->certs_x509[0], |
454 | "[GnuTLS] - Cannot find a certificate for host '%s:%d'!", | 474 | &sc->cert_cn); |
455 | s->server_hostname, s->port); | 475 | if (rv < 0 && sc->cert_pgp != NULL) /* try openpgp certificate */ |
456 | sc->cert_cn = NULL; | 476 | rv = read_pgpcrt_cn(s, p, sc->cert_pgp, |
457 | continue; | 477 | &sc->cert_cn); |
478 | |||
479 | if (rv < 0) { | ||
480 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, | ||
481 | s, | ||
482 | "[GnuTLS] - Cannot find a certificate for host '%s:%d'!", | ||
483 | s->server_hostname, s->port); | ||
484 | sc->cert_cn = NULL; | ||
485 | continue; | ||
486 | } | ||
458 | } | 487 | } |
459 | } | ||
460 | } | 488 | } |
461 | } | ||
462 | 489 | ||
463 | ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION); | ||
464 | 490 | ||
465 | return OK; | 491 | ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION); |
492 | |||
493 | return OK; | ||
466 | } | 494 | } |
467 | 495 | ||
468 | void mgs_hook_child_init(apr_pool_t * p, server_rec * s) | 496 | void mgs_hook_child_init(apr_pool_t * p, server_rec * s) |
469 | { | 497 | { |
470 | apr_status_t rv = APR_SUCCESS; | 498 | apr_status_t rv = APR_SUCCESS; |
471 | mgs_srvconf_rec *sc = ap_get_module_config(s->module_config, | 499 | mgs_srvconf_rec *sc = ap_get_module_config(s->module_config, |
472 | &gnutls_module); | 500 | &gnutls_module); |
473 | 501 | ||
474 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 502 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
475 | if (sc->cache_type != mgs_cache_none) { | 503 | if (sc->cache_type != mgs_cache_none) { |
476 | rv = mgs_cache_child_init(p, s, sc); | 504 | rv = mgs_cache_child_init(p, s, sc); |
477 | if (rv != APR_SUCCESS) { | 505 | if (rv != APR_SUCCESS) { |
478 | ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, | 506 | ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, |
479 | "[GnuTLS] - Failed to run Cache Init"); | 507 | "[GnuTLS] - Failed to run Cache Init"); |
508 | } | ||
509 | } else { | ||
510 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, | ||
511 | "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache"); | ||
480 | } | 512 | } |
481 | } else { | ||
482 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, | ||
483 | "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache"); | ||
484 | } | ||
485 | } | 513 | } |
486 | 514 | ||
487 | const char *mgs_hook_http_scheme(const request_rec * r) | 515 | const char *mgs_hook_http_scheme(const request_rec * r) |
488 | { | 516 | { |
489 | mgs_srvconf_rec *sc; | 517 | mgs_srvconf_rec *sc; |
490 | |||
491 | if (r == NULL) | ||
492 | return NULL; | ||
493 | |||
494 | sc = | ||
495 | (mgs_srvconf_rec *) ap_get_module_config(r->server->module_config, | ||
496 | &gnutls_module); | ||
497 | |||
498 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | ||
499 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { | ||
500 | return NULL; | ||
501 | } | ||
502 | 518 | ||
503 | return "https"; | 519 | if (r == NULL) |
520 | return NULL; | ||
521 | |||
522 | sc = (mgs_srvconf_rec *) ap_get_module_config(r-> | ||
523 | server->module_config, | ||
524 | &gnutls_module); | ||
525 | |||
526 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | ||
527 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { | ||
528 | return NULL; | ||
529 | } | ||
530 | |||
531 | return "https"; | ||
504 | } | 532 | } |
505 | 533 | ||
506 | apr_port_t mgs_hook_default_port(const request_rec * r) | 534 | apr_port_t mgs_hook_default_port(const request_rec * r) |
507 | { | 535 | { |
508 | mgs_srvconf_rec *sc; | 536 | mgs_srvconf_rec *sc; |
509 | 537 | ||
510 | if (r == NULL) | 538 | if (r == NULL) |
511 | return 0; | 539 | return 0; |
512 | 540 | ||
513 | sc = | 541 | sc = (mgs_srvconf_rec *) ap_get_module_config(r-> |
514 | (mgs_srvconf_rec *) ap_get_module_config(r->server->module_config, | 542 | server->module_config, |
515 | &gnutls_module); | 543 | &gnutls_module); |
516 | 544 | ||
517 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 545 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
518 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { | 546 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { |
519 | return 0; | 547 | return 0; |
520 | } | 548 | } |
521 | 549 | ||
522 | return 443; | 550 | return 443; |
523 | } | 551 | } |
524 | 552 | ||
525 | #define MAX_HOST_LEN 255 | 553 | #define MAX_HOST_LEN 255 |
526 | 554 | ||
527 | #if USING_2_1_RECENT | 555 | #if USING_2_1_RECENT |
528 | typedef struct { | 556 | typedef struct { |
529 | mgs_handle_t *ctxt; | 557 | mgs_handle_t *ctxt; |
530 | mgs_srvconf_rec *sc; | 558 | mgs_srvconf_rec *sc; |
531 | const char *sni_name; | 559 | const char *sni_name; |
532 | } vhost_cb_rec; | 560 | } vhost_cb_rec; |
533 | 561 | ||
534 | static int vhost_cb(void *baton, conn_rec * conn, server_rec * s) | 562 | static int vhost_cb(void *baton, conn_rec * conn, server_rec * s) |
535 | { | 563 | { |
536 | mgs_srvconf_rec *tsc; | 564 | mgs_srvconf_rec *tsc; |
537 | vhost_cb_rec *x = baton; | 565 | vhost_cb_rec *x = baton; |
538 | 566 | ||
539 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 567 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
540 | tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, | 568 | tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, |
541 | &gnutls_module); | 569 | &gnutls_module); |
542 | 570 | ||
543 | if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) { | 571 | if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) { |
544 | return 0; | 572 | return 0; |
545 | } | 573 | } |
546 | 574 | ||
547 | /* The CN can contain a * -- this will match those too. */ | 575 | /* The CN can contain a * -- this will match those too. */ |
548 | if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) { | 576 | if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) { |
549 | /* found a match */ | 577 | /* found a match */ |
550 | #if MOD_GNUTLS_DEBUG | 578 | #if MOD_GNUTLS_DEBUG |
551 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | 579 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, |
552 | x->ctxt->c->base_server, | 580 | x->ctxt->c->base_server, |
553 | "GnuTLS: Virtual Host CB: " | 581 | "GnuTLS: Virtual Host CB: " |
554 | "'%s' == '%s'", tsc->cert_cn, x->sni_name); | 582 | "'%s' == '%s'", tsc->cert_cn, x->sni_name); |
555 | #endif | 583 | #endif |
556 | /* Because we actually change the server used here, we need to reset | 584 | /* Because we actually change the server used here, we need to reset |
557 | * things like ClientVerify. | 585 | * things like ClientVerify. |
558 | */ | 586 | */ |
559 | x->sc = tsc; | 587 | x->sc = tsc; |
560 | /* Shit. Crap. Dammit. We *really* should rehandshake here, as our | 588 | /* Shit. Crap. Dammit. We *really* should rehandshake here, as our |
561 | * certificate structure *should* change when the server changes. | 589 | * certificate structure *should* change when the server changes. |
562 | * acccckkkkkk. | 590 | * acccckkkkkk. |
563 | */ | 591 | */ |
564 | return 1; | 592 | return 1; |
565 | } else { | 593 | } else { |
566 | #if MOD_GNUTLS_DEBUG | 594 | #if MOD_GNUTLS_DEBUG |
567 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | 595 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, |
568 | x->ctxt->c->base_server, | 596 | x->ctxt->c->base_server, |
569 | "GnuTLS: Virtual Host CB: " | 597 | "GnuTLS: Virtual Host CB: " |
570 | "'%s' != '%s'", tsc->cert_cn, x->sni_name); | 598 | "'%s' != '%s'", tsc->cert_cn, x->sni_name); |
571 | #endif | 599 | #endif |
572 | 600 | ||
573 | } | 601 | } |
574 | return 0; | 602 | return 0; |
575 | } | 603 | } |
576 | #endif | 604 | #endif |
577 | 605 | ||
578 | mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session) | 606 | mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session) |
579 | { | 607 | { |
580 | int rv; | 608 | int rv; |
581 | unsigned int sni_type; | 609 | unsigned int sni_type; |
582 | size_t data_len = MAX_HOST_LEN; | 610 | size_t data_len = MAX_HOST_LEN; |
583 | char sni_name[MAX_HOST_LEN]; | 611 | char sni_name[MAX_HOST_LEN]; |
584 | mgs_handle_t *ctxt; | 612 | mgs_handle_t *ctxt; |
585 | #if USING_2_1_RECENT | 613 | #if USING_2_1_RECENT |
586 | vhost_cb_rec cbx; | 614 | vhost_cb_rec cbx; |
587 | #else | 615 | #else |
588 | server_rec *s; | 616 | server_rec *s; |
589 | mgs_srvconf_rec *tsc; | 617 | mgs_srvconf_rec *tsc; |
590 | #endif | 618 | #endif |
591 | 619 | ||
592 | if (session == NULL) | 620 | if (session == NULL) |
593 | return NULL; | 621 | return NULL; |
594 | 622 | ||
595 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 623 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
596 | ctxt = gnutls_transport_get_ptr(session); | 624 | ctxt = gnutls_transport_get_ptr(session); |
597 | 625 | ||
598 | rv = gnutls_server_name_get(ctxt->session, sni_name, | 626 | rv = gnutls_server_name_get(ctxt->session, sni_name, |
599 | &data_len, &sni_type, 0); | 627 | &data_len, &sni_type, 0); |
600 | 628 | ||
601 | if (rv != 0) { | 629 | if (rv != 0) { |
602 | return NULL; | 630 | return NULL; |
603 | } | 631 | } |
604 | 632 | ||
605 | if (sni_type != GNUTLS_NAME_DNS) { | 633 | if (sni_type != GNUTLS_NAME_DNS) { |
606 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, | 634 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, |
607 | ctxt->c->base_server, | 635 | ctxt->c->base_server, |
608 | "GnuTLS: Unknown type '%d' for SNI: " | 636 | "GnuTLS: Unknown type '%d' for SNI: " |
609 | "'%s'", sni_type, sni_name); | 637 | "'%s'", sni_type, sni_name); |
610 | return NULL; | 638 | return NULL; |
611 | } | 639 | } |
612 | 640 | ||
613 | /** | 641 | /** |
614 | * Code in the Core already sets up the c->base_server as the base | 642 | * Code in the Core already sets up the c->base_server as the base |
615 | * for this IP/Port combo. Trust that the core did the 'right' thing. | 643 | * for this IP/Port combo. Trust that the core did the 'right' thing. |
616 | */ | 644 | */ |
617 | #if USING_2_1_RECENT | 645 | #if USING_2_1_RECENT |
618 | cbx.ctxt = ctxt; | 646 | cbx.ctxt = ctxt; |
619 | cbx.sc = NULL; | 647 | cbx.sc = NULL; |
620 | cbx.sni_name = sni_name; | 648 | cbx.sni_name = sni_name; |
621 | |||
622 | rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx); | ||
623 | if (rv == 1) { | ||
624 | return cbx.sc; | ||
625 | } | ||
626 | #else | ||
627 | for (s = ap_server_conf; s; s = s->next) { | ||
628 | 649 | ||
629 | tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, | 650 | rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx); |
630 | &gnutls_module); | 651 | if (rv == 1) { |
631 | if (tsc->enabled != GNUTLS_ENABLED_TRUE) { | 652 | return cbx.sc; |
632 | continue; | ||
633 | } | 653 | } |
654 | #else | ||
655 | for (s = ap_server_conf; s; s = s->next) { | ||
656 | |||
657 | tsc = | ||
658 | (mgs_srvconf_rec *) | ||
659 | ap_get_module_config(s->module_config, &gnutls_module); | ||
660 | if (tsc->enabled != GNUTLS_ENABLED_TRUE) { | ||
661 | continue; | ||
662 | } | ||
634 | #if MOD_GNUTLS_DEBUG | 663 | #if MOD_GNUTLS_DEBUG |
635 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | 664 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, |
636 | ctxt->c->base_server, | 665 | ctxt->c->base_server, |
637 | "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X", | 666 | "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X", |
638 | tsc->cert_cn, rv, | 667 | tsc->cert_cn, rv, |
639 | gnutls_pk_algorithm_get_name | 668 | gnutls_pk_algorithm_get_name |
640 | (gnutls_x509_privkey_get_pk_algorithm | 669 | (gnutls_x509_privkey_get_pk_algorithm |
641 | (ctxt->sc->privkey_x509)), (unsigned int) s, | 670 | (ctxt->sc->privkey_x509)), (unsigned int) s, |
642 | (unsigned int) s->next, (unsigned int) tsc); | 671 | (unsigned int) s->next, (unsigned int) tsc); |
643 | #endif | 672 | #endif |
644 | /* The CN can contain a * -- this will match those too. */ | 673 | /* The CN can contain a * -- this will match those too. */ |
645 | if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) { | 674 | if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) { |
646 | #if MOD_GNUTLS_DEBUG | 675 | #if MOD_GNUTLS_DEBUG |
647 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | 676 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, |
648 | ctxt->c->base_server, | 677 | ctxt->c->base_server, |
649 | "GnuTLS: Virtual Host: " | 678 | "GnuTLS: Virtual Host: " |
650 | "'%s' == '%s'", tsc->cert_cn, sni_name); | 679 | "'%s' == '%s'", tsc->cert_cn, |
680 | sni_name); | ||
651 | #endif | 681 | #endif |
652 | return tsc; | 682 | return tsc; |
683 | } | ||
653 | } | 684 | } |
654 | } | ||
655 | #endif | 685 | #endif |
656 | return NULL; | 686 | return NULL; |
657 | } | 687 | } |
658 | 688 | ||
659 | 689 | ||
660 | static const int protocol_priority[] = { | 690 | static const int protocol_priority[] = { |
661 | GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 | 691 | GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 |
662 | }; | 692 | }; |
663 | 693 | ||
664 | 694 | ||
665 | static mgs_handle_t *create_gnutls_handle(apr_pool_t * pool, conn_rec * c) | 695 | static mgs_handle_t *create_gnutls_handle(apr_pool_t * pool, conn_rec * c) |
666 | { | 696 | { |
667 | mgs_handle_t *ctxt; | 697 | mgs_handle_t *ctxt; |
668 | mgs_srvconf_rec *sc = | 698 | mgs_srvconf_rec *sc = |
669 | (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> | 699 | (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> |
670 | module_config, | 700 | module_config, |
671 | &gnutls_module); | 701 | &gnutls_module); |
672 | 702 | ||
673 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 703 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
674 | ctxt = apr_pcalloc(pool, sizeof(*ctxt)); | 704 | ctxt = apr_pcalloc(pool, sizeof(*ctxt)); |
675 | ctxt->c = c; | 705 | ctxt->c = c; |
676 | ctxt->sc = sc; | 706 | ctxt->sc = sc; |
677 | ctxt->status = 0; | 707 | ctxt->status = 0; |
678 | 708 | ||
679 | ctxt->input_rc = APR_SUCCESS; | 709 | ctxt->input_rc = APR_SUCCESS; |
680 | ctxt->input_bb = apr_brigade_create(c->pool, c->bucket_alloc); | 710 | ctxt->input_bb = apr_brigade_create(c->pool, c->bucket_alloc); |
681 | ctxt->input_cbuf.length = 0; | 711 | ctxt->input_cbuf.length = 0; |
682 | 712 | ||
683 | ctxt->output_rc = APR_SUCCESS; | 713 | ctxt->output_rc = APR_SUCCESS; |
684 | ctxt->output_bb = apr_brigade_create(c->pool, c->bucket_alloc); | 714 | ctxt->output_bb = apr_brigade_create(c->pool, c->bucket_alloc); |
685 | ctxt->output_blen = 0; | 715 | ctxt->output_blen = 0; |
686 | ctxt->output_length = 0; | 716 | ctxt->output_length = 0; |
687 | 717 | ||
688 | gnutls_init(&ctxt->session, GNUTLS_SERVER); | 718 | gnutls_init(&ctxt->session, GNUTLS_SERVER); |
689 | if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0) | 719 | if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0) |
690 | gnutls_session_ticket_enable_server(ctxt->session, &session_ticket_key); | 720 | gnutls_session_ticket_enable_server(ctxt->session, |
691 | 721 | &session_ticket_key); | |
692 | /* because we don't set any default priorities here (we set later at | 722 | |
693 | * the user hello callback) we need to at least set this in order for | 723 | /* because we don't set any default priorities here (we set later at |
694 | * gnutls to be able to read packets. | 724 | * the user hello callback) we need to at least set this in order for |
695 | */ | 725 | * gnutls to be able to read packets. |
696 | gnutls_protocol_set_priority(ctxt->session, protocol_priority); | 726 | */ |
727 | gnutls_protocol_set_priority(ctxt->session, protocol_priority); | ||
697 | 728 | ||
698 | gnutls_handshake_set_post_client_hello_function(ctxt->session, | 729 | gnutls_handshake_set_post_client_hello_function(ctxt->session, |
699 | mgs_select_virtual_server_cb); | 730 | mgs_select_virtual_server_cb); |
700 | 731 | ||
701 | mgs_cache_session_init(ctxt); | 732 | mgs_cache_session_init(ctxt); |
702 | 733 | ||
703 | return ctxt; | 734 | return ctxt; |
704 | } | 735 | } |
705 | 736 | ||
706 | int mgs_hook_pre_connection(conn_rec * c, void *csd) | 737 | int mgs_hook_pre_connection(conn_rec * c, void *csd) |
707 | { | 738 | { |
708 | mgs_handle_t *ctxt; | 739 | mgs_handle_t *ctxt; |
709 | mgs_srvconf_rec *sc; | 740 | mgs_srvconf_rec *sc; |
710 | 741 | ||
711 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 742 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
712 | 743 | ||
713 | if (c == NULL) | 744 | if (c == NULL) |
714 | return DECLINED; | 745 | return DECLINED; |
715 | |||
716 | sc = | ||
717 | (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> | ||
718 | module_config, | ||
719 | &gnutls_module); | ||
720 | |||
721 | if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) { | ||
722 | return DECLINED; | ||
723 | } | ||
724 | 746 | ||
725 | if(c->remote_addr->hostname) | 747 | sc = (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> |
726 | /* Connection initiated by Apache (mod_proxy) => ignore */ | 748 | module_config, |
727 | return OK; | 749 | &gnutls_module); |
728 | 750 | ||
729 | ctxt = create_gnutls_handle(c->pool, c); | 751 | if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) { |
752 | return DECLINED; | ||
753 | } | ||
754 | |||
755 | if (c->remote_addr->hostname) | ||
756 | /* Connection initiated by Apache (mod_proxy) => ignore */ | ||
757 | return OK; | ||
758 | |||
759 | ctxt = create_gnutls_handle(c->pool, c); | ||
730 | 760 | ||
731 | ap_set_module_config(c->conn_config, &gnutls_module, ctxt); | 761 | ap_set_module_config(c->conn_config, &gnutls_module, ctxt); |
732 | 762 | ||
733 | gnutls_transport_set_pull_function(ctxt->session, mgs_transport_read); | 763 | gnutls_transport_set_pull_function(ctxt->session, |
734 | gnutls_transport_set_push_function(ctxt->session, mgs_transport_write); | 764 | mgs_transport_read); |
735 | gnutls_transport_set_ptr(ctxt->session, ctxt); | 765 | gnutls_transport_set_push_function(ctxt->session, |
766 | mgs_transport_write); | ||
767 | gnutls_transport_set_ptr(ctxt->session, ctxt); | ||
736 | 768 | ||
737 | ctxt->input_filter = | 769 | ctxt->input_filter = |
738 | ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c); | 770 | ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c); |
739 | ctxt->output_filter = | 771 | ctxt->output_filter = |
740 | ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c); | 772 | ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c); |
741 | 773 | ||
742 | return OK; | 774 | return OK; |
743 | } | 775 | } |
744 | 776 | ||
745 | int mgs_hook_fixups(request_rec * r) | 777 | int mgs_hook_fixups(request_rec * r) |
746 | { | 778 | { |
747 | unsigned char sbuf[GNUTLS_MAX_SESSION_ID]; | 779 | unsigned char sbuf[GNUTLS_MAX_SESSION_ID]; |
748 | char buf[AP_IOBUFSIZE]; | 780 | char buf[AP_IOBUFSIZE]; |
749 | const char *tmp; | 781 | const char *tmp; |
750 | size_t len; | 782 | size_t len; |
751 | mgs_handle_t *ctxt; | 783 | mgs_handle_t *ctxt; |
752 | int rv = OK; | 784 | int rv = OK; |
753 | 785 | ||
754 | if (r == NULL) | 786 | if (r == NULL) |
755 | return DECLINED; | 787 | return DECLINED; |
756 | 788 | ||
757 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 789 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
758 | apr_table_t *env = r->subprocess_env; | 790 | apr_table_t *env = r->subprocess_env; |
759 | 791 | ||
760 | ctxt = | 792 | ctxt = |
761 | ap_get_module_config(r->connection->conn_config, &gnutls_module); | 793 | ap_get_module_config(r->connection->conn_config, |
794 | &gnutls_module); | ||
762 | 795 | ||
763 | if (!ctxt || ctxt->session == NULL) { | 796 | if (!ctxt || ctxt->session == NULL) { |
764 | return DECLINED; | 797 | return DECLINED; |
765 | } | 798 | } |
766 | 799 | ||
767 | apr_table_setn(env, "HTTPS", "on"); | 800 | apr_table_setn(env, "HTTPS", "on"); |
768 | 801 | ||
769 | apr_table_setn(env, "SSL_VERSION_LIBRARY", | 802 | apr_table_setn(env, "SSL_VERSION_LIBRARY", |
770 | "GnuTLS/" LIBGNUTLS_VERSION); | 803 | "GnuTLS/" LIBGNUTLS_VERSION); |
771 | apr_table_setn(env, "SSL_VERSION_INTERFACE", | 804 | apr_table_setn(env, "SSL_VERSION_INTERFACE", |
772 | "mod_gnutls/" MOD_GNUTLS_VERSION); | 805 | "mod_gnutls/" MOD_GNUTLS_VERSION); |
773 | 806 | ||
774 | apr_table_setn(env, "SSL_PROTOCOL", | 807 | apr_table_setn(env, "SSL_PROTOCOL", |
775 | gnutls_protocol_get_name(gnutls_protocol_get_version | 808 | gnutls_protocol_get_name(gnutls_protocol_get_version |
776 | (ctxt->session))); | 809 | (ctxt->session))); |
777 | 810 | ||
778 | /* should have been called SSL_CIPHERSUITE instead */ | 811 | /* should have been called SSL_CIPHERSUITE instead */ |
779 | apr_table_setn(env, "SSL_CIPHER", | 812 | apr_table_setn(env, "SSL_CIPHER", |
780 | gnutls_cipher_suite_get_name(gnutls_kx_get | 813 | gnutls_cipher_suite_get_name(gnutls_kx_get |
781 | (ctxt->session), | 814 | (ctxt->session), |
782 | gnutls_cipher_get(ctxt-> | 815 | gnutls_cipher_get |
783 | session), | 816 | (ctxt->session), |
784 | gnutls_mac_get(ctxt-> | 817 | gnutls_mac_get |
785 | session))); | 818 | (ctxt->session))); |
786 | 819 | ||
787 | apr_table_setn(env, "SSL_COMPRESS_METHOD", | 820 | apr_table_setn(env, "SSL_COMPRESS_METHOD", |
788 | gnutls_compression_get_name(gnutls_compression_get | 821 | gnutls_compression_get_name(gnutls_compression_get |
789 | (ctxt->session))); | 822 | (ctxt->session))); |
790 | 823 | ||
791 | #ifdef ENABLE_SRP | 824 | #ifdef ENABLE_SRP |
792 | tmp = gnutls_srp_server_get_username(ctxt->session); | 825 | tmp = gnutls_srp_server_get_username(ctxt->session); |
793 | apr_table_setn(env, "SSL_SRP_USER", (tmp!=NULL)?tmp:""); | 826 | apr_table_setn(env, "SSL_SRP_USER", (tmp != NULL) ? tmp : ""); |
794 | #endif | 827 | #endif |
795 | 828 | ||
796 | if (apr_table_get(env, "SSL_CLIENT_VERIFY") == NULL) | 829 | if (apr_table_get(env, "SSL_CLIENT_VERIFY") == NULL) |
797 | apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE"); | 830 | apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE"); |
798 | 831 | ||
799 | unsigned int key_size = | 832 | unsigned int key_size = |
800 | 8 * gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session)); | 833 | 8 * |
801 | tmp = apr_psprintf(r->pool, "%u", key_size); | 834 | gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session)); |
835 | tmp = apr_psprintf(r->pool, "%u", key_size); | ||
802 | 836 | ||
803 | apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp); | 837 | apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp); |
804 | 838 | ||
805 | apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp); | 839 | apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp); |
806 | 840 | ||
807 | apr_table_setn(env, "SSL_CIPHER_EXPORT", | 841 | apr_table_setn(env, "SSL_CIPHER_EXPORT", |
808 | (key_size <= 40) ? "true" : "false"); | 842 | (key_size <= 40) ? "true" : "false"); |
809 | 843 | ||
810 | len = sizeof(sbuf); | 844 | len = sizeof(sbuf); |
811 | gnutls_session_get_id(ctxt->session, sbuf, &len); | 845 | gnutls_session_get_id(ctxt->session, sbuf, &len); |
812 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); | 846 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); |
813 | apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp)); | 847 | apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp)); |
814 | 848 | ||
815 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) | 849 | if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) |
816 | mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0, | 850 | mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0, |
817 | ctxt->sc->export_certificates_enabled); | 851 | ctxt-> |
818 | else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) | 852 | sc->export_certificates_enabled); |
819 | mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0, | 853 | else if (gnutls_certificate_type_get(ctxt->session) == |
820 | ctxt->sc->export_certificates_enabled); | 854 | GNUTLS_CRT_OPENPGP) |
855 | mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0, | ||
856 | ctxt-> | ||
857 | sc->export_certificates_enabled); | ||
821 | 858 | ||
822 | return rv; | 859 | return rv; |
823 | } | 860 | } |
824 | 861 | ||
825 | int mgs_hook_authz(request_rec * r) | 862 | int mgs_hook_authz(request_rec * r) |
826 | { | 863 | { |
827 | int rv; | 864 | int rv; |
828 | mgs_handle_t *ctxt; | 865 | mgs_handle_t *ctxt; |
829 | mgs_dirconf_rec *dc; | 866 | mgs_dirconf_rec *dc; |
830 | 867 | ||
831 | if (r == NULL) | 868 | if (r == NULL) |
832 | return DECLINED; | 869 | return DECLINED; |
833 | 870 | ||
834 | dc = ap_get_module_config(r->per_dir_config, | 871 | dc = ap_get_module_config(r->per_dir_config, &gnutls_module); |
835 | &gnutls_module); | 872 | |
836 | 873 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | |
837 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 874 | ctxt = |
838 | ctxt = | 875 | ap_get_module_config(r->connection->conn_config, |
839 | ap_get_module_config(r->connection->conn_config, &gnutls_module); | 876 | &gnutls_module); |
840 | 877 | ||
841 | if (!ctxt || ctxt->session == NULL) { | 878 | if (!ctxt || ctxt->session == NULL) { |
842 | return DECLINED; | 879 | return DECLINED; |
843 | } | 880 | } |
844 | 881 | ||
845 | if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) { | 882 | if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) { |
846 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | 883 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
847 | "GnuTLS: Directory set to Ignore Client Certificate!"); | 884 | "GnuTLS: Directory set to Ignore Client Certificate!"); |
848 | } else { | 885 | } else { |
849 | if (ctxt->sc->client_verify_mode < dc->client_verify_mode) { | 886 | if (ctxt->sc->client_verify_mode < dc->client_verify_mode) { |
850 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | 887 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
851 | "GnuTLS: Attempting to rehandshake with peer. %d %d", | 888 | "GnuTLS: Attempting to rehandshake with peer. %d %d", |
852 | ctxt->sc->client_verify_mode, | 889 | ctxt->sc->client_verify_mode, |
853 | dc->client_verify_mode); | 890 | dc->client_verify_mode); |
854 | 891 | ||
855 | /* If we already have a client certificate, there's no point in | 892 | /* If we already have a client certificate, there's no point in |
856 | * re-handshaking... */ | 893 | * re-handshaking... */ |
857 | rv = mgs_cert_verify(r, ctxt); | 894 | rv = mgs_cert_verify(r, ctxt); |
858 | if (rv != DECLINED && rv != HTTP_FORBIDDEN) | 895 | if (rv != DECLINED && rv != HTTP_FORBIDDEN) |
859 | return rv; | 896 | return rv; |
860 | 897 | ||
861 | gnutls_certificate_server_set_request(ctxt->session, | 898 | gnutls_certificate_server_set_request |
862 | dc->client_verify_mode); | 899 | (ctxt->session, dc->client_verify_mode); |
863 | 900 | ||
864 | if (mgs_rehandshake(ctxt) != 0) { | 901 | if (mgs_rehandshake(ctxt) != 0) { |
865 | return HTTP_FORBIDDEN; | 902 | return HTTP_FORBIDDEN; |
866 | } | 903 | } |
867 | } else if (ctxt->sc->client_verify_mode == GNUTLS_CERT_IGNORE) { | 904 | } else if (ctxt->sc->client_verify_mode == |
905 | GNUTLS_CERT_IGNORE) { | ||
868 | #if MOD_GNUTLS_DEBUG | 906 | #if MOD_GNUTLS_DEBUG |
869 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 907 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
870 | "GnuTLS: Peer is set to IGNORE"); | 908 | "GnuTLS: Peer is set to IGNORE"); |
871 | #endif | 909 | #endif |
872 | return DECLINED; | 910 | return DECLINED; |
873 | } | 911 | } |
874 | rv = mgs_cert_verify(r, ctxt); | 912 | rv = mgs_cert_verify(r, ctxt); |
875 | if (rv != DECLINED && | 913 | if (rv != DECLINED && |
876 | (rv != HTTP_FORBIDDEN || | 914 | (rv != HTTP_FORBIDDEN || |
877 | dc->client_verify_mode == GNUTLS_CERT_REQUIRE)) { | 915 | dc->client_verify_mode == GNUTLS_CERT_REQUIRE)) { |
878 | return rv; | 916 | return rv; |
917 | } | ||
879 | } | 918 | } |
880 | } | ||
881 | 919 | ||
882 | return DECLINED; | 920 | return DECLINED; |
883 | } | 921 | } |
884 | 922 | ||
885 | /* variables that are not sent by default: | 923 | /* variables that are not sent by default: |
@@ -895,359 +933,413 @@ static void | |||
895 | mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side, | 933 | mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side, |
896 | int export_certificates_enabled) | 934 | int export_certificates_enabled) |
897 | { | 935 | { |
898 | unsigned char sbuf[64]; /* buffer to hold serials */ | 936 | unsigned char sbuf[64]; /* buffer to hold serials */ |
899 | char buf[AP_IOBUFSIZE]; | 937 | char buf[AP_IOBUFSIZE]; |
900 | const char *tmp; | 938 | const char *tmp; |
901 | char *tmp2; | 939 | char *tmp2; |
902 | size_t len; | 940 | size_t len; |
903 | int ret, i; | 941 | int ret, i; |
904 | 942 | ||
905 | if (r == NULL) | 943 | if (r == NULL) |
906 | return; | 944 | return; |
907 | 945 | ||
908 | apr_table_t *env = r->subprocess_env; | 946 | apr_table_t *env = r->subprocess_env; |
909 | 947 | ||
910 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 948 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
911 | if (export_certificates_enabled != 0) { | 949 | if (export_certificates_enabled != 0) { |
912 | char cert_buf[10 * 1024]; | 950 | char cert_buf[10 * 1024]; |
913 | len = sizeof(cert_buf); | 951 | len = sizeof(cert_buf); |
914 | 952 | ||
915 | if (gnutls_x509_crt_export | 953 | if (gnutls_x509_crt_export |
916 | (cert, GNUTLS_X509_FMT_PEM, cert_buf, &len) >= 0) | 954 | (cert, GNUTLS_X509_FMT_PEM, cert_buf, &len) >= 0) |
917 | apr_table_setn(env, | 955 | apr_table_setn(env, |
918 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), | 956 | apr_pstrcat(r->pool, MGS_SIDE, |
919 | apr_pstrmemdup(r->pool, cert_buf, len)); | 957 | "_CERT", NULL), |
920 | 958 | apr_pstrmemdup(r->pool, cert_buf, | |
921 | } | 959 | len)); |
922 | 960 | ||
923 | len = sizeof(buf); | 961 | } |
924 | gnutls_x509_crt_get_dn(cert, buf, &len); | 962 | |
925 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_S_DN", NULL), | 963 | len = sizeof(buf); |
926 | apr_pstrmemdup(r->pool, buf, len)); | 964 | gnutls_x509_crt_get_dn(cert, buf, &len); |
927 | 965 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_S_DN", NULL), | |
928 | len = sizeof(buf); | 966 | apr_pstrmemdup(r->pool, buf, len)); |
929 | gnutls_x509_crt_get_issuer_dn(cert, buf, &len); | 967 | |
930 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_I_DN", NULL), | 968 | len = sizeof(buf); |
931 | apr_pstrmemdup(r->pool, buf, len)); | 969 | gnutls_x509_crt_get_issuer_dn(cert, buf, &len); |
932 | 970 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_I_DN", NULL), | |
933 | len = sizeof(sbuf); | 971 | apr_pstrmemdup(r->pool, buf, len)); |
934 | gnutls_x509_crt_get_serial(cert, sbuf, &len); | 972 | |
935 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); | 973 | len = sizeof(sbuf); |
936 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_M_SERIAL", NULL), | 974 | gnutls_x509_crt_get_serial(cert, sbuf, &len); |
937 | apr_pstrdup(r->pool, tmp)); | 975 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); |
938 | |||
939 | ret = gnutls_x509_crt_get_version(cert); | ||
940 | if (ret > 0) | ||
941 | apr_table_setn(env, | 976 | apr_table_setn(env, |
942 | apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL), | 977 | apr_pstrcat(r->pool, MGS_SIDE, "_M_SERIAL", NULL), |
943 | apr_psprintf(r->pool, "%u", ret)); | 978 | apr_pstrdup(r->pool, tmp)); |
944 | 979 | ||
945 | apr_table_setn(env, | 980 | ret = gnutls_x509_crt_get_version(cert); |
946 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "X.509"); | 981 | if (ret > 0) |
947 | |||
948 | tmp = | ||
949 | mgs_time2sz(gnutls_x509_crt_get_expiration_time | ||
950 | (cert), buf, sizeof(buf)); | ||
951 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), | ||
952 | apr_pstrdup(r->pool, tmp)); | ||
953 | |||
954 | tmp = | ||
955 | mgs_time2sz(gnutls_x509_crt_get_activation_time | ||
956 | (cert), buf, sizeof(buf)); | ||
957 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), | ||
958 | apr_pstrdup(r->pool, tmp)); | ||
959 | |||
960 | ret = gnutls_x509_crt_get_signature_algorithm(cert); | ||
961 | if (ret >= 0) { | ||
962 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_SIG", NULL), | ||
963 | gnutls_sign_algorithm_get_name(ret)); | ||
964 | } | ||
965 | |||
966 | ret = gnutls_x509_crt_get_pk_algorithm(cert, NULL); | ||
967 | if (ret >= 0) { | ||
968 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL), | ||
969 | gnutls_pk_algorithm_get_name(ret)); | ||
970 | } | ||
971 | |||
972 | /* export all the alternative names (DNS, RFC822 and URI) */ | ||
973 | for (i = 0; !(ret < 0); i++) { | ||
974 | len = 0; | ||
975 | ret = gnutls_x509_crt_get_subject_alt_name(cert, i, | ||
976 | NULL, &len, NULL); | ||
977 | |||
978 | if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER && len > 1) { | ||
979 | tmp2 = apr_palloc(r->pool, len + 1); | ||
980 | |||
981 | ret = | ||
982 | gnutls_x509_crt_get_subject_alt_name(cert, i, tmp2, &len, | ||
983 | NULL); | ||
984 | tmp2[len] = 0; | ||
985 | |||
986 | if (ret == GNUTLS_SAN_DNSNAME) { | ||
987 | apr_table_setn(env, | ||
988 | apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), | ||
989 | apr_psprintf(r->pool, "DNSNAME:%s", tmp2)); | ||
990 | } else if (ret == GNUTLS_SAN_RFC822NAME) { | ||
991 | apr_table_setn(env, | 982 | apr_table_setn(env, |
992 | apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), | 983 | apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", |
993 | apr_psprintf(r->pool, "RFC822NAME:%s", tmp2)); | 984 | NULL), apr_psprintf(r->pool, |
994 | } else if (ret == GNUTLS_SAN_URI) { | 985 | "%u", ret)); |
986 | |||
987 | apr_table_setn(env, | ||
988 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), | ||
989 | "X.509"); | ||
990 | |||
991 | tmp = | ||
992 | mgs_time2sz(gnutls_x509_crt_get_expiration_time | ||
993 | (cert), buf, sizeof(buf)); | ||
994 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), | ||
995 | apr_pstrdup(r->pool, tmp)); | ||
996 | |||
997 | tmp = | ||
998 | mgs_time2sz(gnutls_x509_crt_get_activation_time | ||
999 | (cert), buf, sizeof(buf)); | ||
1000 | apr_table_setn(env, | ||
1001 | apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), | ||
1002 | apr_pstrdup(r->pool, tmp)); | ||
1003 | |||
1004 | ret = gnutls_x509_crt_get_signature_algorithm(cert); | ||
1005 | if (ret >= 0) { | ||
995 | apr_table_setn(env, | 1006 | apr_table_setn(env, |
996 | apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), | 1007 | apr_pstrcat(r->pool, MGS_SIDE, "_A_SIG", |
997 | apr_psprintf(r->pool, "URI:%s", tmp2)); | 1008 | NULL), |
998 | } else { | 1009 | gnutls_sign_algorithm_get_name(ret)); |
1010 | } | ||
1011 | |||
1012 | ret = gnutls_x509_crt_get_pk_algorithm(cert, NULL); | ||
1013 | if (ret >= 0) { | ||
999 | apr_table_setn(env, | 1014 | apr_table_setn(env, |
1000 | apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), | 1015 | apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", |
1001 | "UNSUPPORTED"); | 1016 | NULL), |
1002 | } | 1017 | gnutls_pk_algorithm_get_name(ret)); |
1018 | } | ||
1019 | |||
1020 | /* export all the alternative names (DNS, RFC822 and URI) */ | ||
1021 | for (i = 0; !(ret < 0); i++) { | ||
1022 | len = 0; | ||
1023 | ret = gnutls_x509_crt_get_subject_alt_name(cert, i, | ||
1024 | NULL, &len, | ||
1025 | NULL); | ||
1026 | |||
1027 | if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER && len > 1) { | ||
1028 | tmp2 = apr_palloc(r->pool, len + 1); | ||
1029 | |||
1030 | ret = | ||
1031 | gnutls_x509_crt_get_subject_alt_name(cert, i, | ||
1032 | tmp2, | ||
1033 | &len, | ||
1034 | NULL); | ||
1035 | tmp2[len] = 0; | ||
1036 | |||
1037 | if (ret == GNUTLS_SAN_DNSNAME) { | ||
1038 | apr_table_setn(env, | ||
1039 | apr_psprintf(r->pool, | ||
1040 | "%s_S_AN%u", | ||
1041 | MGS_SIDE, i), | ||
1042 | apr_psprintf(r->pool, | ||
1043 | "DNSNAME:%s", | ||
1044 | tmp2)); | ||
1045 | } else if (ret == GNUTLS_SAN_RFC822NAME) { | ||
1046 | apr_table_setn(env, | ||
1047 | apr_psprintf(r->pool, | ||
1048 | "%s_S_AN%u", | ||
1049 | MGS_SIDE, i), | ||
1050 | apr_psprintf(r->pool, | ||
1051 | "RFC822NAME:%s", | ||
1052 | tmp2)); | ||
1053 | } else if (ret == GNUTLS_SAN_URI) { | ||
1054 | apr_table_setn(env, | ||
1055 | apr_psprintf(r->pool, | ||
1056 | "%s_S_AN%u", | ||
1057 | MGS_SIDE, i), | ||
1058 | apr_psprintf(r->pool, | ||
1059 | "URI:%s", | ||
1060 | tmp2)); | ||
1061 | } else { | ||
1062 | apr_table_setn(env, | ||
1063 | apr_psprintf(r->pool, | ||
1064 | "%s_S_AN%u", | ||
1065 | MGS_SIDE, i), | ||
1066 | "UNSUPPORTED"); | ||
1067 | } | ||
1068 | } | ||
1003 | } | 1069 | } |
1004 | } | ||
1005 | } | 1070 | } |
1006 | 1071 | ||
1007 | static void | 1072 | static void |
1008 | mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side, | 1073 | mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, |
1009 | int export_certificates_enabled) | 1074 | int side, int export_certificates_enabled) |
1010 | { | 1075 | { |
1011 | unsigned char sbuf[64]; /* buffer to hold serials */ | 1076 | unsigned char sbuf[64]; /* buffer to hold serials */ |
1012 | char buf[AP_IOBUFSIZE]; | 1077 | char buf[AP_IOBUFSIZE]; |
1013 | const char *tmp; | 1078 | const char *tmp; |
1014 | size_t len; | 1079 | size_t len; |
1015 | int ret; | 1080 | int ret; |
1016 | 1081 | ||
1017 | if (r == NULL) | 1082 | if (r == NULL) |
1018 | return; | 1083 | return; |
1019 | 1084 | ||
1020 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 1085 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
1021 | apr_table_t *env = r->subprocess_env; | 1086 | apr_table_t *env = r->subprocess_env; |
1022 | 1087 | ||
1023 | if (export_certificates_enabled != 0) { | 1088 | if (export_certificates_enabled != 0) { |
1024 | char cert_buf[10 * 1024]; | 1089 | char cert_buf[10 * 1024]; |
1025 | len = sizeof(cert_buf); | 1090 | len = sizeof(cert_buf); |
1026 | 1091 | ||
1027 | if (gnutls_openpgp_crt_export | 1092 | if (gnutls_openpgp_crt_export |
1028 | (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0) | 1093 | (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0) |
1029 | apr_table_setn(env, | 1094 | apr_table_setn(env, |
1030 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), | 1095 | apr_pstrcat(r->pool, MGS_SIDE, |
1031 | apr_pstrmemdup(r->pool, cert_buf, len)); | 1096 | "_CERT", NULL), |
1032 | 1097 | apr_pstrmemdup(r->pool, cert_buf, | |
1033 | } | 1098 | len)); |
1034 | 1099 | ||
1035 | len = sizeof(buf); | 1100 | } |
1036 | gnutls_openpgp_crt_get_name(cert, 0, buf, &len); | 1101 | |
1037 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL), | 1102 | len = sizeof(buf); |
1038 | apr_pstrmemdup(r->pool, buf, len)); | 1103 | gnutls_openpgp_crt_get_name(cert, 0, buf, &len); |
1039 | 1104 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL), | |
1040 | len = sizeof(sbuf); | 1105 | apr_pstrmemdup(r->pool, buf, len)); |
1041 | gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len); | 1106 | |
1042 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); | 1107 | len = sizeof(sbuf); |
1043 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", NULL), | 1108 | gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len); |
1044 | apr_pstrdup(r->pool, tmp)); | 1109 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); |
1045 | |||
1046 | ret = gnutls_openpgp_crt_get_version(cert); | ||
1047 | if (ret > 0) | ||
1048 | apr_table_setn(env, | 1110 | apr_table_setn(env, |
1049 | apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL), | 1111 | apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", |
1050 | apr_psprintf(r->pool, "%u", ret)); | 1112 | NULL), apr_pstrdup(r->pool, tmp)); |
1051 | 1113 | ||
1052 | apr_table_setn(env, | 1114 | ret = gnutls_openpgp_crt_get_version(cert); |
1053 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "OPENPGP"); | 1115 | if (ret > 0) |
1054 | 1116 | apr_table_setn(env, | |
1055 | tmp = | 1117 | apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", |
1056 | mgs_time2sz(gnutls_openpgp_crt_get_expiration_time | 1118 | NULL), apr_psprintf(r->pool, |
1057 | (cert), buf, sizeof(buf)); | 1119 | "%u", ret)); |
1058 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), | 1120 | |
1059 | apr_pstrdup(r->pool, tmp)); | 1121 | apr_table_setn(env, |
1060 | 1122 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), | |
1061 | tmp = | 1123 | "OPENPGP"); |
1062 | mgs_time2sz(gnutls_openpgp_crt_get_creation_time | 1124 | |
1063 | (cert), buf, sizeof(buf)); | 1125 | tmp = |
1064 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), | 1126 | mgs_time2sz(gnutls_openpgp_crt_get_expiration_time |
1065 | apr_pstrdup(r->pool, tmp)); | 1127 | (cert), buf, sizeof(buf)); |
1066 | 1128 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), | |
1067 | ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL); | 1129 | apr_pstrdup(r->pool, tmp)); |
1068 | if (ret >= 0) { | 1130 | |
1069 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL), | 1131 | tmp = |
1070 | gnutls_pk_algorithm_get_name(ret)); | 1132 | mgs_time2sz(gnutls_openpgp_crt_get_creation_time |
1071 | } | 1133 | (cert), buf, sizeof(buf)); |
1134 | apr_table_setn(env, | ||
1135 | apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), | ||
1136 | apr_pstrdup(r->pool, tmp)); | ||
1137 | |||
1138 | ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL); | ||
1139 | if (ret >= 0) { | ||
1140 | apr_table_setn(env, | ||
1141 | apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", | ||
1142 | NULL), | ||
1143 | gnutls_pk_algorithm_get_name(ret)); | ||
1144 | } | ||
1072 | 1145 | ||
1073 | } | 1146 | } |
1074 | 1147 | ||
1075 | /* TODO: Allow client sending a X.509 certificate chain */ | 1148 | /* TODO: Allow client sending a X.509 certificate chain */ |
1076 | static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) | 1149 | static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) |
1077 | { | 1150 | { |
1078 | const gnutls_datum_t *cert_list; | 1151 | const gnutls_datum_t *cert_list; |
1079 | unsigned int cert_list_size, status; | 1152 | unsigned int cert_list_size, status; |
1080 | int rv = GNUTLS_E_NO_CERTIFICATE_FOUND, ret; | 1153 | int rv = GNUTLS_E_NO_CERTIFICATE_FOUND, ret; |
1081 | unsigned int ch_size = 0; | 1154 | unsigned int ch_size = 0; |
1082 | union { | 1155 | union { |
1083 | gnutls_x509_crt_t x509[MAX_CHAIN_SIZE]; | 1156 | gnutls_x509_crt_t x509[MAX_CHAIN_SIZE]; |
1084 | gnutls_openpgp_crt_t pgp; | 1157 | gnutls_openpgp_crt_t pgp; |
1085 | } cert; | 1158 | } cert; |
1086 | apr_time_t expiration_time, cur_time; | 1159 | apr_time_t expiration_time, cur_time; |
1087 | 1160 | ||
1088 | if (r == NULL || ctxt == NULL || ctxt->session == NULL) | 1161 | if (r == NULL || ctxt == NULL || ctxt->session == NULL) |
1089 | return HTTP_FORBIDDEN; | 1162 | return HTTP_FORBIDDEN; |
1090 | 1163 | ||
1091 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 1164 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
1092 | cert_list = | 1165 | cert_list = |
1093 | gnutls_certificate_get_peers(ctxt->session, &cert_list_size); | 1166 | gnutls_certificate_get_peers(ctxt->session, &cert_list_size); |
1094 | 1167 | ||
1095 | if (cert_list == NULL || cert_list_size == 0) { | 1168 | if (cert_list == NULL || cert_list_size == 0) { |
1096 | /* It is perfectly OK for a client not to send a certificate if on REQUEST mode | 1169 | /* It is perfectly OK for a client not to send a certificate if on REQUEST mode |
1170 | */ | ||
1171 | if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) | ||
1172 | return OK; | ||
1173 | |||
1174 | /* no certificate provided by the client, but one was required. */ | ||
1175 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
1176 | "GnuTLS: Failed to Verify Peer: " | ||
1177 | "Client did not submit a certificate"); | ||
1178 | return HTTP_FORBIDDEN; | ||
1179 | } | ||
1180 | |||
1181 | if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) { | ||
1182 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | ||
1183 | "GnuTLS: A Chain of %d certificate(s) was provided for validation", | ||
1184 | cert_list_size); | ||
1185 | |||
1186 | for (ch_size = 0; ch_size < cert_list_size; ch_size++) { | ||
1187 | gnutls_x509_crt_init(&cert.x509[ch_size]); | ||
1188 | rv = gnutls_x509_crt_import(cert.x509[ch_size], | ||
1189 | &cert_list[ch_size], | ||
1190 | GNUTLS_X509_FMT_DER); | ||
1191 | // When failure to import, leave the loop | ||
1192 | if (rv != GNUTLS_E_SUCCESS) { | ||
1193 | if (ch_size < 1) { | ||
1194 | ap_log_rerror(APLOG_MARK, | ||
1195 | APLOG_INFO, 0, r, | ||
1196 | "GnuTLS: Failed to Verify Peer: " | ||
1197 | "Failed to import peer certificates."); | ||
1198 | ret = HTTP_FORBIDDEN; | ||
1199 | goto exit; | ||
1200 | } | ||
1201 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
1202 | "GnuTLS: Failed to import some peer certificates. Using %d certificates", | ||
1203 | ch_size); | ||
1204 | rv = GNUTLS_E_SUCCESS; | ||
1205 | break; | ||
1206 | } | ||
1207 | } | ||
1208 | } else if (gnutls_certificate_type_get(ctxt->session) == | ||
1209 | GNUTLS_CRT_OPENPGP) { | ||
1210 | if (cert_list_size > 1) { | ||
1211 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
1212 | "GnuTLS: Failed to Verify Peer: " | ||
1213 | "Chained Client Certificates are not supported."); | ||
1214 | return HTTP_FORBIDDEN; | ||
1215 | } | ||
1216 | |||
1217 | gnutls_openpgp_crt_init(&cert.pgp); | ||
1218 | rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], | ||
1219 | GNUTLS_OPENPGP_FMT_RAW); | ||
1220 | |||
1221 | } else | ||
1222 | return HTTP_FORBIDDEN; | ||
1223 | |||
1224 | if (rv < 0) { | ||
1225 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
1226 | "GnuTLS: Failed to Verify Peer: " | ||
1227 | "Failed to import peer certificates."); | ||
1228 | ret = HTTP_FORBIDDEN; | ||
1229 | goto exit; | ||
1230 | } | ||
1231 | |||
1232 | if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) { | ||
1233 | apr_time_ansi_put(&expiration_time, | ||
1234 | gnutls_x509_crt_get_expiration_time | ||
1235 | (cert.x509[0])); | ||
1236 | |||
1237 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | ||
1238 | "GnuTLS: Verifying list of %d certificate(s)", | ||
1239 | ch_size); | ||
1240 | rv = gnutls_x509_crt_list_verify(cert.x509, ch_size, | ||
1241 | ctxt->sc->ca_list, | ||
1242 | ctxt->sc->ca_list_size, | ||
1243 | NULL, 0, 0, &status); | ||
1244 | } else { | ||
1245 | apr_time_ansi_put(&expiration_time, | ||
1246 | gnutls_openpgp_crt_get_expiration_time | ||
1247 | (cert.pgp)); | ||
1248 | |||
1249 | rv = gnutls_openpgp_crt_verify_ring(cert.pgp, | ||
1250 | ctxt->sc->pgp_list, 0, | ||
1251 | &status); | ||
1252 | } | ||
1253 | |||
1254 | if (rv < 0) { | ||
1255 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
1256 | "GnuTLS: Failed to Verify Peer certificate: (%d) %s", | ||
1257 | rv, gnutls_strerror(rv)); | ||
1258 | if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND) | ||
1259 | ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, r, | ||
1260 | "GnuTLS: No certificate was found for verification. Did you set the GnuTLSX509CAFile or GnuTLSPGPKeyringFile directives?"); | ||
1261 | ret = HTTP_FORBIDDEN; | ||
1262 | goto exit; | ||
1263 | } | ||
1264 | |||
1265 | /* TODO: X509 CRL Verification. */ | ||
1266 | /* May add later if anyone needs it. | ||
1097 | */ | 1267 | */ |
1098 | if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) | 1268 | /* ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); */ |
1099 | return OK; | 1269 | |
1100 | 1270 | cur_time = apr_time_now(); | |
1101 | /* no certificate provided by the client, but one was required. */ | 1271 | |
1102 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 1272 | if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { |
1103 | "GnuTLS: Failed to Verify Peer: " | 1273 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
1104 | "Client did not submit a certificate"); | 1274 | "GnuTLS: Could not find Signer for Peer Certificate"); |
1105 | return HTTP_FORBIDDEN; | 1275 | } |
1106 | } | 1276 | |
1107 | 1277 | if (status & GNUTLS_CERT_SIGNER_NOT_CA) { | |
1108 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { | 1278 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
1109 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | 1279 | "GnuTLS: Peer's Certificate signer is not a CA"); |
1110 | "GnuTLS: A Chain of %d certificate(s) was provided for validation", cert_list_size); | 1280 | } |
1111 | 1281 | ||
1112 | for (ch_size = 0; ch_size<cert_list_size; ch_size++) { | 1282 | if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { |
1113 | gnutls_x509_crt_init(&cert.x509[ch_size]); | 1283 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
1114 | rv = gnutls_x509_crt_import(cert.x509[ch_size], &cert_list[ch_size], GNUTLS_X509_FMT_DER); | 1284 | "GnuTLS: Peer's Certificate is using insecure algorithms"); |
1115 | // When failure to import, leave the loop | 1285 | } |
1116 | if ( rv != GNUTLS_E_SUCCESS ) { | 1286 | |
1117 | if (ch_size < 1) { | 1287 | if (status & GNUTLS_CERT_EXPIRED |
1118 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 1288 | || status & GNUTLS_CERT_NOT_ACTIVATED) { |
1119 | "GnuTLS: Failed to Verify Peer: " | 1289 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
1120 | "Failed to import peer certificates."); | 1290 | "GnuTLS: Peer's Certificate signer is expired or not yet activated"); |
1121 | ret = HTTP_FORBIDDEN; | 1291 | } |
1122 | goto exit; | 1292 | |
1123 | } | 1293 | if (status & GNUTLS_CERT_INVALID) { |
1124 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 1294 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
1125 | "GnuTLS: Failed to import some peer certificates. Using %d certificates", | 1295 | "GnuTLS: Peer Certificate is invalid."); |
1126 | ch_size); | 1296 | } else if (status & GNUTLS_CERT_REVOKED) { |
1127 | rv = GNUTLS_E_SUCCESS; | 1297 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
1128 | break; | 1298 | "GnuTLS: Peer Certificate is revoked."); |
1129 | } | 1299 | } |
1130 | } | 1300 | |
1131 | } else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) { | 1301 | if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) |
1132 | if (cert_list_size > 1) { | 1302 | mgs_add_common_cert_vars(r, cert.x509[0], 1, |
1133 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 1303 | ctxt-> |
1134 | "GnuTLS: Failed to Verify Peer: " | 1304 | sc->export_certificates_enabled); |
1135 | "Chained Client Certificates are not supported."); | 1305 | else if (gnutls_certificate_type_get(ctxt->session) == |
1136 | return HTTP_FORBIDDEN; | 1306 | GNUTLS_CRT_OPENPGP) |
1137 | } | 1307 | mgs_add_common_pgpcert_vars(r, cert.pgp, 1, |
1138 | 1308 | ctxt-> | |
1139 | gnutls_openpgp_crt_init(&cert.pgp); | 1309 | sc->export_certificates_enabled); |
1140 | rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW); | 1310 | |
1141 | 1311 | { | |
1142 | } else return HTTP_FORBIDDEN; | 1312 | /* days remaining */ |
1143 | 1313 | unsigned long remain = | |
1144 | if (rv < 0) { | 1314 | (apr_time_sec(expiration_time) - |
1145 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 1315 | apr_time_sec(cur_time)) / 86400; |
1146 | "GnuTLS: Failed to Verify Peer: " | 1316 | apr_table_setn(r->subprocess_env, "SSL_CLIENT_V_REMAIN", |
1147 | "Failed to import peer certificates."); | 1317 | apr_psprintf(r->pool, "%lu", remain)); |
1148 | ret = HTTP_FORBIDDEN; | 1318 | } |
1149 | goto exit; | 1319 | |
1150 | } | 1320 | if (status == 0) { |
1151 | 1321 | apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", | |
1152 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { | 1322 | "SUCCESS"); |
1153 | apr_time_ansi_put(&expiration_time, | 1323 | ret = OK; |
1154 | gnutls_x509_crt_get_expiration_time(cert.x509[0])); | 1324 | } else { |
1155 | 1325 | apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", | |
1156 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | 1326 | "FAILED"); |
1157 | "GnuTLS: Verifying list of %d certificate(s)", ch_size); | 1327 | if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) |
1158 | rv = gnutls_x509_crt_list_verify(cert.x509, ch_size, | 1328 | ret = OK; |
1159 | ctxt->sc->ca_list, ctxt->sc->ca_list_size, | 1329 | else |
1160 | NULL, 0, 0, &status); | 1330 | ret = HTTP_FORBIDDEN; |
1161 | } else { | 1331 | } |
1162 | apr_time_ansi_put(&expiration_time, | 1332 | |
1163 | gnutls_openpgp_crt_get_expiration_time(cert.pgp)); | 1333 | exit: |
1164 | 1334 | if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) { | |
1165 | rv = gnutls_openpgp_crt_verify_ring(cert.pgp, ctxt->sc->pgp_list, | 1335 | int i; |
1166 | 0, &status); | 1336 | for (i = 0; i < ch_size; i++) { |
1167 | } | 1337 | gnutls_x509_crt_deinit(cert.x509[i]); |
1168 | 1338 | } | |
1169 | if (rv < 0) { | 1339 | } else if (gnutls_certificate_type_get(ctxt->session) == |
1170 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 1340 | GNUTLS_CRT_OPENPGP) |
1171 | "GnuTLS: Failed to Verify Peer certificate: (%d) %s", | 1341 | gnutls_openpgp_crt_deinit(cert.pgp); |
1172 | rv, gnutls_strerror(rv)); | 1342 | return ret; |
1173 | if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND) | ||
1174 | ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, r, | ||
1175 | "GnuTLS: No certificate was found for verification. Did you set the GnuTLSX509CAFile or GnuTLSPGPKeyringFile directives?"); | ||
1176 | ret = HTTP_FORBIDDEN; | ||
1177 | goto exit; | ||
1178 | } | ||
1179 | |||
1180 | /* TODO: X509 CRL Verification. */ | ||
1181 | /* May add later if anyone needs it. | ||
1182 | */ | ||
1183 | /* ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); */ | ||
1184 | |||
1185 | cur_time = apr_time_now(); | ||
1186 | |||
1187 | if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { | ||
1188 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
1189 | "GnuTLS: Could not find Signer for Peer Certificate"); | ||
1190 | } | ||
1191 | |||
1192 | if (status & GNUTLS_CERT_SIGNER_NOT_CA) { | ||
1193 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
1194 | "GnuTLS: Peer's Certificate signer is not a CA"); | ||
1195 | } | ||
1196 | |||
1197 | if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { | ||
1198 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
1199 | "GnuTLS: Peer's Certificate is using insecure algorithms"); | ||
1200 | } | ||
1201 | |||
1202 | if (status & GNUTLS_CERT_EXPIRED || status & GNUTLS_CERT_NOT_ACTIVATED) { | ||
1203 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
1204 | "GnuTLS: Peer's Certificate signer is expired or not yet activated"); | ||
1205 | } | ||
1206 | |||
1207 | if (status & GNUTLS_CERT_INVALID) { | ||
1208 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
1209 | "GnuTLS: Peer Certificate is invalid."); | ||
1210 | } else if (status & GNUTLS_CERT_REVOKED) { | ||
1211 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
1212 | "GnuTLS: Peer Certificate is revoked."); | ||
1213 | } | ||
1214 | |||
1215 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) | ||
1216 | mgs_add_common_cert_vars(r, cert.x509[0], 1, | ||
1217 | ctxt->sc->export_certificates_enabled); | ||
1218 | else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) | ||
1219 | mgs_add_common_pgpcert_vars(r, cert.pgp, 1, | ||
1220 | ctxt->sc->export_certificates_enabled); | ||
1221 | |||
1222 | { | ||
1223 | /* days remaining */ | ||
1224 | unsigned long remain = | ||
1225 | (apr_time_sec(expiration_time) - | ||
1226 | apr_time_sec(cur_time)) / 86400; | ||
1227 | apr_table_setn(r->subprocess_env, "SSL_CLIENT_V_REMAIN", | ||
1228 | apr_psprintf(r->pool, "%lu", remain)); | ||
1229 | } | ||
1230 | |||
1231 | if (status == 0) { | ||
1232 | apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", "SUCCESS"); | ||
1233 | ret = OK; | ||
1234 | } else { | ||
1235 | apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", "FAILED"); | ||
1236 | if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) | ||
1237 | ret = OK; | ||
1238 | else | ||
1239 | ret = HTTP_FORBIDDEN; | ||
1240 | } | ||
1241 | |||
1242 | exit: | ||
1243 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { | ||
1244 | int i; | ||
1245 | for (i=0; i<ch_size; i++) { | ||
1246 | gnutls_x509_crt_deinit(cert.x509[i]); | ||
1247 | } | ||
1248 | } else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) | ||
1249 | gnutls_openpgp_crt_deinit(cert.pgp); | ||
1250 | return ret; | ||
1251 | 1343 | ||
1252 | 1344 | ||
1253 | } | 1345 | } |
diff --git a/src/gnutls_io.c b/src/gnutls_io.c index 174a424..37b73e7 100644 --- a/src/gnutls_io.c +++ b/src/gnutls_io.c | |||
@@ -32,67 +32,64 @@ | |||
32 | alloc) | 32 | alloc) |
33 | 33 | ||
34 | static apr_status_t gnutls_io_filter_error(ap_filter_t * f, | 34 | 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 | mgs_handle_t *ctxt = (mgs_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) { |
42 | case HTTP_BAD_REQUEST: | 42 | case HTTP_BAD_REQUEST: |
43 | /* log the situation */ | 43 | /* log the situation */ |
44 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, | 44 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, |
45 | f->c->base_server, | 45 | f->c->base_server, |
46 | "GnuTLS handshake failed: HTTP spoken on HTTPS port; " | 46 | "GnuTLS handshake failed: HTTP spoken on HTTPS port; " |
47 | "trying to send HTML error page"); | 47 | "trying to send HTML error page"); |
48 | 48 | ||
49 | ctxt->status = -1; | 49 | ctxt->status = -1; |
50 | 50 | ||
51 | /* fake the request line */ | 51 | /* fake the request line */ |
52 | bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc); | 52 | bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc); |
53 | break; | 53 | break; |
54 | 54 | ||
55 | default: | 55 | default: |
56 | return status; | 56 | return status; |
57 | } | 57 | } |
58 | 58 | ||
59 | APR_BRIGADE_INSERT_TAIL(bb, bucket); | 59 | APR_BRIGADE_INSERT_TAIL(bb, bucket); |
60 | bucket = apr_bucket_eos_create(f->c->bucket_alloc); | 60 | bucket = apr_bucket_eos_create(f->c->bucket_alloc); |
61 | APR_BRIGADE_INSERT_TAIL(bb, bucket); | 61 | APR_BRIGADE_INSERT_TAIL(bb, bucket); |
62 | 62 | ||
63 | return APR_SUCCESS; | 63 | return APR_SUCCESS; |
64 | } | 64 | } |
65 | 65 | ||
66 | static int char_buffer_read(mgs_char_buffer_t * buffer, char *in, | 66 | static int char_buffer_read(mgs_char_buffer_t * buffer, char *in, int inl) |
67 | int inl) | ||
68 | { | 67 | { |
69 | if (!buffer->length) { | 68 | if (!buffer->length) { |
70 | return 0; | 69 | return 0; |
71 | } | 70 | } |
72 | 71 | ||
73 | if (buffer->length > inl) { | 72 | if (buffer->length > inl) { |
74 | /* we have have enough to fill the caller's buffer */ | 73 | /* we have have enough to fill the caller's buffer */ |
75 | memmove(in, buffer->value, inl); | 74 | memmove(in, buffer->value, inl); |
76 | buffer->value += inl; | 75 | buffer->value += inl; |
77 | buffer->length -= inl; | 76 | buffer->length -= inl; |
78 | } | 77 | } else { |
79 | else { | 78 | /* swallow remainder of the buffer */ |
80 | /* swallow remainder of the buffer */ | 79 | memmove(in, buffer->value, buffer->length); |
81 | memmove(in, buffer->value, buffer->length); | 80 | inl = buffer->length; |
82 | inl = buffer->length; | 81 | buffer->value = NULL; |
83 | buffer->value = NULL; | 82 | buffer->length = 0; |
84 | buffer->length = 0; | 83 | } |
85 | } | 84 | |
86 | 85 | return inl; | |
87 | return inl; | ||
88 | } | 86 | } |
89 | 87 | ||
90 | static int char_buffer_write(mgs_char_buffer_t * buffer, char *in, | 88 | static int char_buffer_write(mgs_char_buffer_t * buffer, char *in, int inl) |
91 | int inl) | ||
92 | { | 89 | { |
93 | buffer->value = in; | 90 | buffer->value = in; |
94 | buffer->length = inl; | 91 | buffer->length = inl; |
95 | return inl; | 92 | return inl; |
96 | } | 93 | } |
97 | 94 | ||
98 | /** | 95 | /** |
@@ -101,679 +98,715 @@ static int char_buffer_write(mgs_char_buffer_t * buffer, char *in, | |||
101 | * proceeds. It will read at most *len bytes. | 98 | * proceeds. It will read at most *len bytes. |
102 | */ | 99 | */ |
103 | static apr_status_t brigade_consume(apr_bucket_brigade * bb, | 100 | static apr_status_t brigade_consume(apr_bucket_brigade * bb, |
104 | apr_read_type_e block, | 101 | apr_read_type_e block, |
105 | char *c, apr_size_t * len) | 102 | char *c, apr_size_t * len) |
106 | { | 103 | { |
107 | apr_size_t actual = 0; | 104 | apr_size_t actual = 0; |
108 | apr_status_t status = APR_SUCCESS; | 105 | apr_status_t status = APR_SUCCESS; |
109 | 106 | ||
110 | while (!APR_BRIGADE_EMPTY(bb)) { | 107 | while (!APR_BRIGADE_EMPTY(bb)) { |
111 | apr_bucket *b = APR_BRIGADE_FIRST(bb); | 108 | apr_bucket *b = APR_BRIGADE_FIRST(bb); |
112 | const char *str; | 109 | const char *str; |
113 | apr_size_t str_len; | 110 | apr_size_t str_len; |
114 | apr_size_t consume; | 111 | apr_size_t consume; |
115 | 112 | ||
116 | /* Justin points out this is an http-ism that might | 113 | /* Justin points out this is an http-ism that might |
117 | * not fit if brigade_consume is added to APR. Perhaps | 114 | * not fit if brigade_consume is added to APR. Perhaps |
118 | * apr_bucket_read(eos_bucket) should return APR_EOF? | 115 | * apr_bucket_read(eos_bucket) should return APR_EOF? |
119 | * Then this becomes mainline instead of a one-off. | 116 | * Then this becomes mainline instead of a one-off. |
120 | */ | 117 | */ |
121 | if (APR_BUCKET_IS_EOS(b)) { | 118 | if (APR_BUCKET_IS_EOS(b)) { |
122 | status = APR_EOF; | 119 | status = APR_EOF; |
123 | break; | 120 | break; |
124 | } | 121 | } |
125 | 122 | ||
126 | /* The reason I'm not offering brigade_consume yet | 123 | /* The reason I'm not offering brigade_consume yet |
127 | * across to apr-util is that the following call | 124 | * across to apr-util is that the following call |
128 | * illustrates how borked that API really is. For | 125 | * illustrates how borked that API really is. For |
129 | * this sort of case (caller provided buffer) it | 126 | * this sort of case (caller provided buffer) it |
130 | * would be much more trivial for apr_bucket_consume | 127 | * would be much more trivial for apr_bucket_consume |
131 | * to do all the work that follows, based on the | 128 | * to do all the work that follows, based on the |
132 | * particular characteristics of the bucket we are | 129 | * particular characteristics of the bucket we are |
133 | * consuming here. | 130 | * consuming here. |
134 | */ | 131 | */ |
135 | status = apr_bucket_read(b, &str, &str_len, block); | 132 | status = apr_bucket_read(b, &str, &str_len, block); |
136 | 133 | ||
137 | if (status != APR_SUCCESS) { | 134 | if (status != APR_SUCCESS) { |
138 | if (APR_STATUS_IS_EOF(status)) { | 135 | if (APR_STATUS_IS_EOF(status)) { |
139 | /* This stream bucket was consumed */ | 136 | /* This stream bucket was consumed */ |
140 | apr_bucket_delete(b); | 137 | apr_bucket_delete(b); |
141 | continue; | 138 | continue; |
142 | } | 139 | } |
143 | break; | 140 | break; |
144 | } | 141 | } |
145 | 142 | ||
146 | if (str_len > 0) { | 143 | if (str_len > 0) { |
147 | /* Do not block once some data has been consumed */ | 144 | /* Do not block once some data has been consumed */ |
148 | block = APR_NONBLOCK_READ; | 145 | block = APR_NONBLOCK_READ; |
149 | 146 | ||
150 | /* Assure we don't overflow. */ | 147 | /* Assure we don't overflow. */ |
151 | consume = (str_len + actual > *len) ? *len - actual : str_len; | 148 | consume = |
152 | 149 | (str_len + actual > | |
153 | memcpy(c, str, consume); | 150 | *len) ? *len - actual : str_len; |
154 | 151 | ||
155 | c += consume; | 152 | memcpy(c, str, consume); |
156 | actual += consume; | 153 | |
157 | 154 | c += consume; | |
158 | if (consume >= b->length) { | 155 | actual += consume; |
159 | /* This physical bucket was consumed */ | 156 | |
160 | apr_bucket_delete(b); | 157 | if (consume >= b->length) { |
161 | } | 158 | /* This physical bucket was consumed */ |
162 | else { | 159 | apr_bucket_delete(b); |
163 | /* Only part of this physical bucket was consumed */ | 160 | } else { |
164 | b->start += consume; | 161 | /* Only part of this physical bucket was consumed */ |
165 | b->length -= consume; | 162 | b->start += consume; |
166 | } | 163 | b->length -= consume; |
167 | } | 164 | } |
168 | else if (b->length == 0) { | 165 | } else if (b->length == 0) { |
169 | apr_bucket_delete(b); | 166 | apr_bucket_delete(b); |
170 | } | 167 | } |
171 | 168 | ||
172 | /* This could probably be actual == *len, but be safe from stray | 169 | /* This could probably be actual == *len, but be safe from stray |
173 | * photons. */ | 170 | * photons. */ |
174 | if (actual >= *len) { | 171 | if (actual >= *len) { |
175 | break; | 172 | break; |
176 | } | 173 | } |
177 | } | 174 | } |
178 | 175 | ||
179 | *len = actual; | 176 | *len = actual; |
180 | return status; | 177 | return status; |
181 | } | 178 | } |
182 | 179 | ||
183 | 180 | ||
184 | static apr_status_t gnutls_io_input_read(mgs_handle_t * ctxt, | 181 | static apr_status_t gnutls_io_input_read(mgs_handle_t * ctxt, |
185 | char *buf, apr_size_t * len) | 182 | char *buf, apr_size_t * len) |
186 | { | 183 | { |
187 | apr_size_t wanted = *len; | 184 | apr_size_t wanted = *len; |
188 | apr_size_t bytes = 0; | 185 | apr_size_t bytes = 0; |
189 | int rc; | 186 | int rc; |
190 | 187 | ||
191 | *len = 0; | 188 | *len = 0; |
192 | 189 | ||
193 | /* If we have something leftover from last time, try that first. */ | 190 | /* If we have something leftover from last time, try that first. */ |
194 | if ((bytes = char_buffer_read(&ctxt->input_cbuf, buf, wanted))) { | 191 | if ((bytes = char_buffer_read(&ctxt->input_cbuf, buf, wanted))) { |
195 | *len = bytes; | 192 | *len = bytes; |
196 | if (ctxt->input_mode == AP_MODE_SPECULATIVE) { | 193 | if (ctxt->input_mode == AP_MODE_SPECULATIVE) { |
197 | /* We want to rollback this read. */ | 194 | /* We want to rollback this read. */ |
198 | if (ctxt->input_cbuf.length > 0) { | 195 | if (ctxt->input_cbuf.length > 0) { |
199 | ctxt->input_cbuf.value -= bytes; | 196 | ctxt->input_cbuf.value -= bytes; |
200 | ctxt->input_cbuf.length += bytes; | 197 | ctxt->input_cbuf.length += bytes; |
201 | } | 198 | } else { |
202 | else { | 199 | char_buffer_write(&ctxt->input_cbuf, buf, |
203 | char_buffer_write(&ctxt->input_cbuf, buf, (int) bytes); | 200 | (int) bytes); |
204 | } | 201 | } |
205 | return APR_SUCCESS; | 202 | return APR_SUCCESS; |
206 | } | 203 | } |
207 | /* This could probably be *len == wanted, but be safe from stray | 204 | /* This could probably be *len == wanted, but be safe from stray |
208 | * photons. | 205 | * photons. |
209 | */ | 206 | */ |
210 | if (*len >= wanted) { | 207 | if (*len >= wanted) { |
211 | return APR_SUCCESS; | 208 | return APR_SUCCESS; |
212 | } | 209 | } |
213 | if (ctxt->input_mode == AP_MODE_GETLINE) { | 210 | if (ctxt->input_mode == AP_MODE_GETLINE) { |
214 | if (memchr(buf, APR_ASCII_LF, *len)) { | 211 | if (memchr(buf, APR_ASCII_LF, *len)) { |
215 | return APR_SUCCESS; | 212 | return APR_SUCCESS; |
216 | } | 213 | } |
217 | } | 214 | } else { |
218 | else { | 215 | /* Down to a nonblock pattern as we have some data already |
219 | /* Down to a nonblock pattern as we have some data already | 216 | */ |
220 | */ | 217 | ctxt->input_block = APR_NONBLOCK_READ; |
221 | ctxt->input_block = APR_NONBLOCK_READ; | 218 | } |
222 | } | 219 | } |
223 | } | 220 | |
224 | 221 | if (ctxt->session == NULL) { | |
225 | if (ctxt->session == NULL) { | 222 | return APR_EGENERAL; |
226 | return APR_EGENERAL; | 223 | } |
227 | } | 224 | |
228 | 225 | while (1) { | |
229 | while (1) { | 226 | |
230 | 227 | rc = gnutls_record_recv(ctxt->session, buf + bytes, | |
231 | rc = gnutls_record_recv(ctxt->session, buf + bytes, wanted - bytes); | 228 | wanted - bytes); |
232 | 229 | ||
233 | if (rc > 0) { | 230 | if (rc > 0) { |
234 | *len += rc; | 231 | *len += rc; |
235 | if (ctxt->input_mode == AP_MODE_SPECULATIVE) { | 232 | if (ctxt->input_mode == AP_MODE_SPECULATIVE) { |
236 | /* We want to rollback this read. */ | 233 | /* We want to rollback this read. */ |
237 | char_buffer_write(&ctxt->input_cbuf, buf, rc); | 234 | char_buffer_write(&ctxt->input_cbuf, buf, |
238 | } | 235 | rc); |
239 | return ctxt->input_rc; | 236 | } |
240 | } | 237 | return ctxt->input_rc; |
241 | else if (rc == 0) { | 238 | } else if (rc == 0) { |
242 | /* If EAGAIN, we will loop given a blocking read, | 239 | /* If EAGAIN, we will loop given a blocking read, |
243 | * otherwise consider ourselves at EOF. | 240 | * otherwise consider ourselves at EOF. |
244 | */ | 241 | */ |
245 | if (APR_STATUS_IS_EAGAIN(ctxt->input_rc) | 242 | if (APR_STATUS_IS_EAGAIN(ctxt->input_rc) |
246 | || APR_STATUS_IS_EINTR(ctxt->input_rc)) { | 243 | || APR_STATUS_IS_EINTR(ctxt->input_rc)) { |
247 | /* Already read something, return APR_SUCCESS instead. | 244 | /* Already read something, return APR_SUCCESS instead. |
248 | * On win32 in particular, but perhaps on other kernels, | 245 | * On win32 in particular, but perhaps on other kernels, |
249 | * a blocking call isn't 'always' blocking. | 246 | * a blocking call isn't 'always' blocking. |
250 | */ | 247 | */ |
251 | if (*len > 0) { | 248 | if (*len > 0) { |
252 | ctxt->input_rc = APR_SUCCESS; | 249 | ctxt->input_rc = APR_SUCCESS; |
253 | break; | 250 | break; |
254 | } | 251 | } |
255 | if (ctxt->input_block == APR_NONBLOCK_READ) { | 252 | if (ctxt->input_block == APR_NONBLOCK_READ) { |
256 | break; | 253 | break; |
257 | } | 254 | } |
258 | } | 255 | } else { |
259 | else { | 256 | if (*len > 0) { |
260 | if (*len > 0) { | 257 | ctxt->input_rc = APR_SUCCESS; |
261 | ctxt->input_rc = APR_SUCCESS; | 258 | } else { |
262 | } | 259 | ctxt->input_rc = APR_EOF; |
263 | else { | 260 | } |
264 | ctxt->input_rc = APR_EOF; | 261 | break; |
265 | } | 262 | } |
266 | break; | 263 | } else { /* (rc < 0) */ |
267 | } | 264 | |
268 | } | 265 | if (rc == GNUTLS_E_REHANDSHAKE) { |
269 | else { /* (rc < 0) */ | 266 | /* A client has asked for a new Hankshake. Currently, we don't do it */ |
270 | 267 | ap_log_error(APLOG_MARK, APLOG_INFO, | |
271 | if (rc == GNUTLS_E_REHANDSHAKE) { | 268 | ctxt->input_rc, |
272 | /* A client has asked for a new Hankshake. Currently, we don't do it */ | 269 | ctxt->c->base_server, |
273 | ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, | 270 | "GnuTLS: Error reading data. Client Requested a New Handshake." |
274 | ctxt->c->base_server, | 271 | " (%d) '%s'", rc, |
275 | "GnuTLS: Error reading data. Client Requested a New Handshake." | 272 | gnutls_strerror(rc)); |
276 | " (%d) '%s'", rc, gnutls_strerror(rc)); | 273 | } else if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED) { |
277 | } | 274 | rc = gnutls_alert_get(ctxt->session); |
278 | else if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED) { | 275 | ap_log_error(APLOG_MARK, APLOG_INFO, |
279 | rc = gnutls_alert_get(ctxt->session); | 276 | ctxt->input_rc, |
280 | ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, | 277 | ctxt->c->base_server, |
281 | ctxt->c->base_server, | 278 | "GnuTLS: Warning Alert From Client: " |
282 | "GnuTLS: Warning Alert From Client: " | 279 | " (%d) '%s'", rc, |
283 | " (%d) '%s'", rc, gnutls_alert_get_name(rc)); | 280 | gnutls_alert_get_name(rc)); |
284 | } | 281 | } else if (rc == GNUTLS_E_FATAL_ALERT_RECEIVED) { |
285 | else if (rc == GNUTLS_E_FATAL_ALERT_RECEIVED) { | 282 | rc = gnutls_alert_get(ctxt->session); |
286 | rc = gnutls_alert_get(ctxt->session); | 283 | ap_log_error(APLOG_MARK, APLOG_INFO, |
287 | ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, | 284 | ctxt->input_rc, |
288 | ctxt->c->base_server, | 285 | ctxt->c->base_server, |
289 | "GnuTLS: Fatal Alert From Client: " | 286 | "GnuTLS: Fatal Alert From Client: " |
290 | "(%d) '%s'", rc, gnutls_alert_get_name(rc)); | 287 | "(%d) '%s'", rc, |
291 | ctxt->input_rc = APR_EGENERAL; | 288 | gnutls_alert_get_name(rc)); |
292 | break; | 289 | ctxt->input_rc = APR_EGENERAL; |
293 | } | 290 | break; |
294 | else { | 291 | } else { |
295 | /* Some Other Error. Report it. Die. */ | 292 | /* Some Other Error. Report it. Die. */ |
296 | if(gnutls_error_is_fatal(rc)) { | 293 | if (gnutls_error_is_fatal(rc)) { |
297 | ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, | 294 | ap_log_error(APLOG_MARK, |
298 | ctxt->c->base_server, | 295 | APLOG_INFO, |
299 | "GnuTLS: Error reading data. (%d) '%s'", rc, | 296 | ctxt->input_rc, |
300 | gnutls_strerror(rc)); | 297 | ctxt->c->base_server, |
301 | } | 298 | "GnuTLS: Error reading data. (%d) '%s'", |
302 | else if(*len > 0) { | 299 | rc, |
303 | ctxt->input_rc = APR_SUCCESS; | 300 | gnutls_strerror(rc)); |
304 | break; | 301 | } else if (*len > 0) { |
305 | } | 302 | ctxt->input_rc = APR_SUCCESS; |
306 | } | 303 | break; |
307 | 304 | } | |
308 | if (ctxt->input_rc == APR_SUCCESS) { | 305 | } |
309 | ctxt->input_rc = APR_EGENERAL; | 306 | |
310 | } | 307 | if (ctxt->input_rc == APR_SUCCESS) { |
311 | break; | 308 | ctxt->input_rc = APR_EGENERAL; |
312 | } | 309 | } |
313 | } | 310 | break; |
314 | return ctxt->input_rc; | 311 | } |
312 | } | ||
313 | return ctxt->input_rc; | ||
315 | } | 314 | } |
316 | 315 | ||
317 | static apr_status_t gnutls_io_input_getline(mgs_handle_t * ctxt, | 316 | static apr_status_t gnutls_io_input_getline(mgs_handle_t * ctxt, |
318 | char *buf, apr_size_t * len) | 317 | char *buf, apr_size_t * len) |
319 | { | 318 | { |
320 | const char *pos = NULL; | 319 | const char *pos = NULL; |
321 | apr_status_t status; | 320 | apr_status_t status; |
322 | apr_size_t tmplen = *len, buflen = *len, offset = 0; | 321 | apr_size_t tmplen = *len, buflen = *len, offset = 0; |
323 | 322 | ||
324 | *len = 0; | 323 | *len = 0; |
325 | 324 | ||
326 | while (tmplen > 0) { | 325 | while (tmplen > 0) { |
327 | status = gnutls_io_input_read(ctxt, buf + offset, &tmplen); | 326 | status = gnutls_io_input_read(ctxt, buf + offset, &tmplen); |
328 | 327 | ||
329 | if (status != APR_SUCCESS) { | 328 | if (status != APR_SUCCESS) { |
330 | return status; | 329 | return status; |
331 | } | 330 | } |
332 | 331 | ||
333 | *len += tmplen; | 332 | *len += tmplen; |
334 | 333 | ||
335 | if ((pos = memchr(buf, APR_ASCII_LF, *len))) { | 334 | if ((pos = memchr(buf, APR_ASCII_LF, *len))) { |
336 | break; | 335 | break; |
337 | } | 336 | } |
338 | 337 | ||
339 | offset += tmplen; | 338 | offset += tmplen; |
340 | tmplen = buflen - offset; | 339 | tmplen = buflen - offset; |
341 | } | 340 | } |
342 | 341 | ||
343 | if (pos) { | 342 | if (pos) { |
344 | char *value; | 343 | char *value; |
345 | int length; | 344 | int length; |
346 | apr_size_t bytes = pos - buf; | 345 | apr_size_t bytes = pos - buf; |
347 | 346 | ||
348 | bytes += 1; | 347 | bytes += 1; |
349 | value = buf + bytes; | 348 | value = buf + bytes; |
350 | length = *len - bytes; | 349 | length = *len - bytes; |
351 | 350 | ||
352 | char_buffer_write(&ctxt->input_cbuf, value, length); | 351 | char_buffer_write(&ctxt->input_cbuf, value, length); |
353 | 352 | ||
354 | *len = bytes; | 353 | *len = bytes; |
355 | } | 354 | } |
356 | 355 | ||
357 | return APR_SUCCESS; | 356 | return APR_SUCCESS; |
358 | } | 357 | } |
359 | 358 | ||
360 | #define HANDSHAKE_MAX_TRIES 1024 | 359 | #define HANDSHAKE_MAX_TRIES 1024 |
361 | static int gnutls_do_handshake(mgs_handle_t * ctxt) | 360 | static int gnutls_do_handshake(mgs_handle_t * ctxt) |
362 | { | 361 | { |
363 | int ret; | 362 | int ret; |
364 | int errcode; | 363 | int errcode; |
365 | int maxtries = HANDSHAKE_MAX_TRIES; | 364 | int maxtries = HANDSHAKE_MAX_TRIES; |
366 | 365 | ||
367 | if (ctxt->status != 0 || ctxt->session == NULL) { | 366 | if (ctxt->status != 0 || ctxt->session == NULL) { |
368 | return -1; | 367 | return -1; |
369 | } | 368 | } |
370 | 369 | ||
371 | tryagain: | 370 | tryagain: |
372 | do { | 371 | do { |
373 | ret = gnutls_handshake(ctxt->session); | 372 | ret = gnutls_handshake(ctxt->session); |
374 | maxtries--; | 373 | maxtries--; |
375 | } while ((ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) && maxtries > 0); | 374 | } while ((ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) |
376 | 375 | && maxtries > 0); | |
377 | if (maxtries < 1) { | 376 | |
378 | ctxt->status = -1; | 377 | if (maxtries < 1) { |
378 | ctxt->status = -1; | ||
379 | #if USING_2_1_RECENT | 379 | #if USING_2_1_RECENT |
380 | ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, ctxt->c, | 380 | ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, ctxt->c, |
381 | "GnuTLS: Handshake Failed. Hit Maximum Attempts"); | 381 | "GnuTLS: Handshake Failed. Hit Maximum Attempts"); |
382 | #else | 382 | #else |
383 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, ctxt->c->base_server, | 383 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, |
384 | "GnuTLS: Handshake Failed. Hit Maximum Attempts"); | 384 | ctxt->c->base_server, |
385 | "GnuTLS: Handshake Failed. Hit Maximum Attempts"); | ||
385 | #endif | 386 | #endif |
386 | if (ctxt->session) { | 387 | if (ctxt->session) { |
387 | gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, | 388 | gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, |
388 | gnutls_error_to_alert(GNUTLS_E_INTERNAL_ERROR, NULL)); | 389 | gnutls_error_to_alert |
389 | gnutls_deinit(ctxt->session); | 390 | (GNUTLS_E_INTERNAL_ERROR, NULL)); |
390 | } | 391 | gnutls_deinit(ctxt->session); |
391 | ctxt->session = NULL; | 392 | } |
392 | return -1; | 393 | ctxt->session = NULL; |
393 | } | 394 | return -1; |
394 | 395 | } | |
395 | if (ret < 0) { | 396 | |
396 | if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED | 397 | if (ret < 0) { |
397 | || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { | 398 | if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED |
398 | errcode = gnutls_alert_get(ctxt->session); | 399 | || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { |
399 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, ctxt->c->base_server, | 400 | errcode = gnutls_alert_get(ctxt->session); |
400 | "GnuTLS: Hanshake Alert (%d) '%s'.", errcode, | 401 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, |
401 | gnutls_alert_get_name(errcode)); | 402 | ctxt->c->base_server, |
402 | } | 403 | "GnuTLS: Hanshake Alert (%d) '%s'.", |
403 | 404 | errcode, | |
404 | if (!gnutls_error_is_fatal(ret)) { | 405 | gnutls_alert_get_name(errcode)); |
405 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, ctxt->c->base_server, | 406 | } |
406 | "GnuTLS: Non-Fatal Handshake Error: (%d) '%s'", ret, | 407 | |
407 | gnutls_strerror(ret)); | 408 | if (!gnutls_error_is_fatal(ret)) { |
408 | goto tryagain; | 409 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, |
409 | } | 410 | ctxt->c->base_server, |
411 | "GnuTLS: Non-Fatal Handshake Error: (%d) '%s'", | ||
412 | ret, gnutls_strerror(ret)); | ||
413 | goto tryagain; | ||
414 | } | ||
410 | #if USING_2_1_RECENT | 415 | #if USING_2_1_RECENT |
411 | ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c, | 416 | ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c, |
412 | "GnuTLS: Handshake Failed (%d) '%s'", ret, | 417 | "GnuTLS: Handshake Failed (%d) '%s'", ret, |
413 | gnutls_strerror(ret)); | 418 | gnutls_strerror(ret)); |
414 | #else | 419 | #else |
415 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, ctxt->c->base_server, | 420 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, |
416 | "GnuTLS: Handshake Failed (%d) '%s'", ret, | 421 | ctxt->c->base_server, |
417 | gnutls_strerror(ret)); | 422 | "GnuTLS: Handshake Failed (%d) '%s'", ret, |
423 | gnutls_strerror(ret)); | ||
418 | #endif | 424 | #endif |
419 | ctxt->status = -1; | 425 | ctxt->status = -1; |
420 | if (ctxt->session) { | 426 | if (ctxt->session) { |
421 | gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, | 427 | gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, |
422 | gnutls_error_to_alert(ret, NULL)); | 428 | gnutls_error_to_alert(ret, |
423 | gnutls_deinit(ctxt->session); | 429 | NULL)); |
424 | } | 430 | gnutls_deinit(ctxt->session); |
425 | ctxt->session = NULL; | 431 | } |
426 | return ret; | 432 | ctxt->session = NULL; |
427 | } | 433 | return ret; |
428 | else { | 434 | } else { |
429 | /* all done with the handshake */ | 435 | /* all done with the handshake */ |
430 | ctxt->status = 1; | 436 | ctxt->status = 1; |
431 | /* If the session was resumed, we did not set the correct | 437 | /* If the session was resumed, we did not set the correct |
432 | * server_rec in ctxt->sc. Go Find it. (ick!) | 438 | * server_rec in ctxt->sc. Go Find it. (ick!) |
433 | */ | 439 | */ |
434 | if (gnutls_session_is_resumed(ctxt->session)) { | 440 | if (gnutls_session_is_resumed(ctxt->session)) { |
435 | mgs_srvconf_rec* sc; | 441 | mgs_srvconf_rec *sc; |
436 | sc = mgs_find_sni_server(ctxt->session); | 442 | sc = mgs_find_sni_server(ctxt->session); |
437 | if (sc) { | 443 | if (sc) { |
438 | ctxt->sc = sc; | 444 | ctxt->sc = sc; |
439 | } | 445 | } |
440 | } | 446 | } |
441 | return 0; | 447 | return 0; |
442 | } | 448 | } |
443 | } | 449 | } |
444 | 450 | ||
445 | int mgs_rehandshake(mgs_handle_t * ctxt) | 451 | int mgs_rehandshake(mgs_handle_t * ctxt) |
446 | { | 452 | { |
447 | int rv; | 453 | int rv; |
448 | 454 | ||
449 | if (ctxt->session == NULL) | 455 | if (ctxt->session == NULL) |
450 | return -1; | 456 | return -1; |
451 | 457 | ||
452 | rv = gnutls_rehandshake(ctxt->session); | 458 | rv = gnutls_rehandshake(ctxt->session); |
453 | 459 | ||
454 | if (rv != 0) { | 460 | if (rv != 0) { |
455 | /* the client did not want to rehandshake. goodbye */ | 461 | /* the client did not want to rehandshake. goodbye */ |
456 | ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ctxt->c->base_server, | 462 | ap_log_error(APLOG_MARK, APLOG_WARNING, 0, |
457 | "GnuTLS: Client Refused Rehandshake request."); | 463 | ctxt->c->base_server, |
458 | return -1; | 464 | "GnuTLS: Client Refused Rehandshake request."); |
459 | } | 465 | return -1; |
460 | 466 | } | |
461 | ctxt->status = 0; | 467 | |
462 | 468 | ctxt->status = 0; | |
463 | rv = gnutls_do_handshake(ctxt); | 469 | |
464 | 470 | rv = gnutls_do_handshake(ctxt); | |
465 | return rv; | 471 | |
472 | return rv; | ||
466 | } | 473 | } |
467 | 474 | ||
468 | 475 | ||
469 | apr_status_t mgs_filter_input(ap_filter_t* f, | 476 | apr_status_t mgs_filter_input(ap_filter_t * f, |
470 | apr_bucket_brigade * bb, | 477 | apr_bucket_brigade * bb, |
471 | ap_input_mode_t mode, | 478 | ap_input_mode_t mode, |
472 | apr_read_type_e block, | 479 | apr_read_type_e block, apr_off_t readbytes) |
473 | apr_off_t readbytes) | ||
474 | { | 480 | { |
475 | apr_status_t status = APR_SUCCESS; | 481 | apr_status_t status = APR_SUCCESS; |
476 | mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; | 482 | mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; |
477 | apr_size_t len = sizeof(ctxt->input_buffer); | 483 | apr_size_t len = sizeof(ctxt->input_buffer); |
478 | 484 | ||
479 | if (f->c->aborted) { | 485 | if (f->c->aborted) { |
480 | apr_bucket *bucket = apr_bucket_eos_create(f->c->bucket_alloc); | 486 | apr_bucket *bucket = |
481 | APR_BRIGADE_INSERT_TAIL(bb, bucket); | 487 | apr_bucket_eos_create(f->c->bucket_alloc); |
482 | return APR_ECONNABORTED; | 488 | APR_BRIGADE_INSERT_TAIL(bb, bucket); |
483 | } | 489 | return APR_ECONNABORTED; |
484 | 490 | } | |
485 | if (ctxt->status == 0) { | 491 | |
486 | gnutls_do_handshake(ctxt); | 492 | if (ctxt->status == 0) { |
487 | } | 493 | gnutls_do_handshake(ctxt); |
488 | 494 | } | |
489 | if (ctxt->status < 0) { | 495 | |
490 | return ap_get_brigade(f->next, bb, mode, block, readbytes); | 496 | if (ctxt->status < 0) { |
491 | } | 497 | return ap_get_brigade(f->next, bb, mode, block, readbytes); |
492 | 498 | } | |
493 | /* XXX: we don't currently support anything other than these modes. */ | 499 | |
494 | if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE && | 500 | /* XXX: we don't currently support anything other than these modes. */ |
495 | mode != AP_MODE_SPECULATIVE && mode != AP_MODE_INIT) { | 501 | if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE && |
496 | return APR_ENOTIMPL; | 502 | mode != AP_MODE_SPECULATIVE && mode != AP_MODE_INIT) { |
497 | } | 503 | return APR_ENOTIMPL; |
498 | 504 | } | |
499 | ctxt->input_mode = mode; | 505 | |
500 | ctxt->input_block = block; | 506 | ctxt->input_mode = mode; |
501 | 507 | ctxt->input_block = block; | |
502 | if (ctxt->input_mode == AP_MODE_READBYTES || | 508 | |
503 | ctxt->input_mode == AP_MODE_SPECULATIVE) { | 509 | if (ctxt->input_mode == AP_MODE_READBYTES || |
504 | /* Err. This is bad. readbytes *can* be a 64bit int! len.. is NOT */ | 510 | ctxt->input_mode == AP_MODE_SPECULATIVE) { |
505 | if (readbytes < len) { | 511 | /* Err. This is bad. readbytes *can* be a 64bit int! len.. is NOT */ |
506 | len = (apr_size_t) readbytes; | 512 | if (readbytes < len) { |
507 | } | 513 | len = (apr_size_t) readbytes; |
508 | status = gnutls_io_input_read(ctxt, ctxt->input_buffer, &len); | 514 | } |
509 | } | 515 | status = |
510 | else if (ctxt->input_mode == AP_MODE_GETLINE) { | 516 | gnutls_io_input_read(ctxt, ctxt->input_buffer, &len); |
511 | status = gnutls_io_input_getline(ctxt, ctxt->input_buffer, &len); | 517 | } else if (ctxt->input_mode == AP_MODE_GETLINE) { |
512 | } | 518 | status = |
513 | else { | 519 | gnutls_io_input_getline(ctxt, ctxt->input_buffer, |
514 | /* We have no idea what you are talking about, so return an error. */ | 520 | &len); |
515 | return APR_ENOTIMPL; | 521 | } else { |
516 | } | 522 | /* We have no idea what you are talking about, so return an error. */ |
517 | 523 | return APR_ENOTIMPL; | |
518 | if (status != APR_SUCCESS) { | 524 | } |
519 | return gnutls_io_filter_error(f, bb, status); | 525 | |
520 | } | 526 | if (status != APR_SUCCESS) { |
521 | 527 | return gnutls_io_filter_error(f, bb, status); | |
522 | /* Create a transient bucket out of the decrypted data. */ | 528 | } |
523 | if (len > 0) { | 529 | |
524 | apr_bucket *bucket = | 530 | /* Create a transient bucket out of the decrypted data. */ |
525 | apr_bucket_transient_create(ctxt->input_buffer, len, | 531 | if (len > 0) { |
526 | f->c->bucket_alloc); | 532 | apr_bucket *bucket = |
527 | APR_BRIGADE_INSERT_TAIL(bb, bucket); | 533 | apr_bucket_transient_create(ctxt->input_buffer, len, |
528 | } | 534 | f->c->bucket_alloc); |
529 | 535 | APR_BRIGADE_INSERT_TAIL(bb, bucket); | |
530 | return status; | 536 | } |
537 | |||
538 | return status; | ||
531 | } | 539 | } |
532 | 540 | ||
533 | apr_status_t mgs_filter_output(ap_filter_t * f, | 541 | apr_status_t mgs_filter_output(ap_filter_t * f, apr_bucket_brigade * bb) |
534 | apr_bucket_brigade * bb) | ||
535 | { | 542 | { |
536 | apr_size_t ret; | 543 | apr_size_t ret; |
537 | apr_bucket* e; | 544 | apr_bucket *e; |
538 | mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; | 545 | mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; |
539 | apr_status_t status = APR_SUCCESS; | 546 | apr_status_t status = APR_SUCCESS; |
540 | apr_read_type_e rblock = APR_NONBLOCK_READ; | 547 | apr_read_type_e rblock = APR_NONBLOCK_READ; |
541 | 548 | ||
542 | if (f->c->aborted) { | 549 | if (f->c->aborted) { |
543 | apr_brigade_cleanup(bb); | 550 | apr_brigade_cleanup(bb); |
544 | return APR_ECONNABORTED; | 551 | return APR_ECONNABORTED; |
545 | } | 552 | } |
546 | 553 | ||
547 | if (ctxt->status == 0) { | 554 | if (ctxt->status == 0) { |
548 | gnutls_do_handshake(ctxt); | 555 | gnutls_do_handshake(ctxt); |
549 | } | 556 | } |
550 | 557 | ||
551 | if (ctxt->status < 0) { | 558 | if (ctxt->status < 0) { |
552 | return ap_pass_brigade(f->next, bb); | 559 | return ap_pass_brigade(f->next, bb); |
553 | } | 560 | } |
554 | 561 | ||
555 | while (!APR_BRIGADE_EMPTY(bb)) { | 562 | while (!APR_BRIGADE_EMPTY(bb)) { |
556 | apr_bucket *bucket = APR_BRIGADE_FIRST(bb); | 563 | apr_bucket *bucket = APR_BRIGADE_FIRST(bb); |
557 | 564 | ||
558 | if (AP_BUCKET_IS_EOC(bucket)) { | 565 | if (AP_BUCKET_IS_EOC(bucket)) { |
559 | if (ctxt->session != NULL) { | 566 | if (ctxt->session != NULL) { |
560 | do { | 567 | do { |
561 | ret = gnutls_bye( ctxt->session, GNUTLS_SHUT_WR); | 568 | ret = |
562 | } while(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); | 569 | gnutls_bye(ctxt->session, |
563 | } | 570 | GNUTLS_SHUT_WR); |
564 | 571 | } while (ret == GNUTLS_E_INTERRUPTED | |
565 | apr_bucket_copy(bucket, &e); | 572 | || ret == GNUTLS_E_AGAIN); |
566 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); | 573 | } |
567 | 574 | ||
568 | if ((status = ap_pass_brigade(f->next, ctxt->output_bb)) != APR_SUCCESS) { | 575 | apr_bucket_copy(bucket, &e); |
569 | apr_brigade_cleanup(ctxt->output_bb); | 576 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); |
570 | return status; | 577 | |
571 | } | 578 | if ((status = |
572 | 579 | ap_pass_brigade(f->next, | |
573 | apr_brigade_cleanup(ctxt->output_bb); | 580 | ctxt->output_bb)) != |
574 | if (ctxt->session) { | 581 | APR_SUCCESS) { |
575 | gnutls_deinit(ctxt->session); | 582 | apr_brigade_cleanup(ctxt->output_bb); |
576 | ctxt->session = NULL; | 583 | return status; |
577 | } | 584 | } |
578 | continue; | 585 | |
579 | } else if (APR_BUCKET_IS_FLUSH(bucket) || APR_BUCKET_IS_EOS(bucket)) { | 586 | apr_brigade_cleanup(ctxt->output_bb); |
580 | 587 | if (ctxt->session) { | |
581 | apr_bucket_copy(bucket, &e); | 588 | gnutls_deinit(ctxt->session); |
582 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); | 589 | ctxt->session = NULL; |
583 | if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { | 590 | } |
584 | apr_brigade_cleanup(ctxt->output_bb); | 591 | continue; |
585 | return status; | 592 | } else if (APR_BUCKET_IS_FLUSH(bucket) |
586 | } | 593 | || APR_BUCKET_IS_EOS(bucket)) { |
587 | 594 | ||
588 | apr_brigade_cleanup(ctxt->output_bb); | 595 | apr_bucket_copy(bucket, &e); |
589 | continue; | 596 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); |
590 | } | 597 | if ((status = |
591 | else { | 598 | ap_pass_brigade(f->next, |
592 | /* filter output */ | 599 | bb)) != APR_SUCCESS) { |
593 | const char *data; | 600 | apr_brigade_cleanup(ctxt->output_bb); |
594 | apr_size_t len; | 601 | return status; |
595 | 602 | } | |
596 | status = apr_bucket_read(bucket, &data, &len, rblock); | 603 | |
597 | 604 | apr_brigade_cleanup(ctxt->output_bb); | |
598 | if (APR_STATUS_IS_EAGAIN(status)) { | 605 | continue; |
599 | rblock = APR_BLOCK_READ; | 606 | } else { |
600 | continue; /* and try again with a blocking read. */ | 607 | /* filter output */ |
601 | } | 608 | const char *data; |
602 | 609 | apr_size_t len; | |
603 | rblock = APR_NONBLOCK_READ; | 610 | |
604 | 611 | status = | |
605 | if (!APR_STATUS_IS_EOF(status) && (status != APR_SUCCESS)) { | 612 | apr_bucket_read(bucket, &data, &len, rblock); |
606 | break; | 613 | |
607 | } | 614 | if (APR_STATUS_IS_EAGAIN(status)) { |
608 | 615 | rblock = APR_BLOCK_READ; | |
609 | if (len > 0) { | 616 | continue; /* and try again with a blocking read. */ |
610 | 617 | } | |
611 | if (ctxt->session == NULL) { | 618 | |
612 | ret = GNUTLS_E_INVALID_REQUEST; | 619 | rblock = APR_NONBLOCK_READ; |
613 | } else { | 620 | |
614 | do { | 621 | if (!APR_STATUS_IS_EOF(status) |
615 | ret = gnutls_record_send(ctxt->session, data, len); | 622 | && (status != APR_SUCCESS)) { |
616 | } | 623 | break; |
617 | while(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); | 624 | } |
618 | } | 625 | |
619 | 626 | if (len > 0) { | |
620 | if (ret < 0) { | 627 | |
621 | /* error sending output */ | 628 | if (ctxt->session == NULL) { |
622 | ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->output_rc, | 629 | ret = GNUTLS_E_INVALID_REQUEST; |
623 | ctxt->c->base_server, | 630 | } else { |
624 | "GnuTLS: Error writing data." | 631 | do { |
625 | " (%d) '%s'", (int)ret, gnutls_strerror(ret)); | 632 | ret = |
626 | if (ctxt->output_rc == APR_SUCCESS) { | 633 | gnutls_record_send |
627 | ctxt->output_rc = APR_EGENERAL; | 634 | (ctxt->session, data, |
628 | } | 635 | len); |
629 | } | 636 | } |
630 | else if (ret != len) { | 637 | while (ret == GNUTLS_E_INTERRUPTED |
631 | /* Not able to send the entire bucket, | 638 | || ret == GNUTLS_E_AGAIN); |
632 | split it and send it again. */ | 639 | } |
633 | apr_bucket_split(bucket, ret); | 640 | |
634 | } | 641 | if (ret < 0) { |
635 | } | 642 | /* error sending output */ |
636 | 643 | ap_log_error(APLOG_MARK, | |
637 | apr_bucket_delete(bucket); | 644 | APLOG_INFO, |
638 | 645 | ctxt->output_rc, | |
639 | if (ctxt->output_rc != APR_SUCCESS) { | 646 | ctxt->c->base_server, |
640 | break; | 647 | "GnuTLS: Error writing data." |
641 | } | 648 | " (%d) '%s'", |
642 | } | 649 | (int) ret, |
643 | } | 650 | gnutls_strerror(ret)); |
644 | 651 | if (ctxt->output_rc == APR_SUCCESS) { | |
645 | return status; | 652 | ctxt->output_rc = |
653 | APR_EGENERAL; | ||
654 | } | ||
655 | } else if (ret != len) { | ||
656 | /* Not able to send the entire bucket, | ||
657 | split it and send it again. */ | ||
658 | apr_bucket_split(bucket, ret); | ||
659 | } | ||
660 | } | ||
661 | |||
662 | apr_bucket_delete(bucket); | ||
663 | |||
664 | if (ctxt->output_rc != APR_SUCCESS) { | ||
665 | break; | ||
666 | } | ||
667 | } | ||
668 | } | ||
669 | |||
670 | return status; | ||
646 | } | 671 | } |
647 | 672 | ||
648 | ssize_t mgs_transport_read(gnutls_transport_ptr_t ptr, | 673 | ssize_t mgs_transport_read(gnutls_transport_ptr_t ptr, |
649 | void *buffer, size_t len) | 674 | void *buffer, size_t len) |
650 | { | 675 | { |
651 | mgs_handle_t *ctxt = ptr; | 676 | mgs_handle_t *ctxt = ptr; |
652 | apr_status_t rc; | 677 | apr_status_t rc; |
653 | apr_size_t in = len; | 678 | apr_size_t in = len; |
654 | apr_read_type_e block = ctxt->input_block; | 679 | apr_read_type_e block = ctxt->input_block; |
655 | 680 | ||
656 | ctxt->input_rc = APR_SUCCESS; | 681 | ctxt->input_rc = APR_SUCCESS; |
657 | 682 | ||
658 | /* If Len = 0, we don't do anything. */ | 683 | /* If Len = 0, we don't do anything. */ |
659 | if (!len) | 684 | if (!len) |
660 | return 0; | 685 | return 0; |
661 | 686 | ||
662 | if (!ctxt->input_bb) { | 687 | if (!ctxt->input_bb) { |
663 | ctxt->input_rc = APR_EOF; | 688 | ctxt->input_rc = APR_EOF; |
664 | return -1; | 689 | return -1; |
665 | } | 690 | } |
666 | 691 | ||
667 | if (APR_BRIGADE_EMPTY(ctxt->input_bb)) { | 692 | if (APR_BRIGADE_EMPTY(ctxt->input_bb)) { |
668 | 693 | ||
669 | rc = ap_get_brigade(ctxt->input_filter->next, ctxt->input_bb, | 694 | rc = ap_get_brigade(ctxt->input_filter->next, |
670 | AP_MODE_READBYTES, ctxt->input_block, in); | 695 | ctxt->input_bb, AP_MODE_READBYTES, |
671 | 696 | ctxt->input_block, in); | |
672 | /* Not a problem, there was simply no data ready yet. | 697 | |
673 | */ | 698 | /* Not a problem, there was simply no data ready yet. |
674 | if (APR_STATUS_IS_EAGAIN(rc) || APR_STATUS_IS_EINTR(rc) | 699 | */ |
675 | || (rc == APR_SUCCESS && APR_BRIGADE_EMPTY(ctxt->input_bb))) { | 700 | if (APR_STATUS_IS_EAGAIN(rc) || APR_STATUS_IS_EINTR(rc) |
676 | 701 | || (rc == APR_SUCCESS | |
677 | if (APR_STATUS_IS_EOF(ctxt->input_rc)) { | 702 | && APR_BRIGADE_EMPTY(ctxt->input_bb))) { |
678 | return 0; | 703 | |
679 | } else { | 704 | if (APR_STATUS_IS_EOF(ctxt->input_rc)) { |
680 | if (ctxt->session) | 705 | return 0; |
681 | gnutls_transport_set_errno(ctxt->session, EINTR); | 706 | } else { |
682 | return -1; | 707 | if (ctxt->session) |
683 | } | 708 | gnutls_transport_set_errno(ctxt-> |
684 | } | 709 | session, |
685 | 710 | EINTR); | |
686 | 711 | return -1; | |
687 | if (rc != APR_SUCCESS) { | 712 | } |
688 | /* Unexpected errors discard the brigade */ | 713 | } |
689 | apr_brigade_cleanup(ctxt->input_bb); | 714 | |
690 | ctxt->input_bb = NULL; | 715 | |
691 | return -1; | 716 | if (rc != APR_SUCCESS) { |
692 | } | 717 | /* Unexpected errors discard the brigade */ |
693 | } | 718 | apr_brigade_cleanup(ctxt->input_bb); |
694 | 719 | ctxt->input_bb = NULL; | |
695 | ctxt->input_rc = brigade_consume(ctxt->input_bb, block, buffer, &len); | 720 | return -1; |
696 | 721 | } | |
697 | if (ctxt->input_rc == APR_SUCCESS) { | 722 | } |
698 | return (ssize_t) len; | 723 | |
699 | } | 724 | ctxt->input_rc = |
700 | 725 | brigade_consume(ctxt->input_bb, block, buffer, &len); | |
701 | if (APR_STATUS_IS_EAGAIN(ctxt->input_rc) | 726 | |
702 | || APR_STATUS_IS_EINTR(ctxt->input_rc)) { | 727 | if (ctxt->input_rc == APR_SUCCESS) { |
703 | if (len == 0) { | 728 | return (ssize_t) len; |
704 | if (ctxt->session) | 729 | } |
705 | gnutls_transport_set_errno(ctxt->session, EINTR); | 730 | |
706 | return -1; | 731 | if (APR_STATUS_IS_EAGAIN(ctxt->input_rc) |
707 | } | 732 | || APR_STATUS_IS_EINTR(ctxt->input_rc)) { |
708 | 733 | if (len == 0) { | |
709 | return (ssize_t) len; | 734 | if (ctxt->session) |
710 | } | 735 | gnutls_transport_set_errno(ctxt->session, |
711 | 736 | EINTR); | |
712 | /* Unexpected errors and APR_EOF clean out the brigade. | 737 | return -1; |
713 | * Subsequent calls will return APR_EOF. | 738 | } |
714 | */ | 739 | |
715 | apr_brigade_cleanup(ctxt->input_bb); | 740 | return (ssize_t) len; |
716 | ctxt->input_bb = NULL; | 741 | } |
717 | 742 | ||
718 | if (APR_STATUS_IS_EOF(ctxt->input_rc) && len) { | 743 | /* Unexpected errors and APR_EOF clean out the brigade. |
719 | /* Provide the results of this read pass, | 744 | * Subsequent calls will return APR_EOF. |
720 | * without resetting the BIO retry_read flag | 745 | */ |
721 | */ | 746 | apr_brigade_cleanup(ctxt->input_bb); |
722 | return (ssize_t) len; | 747 | ctxt->input_bb = NULL; |
723 | } | 748 | |
724 | 749 | if (APR_STATUS_IS_EOF(ctxt->input_rc) && len) { | |
725 | return -1; | 750 | /* Provide the results of this read pass, |
751 | * without resetting the BIO retry_read flag | ||
752 | */ | ||
753 | return (ssize_t) len; | ||
754 | } | ||
755 | |||
756 | return -1; | ||
726 | } | 757 | } |
727 | 758 | ||
728 | 759 | ||
729 | static ssize_t write_flush(mgs_handle_t * ctxt) | 760 | static ssize_t write_flush(mgs_handle_t * ctxt) |
730 | { | 761 | { |
731 | apr_bucket *e; | 762 | apr_bucket *e; |
732 | 763 | ||
733 | if (!(ctxt->output_blen || ctxt->output_length)) { | 764 | if (!(ctxt->output_blen || ctxt->output_length)) { |
734 | ctxt->output_rc = APR_SUCCESS; | 765 | ctxt->output_rc = APR_SUCCESS; |
735 | return 1; | 766 | return 1; |
736 | } | 767 | } |
737 | 768 | ||
738 | if (ctxt->output_blen) { | 769 | if (ctxt->output_blen) { |
739 | e = apr_bucket_transient_create(ctxt->output_buffer, | 770 | e = apr_bucket_transient_create(ctxt->output_buffer, |
740 | ctxt->output_blen, | 771 | ctxt->output_blen, |
741 | ctxt->output_bb->bucket_alloc); | 772 | ctxt->output_bb-> |
742 | /* we filled this buffer first so add it to the | 773 | bucket_alloc); |
743 | * head of the brigade | 774 | /* we filled this buffer first so add it to the |
744 | */ | 775 | * head of the brigade |
745 | APR_BRIGADE_INSERT_HEAD(ctxt->output_bb, e); | 776 | */ |
746 | ctxt->output_blen = 0; | 777 | APR_BRIGADE_INSERT_HEAD(ctxt->output_bb, e); |
747 | } | 778 | ctxt->output_blen = 0; |
748 | 779 | } | |
749 | ctxt->output_length = 0; | 780 | |
750 | e = apr_bucket_flush_create(ctxt->output_bb->bucket_alloc); | 781 | ctxt->output_length = 0; |
751 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); | 782 | e = apr_bucket_flush_create(ctxt->output_bb->bucket_alloc); |
752 | 783 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); | |
753 | ctxt->output_rc = ap_pass_brigade(ctxt->output_filter->next, | 784 | |
754 | ctxt->output_bb); | 785 | ctxt->output_rc = ap_pass_brigade(ctxt->output_filter->next, |
755 | /* clear the brigade to be ready for next time */ | 786 | ctxt->output_bb); |
756 | apr_brigade_cleanup(ctxt->output_bb); | 787 | /* clear the brigade to be ready for next time */ |
757 | 788 | apr_brigade_cleanup(ctxt->output_bb); | |
758 | return (ctxt->output_rc == APR_SUCCESS) ? 1 : -1; | 789 | |
790 | return (ctxt->output_rc == APR_SUCCESS) ? 1 : -1; | ||
759 | } | 791 | } |
760 | 792 | ||
761 | ssize_t mgs_transport_write(gnutls_transport_ptr_t ptr, | 793 | ssize_t mgs_transport_write(gnutls_transport_ptr_t ptr, |
762 | const void *buffer, size_t len) | 794 | const void *buffer, size_t len) |
763 | { | 795 | { |
764 | mgs_handle_t *ctxt = ptr; | 796 | mgs_handle_t *ctxt = ptr; |
765 | 797 | ||
766 | /* pass along the encrypted data | 798 | /* pass along the encrypted data |
767 | * need to flush since we're using SSL's malloc-ed buffer | 799 | * need to flush since we're using SSL's malloc-ed buffer |
768 | * which will be overwritten once we leave here | 800 | * which will be overwritten once we leave here |
769 | */ | 801 | */ |
770 | apr_bucket *bucket = apr_bucket_transient_create(buffer, len, | 802 | apr_bucket *bucket = apr_bucket_transient_create(buffer, len, |
771 | ctxt->output_bb->bucket_alloc); | 803 | ctxt->output_bb-> |
772 | ctxt->output_length += len; | 804 | bucket_alloc); |
773 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, bucket); | 805 | ctxt->output_length += len; |
774 | 806 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, bucket); | |
775 | if (write_flush(ctxt) < 0) { | 807 | |
776 | return -1; | 808 | if (write_flush(ctxt) < 0) { |
777 | } | 809 | return -1; |
778 | return len; | 810 | } |
811 | return len; | ||
779 | } | 812 | } |
diff --git a/src/gnutls_lua.c b/src/gnutls_lua.c index 6d80574..4401b61 100644 --- a/src/gnutls_lua.c +++ b/src/gnutls_lua.c | |||
@@ -25,268 +25,285 @@ | |||
25 | 25 | ||
26 | static char *MGS_LUA_RRKEY = "request_rec"; | 26 | static char *MGS_LUA_RRKEY = "request_rec"; |
27 | 27 | ||
28 | static request_rec *mgs_lua_getrr(lua_State *lvm) | 28 | static request_rec *mgs_lua_getrr(lua_State * lvm) |
29 | { | 29 | { |
30 | request_rec *r; | 30 | request_rec *r; |
31 | 31 | ||
32 | /* Push the request_rec off the registry, onto the stack. */ | 32 | /* Push the request_rec off the registry, onto the stack. */ |
33 | lua_pushlightuserdata(lvm, MGS_LUA_RRKEY); | 33 | lua_pushlightuserdata(lvm, MGS_LUA_RRKEY); |
34 | lua_gettable(lvm, LUA_REGISTRYINDEX); | 34 | lua_gettable(lvm, LUA_REGISTRYINDEX); |
35 | r = lua_touserdata(lvm, -1); | 35 | r = lua_touserdata(lvm, -1); |
36 | lua_pop(lvm, 1); | 36 | lua_pop(lvm, 1); |
37 | return r; | 37 | return r; |
38 | } | 38 | } |
39 | 39 | ||
40 | static int get_request_table(lua_State *lvm, long offset) | 40 | static int get_request_table(lua_State * lvm, long offset) |
41 | { | 41 | { |
42 | const char *key; | 42 | const char *key; |
43 | request_rec *r; | 43 | request_rec *r; |
44 | const char *value; | 44 | const char *value; |
45 | apr_table_t *t; | 45 | apr_table_t *t; |
46 | key = luaL_checkstring(lvm, 1); | 46 | key = luaL_checkstring(lvm, 1); |
47 | 47 | ||
48 | r = mgs_lua_getrr(lvm); | 48 | r = mgs_lua_getrr(lvm); |
49 | 49 | ||
50 | t = *(apr_table_t **)((char *)r + offset); | 50 | t = *(apr_table_t **) ((char *) r + offset); |
51 | 51 | ||
52 | value = apr_table_get(t, key); | 52 | value = apr_table_get(t, key); |
53 | 53 | ||
54 | if (value) { | 54 | if (value) { |
55 | lua_pushstring(lvm, value); | 55 | lua_pushstring(lvm, value); |
56 | return 1; | 56 | return 1; |
57 | } | 57 | } else { |
58 | else { | 58 | return 0; |
59 | return 0; | 59 | } |
60 | } | ||
61 | } | 60 | } |
62 | 61 | ||
63 | static int mgs_lua_getenv(lua_State *lvm) | 62 | static int mgs_lua_getenv(lua_State * lvm) |
64 | { | 63 | { |
65 | return get_request_table(lvm, APR_OFFSETOF(request_rec, subprocess_env)); | 64 | return get_request_table(lvm, |
65 | APR_OFFSETOF(request_rec, | ||
66 | subprocess_env)); | ||
66 | } | 67 | } |
67 | 68 | ||
68 | static int mgs_lua_getheader(lua_State *lvm) | 69 | static int mgs_lua_getheader(lua_State * lvm) |
69 | { | 70 | { |
70 | return get_request_table(lvm, APR_OFFSETOF(request_rec, headers_in)); | 71 | return get_request_table(lvm, |
71 | } | 72 | APR_OFFSETOF(request_rec, headers_in)); |
73 | } | ||
72 | 74 | ||
73 | static const luaL_reg mgs_lua_reg[] = { | 75 | static const luaL_reg mgs_lua_reg[] = { |
74 | {"getenv", mgs_lua_getenv}, | 76 | {"getenv", mgs_lua_getenv}, |
75 | {"header", mgs_lua_getheader}, | 77 | {"header", mgs_lua_getheader}, |
76 | {NULL, NULL} | 78 | {NULL, NULL} |
77 | }; | 79 | }; |
78 | 80 | ||
79 | lua_State* get_luastate() | 81 | lua_State *get_luastate() |
80 | { | 82 | { |
81 | lua_State* lvm = lua_open(); | 83 | lua_State *lvm = lua_open(); |
82 | luaopen_base(lvm); | 84 | luaopen_base(lvm); |
83 | luaopen_io(lvm); | 85 | luaopen_io(lvm); |
84 | luaopen_table(lvm); | 86 | luaopen_table(lvm); |
85 | luaopen_string(lvm); | 87 | luaopen_string(lvm); |
86 | luaopen_math(lvm); | 88 | luaopen_math(lvm); |
87 | luaopen_loadlib(lvm); | 89 | luaopen_loadlib(lvm); |
88 | luaL_openlib(lvm, "ap", mgs_lua_reg, 0); | 90 | luaL_openlib(lvm, "ap", mgs_lua_reg, 0); |
89 | 91 | ||
90 | return lvm; | 92 | return lvm; |
91 | } | 93 | } |
92 | 94 | ||
93 | int mgs_authz_lua(request_rec* r) | 95 | int mgs_authz_lua(request_rec * r) |
94 | { | 96 | { |
95 | int rv; | 97 | int rv; |
96 | lua_State* lvm; | 98 | lua_State *lvm; |
97 | mgs_dirconf_rec *dc = ap_get_module_config(r->per_dir_config, | 99 | mgs_dirconf_rec *dc = ap_get_module_config(r->per_dir_config, |
98 | &gnutls_module); | 100 | &gnutls_module); |
99 | 101 | ||
100 | if (dc->lua_bytecode_len <= 0) { | 102 | if (dc->lua_bytecode_len <= 0) { |
101 | return 0; | 103 | return 0; |
102 | } | 104 | } |
103 | 105 | ||
104 | lvm = get_luastate(); | 106 | lvm = get_luastate(); |
105 | lua_pushlightuserdata(lvm, MGS_LUA_RRKEY); | 107 | lua_pushlightuserdata(lvm, MGS_LUA_RRKEY); |
106 | lua_pushlightuserdata(lvm, r); | 108 | lua_pushlightuserdata(lvm, r); |
107 | lua_settable(lvm, LUA_REGISTRYINDEX); | 109 | lua_settable(lvm, LUA_REGISTRYINDEX); |
108 | 110 | ||
109 | /* Push Bytecode onto the stack */ | 111 | /* Push Bytecode onto the stack */ |
110 | rv = luaL_loadbuffer(lvm, dc->lua_bytecode, dc->lua_bytecode_len, "gnutls-lua"); | 112 | rv = luaL_loadbuffer(lvm, dc->lua_bytecode, dc->lua_bytecode_len, |
111 | 113 | "gnutls-lua"); | |
112 | if (rv != 0) { | 114 | |
113 | /* Get the Error message */ | 115 | if (rv != 0) { |
114 | const char* error = lua_tostring(lvm, -1); | 116 | /* Get the Error message */ |
115 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | 117 | const char *error = lua_tostring(lvm, -1); |
116 | "GnuTLS: Error Loading Lua Bytecode: %s", error); | 118 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
117 | lua_pop(lvm, 1); | 119 | "GnuTLS: Error Loading Lua Bytecode: %s", |
118 | return -1; | 120 | error); |
119 | } | 121 | lua_pop(lvm, 1); |
120 | 122 | return -1; | |
121 | rv = lua_pcall(lvm, 0, 1, 0); | 123 | } |
122 | if (rv != 0) { | 124 | |
123 | /* Get the Error message */ | 125 | rv = lua_pcall(lvm, 0, 1, 0); |
124 | const char* error = lua_tostring(lvm, -1); | 126 | if (rv != 0) { |
125 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | 127 | /* Get the Error message */ |
126 | "GnuTLS: Error Running Lua: %s", error); | 128 | const char *error = lua_tostring(lvm, -1); |
127 | lua_pop(lvm, 1); | 129 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
128 | return -1; | 130 | "GnuTLS: Error Running Lua: %s", error); |
129 | } | 131 | lua_pop(lvm, 1); |
130 | 132 | return -1; | |
131 | rv = (int)lua_tonumber(lvm, -1); | 133 | } |
132 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | 134 | |
133 | "GnuTLS: (%d) Lua Return: %d", | 135 | rv = (int) lua_tonumber(lvm, -1); |
134 | dc->lua_bytecode_len, rv); | 136 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
135 | lua_pop(lvm, 1); | 137 | "GnuTLS: (%d) Lua Return: %d", |
136 | lua_close(lvm); | 138 | dc->lua_bytecode_len, rv); |
137 | return rv; | 139 | lua_pop(lvm, 1); |
140 | lua_close(lvm); | ||
141 | return rv; | ||
138 | } | 142 | } |
139 | 143 | ||
140 | static apr_size_t config_getstr(ap_configfile_t *cfg, char *buf, size_t bufsiz) | 144 | static apr_size_t config_getstr(ap_configfile_t * cfg, char *buf, |
145 | size_t bufsiz) | ||
141 | { | 146 | { |
142 | apr_size_t i = 0; | 147 | apr_size_t i = 0; |
143 | 148 | ||
144 | if (cfg->getstr) { | 149 | if (cfg->getstr) { |
145 | const char *res = (cfg->getstr)(buf, bufsiz, cfg->param); | 150 | const char *res = (cfg->getstr) (buf, bufsiz, cfg->param); |
146 | if (res) { | 151 | if (res) { |
147 | i = strlen(buf); | 152 | i = strlen(buf); |
148 | if (i && buf[i - 1] == '\n') ++cfg->line_number; | 153 | if (i && buf[i - 1] == '\n') |
149 | } | 154 | ++cfg->line_number; |
150 | else { | 155 | } else { |
151 | buf[0] = '\0'; | 156 | buf[0] = '\0'; |
152 | i = 0; | 157 | i = 0; |
153 | } | 158 | } |
154 | } | 159 | } else { |
155 | else { | 160 | while (i < bufsiz) { |
156 | while (i < bufsiz) { | 161 | int ch = (cfg->getch) (cfg->param); |
157 | int ch = (cfg->getch)(cfg->param); | 162 | if (ch == EOF) |
158 | if (ch == EOF) break; | 163 | break; |
159 | buf[i++] = ch; | 164 | buf[i++] = ch; |
160 | if (ch == '\n') { | 165 | if (ch == '\n') { |
161 | ++cfg->line_number; | 166 | ++cfg->line_number; |
162 | break; | 167 | break; |
163 | } | 168 | } |
164 | } | 169 | } |
165 | } | 170 | } |
166 | return i; | 171 | return i; |
167 | } | 172 | } |
168 | 173 | ||
169 | struct cr_ctx { | 174 | struct cr_ctx { |
170 | ap_configfile_t *cfp; | 175 | ap_configfile_t *cfp; |
171 | size_t startline; | 176 | size_t startline; |
172 | char buf[HUGE_STRING_LEN]; | 177 | char buf[HUGE_STRING_LEN]; |
173 | }; | 178 | }; |
174 | 179 | ||
175 | static const char *LUACMD = "gnutlsrequire"; | 180 | static const char *LUACMD = "gnutlsrequire"; |
176 | static const char *lf = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; | 181 | static const char *lf = |
182 | "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; | ||
177 | #define N_LF 32 | 183 | #define N_LF 32 |
178 | 184 | ||
179 | static const char *direct_chunkreader(lua_State *lvm, void *udata, size_t *plen) | 185 | static const char *direct_chunkreader(lua_State * lvm, void *udata, |
186 | size_t * plen) | ||
180 | { | 187 | { |
181 | const char *p; | 188 | const char *p; |
182 | struct cr_ctx *ctx = udata; | 189 | struct cr_ctx *ctx = udata; |
183 | 190 | ||
184 | if (ctx->startline) { | 191 | if (ctx->startline) { |
185 | *plen = ctx->startline > N_LF ? N_LF : ctx->startline; | 192 | *plen = ctx->startline > N_LF ? N_LF : ctx->startline; |
186 | ctx->startline -= *plen; | 193 | ctx->startline -= *plen; |
187 | return lf; | 194 | return lf; |
188 | } | 195 | } |
189 | *plen = config_getstr(ctx->cfp, ctx->buf, HUGE_STRING_LEN); | 196 | *plen = config_getstr(ctx->cfp, ctx->buf, HUGE_STRING_LEN); |
190 | 197 | ||
191 | for (p = ctx->buf; isspace(*p); ++p); | 198 | for (p = ctx->buf; isspace(*p); ++p); |
192 | if (p[0] == '<' && p[1] == '/') { | 199 | if (p[0] == '<' && p[1] == '/') { |
193 | int i = 0; | 200 | int i = 0; |
194 | while (i < strlen(LUACMD)) { | 201 | while (i < strlen(LUACMD)) { |
195 | if (tolower(p[i + 2]) != LUACMD[i]) return ctx->buf; | 202 | if (tolower(p[i + 2]) != LUACMD[i]) |
196 | ++i; | 203 | return ctx->buf; |
197 | } | 204 | ++i; |
198 | *plen = 0; | 205 | } |
199 | return NULL; | 206 | *plen = 0; |
200 | } | 207 | return NULL; |
201 | return ctx->buf; | 208 | } |
209 | return ctx->buf; | ||
202 | } | 210 | } |
203 | 211 | ||
204 | static int ldump_writer (lua_State *L, const void* b, size_t size, void* B) { | 212 | static int ldump_writer(lua_State * L, const void *b, size_t size, void *B) |
205 | (void)L; | 213 | { |
206 | luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); | 214 | (void) L; |
207 | return 1; | 215 | luaL_addlstring((luaL_Buffer *) B, (const char *) b, size); |
216 | return 1; | ||
208 | } | 217 | } |
209 | 218 | ||
210 | /* a bytecode buffer*/ | 219 | /* a bytecode buffer*/ |
211 | typedef struct bcbuf_ctx { | 220 | typedef struct bcbuf_ctx { |
212 | apr_size_t buflen; | 221 | apr_size_t buflen; |
213 | char* buf; | 222 | char *buf; |
214 | } bcbuf_ctx; | 223 | } bcbuf_ctx; |
215 | 224 | ||
216 | const char *mgs_set_require_section(cmd_parms *cmd, void *mconfig, const char *arg) | 225 | const char *mgs_set_require_section(cmd_parms * cmd, void *mconfig, |
226 | const char *arg) | ||
217 | { | 227 | { |
218 | apr_size_t bytecode_len; | 228 | apr_size_t bytecode_len; |
219 | const char* bytecode; | 229 | const char *bytecode; |
220 | bcbuf_ctx* bcbuf; | 230 | bcbuf_ctx *bcbuf; |
221 | luaL_Buffer b; | 231 | luaL_Buffer b; |
222 | ap_directive_t **current = mconfig; | 232 | ap_directive_t **current = mconfig; |
223 | struct cr_ctx ctx[1]; | 233 | struct cr_ctx ctx[1]; |
224 | int result; | 234 | int result; |
225 | const char *filename = apr_psprintf(cmd->pool, "@%s", cmd->config_file->name); | 235 | const char *filename = |
226 | // get a word argument | 236 | apr_psprintf(cmd->pool, "@%s", cmd->config_file->name); |
227 | const char *word; | 237 | // get a word argument |
228 | apr_size_t wordlen; | 238 | const char *word; |
229 | lua_State *lvm = get_luastate(); | 239 | apr_size_t wordlen; |
230 | 240 | lua_State *lvm = get_luastate(); | |
231 | word = ap_getword_conf(cmd->pool, &arg); | 241 | |
232 | wordlen = strlen(word); | 242 | word = ap_getword_conf(cmd->pool, &arg); |
233 | do { | 243 | wordlen = strlen(word); |
234 | if (wordlen) { | 244 | do { |
235 | if (word[wordlen - 1] == '>') { | 245 | if (wordlen) { |
236 | --wordlen; | 246 | if (word[wordlen - 1] == '>') { |
237 | break; | 247 | --wordlen; |
238 | } | 248 | break; |
239 | if (*arg == '>') break; | 249 | } |
240 | } | 250 | if (*arg == '>') |
241 | return apr_pstrcat(cmd->pool, "<", LUACMD, "> takes exactly one argument", NULL); | 251 | break; |
242 | } while (0); | 252 | } |
243 | 253 | return apr_pstrcat(cmd->pool, "<", LUACMD, | |
244 | ctx->cfp = cmd->config_file; | 254 | "> takes exactly one argument", NULL); |
245 | ctx->startline = cmd->config_file->line_number; | 255 | } while (0); |
246 | lua_settop(lvm, 0); | 256 | |
247 | result = lua_load(lvm, direct_chunkreader, ctx, filename); | 257 | ctx->cfp = cmd->config_file; |
248 | 258 | ctx->startline = cmd->config_file->line_number; | |
249 | if (result != 0) { | 259 | lua_settop(lvm, 0); |
250 | word = apr_pstrcat(cmd->pool, "Lua Error:", lua_tostring(lvm, -1), NULL); | 260 | result = lua_load(lvm, direct_chunkreader, ctx, filename); |
251 | lua_close(lvm); | 261 | |
252 | return word; | 262 | if (result != 0) { |
253 | } | 263 | word = |
254 | else { | 264 | apr_pstrcat(cmd->pool, "Lua Error:", |
255 | luaL_buffinit(lvm, &b); | 265 | lua_tostring(lvm, -1), NULL); |
256 | lua_dump(lvm, ldump_writer, &b); | 266 | lua_close(lvm); |
257 | luaL_pushresult(&b); | 267 | return word; |
258 | bytecode = lua_tostring(lvm, -1); | 268 | } else { |
259 | bytecode_len = lua_strlen(lvm, -1); | 269 | luaL_buffinit(lvm, &b); |
260 | } | 270 | lua_dump(lvm, ldump_writer, &b); |
261 | 271 | luaL_pushresult(&b); | |
262 | /* Here, we have to replace our current config node for the next pass */ | 272 | bytecode = lua_tostring(lvm, -1); |
263 | if (!*current) { | 273 | bytecode_len = lua_strlen(lvm, -1); |
264 | *current = apr_pcalloc(cmd->pool, sizeof(**current)); | 274 | } |
265 | } | 275 | |
266 | 276 | /* Here, we have to replace our current config node for the next pass */ | |
267 | (*current)->filename = cmd->config_file->name; | 277 | if (!*current) { |
268 | (*current)->line_num = ctx->startline; | 278 | *current = apr_pcalloc(cmd->pool, sizeof(**current)); |
269 | (*current)->directive = apr_pstrdup(cmd->pool, "GnuTLSRequireByteCode"); | 279 | } |
270 | (*current)->args = NULL; | 280 | |
271 | 281 | (*current)->filename = cmd->config_file->name; | |
272 | bcbuf = apr_pcalloc(cmd->pool, sizeof(bcbuf)); | 282 | (*current)->line_num = ctx->startline; |
273 | bcbuf->buflen = bytecode_len; | 283 | (*current)->directive = |
274 | bcbuf->buf = apr_pstrmemdup(cmd->pool, bytecode, bytecode_len); | 284 | apr_pstrdup(cmd->pool, "GnuTLSRequireByteCode"); |
275 | 285 | (*current)->args = NULL; | |
276 | (*current)->data = bcbuf; | 286 | |
277 | lua_close(lvm); | 287 | bcbuf = apr_pcalloc(cmd->pool, sizeof(bcbuf)); |
278 | return NULL; | 288 | bcbuf->buflen = bytecode_len; |
289 | bcbuf->buf = apr_pstrmemdup(cmd->pool, bytecode, bytecode_len); | ||
290 | |||
291 | (*current)->data = bcbuf; | ||
292 | lua_close(lvm); | ||
293 | return NULL; | ||
279 | } | 294 | } |
280 | 295 | ||
281 | const char *mgs_set_require_bytecode(cmd_parms *cmd, void *mconfig, const char *arg) | 296 | const char *mgs_set_require_bytecode(cmd_parms * cmd, void *mconfig, |
297 | const char *arg) | ||
282 | { | 298 | { |
283 | bcbuf_ctx* bcbuf; | 299 | bcbuf_ctx *bcbuf; |
284 | ap_directive_t *directive = cmd->directive; | 300 | ap_directive_t *directive = cmd->directive; |
285 | mgs_dirconf_rec *dc = mconfig; | 301 | mgs_dirconf_rec *dc = mconfig; |
286 | 302 | ||
287 | bcbuf = directive->data; | 303 | bcbuf = directive->data; |
288 | dc->lua_bytecode_len = bcbuf->buflen; | 304 | dc->lua_bytecode_len = bcbuf->buflen; |
289 | dc->lua_bytecode = apr_pstrmemdup(cmd->pool, bcbuf->buf, bcbuf->buflen); | 305 | dc->lua_bytecode = |
290 | 306 | apr_pstrmemdup(cmd->pool, bcbuf->buf, bcbuf->buflen); | |
291 | return NULL; | 307 | |
308 | return NULL; | ||
292 | } | 309 | } |
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c index c95d183..49f4e43 100644 --- a/src/mod_gnutls.c +++ b/src/mod_gnutls.c | |||
@@ -19,143 +19,146 @@ | |||
19 | 19 | ||
20 | static void gnutls_hooks(apr_pool_t * p) | 20 | static void gnutls_hooks(apr_pool_t * p) |
21 | { | 21 | { |
22 | ap_hook_pre_connection(mgs_hook_pre_connection, NULL, NULL, | 22 | ap_hook_pre_connection(mgs_hook_pre_connection, NULL, NULL, |
23 | APR_HOOK_MIDDLE); | 23 | APR_HOOK_MIDDLE); |
24 | ap_hook_post_config(mgs_hook_post_config, NULL, NULL, | 24 | ap_hook_post_config(mgs_hook_post_config, NULL, NULL, |
25 | APR_HOOK_MIDDLE); | 25 | APR_HOOK_MIDDLE); |
26 | ap_hook_child_init(mgs_hook_child_init, NULL, NULL, | 26 | ap_hook_child_init(mgs_hook_child_init, NULL, NULL, |
27 | APR_HOOK_MIDDLE); | 27 | APR_HOOK_MIDDLE); |
28 | #if USING_2_1_RECENT | 28 | #if USING_2_1_RECENT |
29 | ap_hook_http_scheme(mgs_hook_http_scheme, NULL, NULL, | 29 | ap_hook_http_scheme(mgs_hook_http_scheme, NULL, NULL, |
30 | APR_HOOK_MIDDLE); | 30 | APR_HOOK_MIDDLE); |
31 | #else | 31 | #else |
32 | ap_hook_http_method(mgs_hook_http_scheme, NULL, NULL, | 32 | ap_hook_http_method(mgs_hook_http_scheme, NULL, NULL, |
33 | APR_HOOK_MIDDLE); | 33 | APR_HOOK_MIDDLE); |
34 | #endif | 34 | #endif |
35 | ap_hook_default_port(mgs_hook_default_port, NULL, NULL, | 35 | ap_hook_default_port(mgs_hook_default_port, NULL, NULL, |
36 | APR_HOOK_MIDDLE); | 36 | APR_HOOK_MIDDLE); |
37 | ap_hook_pre_config(mgs_hook_pre_config, NULL, NULL, | 37 | ap_hook_pre_config(mgs_hook_pre_config, NULL, NULL, |
38 | APR_HOOK_MIDDLE); | 38 | APR_HOOK_MIDDLE); |
39 | |||
40 | ap_hook_access_checker(mgs_hook_authz, NULL, NULL, APR_HOOK_REALLY_FIRST); | ||
41 | |||
42 | ap_hook_fixups(mgs_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST); | ||
43 | |||
44 | /* TODO: HTTP Upgrade Filter */ | ||
45 | /* ap_register_output_filter ("UPGRADE_FILTER", | ||
46 | * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); | ||
47 | */ | ||
48 | 39 | ||
49 | ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, | 40 | ap_hook_access_checker(mgs_hook_authz, NULL, NULL, |
50 | mgs_filter_input, NULL, | 41 | APR_HOOK_REALLY_FIRST); |
51 | AP_FTYPE_CONNECTION + 5); | 42 | |
52 | ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, | 43 | ap_hook_fixups(mgs_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST); |
53 | mgs_filter_output, NULL, | 44 | |
54 | AP_FTYPE_CONNECTION + 5); | 45 | /* TODO: HTTP Upgrade Filter */ |
46 | /* ap_register_output_filter ("UPGRADE_FILTER", | ||
47 | * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); | ||
48 | */ | ||
49 | |||
50 | ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, | ||
51 | mgs_filter_input, NULL, | ||
52 | AP_FTYPE_CONNECTION + 5); | ||
53 | ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, | ||
54 | mgs_filter_output, NULL, | ||
55 | AP_FTYPE_CONNECTION + 5); | ||
55 | } | 56 | } |
56 | 57 | ||
57 | static const command_rec mgs_config_cmds[] = { | 58 | static const command_rec mgs_config_cmds[] = { |
58 | AP_INIT_TAKE1("GnuTLSClientVerify", mgs_set_client_verify, | 59 | AP_INIT_TAKE1("GnuTLSClientVerify", mgs_set_client_verify, |
59 | NULL, | 60 | NULL, |
60 | RSRC_CONF|OR_AUTHCFG, | 61 | RSRC_CONF | OR_AUTHCFG, |
61 | "Set Verification Requirements of the Client Certificate"), | 62 | "Set Verification Requirements of the Client Certificate"), |
62 | AP_INIT_TAKE1("GnuTLSClientCAFile", mgs_set_client_ca_file, | 63 | AP_INIT_TAKE1("GnuTLSClientCAFile", mgs_set_client_ca_file, |
63 | NULL, | 64 | NULL, |
64 | RSRC_CONF, | 65 | RSRC_CONF, |
65 | "Set the CA File to verify Client Certificates"), | 66 | "Set the CA File to verify Client Certificates"), |
66 | AP_INIT_TAKE1("GnuTLSX509CAFile", mgs_set_client_ca_file, | 67 | AP_INIT_TAKE1("GnuTLSX509CAFile", mgs_set_client_ca_file, |
67 | NULL, | 68 | NULL, |
68 | RSRC_CONF, | 69 | RSRC_CONF, |
69 | "Set the CA File to verify Client Certificates"), | 70 | "Set the CA File to verify Client Certificates"), |
70 | AP_INIT_TAKE1("GnuTLSPGPKeyringFile", mgs_set_keyring_file, | 71 | AP_INIT_TAKE1("GnuTLSPGPKeyringFile", mgs_set_keyring_file, |
71 | NULL, | 72 | NULL, |
72 | RSRC_CONF, | 73 | RSRC_CONF, |
73 | "Set the Keyring File to verify Client Certificates"), | 74 | "Set the Keyring File to verify Client Certificates"), |
74 | AP_INIT_TAKE1("GnuTLSDHFile", mgs_set_dh_file, | 75 | AP_INIT_TAKE1("GnuTLSDHFile", mgs_set_dh_file, |
75 | NULL, | 76 | NULL, |
76 | RSRC_CONF, | 77 | RSRC_CONF, |
77 | "Set the file to read Diffie Hellman parameters from"), | 78 | "Set the file to read Diffie Hellman parameters from"), |
78 | AP_INIT_TAKE1("GnuTLSRSAFile", mgs_set_rsa_export_file, | 79 | AP_INIT_TAKE1("GnuTLSRSAFile", mgs_set_rsa_export_file, |
79 | NULL, | 80 | NULL, |
80 | RSRC_CONF, | 81 | RSRC_CONF, |
81 | "Set the file to read RSA-EXPORT parameters from"), | 82 | "Set the file to read RSA-EXPORT parameters from"), |
82 | AP_INIT_TAKE1("GnuTLSCertificateFile", mgs_set_cert_file, | 83 | AP_INIT_TAKE1("GnuTLSCertificateFile", mgs_set_cert_file, |
83 | NULL, | 84 | NULL, |
84 | RSRC_CONF, | 85 | RSRC_CONF, |
85 | "SSL Server X509 Certificate file"), | 86 | "SSL Server X509 Certificate file"), |
86 | AP_INIT_TAKE1("GnuTLSKeyFile", mgs_set_key_file, | 87 | AP_INIT_TAKE1("GnuTLSKeyFile", mgs_set_key_file, |
87 | NULL, | 88 | NULL, |
88 | RSRC_CONF, | 89 | RSRC_CONF, |
89 | "SSL Server X509 Private Key file"), | 90 | "SSL Server X509 Private Key file"), |
90 | AP_INIT_TAKE1("GnuTLSX509CertificateFile", mgs_set_cert_file, | 91 | AP_INIT_TAKE1("GnuTLSX509CertificateFile", mgs_set_cert_file, |
91 | NULL, | 92 | NULL, |
92 | RSRC_CONF, | 93 | RSRC_CONF, |
93 | "SSL Server X509 Certificate file"), | 94 | "SSL Server X509 Certificate file"), |
94 | AP_INIT_TAKE1("GnuTLSX509KeyFile", mgs_set_key_file, | 95 | AP_INIT_TAKE1("GnuTLSX509KeyFile", mgs_set_key_file, |
95 | NULL, | 96 | NULL, |
96 | RSRC_CONF, | 97 | RSRC_CONF, |
97 | "SSL Server X509 Private Key file"), | 98 | "SSL Server X509 Private Key file"), |
98 | AP_INIT_TAKE1("GnuTLSPGPCertificateFile", mgs_set_pgpcert_file, | 99 | AP_INIT_TAKE1("GnuTLSPGPCertificateFile", mgs_set_pgpcert_file, |
99 | NULL, | 100 | NULL, |
100 | RSRC_CONF, | 101 | RSRC_CONF, |
101 | "SSL Server PGP Certificate file"), | 102 | "SSL Server PGP Certificate file"), |
102 | AP_INIT_TAKE1("GnuTLSPGPKeyFile", mgs_set_pgpkey_file, | 103 | AP_INIT_TAKE1("GnuTLSPGPKeyFile", mgs_set_pgpkey_file, |
103 | NULL, | 104 | NULL, |
104 | RSRC_CONF, | 105 | RSRC_CONF, |
105 | "SSL Server PGP Private key file"), | 106 | "SSL Server PGP Private key file"), |
106 | #ifdef ENABLE_SRP | 107 | #ifdef ENABLE_SRP |
107 | AP_INIT_TAKE1("GnuTLSSRPPasswdFile", mgs_set_srp_tpasswd_file, | 108 | AP_INIT_TAKE1("GnuTLSSRPPasswdFile", mgs_set_srp_tpasswd_file, |
108 | NULL, | 109 | NULL, |
109 | RSRC_CONF, | 110 | RSRC_CONF, |
110 | "SSL Server SRP Password Conf file"), | 111 | "SSL Server SRP Password Conf file"), |
111 | AP_INIT_TAKE1("GnuTLSSRPPasswdConfFile", mgs_set_srp_tpasswd_conf_file, | 112 | AP_INIT_TAKE1("GnuTLSSRPPasswdConfFile", |
112 | NULL, | 113 | mgs_set_srp_tpasswd_conf_file, |
113 | RSRC_CONF, | 114 | NULL, |
114 | "SSL Server SRP Parameters file"), | 115 | RSRC_CONF, |
116 | "SSL Server SRP Parameters file"), | ||
115 | #endif | 117 | #endif |
116 | AP_INIT_TAKE1("GnuTLSCacheTimeout", mgs_set_cache_timeout, | 118 | AP_INIT_TAKE1("GnuTLSCacheTimeout", mgs_set_cache_timeout, |
117 | NULL, | 119 | NULL, |
118 | RSRC_CONF, | 120 | RSRC_CONF, |
119 | "Cache Timeout"), | 121 | "Cache Timeout"), |
120 | AP_INIT_TAKE2("GnuTLSCache", mgs_set_cache, | 122 | AP_INIT_TAKE2("GnuTLSCache", mgs_set_cache, |
121 | NULL, | 123 | NULL, |
122 | RSRC_CONF, | 124 | RSRC_CONF, |
123 | "Cache Configuration"), | 125 | "Cache Configuration"), |
124 | AP_INIT_TAKE1("GnuTLSSessionTickets", mgs_set_tickets, | 126 | AP_INIT_TAKE1("GnuTLSSessionTickets", mgs_set_tickets, |
125 | NULL, | 127 | NULL, |
126 | RSRC_CONF, | 128 | RSRC_CONF, |
127 | "Session Tickets Configuration"), | 129 | "Session Tickets Configuration"), |
128 | AP_INIT_RAW_ARGS("GnuTLSPriorities", mgs_set_priorities, | 130 | AP_INIT_RAW_ARGS("GnuTLSPriorities", mgs_set_priorities, |
129 | NULL, | 131 | NULL, |
130 | RSRC_CONF, | 132 | RSRC_CONF, |
131 | "The priorities to enable (ciphers, Key exchange, macs, compression)."), | 133 | "The priorities to enable (ciphers, Key exchange, macs, compression)."), |
132 | AP_INIT_TAKE1("GnuTLSEnable", mgs_set_enabled, | 134 | AP_INIT_TAKE1("GnuTLSEnable", mgs_set_enabled, |
133 | NULL, | 135 | NULL, |
134 | RSRC_CONF, | 136 | RSRC_CONF, |
135 | "Whether this server has GnuTLS Enabled. Default: Off"), | 137 | "Whether this server has GnuTLS Enabled. Default: Off"), |
136 | AP_INIT_TAKE1("GnuTLSExportCertificates", mgs_set_export_certificates_enabled, | 138 | AP_INIT_TAKE1("GnuTLSExportCertificates", |
137 | NULL, | 139 | mgs_set_export_certificates_enabled, |
138 | RSRC_CONF, | 140 | NULL, |
139 | "Whether to export PEM encoded certificates to CGIs. Default: Off"), | 141 | RSRC_CONF, |
142 | "Whether to export PEM encoded certificates to CGIs. Default: Off"), | ||
140 | #if 0 | 143 | #if 0 |
141 | AP_INIT_RAW_ARGS("<GnuTLSRequire", mgs_set_require_section, | 144 | AP_INIT_RAW_ARGS("<GnuTLSRequire", mgs_set_require_section, |
142 | NULL, | 145 | NULL, |
143 | EXEC_ON_READ|OR_ALL, | 146 | EXEC_ON_READ | OR_ALL, |
144 | "Whether this server has GnuTLS Enabled. Default: Off"), | 147 | "Whether this server has GnuTLS Enabled. Default: Off"), |
145 | AP_INIT_RAW_ARGS("GnuTLSRequireByteCode", mgs_set_require_bytecode, | 148 | AP_INIT_RAW_ARGS("GnuTLSRequireByteCode", mgs_set_require_bytecode, |
146 | NULL, | 149 | NULL, |
147 | OR_ALL, | 150 | OR_ALL, |
148 | "Internal Command for reading Lua Bytecode."), | 151 | "Internal Command for reading Lua Bytecode."), |
149 | #endif | 152 | #endif |
150 | {NULL} | 153 | {NULL} |
151 | }; | 154 | }; |
152 | 155 | ||
153 | module AP_MODULE_DECLARE_DATA gnutls_module = { | 156 | module AP_MODULE_DECLARE_DATA gnutls_module = { |
154 | STANDARD20_MODULE_STUFF, | 157 | STANDARD20_MODULE_STUFF, |
155 | mgs_config_dir_create, | 158 | mgs_config_dir_create, |
156 | mgs_config_dir_merge, | 159 | mgs_config_dir_merge, |
157 | mgs_config_server_create, | 160 | mgs_config_server_create, |
158 | NULL, | 161 | NULL, |
159 | mgs_config_cmds, | 162 | mgs_config_cmds, |
160 | gnutls_hooks | 163 | gnutls_hooks |
161 | }; | 164 | }; |