diff options
Diffstat (limited to 'src/configfile-glue.c')
-rw-r--r-- | src/configfile-glue.c | 675 |
1 files changed, 0 insertions, 675 deletions
diff --git a/src/configfile-glue.c b/src/configfile-glue.c deleted file mode 100644 index 8a31e333..00000000 --- a/src/configfile-glue.c +++ /dev/null @@ -1,675 +0,0 @@ -#include <string.h> -#include <ctype.h> - -#include "base.h" -#include "buffer.h" -#include "array.h" -#include "log.h" -#include "plugin.h" -#include "configfile.h" - -/** - * like all glue code this file contains functions which - * are the external interface of lighttpd. The functions - * are used by the server itself and the plugins. - * - * The main-goal is to have a small library in the end - * which is linked against both and which will define - * the interface itself in the end. - * - */ - - -/* handle global options */ - -/* parse config array */ -int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) { - size_t i; - data_unset *du; - - for (i = 0; cv[i].key; i++) { - - if (NULL == (du = array_get_element(ca, cv[i].key, strlen(cv[i].key)))) { - /* no found */ - - continue; - } - - switch (cv[i].type) { - case T_CONFIG_ARRAY: - if (du->type == TYPE_ARRAY) { - size_t j; - data_array *da = (data_array *)du; - - for (j = 0; j < da->value->used; j++) { - if (da->value->data[j]->type == TYPE_STRING) { - data_string *ds; - - if (NULL == (ds = (data_string *)array_get_unused_element(cv[i].destination, TYPE_STRING))) { - ds = data_string_init(); - } - - buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value); - if (!da->is_index_key) { - /* the id's were generated automaticly, as we copy now we might have to renumber them - * this is used to prepend server.modules by mod_indexfile as it has to be loaded - * before mod_fastcgi and friends */ - buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key); - } - - array_insert_unique(cv[i].destination, (data_unset *)ds); - } else { - log_error_write(srv, __FILE__, __LINE__, "sssd", - "the key of an array can only be a string or a integer, variable:", - cv[i].key, "type:", da->value->data[j]->type); - - return -1; - } - } - } else { - log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings"); - - return -1; - } - break; - case T_CONFIG_STRING: - if (du->type == TYPE_STRING) { - data_string *ds = (data_string *)du; - - buffer_copy_string_buffer(cv[i].destination, ds->value); - } else if (du->type == TYPE_INTEGER) { - data_integer *di = (data_integer *)du; - - buffer_copy_long(cv[i].destination, di->value); - } else { - log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\""); - - return -1; - } - break; - case T_CONFIG_SHORT: - switch(du->type) { - case TYPE_INTEGER: { - data_integer *di = (data_integer *)du; - - *((unsigned short *)(cv[i].destination)) = di->value; - break; - } - case TYPE_STRING: { - data_string *ds = (data_string *)du; - - if (buffer_isdigit(ds->value)) { - *((unsigned short *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10); - break; - } - - log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected a short:", cv[i].key, ds->value); - - return -1; - } - default: - log_error_write(srv, __FILE__, __LINE__, "ssds", "unexpected type for key:", cv[i].key, du->type, "expected a short integer, range 0 ... 65535"); - return -1; - } - break; - case T_CONFIG_INT: - switch(du->type) { - case TYPE_INTEGER: { - data_integer *di = (data_integer *)du; - - *((unsigned int *)(cv[i].destination)) = di->value; - break; - } - case TYPE_STRING: { - data_string *ds = (data_string *)du; - - if (buffer_isdigit(ds->value)) { - *((unsigned int *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10); - break; - } - - log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected a integer:", cv[i].key, ds->value); - - return -1; - } - default: - log_error_write(srv, __FILE__, __LINE__, "ssds", "unexpected type for key:", cv[i].key, du->type, "expected a integer, range 0 ... 4294967295"); - return -1; - } - break; - case T_CONFIG_BOOLEAN: - if (du->type == TYPE_STRING) { - data_string *ds = (data_string *)du; - - if (buffer_is_equal_string(ds->value, CONST_STR_LEN("enable"))) { - *((unsigned short *)(cv[i].destination)) = 1; - } else if (buffer_is_equal_string(ds->value, CONST_STR_LEN("disable"))) { - *((unsigned short *)(cv[i].destination)) = 0; - } else { - log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)"); - - return -1; - } - } else { - log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\""); - - return -1; - } - break; - case T_CONFIG_LOCAL: - case T_CONFIG_UNSET: - break; - case T_CONFIG_UNSUPPORTED: - ERROR("found unsupported key in '%s' = '%s'", cv[i].key, (char *)(cv[i].destination)); - - srv->config_unsupported = 1; - - break; - case T_CONFIG_DEPRECATED: - ERROR("found deprecated key in '%s' = '%s'", cv[i].key, (char *)(cv[i].destination)); - - srv->config_deprecated = 1; - - break; - } - } - return 0; -} - -int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) { - size_t i; - data_unset *du; - - for (i = 0; cv[i].key; i++) { - data_string *touched; - - if (NULL == (du = array_get_element(ca, cv[i].key, strlen(cv[i].key)))) { - /* no found */ - - continue; - } - - /* touched */ - touched = data_string_init(); - - buffer_copy_string_len(touched->value, CONST_STR_LEN("")); - buffer_copy_string_buffer(touched->key, du->key); - - array_insert_unique(srv->config_touched, (data_unset *)touched); - } - - return config_insert_values_internal(srv, ca, cv); -} - -unsigned short sock_addr_get_port(sock_addr *addr) { - switch (addr->plain.sa_family) { - case AF_INET: - return ntohs(addr->ipv4.sin_port); -#ifdef HAVE_IPV6 - case AF_INET6: - return ntohs(addr->ipv6.sin6_port); -#endif - default: - return 0; - } -} - -static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc); - -static cond_result_t config_check_cond_nocache(server *srv, connection *con, data_config *dc) { - buffer *l; - server_socket *srv_sock = con->srv_socket; - /* check parent first */ - if (dc->parent && dc->parent->context_ndx) { - if (con->conf.log_condition_handling) { - TRACE("checking if the parent (%s) evaluates to 'true'", SAFE_BUF_STR(dc->parent->key)); - } - - switch (config_check_cond_cached(srv, con, dc->parent)) { - case COND_RESULT_FALSE: - return COND_RESULT_FALSE; - case COND_RESULT_UNSET: - return COND_RESULT_UNSET; - default: - break; - } - } - - if (dc->prev) { - if (con->conf.log_condition_handling) { - TRACE("triggering eval of successors of (%s) [in else]", SAFE_BUF_STR(dc->key)); - } - - /* make sure prev is checked first */ - config_check_cond_cached(srv, con, dc->prev); - - if (con->conf.log_condition_handling) { - TRACE("(%s) [in else] -> %s", SAFE_BUF_STR(dc->key), con->cond_cache[dc->context_ndx].result == COND_RESULT_FALSE ? "false" : "we will see"); - } - - switch (con->cond_cache[dc->context_ndx].result) { - case COND_RESULT_FALSE: /* one of prev set me to FALSE */ - return con->cond_cache[dc->context_ndx].result; - default: - break; - } - } - - if (!con->conditional_is_valid[dc->comp]) { - if (con->conf.log_condition_handling) { - TRACE("is condition [%d] (%s) already valid ? %s", - dc->comp, - SAFE_BUF_STR(dc->key), - con->conditional_is_valid[dc->comp] ? "yeah" : "nej"); - } - - return COND_RESULT_UNSET; - } - - /* pass the rules */ - - switch (dc->comp) { - case COMP_HTTP_HOST: { - char *ck_colon = NULL, *val_colon = NULL; - - if (!buffer_is_empty(con->uri.authority)) { - - /* - * append server-port to the HTTP_POST if necessary - */ - - l = con->uri.authority; - - switch(dc->cond) { - case CONFIG_COND_NE: - case CONFIG_COND_EQ: - ck_colon = strchr(dc->string->ptr, ':'); - val_colon = strchr(l->ptr, ':'); - - if (NULL != ck_colon && NULL == val_colon) { - /* condition "host:port" but client send "host" */ - buffer_copy_string_buffer(srv->cond_check_buf, l); - buffer_append_string_len(srv->cond_check_buf, CONST_STR_LEN(":")); - buffer_append_long(srv->cond_check_buf, sock_addr_get_port(&(srv_sock->addr))); - l = srv->cond_check_buf; - } else if (NULL != val_colon && NULL == ck_colon) { - /* condition "host" but client send "host:port" */ - buffer_copy_string_len(srv->cond_check_buf, l->ptr, val_colon - l->ptr); - l = srv->cond_check_buf; - } - break; - default: - break; - } -#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT - } else if (!buffer_is_empty(con->sock->tlsext_server_name)) { - l = con->sock->tlsext_server_name; -#endif - } else { - l = srv->empty_string; - } - break; - } - case COMP_HTTP_REMOTE_IP: { - char *nm_slash; - /* handle remoteip limitations - * - * "10.0.0.1" is provided for all comparisions - * - * only for == and != we support - * - * "10.0.0.1/24" - */ - - if ((dc->cond == CONFIG_COND_EQ || - dc->cond == CONFIG_COND_NE) && - (con->dst_addr.plain.sa_family == AF_INET) && - (NULL != (nm_slash = strchr(dc->string->ptr, '/')))) { - int nm_bits; - long nm; - char *err; - struct in_addr val_inp; - - if (con->conf.log_condition_handling) { - l = srv->empty_string; - - log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key, - "(", l, ") compare to", dc->string); - } - - if (*(nm_slash+1) == '\0') { - log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string); - - return COND_RESULT_FALSE; - } - - nm_bits = strtol(nm_slash + 1, &err, 10); - - if (*err) { - log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, *err); - - return COND_RESULT_FALSE; - } - - /* take IP convert to the native */ - buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr); -#ifdef _WIN32 - if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) { - log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf); - - return COND_RESULT_FALSE; - } - -#else - if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) { - log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf); - - return COND_RESULT_FALSE; - } -#endif - - /* build netmask */ - nm = htonl(~((1 << (32 - nm_bits)) - 1)); - - if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) { - return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE; - } else { - return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE; - } - } else { - l = con->dst_addr_buf; - } - break; - } - case COMP_HTTP_SCHEME: - l = con->uri.scheme; - break; - - case COMP_HTTP_URL: - l = con->uri.path; - break; - - case COMP_HTTP_QUERY_STRING: - l = con->uri.query; - break; - - case COMP_SERVER_SOCKET: - l = srv_sock->srv_token; - break; - - case COMP_HTTP_REFERER: { - data_string *ds; - - if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Referer")))) { - l = ds->value; - } else { - l = srv->empty_string; - } - break; - } - case COMP_HTTP_COOKIE: { - data_string *ds; - if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Cookie")))) { - l = ds->value; - } else { - l = srv->empty_string; - } - break; - } - case COMP_HTTP_USER_AGENT: { - data_string *ds; - if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("User-Agent")))) { - l = ds->value; - } else { - l = srv->empty_string; - } - break; - } - case COMP_HTTP_REQUEST_METHOD: { - const char *method = get_http_method_name(con->request.http_method); - - /* we only have the request method as const char but we need a buffer for comparing */ - - buffer_copy_string(srv->tmp_buf, method); - - l = srv->tmp_buf; - - break; - } - case COMP_PHYSICAL_PATH_EXISTS: - case COMP_PHYSICAL_PATH: - l = con->physical.path; - break; - default: - return COND_RESULT_FALSE; - } - - if (NULL == l) { - if (con->conf.log_condition_handling) { - log_error_write(srv, __FILE__, __LINE__, "bsbs", dc->comp_key, - "(", l, ") compare to NULL"); - } - return COND_RESULT_FALSE; - } - - if (con->conf.log_condition_handling) { - TRACE("'%s': '%s' is matched against '%s'", - SAFE_BUF_STR(dc->comp_key), - SAFE_BUF_STR(l), - SAFE_BUF_STR(dc->string)); - } - - switch(dc->cond) { - case CONFIG_COND_NE: - case CONFIG_COND_EQ: - if (buffer_is_equal(l, dc->string)) { - return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE; - } else { - return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE; - } - break; -#ifdef HAVE_PCRE_H - case CONFIG_COND_NOMATCH: - case CONFIG_COND_MATCH: { - cond_cache_t *cache = &con->cond_cache[dc->context_ndx]; - int n; - -#ifndef elementsof -#define elementsof(x) (sizeof(x) / sizeof(x[0])) -#endif - n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0, - cache->matches, elementsof(cache->matches)); - - cache->patterncount = n; - if (n > 0) { - cache->comp_value = l; - cache->comp_type = dc->comp; - - return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE; - } else { - /* cache is already cleared */ - return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_FALSE : COND_RESULT_TRUE; - } - break; - } -#endif - default: - /* no way */ - break; - } - - return COND_RESULT_FALSE; -} - -static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc) { - cond_cache_t *caches = con->cond_cache; - - if (COND_RESULT_UNSET == caches[dc->context_ndx].result) { - if (con->conf.log_condition_handling) { - TRACE("=== start of %d condition block ===", dc->context_ndx); - } - if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) { - /* a node evaluted to true, all else nodes have to false */ - if (dc->next) { - data_config *c; - if (con->conf.log_condition_handling) { - TRACE("setting remains of chaining to %s", "false"); - } - for (c = dc->next; c; c = c->next) { - caches[c->context_ndx].result = COND_RESULT_FALSE; - } - } - } - caches[dc->context_ndx].comp_type = dc->comp; - - if (con->conf.log_condition_handling) { - TRACE("[%d] result: %s", - dc->context_ndx, - caches[dc->context_ndx].result == COND_RESULT_UNSET ? "unknown" : - (caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false") - ); - } - } else { - if (con->conf.log_condition_cache_handling) { - TRACE("[%d] (cached) result: %s", - dc->context_ndx, - caches[dc->context_ndx].result == COND_RESULT_UNSET ? "unknown" : - (caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false") - ); - } - } - - return caches[dc->context_ndx].result; -} - -/** - * reset the config-cache for a named item - * - * if the item is COND_LAST_ELEMENT we reset all items - */ -void config_cond_cache_reset_item(server *srv, connection *con, comp_key_t item) { - size_t i; - - for (i = 0; i < srv->config_context->used; i++) { - if (item == COMP_LAST_ELEMENT || - con->cond_cache[i].comp_type == item) { - con->cond_cache[i].result = COND_RESULT_UNSET; - con->cond_cache[i].patterncount = 0; - con->cond_cache[i].comp_value = NULL; - } - } -} - -/** - * reset the config cache to its initial state at connection start - */ -void config_cond_cache_reset(server *srv, connection *con) { - size_t i; - - config_cond_cache_reset_all_items(srv, con); - - for (i = 0; i < COMP_LAST_ELEMENT; i++) { - con->conditional_is_valid[i] = 0; - } -} - -int config_check_cond(server *srv, connection *con, data_config *dc) { - return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE); -} - -int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n) -{ - cond_cache_t *cache = &con->cond_cache[dc->context_ndx]; - if (n >= cache->patterncount) { - return 0; - } - - n <<= 1; /* n *= 2 */ - buffer_append_string_len(buf, - cache->comp_value->ptr + cache->matches[n], - cache->matches[n + 1] - cache->matches[n]); - return 1; -} - -/* return <0 on error - * return 0-x if matched (and replaced) - */ -int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result) -{ -#ifdef HAVE_PCRE_H - pcre *match; - pcre_extra *extra; - const char *pattern; - size_t pattern_len; - int n; - size_t i; - pcre_keyvalue *kv; -# define N 10 - int ovec[N * 3]; - - for (i = 0; i < kvb->used; i++) { - kv = kvb->kv[i]; - - match = kv->key; - extra = kv->key_extra; - pattern = kv->value->ptr; - pattern_len = kv->value->used - 1; - - if ((n = pcre_exec(match, extra, match_buf->ptr, match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) { - if (n != PCRE_ERROR_NOMATCH) { - return n; - } - } else { - const char **list; - size_t start, end; - size_t k; - - /* it matched */ - pcre_get_substring_list(match_buf->ptr, ovec, n, &list); - - /* search for $[0-9] */ - - buffer_reset(result); - - start = 0; end = pattern_len; - for (k = 0; k < pattern_len; k++) { - if ((pattern[k] == '$' || pattern[k] == '%') && - isdigit((unsigned char)pattern[k + 1])) { - /* got one */ - - size_t num = pattern[k + 1] - '0'; - - end = k; - - buffer_append_string_len(result, pattern + start, end - start); - - if (pattern[k] == '$') { - /* n is always > 0 */ - if (num < (size_t)n) { - buffer_append_string(result, list[num]); - } - } else { - config_append_cond_match_buffer(con, context, result, num); - } - - k++; - start = k + 1; - } - } - - buffer_append_string_len(result, pattern + start, pattern_len - start); - - pcre_free(list); - - return i; - } - } - - return PCRE_ERROR_NOMATCH; -#undef N -#else - UNUSED(kvb); - return -2; -#endif -} - |