aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gnutls_cache.c925
-rw-r--r--src/gnutls_config.c1039
-rw-r--r--src/gnutls_hooks.c1944
-rw-r--r--src/gnutls_io.c1367
-rw-r--r--src/gnutls_lua.c465
-rw-r--r--src/mod_gnutls.c253
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
46char *mgs_session_id2sz(unsigned char *id, int idlen, 46char *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 */
66static int mgs_session_id2dbm(conn_rec* c, unsigned char *id, int idlen, 66static int mgs_session_id2dbm(conn_rec * c, unsigned char *id, int idlen,
67 apr_datum_t* dbmkey) 67 apr_datum_t * dbmkey)
68{ 68{
69char buf[STR_SESSION_LEN]; 69 char buf[STR_SESSION_LEN];
70char *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"
83char *mgs_time2sz(time_t in_time, char *str, int strsize) 86char *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 */
102static char* mgs_session_id2mc(conn_rec* c, unsigned char *id, int idlen) 105static char *mgs_session_id2mc(conn_rec * c, unsigned char *id, int idlen)
103{ 106{
104char buf[STR_SESSION_LEN]; 107 char buf[STR_SESSION_LEN];
105char *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 */
120static apr_memcache_t* mc; 125static apr_memcache_t *mc;
121 126
122static int mc_cache_child_init(apr_pool_t *p, server_rec *s, 127static 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
205static int mc_cache_store(void* baton, gnutls_datum_t key, 209static 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
232static gnutls_datum_t mc_cache_fetch(void* baton, gnutls_datum_t key) 237static 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
272static int mc_cache_delete(void* baton, gnutls_datum_t key) 277static 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
297const char* db_type(mgs_srvconf_rec * sc) 302const 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
307static void dbm_cache_expire(mgs_handle_t *ctxt) 312static 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
371static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key) 379static 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
423static int dbm_cache_store(void* baton, gnutls_datum_t key, 432static 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
483static int dbm_cache_delete(void* baton, gnutls_datum_t key) 493static 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
519static int dbm_cache_post_config(apr_pool_t *p, server_rec *s, 530static 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
555int mgs_cache_post_config(apr_pool_t *p, server_rec *s, 567int 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
564int mgs_cache_child_init(apr_pool_t *p, server_rec *s, 577int 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
580int mgs_cache_session_init(mgs_handle_t *ctxt) 594int 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 @@
21static int load_datum_from_file(apr_pool_t * pool, 21static 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
55const char *mgs_set_dh_file(cmd_parms * parms, void *dummy, 55const 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
95const char *mgs_set_rsa_export_file(cmd_parms * parms, void *dummy, 99const 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
135const char *mgs_set_cert_file(cmd_parms * parms, void *dummy, 143const 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
168const char *mgs_set_key_file(cmd_parms * parms, void *dummy, 179const 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
211const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy, 229const 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
250const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy, 270const 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
288const char *mgs_set_tickets(cmd_parms * parms, void *dummy, 312const 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,
307const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy, 331const 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
320const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy, 344const 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,
335const char *mgs_set_cache(cmd_parms * parms, void *dummy, 360const 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
372const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy, 398const 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
394const 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
420const 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
426const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy, 452const 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
482const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy, 515const 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
520const char *mgs_set_enabled(cmd_parms * parms, void *dummy, 556const 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
538const char *mgs_set_export_certificates_enabled(cmd_parms * parms, void *dummy, 574const 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
557const char *mgs_set_priorities(cmd_parms * parms, void *dummy, const char *arg) 595const 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
577void *mgs_config_server_create(apr_pool_t * p, server_rec * s) 618void *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
620void *mgs_config_dir_merge(apr_pool_t * p, void *basev, void *addv) 663void *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
634void *mgs_config_dir_create(apr_pool_t * p, char *dir) 677void *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
41static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt); 41static 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 */
43static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, 43static 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);
46static 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);
46static 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
50static apr_status_t mgs_cleanup_pre_config(void *data) 51static 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
60static void gnutls_debug_log_all(int level, const char *str) 61static 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
69int 71int
70mgs_hook_pre_config(apr_pool_t * pconf, 72mgs_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{
73int 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
123static int mgs_select_virtual_server_cb(gnutls_session_t session) 131static 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
184static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st * ret) 195static 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"
233static int read_crt_cn(server_rec * s, apr_pool_t * p, 245static 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
285static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p, 299static 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
312mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, 327mgs_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
468void mgs_hook_child_init(apr_pool_t * p, server_rec * s) 496void 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
487const char *mgs_hook_http_scheme(const request_rec * r) 515const 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
506apr_port_t mgs_hook_default_port(const request_rec * r) 534apr_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
528typedef struct { 556typedef 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
534static int vhost_cb(void *baton, conn_rec * conn, server_rec * s) 562static 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
578mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session) 606mgs_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
660static const int protocol_priority[] = { 690static 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
665static mgs_handle_t *create_gnutls_handle(apr_pool_t * pool, conn_rec * c) 695static 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
706int mgs_hook_pre_connection(conn_rec * c, void *csd) 737int 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
745int mgs_hook_fixups(request_rec * r) 777int 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
825int mgs_hook_authz(request_rec * r) 862int 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
895mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side, 933mgs_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
1007static void 1072static void
1008mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side, 1073mgs_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 */
1076static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) 1149static 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
34static apr_status_t gnutls_io_filter_error(ap_filter_t * f, 34static 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
66static int char_buffer_read(mgs_char_buffer_t * buffer, char *in, 66static 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
90static int char_buffer_write(mgs_char_buffer_t * buffer, char *in, 88static 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 */
103static apr_status_t brigade_consume(apr_bucket_brigade * bb, 100static 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
184static apr_status_t gnutls_io_input_read(mgs_handle_t * ctxt, 181static 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
317static apr_status_t gnutls_io_input_getline(mgs_handle_t * ctxt, 316static 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
361static int gnutls_do_handshake(mgs_handle_t * ctxt) 360static 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
371tryagain: 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
445int mgs_rehandshake(mgs_handle_t * ctxt) 451int 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
469apr_status_t mgs_filter_input(ap_filter_t* f, 476apr_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
533apr_status_t mgs_filter_output(ap_filter_t * f, 541apr_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
648ssize_t mgs_transport_read(gnutls_transport_ptr_t ptr, 673ssize_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
729static ssize_t write_flush(mgs_handle_t * ctxt) 760static 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
761ssize_t mgs_transport_write(gnutls_transport_ptr_t ptr, 793ssize_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
26static char *MGS_LUA_RRKEY = "request_rec"; 26static char *MGS_LUA_RRKEY = "request_rec";
27 27
28static request_rec *mgs_lua_getrr(lua_State *lvm) 28static 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
40static int get_request_table(lua_State *lvm, long offset) 40static 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
63static int mgs_lua_getenv(lua_State *lvm) 62static 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
68static int mgs_lua_getheader(lua_State *lvm) 69static 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
73static const luaL_reg mgs_lua_reg[] = { 75static 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
79lua_State* get_luastate() 81lua_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
93int mgs_authz_lua(request_rec* r) 95int 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
140static apr_size_t config_getstr(ap_configfile_t *cfg, char *buf, size_t bufsiz) 144static 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
169struct cr_ctx { 174struct 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
175static const char *LUACMD = "gnutlsrequire"; 180static const char *LUACMD = "gnutlsrequire";
176static 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"; 181static 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
179static const char *direct_chunkreader(lua_State *lvm, void *udata, size_t *plen) 185static 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
204static int ldump_writer (lua_State *L, const void* b, size_t size, void* B) { 212static 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*/
211typedef struct bcbuf_ctx { 220typedef 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
216const char *mgs_set_require_section(cmd_parms *cmd, void *mconfig, const char *arg) 225const 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
281const char *mgs_set_require_bytecode(cmd_parms *cmd, void *mconfig, const char *arg) 296const 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
20static void gnutls_hooks(apr_pool_t * p) 20static 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
57static const command_rec mgs_config_cmds[] = { 58static 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
153module AP_MODULE_DECLARE_DATA gnutls_module = { 156module 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};