36 | 36 |
ngx_slab_pool_t *shpool, ngx_uint_t n);
|
37 | 37 |
static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
|
38 | 38 |
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
|
|
39 |
|
|
40 |
#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
|
|
41 |
static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
|
|
42 |
unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
|
|
43 |
HMAC_CTX *hctx, int enc);
|
|
44 |
#endif
|
39 | 45 |
|
40 | 46 |
static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
|
41 | 47 |
static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
|
81 | 87 |
int ngx_ssl_connection_index;
|
82 | 88 |
int ngx_ssl_server_conf_index;
|
83 | 89 |
int ngx_ssl_session_cache_index;
|
|
90 |
int ngx_ssl_session_ticket_keys_index;
|
84 | 91 |
int ngx_ssl_certificate_index;
|
85 | 92 |
int ngx_ssl_stapling_index;
|
86 | 93 |
|
|
133 | 140 |
ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
|
134 | 141 |
NULL);
|
135 | 142 |
if (ngx_ssl_session_cache_index == -1) {
|
|
143 |
ngx_ssl_error(NGX_LOG_ALERT, log, 0,
|
|
144 |
"SSL_CTX_get_ex_new_index() failed");
|
|
145 |
return NGX_ERROR;
|
|
146 |
}
|
|
147 |
|
|
148 |
ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL,
|
|
149 |
NULL, NULL);
|
|
150 |
if (ngx_ssl_session_ticket_keys_index == -1) {
|
136 | 151 |
ngx_ssl_error(NGX_LOG_ALERT, log, 0,
|
137 | 152 |
"SSL_CTX_get_ex_new_index() failed");
|
138 | 153 |
return NGX_ERROR;
|
|
2239 | 2254 |
}
|
2240 | 2255 |
|
2241 | 2256 |
|
|
2257 |
#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
|
|
2258 |
|
|
2259 |
ngx_int_t
|
|
2260 |
ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
|
|
2261 |
{
|
|
2262 |
u_char buf[48];
|
|
2263 |
ssize_t n;
|
|
2264 |
ngx_str_t *path;
|
|
2265 |
ngx_file_t file;
|
|
2266 |
ngx_uint_t i;
|
|
2267 |
ngx_array_t *keys;
|
|
2268 |
ngx_file_info_t fi;
|
|
2269 |
ngx_ssl_session_ticket_key_t *key;
|
|
2270 |
|
|
2271 |
if (paths == NULL) {
|
|
2272 |
return NGX_OK;
|
|
2273 |
}
|
|
2274 |
|
|
2275 |
keys = ngx_array_create(cf->pool, paths->nelts,
|
|
2276 |
sizeof(ngx_ssl_session_ticket_key_t));
|
|
2277 |
if (keys == NULL) {
|
|
2278 |
return NGX_ERROR;
|
|
2279 |
}
|
|
2280 |
|
|
2281 |
path = paths->elts;
|
|
2282 |
for (i = 0; i < paths->nelts; i++) {
|
|
2283 |
|
|
2284 |
if (ngx_conf_full_name(cf->cycle, &path[i], 1) != NGX_OK) {
|
|
2285 |
return NGX_ERROR;
|
|
2286 |
}
|
|
2287 |
|
|
2288 |
ngx_memzero(&file, sizeof(ngx_file_t));
|
|
2289 |
file.name = path[i];
|
|
2290 |
file.log = cf->log;
|
|
2291 |
|
|
2292 |
file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, 0, 0);
|
|
2293 |
if (file.fd == NGX_INVALID_FILE) {
|
|
2294 |
ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
|
|
2295 |
ngx_open_file_n " \"%V\" failed", &file.name);
|
|
2296 |
return NGX_ERROR;
|
|
2297 |
}
|
|
2298 |
|
|
2299 |
if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) {
|
|
2300 |
ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
|
|
2301 |
ngx_fd_info_n " \"%V\" failed", &file.name);
|
|
2302 |
goto failed;
|
|
2303 |
}
|
|
2304 |
|
|
2305 |
if (ngx_file_size(&fi) != 48) {
|
|
2306 |
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
|
2307 |
"\"%V\" must be 48 bytes", &file.name);
|
|
2308 |
goto failed;
|
|
2309 |
}
|
|
2310 |
|
|
2311 |
n = ngx_read_file(&file, buf, 48, 0);
|
|
2312 |
|
|
2313 |
if (n == NGX_ERROR) {
|
|
2314 |
ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
|
|
2315 |
ngx_read_file_n " \"%V\" failed", &file.name);
|
|
2316 |
goto failed;
|
|
2317 |
}
|
|
2318 |
|
|
2319 |
if (n != 48) {
|
|
2320 |
ngx_conf_log_error(NGX_LOG_CRIT, cf, 0,
|
|
2321 |
ngx_read_file_n " \"%V\" returned only "
|
|
2322 |
"%z bytes instead of 48", &file.name, n);
|
|
2323 |
goto failed;
|
|
2324 |
}
|
|
2325 |
|
|
2326 |
key = ngx_array_push(keys);
|
|
2327 |
if (key == NULL) {
|
|
2328 |
goto failed;
|
|
2329 |
}
|
|
2330 |
|
|
2331 |
ngx_memcpy(key->name, buf, 16);
|
|
2332 |
ngx_memcpy(key->aes_key, buf + 16, 16);
|
|
2333 |
ngx_memcpy(key->hmac_key, buf + 32, 16);
|
|
2334 |
|
|
2335 |
if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
|
|
2336 |
ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
|
|
2337 |
ngx_close_file_n " \"%V\" failed", &file.name);
|
|
2338 |
}
|
|
2339 |
}
|
|
2340 |
|
|
2341 |
if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_ticket_keys_index, keys)
|
|
2342 |
== 0)
|
|
2343 |
{
|
|
2344 |
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
|
|
2345 |
"SSL_CTX_set_ex_data() failed");
|
|
2346 |
return NGX_ERROR;
|
|
2347 |
}
|
|
2348 |
|
|
2349 |
if (SSL_CTX_set_tlsext_ticket_key_cb(ssl->ctx,
|
|
2350 |
ngx_ssl_session_ticket_key_callback)
|
|
2351 |
== 0)
|
|
2352 |
{
|
|
2353 |
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
|
|
2354 |
"nginx was built with Session Tickets support, however, "
|
|
2355 |
"now it is linked dynamically to an OpenSSL library "
|
|
2356 |
"which has no tlsext support, therefore Session Tickets "
|
|
2357 |
"are not available");
|
|
2358 |
}
|
|
2359 |
|
|
2360 |
return NGX_OK;
|
|
2361 |
|
|
2362 |
failed:
|
|
2363 |
|
|
2364 |
if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
|
|
2365 |
ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
|
|
2366 |
ngx_close_file_n " \"%V\" failed", &file.name);
|
|
2367 |
}
|
|
2368 |
|
|
2369 |
return NGX_ERROR;
|
|
2370 |
}
|
|
2371 |
|
|
2372 |
|
|
2373 |
#ifdef OPENSSL_NO_SHA256
|
|
2374 |
#define ngx_ssl_session_ticket_md EVP_sha1
|
|
2375 |
#else
|
|
2376 |
#define ngx_ssl_session_ticket_md EVP_sha256
|
|
2377 |
#endif
|
|
2378 |
|
|
2379 |
|
|
2380 |
static int
|
|
2381 |
ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
|
|
2382 |
unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
|
|
2383 |
HMAC_CTX *hctx, int enc)
|
|
2384 |
{
|
|
2385 |
SSL_CTX *ssl_ctx;
|
|
2386 |
ngx_uint_t i;
|
|
2387 |
ngx_array_t *keys;
|
|
2388 |
ngx_ssl_session_ticket_key_t *key;
|
|
2389 |
#if (NGX_DEBUG)
|
|
2390 |
u_char buf[32];
|
|
2391 |
ngx_connection_t *c;
|
|
2392 |
#endif
|
|
2393 |
|
|
2394 |
ssl_ctx = SSL_get_SSL_CTX(ssl_conn);
|
|
2395 |
|
|
2396 |
keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_ticket_keys_index);
|
|
2397 |
if (keys == NULL) {
|
|
2398 |
return -1;
|
|
2399 |
}
|
|
2400 |
|
|
2401 |
key = keys->elts;
|
|
2402 |
|
|
2403 |
#if (NGX_DEBUG)
|
|
2404 |
c = ngx_ssl_get_connection(ssl_conn);
|
|
2405 |
#endif
|
|
2406 |
|
|
2407 |
if (enc == 1) {
|
|
2408 |
/* encrypt session ticket */
|
|
2409 |
|
|
2410 |
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
|
2411 |
"ssl session ticket encrypt, key: \"%*s\" (%s session)",
|
|
2412 |
ngx_hex_dump(buf, key[0].name, 16) - buf, buf,
|
|
2413 |
SSL_session_reused(ssl_conn) ? "reused" : "new");
|
|
2414 |
|
|
2415 |
RAND_pseudo_bytes(iv, 16);
|
|
2416 |
EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[0].aes_key, iv);
|
|
2417 |
HMAC_Init_ex(hctx, key[0].hmac_key, 16,
|
|
2418 |
ngx_ssl_session_ticket_md(), NULL);
|
|
2419 |
memcpy(name, key[0].name, 16);
|
|
2420 |
|
|
2421 |
return 0;
|
|
2422 |
|
|
2423 |
} else {
|
|
2424 |
/* decrypt session ticket */
|
|
2425 |
|
|
2426 |
for (i = 0; i < keys->nelts; i++) {
|
|
2427 |
if (ngx_memcmp(name, key[i].name, 16) == 0) {
|
|
2428 |
goto found;
|
|
2429 |
}
|
|
2430 |
}
|
|
2431 |
|
|
2432 |
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
|
2433 |
"ssl session ticket decrypt, key: \"%*s\" not found",
|
|
2434 |
ngx_hex_dump(buf, name, 16) - buf, buf);
|
|
2435 |
|
|
2436 |
return 0;
|
|
2437 |
|
|
2438 |
found:
|
|
2439 |
|
|
2440 |
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
|
2441 |
"ssl session ticket decrypt, key: \"%*s\"%s",
|
|
2442 |
ngx_hex_dump(buf, key[i].name, 16) - buf, buf,
|
|
2443 |
(i == 0) ? " (default)" : "");
|
|
2444 |
|
|
2445 |
HMAC_Init_ex(hctx, key[i].hmac_key, 16,
|
|
2446 |
ngx_ssl_session_ticket_md(), NULL);
|
|
2447 |
EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[i].aes_key, iv);
|
|
2448 |
|
|
2449 |
return (i == 0) ? 1 : 2 /* renew */;
|
|
2450 |
}
|
|
2451 |
}
|
|
2452 |
|
|
2453 |
#else
|
|
2454 |
|
|
2455 |
ngx_int_t
|
|
2456 |
ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
|
|
2457 |
{
|
|
2458 |
if (paths) {
|
|
2459 |
ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
|
|
2460 |
"\"ssl_session_ticket_keys\" ignored, not supported");
|
|
2461 |
}
|
|
2462 |
|
|
2463 |
return NGX_OK;
|
|
2464 |
}
|
|
2465 |
|
|
2466 |
#endif
|
|
2467 |
|
|
2468 |
|
2242 | 2469 |
void
|
2243 | 2470 |
ngx_ssl_cleanup_ctx(void *data)
|
2244 | 2471 |
{
|