--- embedaddon/lighttpd/src/mod_access.c 2013/10/14 10:32:48 1.1 +++ embedaddon/lighttpd/src/mod_access.c 2016/11/02 10:35:00 1.1.1.3 @@ -1,3 +1,5 @@ +#include "first.h" + #include "base.h" #include "log.h" #include "buffer.h" @@ -9,6 +11,7 @@ #include typedef struct { + array *access_allow; array *access_deny; } plugin_config; @@ -40,6 +43,9 @@ FREE_FUNC(mod_access_free) { for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; + if (NULL == s) continue; + + array_free(s->access_allow); array_free(s->access_deny); free(s); @@ -58,22 +64,26 @@ SETDEFAULTS_FUNC(mod_access_set_defaults) { config_values_t cv[] = { { "url.access-deny", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, + { "url.access-allow", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); + p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *)); for (i = 0; i < srv->config_context->used; i++) { + data_config const* config = (data_config const*)srv->config_context->data[i]; plugin_config *s; s = calloc(1, sizeof(plugin_config)); s->access_deny = array_init(); + s->access_allow = array_init(); cv[0].destination = s->access_deny; + cv[1].destination = s->access_allow; p->config_storage[i] = s; - if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) { + if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) { return HANDLER_ERROR; } } @@ -87,6 +97,7 @@ static int mod_access_patch_connection(server *srv, co size_t i, j; plugin_config *s = p->config_storage[0]; + PATCH(access_allow); PATCH(access_deny); /* skip the first, the global context */ @@ -103,6 +114,8 @@ static int mod_access_patch_connection(server *srv, co if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-deny"))) { PATCH(access_deny); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-allow"))) { + PATCH(access_allow); } } } @@ -125,25 +138,62 @@ URIHANDLER_FUNC(mod_access_uri_handler) { int s_len; size_t k; - if (con->uri.path->used == 0) return HANDLER_GO_ON; + if (buffer_is_empty(con->uri.path)) return HANDLER_GO_ON; mod_access_patch_connection(srv, con, p); - s_len = con->uri.path->used - 1; + s_len = buffer_string_length(con->uri.path); if (con->conf.log_request_handling) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "-- mod_access_uri_handler called"); } + for (k = 0; k < p->conf.access_allow->used; ++k) { + data_string *ds = (data_string *)p->conf.access_allow->data[k]; + int ct_len = buffer_string_length(ds->value); + int allowed = 0; + + if (ct_len > s_len) continue; + if (buffer_is_empty(ds->value)) continue; + + /* if we have a case-insensitive FS we have to lower-case the URI here too */ + + if (con->conf.force_lowercase_filenames) { + if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) { + allowed = 1; + } + } else { + if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) { + allowed = 1; + } + } + + if (allowed) { + return HANDLER_GO_ON; + } + } + + if (k > 0) { /* have access_allow but none matched */ + con->http_status = 403; + con->mode = DIRECT; + + if (con->conf.log_request_handling) { + log_error_write(srv, __FILE__, __LINE__, "sb", + "url denied as failed to match any from access_allow", con->uri.path); + } + + return HANDLER_FINISHED; + } + for (k = 0; k < p->conf.access_deny->used; k++) { data_string *ds = (data_string *)p->conf.access_deny->data[k]; - int ct_len = ds->value->used - 1; + int ct_len = buffer_string_length(ds->value); int denied = 0; if (ct_len > s_len) continue; - if (ds->value->used == 0) continue; + if (buffer_is_empty(ds->value)) continue; /* if we have a case-insensitive FS we have to lower-case the URI here too */