import Variable-* from FastCGI authorizer response into con->environment restart request after FastCGI authorizer if no fastcgi.server docroot (thx Christoph Kreutzer for initial patch attempt) x-ref: "mod_fastcgi authorizers cannot protect fastcgi responders" http://redmine.lighttpd.net/issues/321 x-ref: "FastCGI Authorizer support for Variable-name variable passing" http://redmine.lighttpd.net/issues/322 github: closes #70
This commit is contained in:
parent
5dfe21acc9
commit
2dcfe1733e
|
@ -333,6 +333,7 @@ typedef struct {
|
|||
fcgi_proc *proc;
|
||||
fcgi_extension_host *host;
|
||||
fcgi_extension *ext;
|
||||
fcgi_extension *ext_auth;
|
||||
|
||||
fcgi_connection_state_t state;
|
||||
time_t state_timestamp;
|
||||
|
@ -501,11 +502,8 @@ static handler_ctx * handler_ctx_init(void) {
|
|||
return hctx;
|
||||
}
|
||||
|
||||
static void handler_ctx_free(server *srv, handler_ctx *hctx) {
|
||||
if (hctx->host) {
|
||||
fcgi_host_reset(srv, hctx);
|
||||
}
|
||||
|
||||
static void handler_ctx_free(handler_ctx *hctx) {
|
||||
/* caller MUST have called fcgi_backend_close(srv, hctx) if necessary */
|
||||
buffer_free(hctx->response_header);
|
||||
|
||||
chunkqueue_free(hctx->rb);
|
||||
|
@ -514,6 +512,37 @@ static void handler_ctx_free(server *srv, handler_ctx *hctx) {
|
|||
free(hctx);
|
||||
}
|
||||
|
||||
static void handler_ctx_clear(handler_ctx *hctx) {
|
||||
/* caller MUST have called fcgi_backend_close(srv, hctx) if necessary */
|
||||
|
||||
hctx->proc = NULL;
|
||||
hctx->host = NULL;
|
||||
hctx->ext = NULL;
|
||||
/*hctx->ext_auth is intentionally preserved to flag that auth occurred*/
|
||||
|
||||
hctx->state = FCGI_STATE_INIT;
|
||||
/*hctx->state_timestamp = 0;*//*(unused; left as-is)*/
|
||||
|
||||
chunkqueue_reset(hctx->rb);
|
||||
chunkqueue_reset(hctx->wb);
|
||||
hctx->wb_reqlen = 0;
|
||||
|
||||
buffer_reset(hctx->response_header);
|
||||
|
||||
hctx->fd = -1;
|
||||
hctx->fde_ndx = -1;
|
||||
/*hctx->pid = -1;*//*(unused; left as-is)*/
|
||||
hctx->got_proc = 0;
|
||||
hctx->reconnects = 0;
|
||||
hctx->request_id = 0;
|
||||
hctx->send_content_body = 1;
|
||||
|
||||
/*plugin_config conf;*//*(no need to reset for same request)*/
|
||||
|
||||
/*hctx->remote_conn = NULL;*//*(no need to reset for same request)*/
|
||||
/*hctx->plugin_data = NULL;*//*(no need to reset for same request)*/
|
||||
}
|
||||
|
||||
static fcgi_proc *fastcgi_process_init(void) {
|
||||
fcgi_proc *f;
|
||||
|
||||
|
@ -1511,11 +1540,6 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
|
|||
host->mode = FCGI_RESPONDER;
|
||||
} else if (strcmp(fcgi_mode->ptr, "authorizer") == 0) {
|
||||
host->mode = FCGI_AUTHORIZER;
|
||||
if (buffer_string_is_empty(host->docroot)) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "s",
|
||||
"ERROR: docroot is required for authorizer mode.");
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sbs",
|
||||
"WARNING: unknown fastcgi mode:",
|
||||
|
@ -1567,25 +1591,20 @@ static int fcgi_set_state(server *srv, handler_ctx *hctx, fcgi_connection_state_
|
|||
}
|
||||
|
||||
|
||||
static void fcgi_connection_close(server *srv, handler_ctx *hctx) {
|
||||
plugin_data *p;
|
||||
connection *con;
|
||||
|
||||
p = hctx->plugin_data;
|
||||
con = hctx->remote_conn;
|
||||
|
||||
static void fcgi_backend_close(server *srv, handler_ctx *hctx) {
|
||||
if (hctx->fd != -1) {
|
||||
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
|
||||
fdevent_unregister(srv->ev, hctx->fd);
|
||||
fdevent_sched_close(srv->ev, hctx->fd, 1);
|
||||
hctx->fd = -1;
|
||||
}
|
||||
|
||||
if (hctx->host && hctx->proc) {
|
||||
if (hctx->got_proc) {
|
||||
if (hctx->host) {
|
||||
if (hctx->proc && hctx->got_proc) {
|
||||
/* after the connect the process gets a load */
|
||||
fcgi_proc_load_dec(srv, hctx);
|
||||
|
||||
if (p->conf.debug) {
|
||||
if (hctx->plugin_data->conf.debug) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
|
||||
"released proc:",
|
||||
"pid:", hctx->proc->pid,
|
||||
|
@ -1593,10 +1612,20 @@ static void fcgi_connection_close(server *srv, handler_ctx *hctx) {
|
|||
"load:", hctx->proc->load);
|
||||
}
|
||||
}
|
||||
|
||||
fcgi_host_reset(srv, hctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void fcgi_connection_close(server *srv, handler_ctx *hctx) {
|
||||
plugin_data *p;
|
||||
connection *con;
|
||||
|
||||
handler_ctx_free(srv, hctx);
|
||||
p = hctx->plugin_data;
|
||||
con = hctx->remote_conn;
|
||||
|
||||
fcgi_backend_close(srv, hctx);
|
||||
handler_ctx_free(hctx);
|
||||
con->plugin_ctx[p->id] = NULL;
|
||||
|
||||
/* finish response (if not already con->file_started, con->file_finished) */
|
||||
|
@ -2244,6 +2273,19 @@ static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buf
|
|||
}
|
||||
}
|
||||
|
||||
if (host->mode == FCGI_AUTHORIZER &&
|
||||
key_len > 9 &&
|
||||
0 == strncasecmp(key, CONST_STR_LEN("Variable-"))) {
|
||||
data_string *ds;
|
||||
if (NULL == (ds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
|
||||
ds = data_response_init();
|
||||
}
|
||||
buffer_copy_string_len(ds->key, key + 9, key_len - 9);
|
||||
buffer_copy_string(ds->value, value);
|
||||
|
||||
array_insert_unique(con->environment, (data_unset *)ds);
|
||||
}
|
||||
|
||||
switch(key_len) {
|
||||
case 4:
|
||||
if (0 == strncasecmp(key, "Date", key_len)) {
|
||||
|
@ -3233,9 +3275,16 @@ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
|
|||
}
|
||||
}
|
||||
|
||||
if (0 == hctx->wb->bytes_in
|
||||
? con->state == CON_STATE_READ_POST
|
||||
: hctx->wb->bytes_in < hctx->wb_reqlen) {
|
||||
/* (do not receive request body before FCGI_AUTHORIZER has run or else
|
||||
* the request body is discarded with fcgi_connection_close() of the
|
||||
* FastCGI Authorizer)
|
||||
* (hctx->host might not be assigned yet, so check first host in list
|
||||
* of potential hosts (hctx->ext->hosts[0]->mode != FCGI_AUTHORIZER))*/
|
||||
|
||||
if (hctx->ext->hosts[0]->mode != FCGI_AUTHORIZER
|
||||
&& (0 == hctx->wb->bytes_in
|
||||
? con->state == CON_STATE_READ_POST
|
||||
: hctx->wb->bytes_in < hctx->wb_reqlen)) {
|
||||
/*(64k - 4k to attempt to avoid temporary files
|
||||
* in conjunction with FDEVENT_STREAM_REQUEST_BUFMIN)*/
|
||||
if (hctx->wb->bytes_in - hctx->wb->bytes_out > 65536 - 4096
|
||||
|
@ -3282,17 +3331,39 @@ static handler_t fcgi_recv_response(server *srv, handler_ctx *hctx) {
|
|||
* was processed already, and status 200 has been returned. We need
|
||||
* now to handle authorized request.
|
||||
*/
|
||||
buffer *physpath = NULL;
|
||||
|
||||
buffer_copy_buffer(con->physical.doc_root, host->docroot);
|
||||
buffer_copy_buffer(con->physical.basedir, host->docroot);
|
||||
if (!buffer_string_is_empty(host->docroot)) {
|
||||
buffer_copy_buffer(con->physical.doc_root, host->docroot);
|
||||
buffer_copy_buffer(con->physical.basedir, host->docroot);
|
||||
|
||||
buffer_copy_buffer(con->physical.path, host->docroot);
|
||||
buffer_append_string_buffer(con->physical.path, con->uri.path);
|
||||
buffer_copy_buffer(con->physical.path, host->docroot);
|
||||
buffer_append_string_buffer(con->physical.path, con->uri.path);
|
||||
physpath = con->physical.path;
|
||||
}
|
||||
|
||||
con->mode = DIRECT;/*(avoid changing con->state, con->http_status)*/
|
||||
fcgi_connection_close(srv, hctx);
|
||||
con->http_status = 0;
|
||||
con->file_started = 1; /* fcgi_extension won't touch the request afterwards */
|
||||
fcgi_backend_close(srv, hctx);
|
||||
handler_ctx_clear(hctx);
|
||||
|
||||
/* don't do more than 6 loops here, that normally shouldn't happen */
|
||||
if (++con->loops_per_request > 5) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb", "too many loops while processing request:", con->request.orig_uri);
|
||||
con->http_status = 500; /* Internal Server Error */
|
||||
con->mode = DIRECT;
|
||||
return HANDLER_FINISHED;
|
||||
}
|
||||
|
||||
/* restart the request so other handlers can process it */
|
||||
|
||||
if (physpath) con->physical.path = NULL;
|
||||
connection_response_reset(srv, con); /*(includes con->http_status = 0)*/
|
||||
if (physpath) con->physical.path = physpath; /* preserve con->physical.path with modified docroot */
|
||||
|
||||
/*(FYI: if multiple FastCGI authorizers were to be supported,
|
||||
* next one could be started here instead of restarting request)*/
|
||||
|
||||
con->mode = DIRECT;
|
||||
return HANDLER_COMEBACK;
|
||||
} else {
|
||||
/* we are done */
|
||||
fcgi_connection_close(srv, hctx);
|
||||
|
@ -3486,12 +3557,11 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i
|
|||
buffer *fn;
|
||||
fcgi_extension *extension = NULL;
|
||||
fcgi_extension_host *host = NULL;
|
||||
handler_ctx *hctx;
|
||||
fcgi_extension *ext_auth;
|
||||
|
||||
if (con->mode != DIRECT) return HANDLER_GO_ON;
|
||||
|
||||
/* Possibly, we processed already this request */
|
||||
if (con->file_started == 1) return HANDLER_GO_ON;
|
||||
|
||||
fn = uri_path_handler ? con->uri.path : con->physical.path;
|
||||
|
||||
if (buffer_string_is_empty(fn)) return HANDLER_GO_ON;
|
||||
|
@ -3500,6 +3570,9 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i
|
|||
|
||||
fcgi_patch_connection(srv, con, p);
|
||||
|
||||
hctx = con->plugin_ctx[p->id]; /*(not NULL if FCGI_AUTHORIZER ran)*/
|
||||
ext_auth = hctx ? hctx->ext_auth : NULL;
|
||||
|
||||
/* fastcgi.map-extensions maps extensions to existing fastcgi.server entries
|
||||
*
|
||||
* fastcgi.map-extensions = ( ".php3" => ".php" )
|
||||
|
@ -3528,7 +3601,8 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i
|
|||
extension = p->conf.exts->exts[k];
|
||||
|
||||
if (buffer_is_equal(ds->value, extension->key)) {
|
||||
break;
|
||||
/* do not reuse same authorizer; skip if ext matches ext_auth */
|
||||
if (extension != ext_auth) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3550,6 +3624,9 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i
|
|||
|
||||
if (buffer_is_empty(ext->key)) continue;
|
||||
|
||||
/* do not reuse same authorizer; skip if ext matches ext_auth */
|
||||
if (ext == ext_auth) continue;
|
||||
|
||||
ct_len = buffer_string_length(ext->key);
|
||||
|
||||
/* check _url_ in the form "/fcgi_pattern" */
|
||||
|
@ -3613,30 +3690,9 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i
|
|||
|
||||
/* init handler-context */
|
||||
if (uri_path_handler) {
|
||||
if (host->check_local == 0) {
|
||||
handler_ctx *hctx;
|
||||
char *pathinfo;
|
||||
|
||||
hctx = handler_ctx_init();
|
||||
|
||||
hctx->remote_conn = con;
|
||||
hctx->plugin_data = p;
|
||||
hctx->proc = NULL;
|
||||
hctx->ext = extension;
|
||||
|
||||
|
||||
hctx->conf.exts = p->conf.exts;
|
||||
hctx->conf.debug = p->conf.debug;
|
||||
|
||||
con->plugin_ctx[p->id] = hctx;
|
||||
|
||||
con->mode = p->id;
|
||||
|
||||
if (con->conf.log_request_handling) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "s",
|
||||
"handling it in mod_fastcgi");
|
||||
}
|
||||
|
||||
if (host->check_local != 0) {
|
||||
return HANDLER_GO_ON;
|
||||
} else {
|
||||
/* do not split path info for authorizer */
|
||||
if (host->mode != FCGI_AUTHORIZER) {
|
||||
/* the prefix is the SCRIPT_NAME,
|
||||
|
@ -3665,6 +3721,7 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i
|
|||
* PATH_INFO = /bar
|
||||
*
|
||||
*/
|
||||
char *pathinfo;
|
||||
|
||||
/* the rewrite is only done for /prefix/? matches */
|
||||
if (host->fix_root_path_name && extension->key->ptr[0] == '/' && extension->key->ptr[1] == '\0') {
|
||||
|
@ -3680,25 +3737,28 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handler_ctx *hctx;
|
||||
hctx = handler_ctx_init();
|
||||
}
|
||||
|
||||
hctx->remote_conn = con;
|
||||
hctx->plugin_data = p;
|
||||
hctx->proc = NULL;
|
||||
hctx->ext = extension;
|
||||
if (!hctx) hctx = handler_ctx_init();
|
||||
|
||||
hctx->conf.exts = p->conf.exts;
|
||||
hctx->conf.debug = p->conf.debug;
|
||||
hctx->remote_conn = con;
|
||||
hctx->plugin_data = p;
|
||||
hctx->proc = NULL;
|
||||
hctx->ext = extension;
|
||||
|
||||
con->plugin_ctx[p->id] = hctx;
|
||||
hctx->conf.exts = p->conf.exts;
|
||||
hctx->conf.debug = p->conf.debug;
|
||||
|
||||
con->mode = p->id;
|
||||
if (host->mode == FCGI_AUTHORIZER) {
|
||||
hctx->ext_auth = hctx->ext; /* save pointer to authorizer ext */
|
||||
}
|
||||
|
||||
if (con->conf.log_request_handling) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
|
||||
}
|
||||
con->plugin_ctx[p->id] = hctx;
|
||||
|
||||
con->mode = p->id;
|
||||
|
||||
if (con->conf.log_request_handling) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
|
||||
}
|
||||
|
||||
return HANDLER_GO_ON;
|
||||
|
|
Loading…
Reference in New Issue