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