/* callback for new session caching, to be set with SSL_CTX_sess_set_new_cb */ int ngx_http_lua_ssl_sess_store_handler(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess) { lua_State *L; ngx_int_t rc; #if OPENSSL_VERSION_NUMBER >= 0x1010005fL unsigned int len; #endif ngx_connection_t *c, *fc = NULL; ngx_http_request_t *r = NULL; ngx_http_connection_t *hc; ngx_http_lua_ssl_ctx_t *cctx; ngx_http_lua_srv_conf_t *lscf; ngx_http_core_loc_conf_t *clcf; c = ngx_ssl_get_connection(ssl_conn); dd("c = %p", c); cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); dd("ssl sess_store handler, sess_store-ctx=%p", cctx); hc = c->data; fc = ngx_http_lua_create_fake_connection(NULL); if (fc == NULL) { goto failed; } fc->log->handler = ngx_http_lua_log_ssl_sess_store_error; fc->log->data = fc; fc->addr_text = c->addr_text; fc->listening = c->listening; r = ngx_http_lua_create_fake_request(fc); if (r == NULL) { goto failed; } r->main_conf = hc->conf_ctx->main_conf; r->srv_conf = hc->conf_ctx->srv_conf; r->loc_conf = hc->conf_ctx->loc_conf; fc->log->file = c->log->file; fc->log->log_level = c->log->log_level; fc->ssl = c->ssl; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); #if defined(nginx_version) && nginx_version >= 1003014 # if nginx_version >= 1009000 ngx_set_connection_log(fc, clcf->error_log); # else ngx_http_set_connection_log(fc, clcf->error_log); # endif #else fc->log->file = clcf->error_log->file; if (!(fc->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { fc->log->log_level = clcf->error_log->log_level; } #endif if (cctx == NULL) { cctx = ngx_pcalloc(c->pool, sizeof(ngx_http_lua_ssl_ctx_t)); if (cctx == NULL) { goto failed; /* error */ } } cctx->connection = c; cctx->request = r; cctx->session = sess; #if OPENSSL_VERSION_NUMBER < 0x1010005fL cctx->session_id.data = sess->session_id; cctx->session_id.len = sess->session_id_length; #else cctx->session_id.data = (u_char *)SSL_SESSION_get_id(sess, &len); cctx->session_id.len = len; #endif cctx->done = 0; dd("setting cctx"); if (SSL_set_ex_data(c->ssl->connection, ngx_http_lua_ssl_ctx_index, cctx) == 0) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed"); goto failed; } lscf = ngx_http_get_module_srv_conf(r, ngx_http_lua_module); /* TODO honor lua_code_cache off */ L = ngx_http_lua_get_lua_vm(r, NULL); c->log->action = "storing SSL session by lua"; rc = lscf->srv.ssl_sess_store_handler(r, lscf, L); if (rc >= NGX_OK || rc == NGX_ERROR) { cctx->done = 1; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl_session_store_by_lua*: handler return value: %i, " "sess new cb exit code: %d", rc, cctx->exit_code); c->log->action = "SSL handshaking"; /* Return value is a flag indicating whether the passed-in session * has been freed by this callback; always return 0 so OpenSSL will * free the session. Nginx's own session caching logic has the same * practice. */ return 0; } /* impossible to reach here */ ngx_http_lua_assert(0); failed: if (r && r->pool) { ngx_http_lua_free_fake_request(r); } if (fc) { ngx_http_lua_close_fake_connection(fc); } return 0; }
/* cached session fetching callback to be set with SSL_CTX_sess_set_get_cb */ ngx_ssl_session_t * ngx_http_lua_ssl_sess_fetch_handler(ngx_ssl_conn_t *ssl_conn, u_char *id, int len, int *copy) { lua_State *L; ngx_int_t rc; ngx_connection_t *c, *fc = NULL; ngx_http_request_t *r = NULL; ngx_pool_cleanup_t *cln; ngx_http_connection_t *hc; ngx_http_lua_ssl_ctx_t *cctx; ngx_http_lua_srv_conf_t *lscf; ngx_http_core_loc_conf_t *clcf; /* set copy to 0 as we expect OpenSSL to handle * the memory of returned session */ *copy = 0; c = ngx_ssl_get_connection(ssl_conn); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl session fetch: connection reusable: %ud", c->reusable); cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); dd("ssl sess_fetch handler, sess_fetch-ctx=%p", cctx); if (cctx && cctx->entered_sess_fetch_handler) { /* not the first time */ dd("here: %d", (int) cctx->entered_sess_fetch_handler); if (cctx->done) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl_session_fetch_by_lua*: " "sess get cb exit code: %d", cctx->exit_code); dd("lua ssl sess_fetch done, finally"); return cctx->session; } #ifdef SSL_ERROR_PENDING_SESSION return SSL_magic_pending_session_ptr(); #else ngx_log_error(NGX_LOG_CRIT, c->log, 0, "lua: cannot yield in sess get cb: " "missing async sess get cb support in OpenSSL"); return NULL; #endif } dd("first time"); ngx_reusable_connection(c, 0); hc = c->data; fc = ngx_http_lua_create_fake_connection(NULL); if (fc == NULL) { goto failed; } fc->log->handler = ngx_http_lua_log_ssl_sess_fetch_error; fc->log->data = fc; fc->addr_text = c->addr_text; fc->listening = c->listening; r = ngx_http_lua_create_fake_request(fc); if (r == NULL) { goto failed; } r->main_conf = hc->conf_ctx->main_conf; r->srv_conf = hc->conf_ctx->srv_conf; r->loc_conf = hc->conf_ctx->loc_conf; fc->log->file = c->log->file; fc->log->log_level = c->log->log_level; fc->ssl = c->ssl; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); #if defined(nginx_version) && nginx_version >= 1003014 # if nginx_version >= 1009000 ngx_set_connection_log(fc, clcf->error_log); # else ngx_http_set_connection_log(fc, clcf->error_log); # endif #else fc->log->file = clcf->error_log->file; if (!(fc->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { fc->log->log_level = clcf->error_log->log_level; } #endif if (cctx == NULL) { cctx = ngx_pcalloc(c->pool, sizeof(ngx_http_lua_ssl_ctx_t)); if (cctx == NULL) { goto failed; /* error */ } } cctx->exit_code = 1; /* successful by default */ cctx->connection = c; cctx->request = r; cctx->session_id.data = id; cctx->session_id.len = len; cctx->entered_sess_fetch_handler = 1; cctx->done = 0; dd("setting cctx = %p", cctx); if (SSL_set_ex_data(c->ssl->connection, ngx_http_lua_ssl_ctx_index, cctx) == 0) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed"); goto failed; } lscf = ngx_http_get_module_srv_conf(r, ngx_http_lua_module); /* TODO honor lua_code_cache off */ L = ngx_http_lua_get_lua_vm(r, NULL); c->log->action = "fetching SSL session by lua"; rc = lscf->srv.ssl_sess_fetch_handler(r, lscf, L); if (rc >= NGX_OK || rc == NGX_ERROR) { cctx->done = 1; if (cctx->cleanup) { *cctx->cleanup = NULL; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl_session_fetch_by_lua*: handler return value: %i, " "sess get cb exit code: %d", rc, cctx->exit_code); c->log->action = "SSL handshaking"; return cctx->session; } /* rc == NGX_DONE */ cln = ngx_pool_cleanup_add(fc->pool, 0); if (cln == NULL) { goto failed; } cln->handler = ngx_http_lua_ssl_sess_fetch_done; cln->data = cctx; if (cctx->cleanup == NULL) { /* we only want exactly one cleanup handler to be registered with the * connection to clean up cctx when connection is aborted */ cln = ngx_pool_cleanup_add(c->pool, 0); if (cln == NULL) { goto failed; } cln->data = cctx; cctx->cleanup = &cln->handler; } *cctx->cleanup = ngx_http_lua_ssl_sess_fetch_aborted; #ifdef SSL_ERROR_PENDING_SESSION return SSL_magic_pending_session_ptr(); #else ngx_log_error(NGX_LOG_CRIT, c->log, 0, "lua: cannot yield in sess get cb: " "missing async sess get cb support in OpenSSL"); /* fall through to the "failed" label below */ #endif failed: if (r && r->pool) { ngx_http_lua_free_fake_request(r); } if (fc) { ngx_http_lua_close_fake_connection(fc); } return NULL; }