From ec2cb646eff482dfe32955d01781b01211b0a77c Mon Sep 17 00:00:00 2001 From: Arno Töll Date: Wed, 21 Nov 2012 23:03:39 +0100 Subject: Imported Upstream version 1.4.12~20060907 --- src/array.h | 26 +++++- src/base.h | 15 +++- src/configfile-glue.c | 25 +++++- src/configfile.c | 44 ++++++--- src/configparser.c | 232 +++++++++++++++++++++++++----------------------- src/configparser.y | 78 ++++++++-------- src/http-header-glue.c | 61 ++++++++----- src/mod_flv_streaming.c | 6 +- src/mod_staticfile.c | 13 +++ src/network.c | 18 ++++ src/proc_open.c | 24 +++-- src/response.c | 28 +++++- src/server.c | 17 ++-- src/stat_cache.c | 64 +++++++++++-- 14 files changed, 442 insertions(+), 209 deletions(-) (limited to 'src') diff --git a/src/array.h b/src/array.h index 27f27a4..b9687d7 100644 --- a/src/array.h +++ b/src/array.h @@ -66,12 +66,30 @@ typedef struct { data_array *data_array_init(void); -typedef enum { CONFIG_COND_UNSET, CONFIG_COND_EQ, CONFIG_COND_MATCH, CONFIG_COND_NE, CONFIG_COND_NOMATCH } config_cond_t; - -#define PATCHES NULL, "SERVERsocket", "HTTPurl", "HTTPhost", "HTTPreferer", "HTTPuseragent", "HTTPcookie", "HTTPremoteip" +/** + * possible compare ops in the configfile parser + */ +typedef enum { + CONFIG_COND_UNSET, + CONFIG_COND_EQ, /** == */ + CONFIG_COND_MATCH, /** =~ */ + CONFIG_COND_NE, /** != */ + CONFIG_COND_NOMATCH /** !~ */ +} config_cond_t; + +/** + * possible fields to match against + */ typedef enum { COMP_UNSET, - COMP_SERVER_SOCKET, COMP_HTTP_URL, COMP_HTTP_HOST, COMP_HTTP_REFERER, COMP_HTTP_USERAGENT, COMP_HTTP_COOKIE, COMP_HTTP_REMOTEIP + COMP_SERVER_SOCKET, + COMP_HTTP_URL, + COMP_HTTP_HOST, + COMP_HTTP_REFERER, + COMP_HTTP_USERAGENT, + COMP_HTTP_COOKIE, + COMP_HTTP_REMOTEIP, + COMP_HTTP_QUERYSTRING } comp_key_t; /* $HTTP["host"] == "incremental.home.kneschke.de" { ... } diff --git a/src/base.h b/src/base.h index 0b5ca76..654f2ed 100644 --- a/src/base.h +++ b/src/base.h @@ -86,7 +86,8 @@ typedef enum { T_CONFIG_UNSET, T_CONFIG_BOOLEAN, T_CONFIG_ARRAY, T_CONFIG_LOCAL, - T_CONFIG_DEPRECATED + T_CONFIG_DEPRECATED, + T_CONFIG_UNSUPPORTED } config_values_type_t; typedef enum { T_CONFIG_SCOPE_UNSET, @@ -206,6 +207,10 @@ typedef struct { time_t stat_ts; +#ifdef HAVE_LSTAT + char is_symlink; +#endif + #ifdef HAVE_FAM_H int dir_version; int dir_ndx; @@ -257,6 +262,9 @@ typedef struct { /* server wide */ buffer *ssl_pemfile; buffer *ssl_ca_file; + buffer *ssl_cipher_list; + unsigned short ssl_use_sslv2; + unsigned short use_ipv6; unsigned short is_ssl; unsigned short allow_http11; @@ -484,6 +492,8 @@ typedef struct { buffer *ssl_pemfile; buffer *ssl_ca_file; + buffer *ssl_cipher_list; + unsigned short ssl_use_sslv2; unsigned short use_ipv6; unsigned short is_ssl; @@ -567,7 +577,8 @@ typedef struct server { server_config srvconf; - int config_deprecated; + short int config_deprecated; + short int config_unsupported; connections *conns; connections *joblist; diff --git a/src/configfile-glue.c b/src/configfile-glue.c index 6401854..6d5132a 100644 --- a/src/configfile-glue.c +++ b/src/configfile-glue.c @@ -118,6 +118,12 @@ int config_insert_values_internal(server *srv, array *ca, const config_values_t break; case T_CONFIG_LOCAL: case T_CONFIG_UNSET: + break; + case T_CONFIG_UNSUPPORTED: + log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found unsupported key:", cv[i].key, "-", (char *)(cv[i].destination)); + + srv->config_unsupported = 1; + break; case T_CONFIG_DEPRECATED: log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination)); @@ -230,7 +236,7 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat break; } } else { - l = NULL; + l = srv->empty_string; } break; } @@ -302,6 +308,10 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat l = con->uri.path; break; + case COMP_HTTP_QUERYSTRING: + l = con->uri.query; + break; + case COMP_SERVER_SOCKET: l = srv_sock->srv_token; break; @@ -422,6 +432,19 @@ static cond_result_t config_check_cond_cached(server *srv, connection *con, data return caches[dc->context_ndx].result; } +void config_cond_cache_reset(server *srv, connection *con) { +#if COND_RESULT_UNSET + size_t i; + + for (i = srv->config_context->used - 1; i >= 0; i --) { + con->cond_cache[i].result = COND_RESULT_UNSET; + con->cond_cache[i].patterncount = 0; + } +#else + memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used); +#endif +} + int config_check_cond(server *srv, connection *con, data_config *dc) { if (con->conf.log_condition_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "=== start of condition block ==="); diff --git a/src/configfile.c b/src/configfile.c index acb1e0a..e5d1610 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -54,7 +54,14 @@ static int config_insert(server *srv) { { "server.max-write-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 21 */ { "server.error-handler-404", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 22 */ { "server.max-fds", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 23 */ +#ifdef HAVE_LSTAT { "server.follow-symlink", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 24 */ +#else + { "server.follow-symlink", + "Your system lacks lstat(). We can not differ symlinks from files." + "Please remove server.follow-symlinks from your config.", + T_CONFIG_UNSUPPORTED, T_CONFIG_SCOPE_UNSET }, /* 24 */ +#endif { "server.kbytes-per-second", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 25 */ { "connection.kbytes-per-second", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 26 */ { "mimetype.use-xattr", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */ @@ -80,6 +87,8 @@ static int config_insert(server *srv) { { "server.network-backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 43 */ { "server.upload-dirs", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 44 */ { "server.core-files", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 45 */ + { "ssl.cipher-list", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 46 */ + { "ssl.use-sslv2", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 47 */ { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, { "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, @@ -138,6 +147,7 @@ static int config_insert(server *srv) { s->ssl_ca_file = buffer_init(); s->error_handler = buffer_init(); s->server_tag = buffer_init(); + s->ssl_cipher_list = buffer_init(); s->errorfile_prefix = buffer_init(); s->max_keep_alive_requests = 16; s->max_keep_alive_idle = 5; @@ -145,8 +155,11 @@ static int config_insert(server *srv) { s->max_write_idle = 360; s->use_xattr = 0; s->is_ssl = 0; + s->ssl_use_sslv2 = 1; s->use_ipv6 = 0; +#ifdef HAVE_LSTAT s->follow_symlink = 1; +#endif s->kbytes_per_second = 0; s->allow_http11 = 1; s->range_requests = 1; @@ -171,7 +184,9 @@ static int config_insert(server *srv) { cv[20].destination = &(s->max_read_idle); cv[21].destination = &(s->max_write_idle); cv[22].destination = s->error_handler; +#ifdef HAVE_LSTAT cv[24].destination = &(s->follow_symlink); +#endif /* 23 -> max-fds */ cv[25].destination = &(s->global_kbytes_per_second); cv[26].destination = &(s->kbytes_per_second); @@ -189,6 +204,9 @@ static int config_insert(server *srv) { cv[38].destination = s->ssl_ca_file; cv[40].destination = &(s->range_requests); + cv[46].destination = s->ssl_cipher_list; + cv[47].destination = &(s->ssl_use_sslv2); + srv->config_storage[i] = s; if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) { @@ -231,7 +249,9 @@ int config_setup_connection(server *srv, connection *con) { PATCH(use_xattr); PATCH(error_handler); PATCH(errorfile_prefix); +#ifdef HAVE_LSTAT PATCH(follow_symlink); +#endif PATCH(server_tag); PATCH(kbytes_per_second); PATCH(global_kbytes_per_second); @@ -252,6 +272,10 @@ int config_setup_connection(server *srv, connection *con) { PATCH(ssl_pemfile); PATCH(ssl_ca_file); + PATCH(ssl_cipher_list); + PATCH(ssl_use_sslv2); + + return 0; } @@ -297,10 +321,16 @@ int config_patch_connection(server *srv, connection *con, comp_key_t comp) { PATCH(ssl_pemfile); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ca-file"))) { PATCH(ssl_ca_file); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv2"))) { + PATCH(ssl_use_sslv2); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.cipher-list"))) { + PATCH(ssl_cipher_list); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.engine"))) { PATCH(is_ssl); +#ifdef HAVE_LSTAT } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.follow-symlink"))) { PATCH(follow_symlink); +#endif } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.name"))) { buffer_copy_string_buffer(con->server_name, s->server_name); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.tag"))) { @@ -540,7 +570,7 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer * } else { config_skip_newline(t); t->line_pos = 1; - t->line++; + t->line++; } break; case ',': @@ -699,21 +729,13 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer * for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]); i++); /* was there it least a digit ? */ - if (i && t->input[t->offset + i]) { + if (i) { tid = TK_INTEGER; buffer_copy_string_len(token, t->input + t->offset, i); t->offset += i; t->line_pos += i; - } else { - /* ERROR */ - log_error_write(srv, __FILE__, __LINE__, "sbsdsds", - "source:", t->source, - "line:", t->line, "pos:", t->line_pos, - "unexpected EOF"); - - return -1; } } else { /* the key might consist of [-.0-9a-z] */ @@ -800,7 +822,7 @@ static int config_parse(server *srv, config_t *context, tokenizer_t *t) { if (ret == -1) { log_error_write(srv, __FILE__, __LINE__, "sb", - "configfile parser failed:", lasttoken); + "configfile parser failed at:", lasttoken); } else if (context->ok == 0) { log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb", "source:", t->source, diff --git a/src/configparser.c b/src/configparser.c index c2a3960..bc1a2ec 100644 --- a/src/configparser.c +++ b/src/configparser.c @@ -36,40 +36,22 @@ static data_config *configparser_pop(config_t *ctx) { /* return a copied variable */ static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) { - if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) { - char *env; - - if (NULL != (env = getenv(key->ptr + 4))) { - data_string *ds; - ds = data_string_init(); - buffer_append_string(ds->value, env); - return (data_unset *)ds; - } - - fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4); - ctx->ok = 0; - - return NULL; - } else { - data_unset *du; - data_config *dc; + data_unset *du; + data_config *dc; #if 0 - fprintf(stderr, "get var %s\n", key->ptr); + fprintf(stderr, "get var %s\n", key->ptr); #endif - for (dc = ctx->current; dc; dc = dc->parent) { + for (dc = ctx->current; dc; dc = dc->parent) { #if 0 - fprintf(stderr, "get var on block: %s\n", dc->key->ptr); - array_print(dc->value, 0); + fprintf(stderr, "get var on block: %s\n", dc->key->ptr); + array_print(dc->value, 0); #endif - if (NULL != (du = array_get_element(dc->value, key->ptr))) { - return du->copy(du); - } + if (NULL != (du = array_get_element(dc->value, key->ptr))) { + return du->copy(du); } - fprintf(stderr, "Undefined config variable: %s\n", key->ptr); - ctx->ok = 0; - return NULL; } + return NULL; } /* op1 is to be eat/return by this function, op1->key is not cared @@ -124,7 +106,7 @@ data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) { } -#line 128 "configparser.c" +#line 110 "configparser.c" /* Next is all token values, in a form suitable for use by makeheaders. ** This section will be null unless lemon is run with the -m switch. */ @@ -528,44 +510,44 @@ static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ case 23: case 24: case 25: -#line 160 "./configparser.y" +#line 142 "./configparser.y" { buffer_free((yypminor->yy0)); } -#line 533 "configparser.c" +#line 515 "configparser.c" break; case 35: -#line 151 "./configparser.y" +#line 133 "./configparser.y" { (yypminor->yy41)->free((yypminor->yy41)); } -#line 538 "configparser.c" +#line 520 "configparser.c" break; case 36: -#line 152 "./configparser.y" +#line 134 "./configparser.y" { (yypminor->yy41)->free((yypminor->yy41)); } -#line 543 "configparser.c" +#line 525 "configparser.c" break; case 37: -#line 153 "./configparser.y" +#line 135 "./configparser.y" { (yypminor->yy41)->free((yypminor->yy41)); } -#line 548 "configparser.c" +#line 530 "configparser.c" break; case 39: -#line 154 "./configparser.y" +#line 136 "./configparser.y" { array_free((yypminor->yy40)); } -#line 553 "configparser.c" +#line 535 "configparser.c" break; case 40: -#line 155 "./configparser.y" +#line 137 "./configparser.y" { array_free((yypminor->yy40)); } -#line 558 "configparser.c" +#line 540 "configparser.c" break; case 41: -#line 156 "./configparser.y" +#line 138 "./configparser.y" { buffer_free((yypminor->yy43)); } -#line 563 "configparser.c" +#line 545 "configparser.c" break; case 42: -#line 157 "./configparser.y" +#line 139 "./configparser.y" { buffer_free((yypminor->yy43)); } -#line 568 "configparser.c" +#line 550 "configparser.c" break; default: break; /* If no destructor action specified: do nothing */ } @@ -832,9 +814,9 @@ static void yy_reduce( /* No destructor defined for global */ break; case 5: -#line 134 "./configparser.y" +#line 116 "./configparser.y" { yymsp[-1].minor.yy78 = NULL; } -#line 837 "configparser.c" +#line 819 "configparser.c" yy_destructor(1,&yymsp[0].minor); break; case 6: @@ -847,10 +829,15 @@ static void yy_reduce( yy_destructor(1,&yymsp[0].minor); break; case 9: -#line 162 "./configparser.y" +#line 144 "./configparser.y" { buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43); - if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) { + if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) { + fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n", + ctx->current->context_ndx, + ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr); + ctx->ok = 0; + } else if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) { array_insert_unique(ctx->current->value, yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } else { @@ -864,16 +851,21 @@ static void yy_reduce( buffer_free(yymsp[-2].minor.yy43); yymsp[-2].minor.yy43 = NULL; } -#line 867 "configparser.c" +#line 854 "configparser.c" yy_destructor(2,&yymsp[-1].minor); break; case 10: -#line 179 "./configparser.y" +#line 166 "./configparser.y" { array *vars = ctx->current->value; data_unset *du; - if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) { + if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) { + fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n", + ctx->current->context_ndx, + ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr); + ctx->ok = 0; + } else if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) { /* exists in current block */ du = configparser_merge_data(du, yymsp[0].minor.yy41); if (NULL == du) { @@ -883,6 +875,7 @@ static void yy_reduce( buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43); array_replace(vars, du); } + yymsp[0].minor.yy41->free(yymsp[0].minor.yy41); } else if (NULL != (du = configparser_get_variable(ctx, yymsp[-2].minor.yy43))) { du = configparser_merge_data(du, yymsp[0].minor.yy41); if (NULL == du) { @@ -892,22 +885,20 @@ static void yy_reduce( buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43); array_insert_unique(ctx->current->value, du); } + yymsp[0].minor.yy41->free(yymsp[0].minor.yy41); } else { - fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n", - ctx->current->context_ndx, - ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr); - ctx->ok = 0; + buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43); + array_insert_unique(ctx->current->value, yymsp[0].minor.yy41); } buffer_free(yymsp[-2].minor.yy43); yymsp[-2].minor.yy43 = NULL; - yymsp[0].minor.yy41->free(yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } -#line 906 "configparser.c" +#line 897 "configparser.c" yy_destructor(3,&yymsp[-1].minor); break; case 11: -#line 214 "./configparser.y" +#line 205 "./configparser.y" { if (strchr(yymsp[0].minor.yy0->ptr, '.') == NULL) { yygotominor.yy43 = buffer_init_string("var."); @@ -919,10 +910,10 @@ static void yy_reduce( yymsp[0].minor.yy0 = NULL; } } -#line 922 "configparser.c" +#line 913 "configparser.c" break; case 12: -#line 226 "./configparser.y" +#line 217 "./configparser.y" { yygotominor.yy41 = configparser_merge_data(yymsp[-2].minor.yy41, yymsp[0].minor.yy41); if (NULL == yygotominor.yy41) { @@ -932,21 +923,37 @@ static void yy_reduce( yymsp[0].minor.yy41->free(yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } -#line 935 "configparser.c" +#line 926 "configparser.c" yy_destructor(5,&yymsp[-1].minor); break; case 13: -#line 236 "./configparser.y" +#line 227 "./configparser.y" { yygotominor.yy41 = yymsp[0].minor.yy41; yymsp[0].minor.yy41 = NULL; } -#line 944 "configparser.c" +#line 935 "configparser.c" break; case 14: -#line 241 "./configparser.y" +#line 232 "./configparser.y" { - yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43); + if (strncmp(yymsp[0].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) { + char *env; + + if (NULL != (env = getenv(yymsp[0].minor.yy43->ptr + 4))) { + data_string *ds; + ds = data_string_init(); + buffer_append_string(ds->value, env); + yygotominor.yy41 = (data_unset *)ds; + } + else { + fprintf(stderr, "Undefined env variable: %s\n", yymsp[0].minor.yy43->ptr + 4); + ctx->ok = 0; + } + } else if (NULL == (yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43))) { + fprintf(stderr, "Undefined config variable: %s\n", yymsp[0].minor.yy43->ptr); + ctx->ok = 0; + } if (!yygotominor.yy41) { /* make a dummy so it won't crash */ yygotominor.yy41 = (data_unset *)data_string_init(); @@ -954,50 +961,50 @@ static void yy_reduce( buffer_free(yymsp[0].minor.yy43); yymsp[0].minor.yy43 = NULL; } -#line 957 "configparser.c" +#line 964 "configparser.c" break; case 15: -#line 251 "./configparser.y" +#line 258 "./configparser.y" { yygotominor.yy41 = (data_unset *)data_string_init(); buffer_copy_string_buffer(((data_string *)(yygotominor.yy41))->value, yymsp[0].minor.yy0); buffer_free(yymsp[0].minor.yy0); yymsp[0].minor.yy0 = NULL; } -#line 967 "configparser.c" +#line 974 "configparser.c" break; case 16: -#line 258 "./configparser.y" +#line 265 "./configparser.y" { yygotominor.yy41 = (data_unset *)data_integer_init(); ((data_integer *)(yygotominor.yy41))->value = strtol(yymsp[0].minor.yy0->ptr, NULL, 10); buffer_free(yymsp[0].minor.yy0); yymsp[0].minor.yy0 = NULL; } -#line 977 "configparser.c" +#line 984 "configparser.c" break; case 17: -#line 264 "./configparser.y" +#line 271 "./configparser.y" { yygotominor.yy41 = (data_unset *)data_array_init(); array_free(((data_array *)(yygotominor.yy41))->value); ((data_array *)(yygotominor.yy41))->value = yymsp[0].minor.yy40; yymsp[0].minor.yy40 = NULL; } -#line 987 "configparser.c" +#line 994 "configparser.c" break; case 18: -#line 270 "./configparser.y" +#line 277 "./configparser.y" { yygotominor.yy40 = yymsp[-1].minor.yy40; yymsp[-1].minor.yy40 = NULL; } -#line 995 "configparser.c" +#line 1002 "configparser.c" yy_destructor(8,&yymsp[-2].minor); yy_destructor(9,&yymsp[0].minor); break; case 19: -#line 275 "./configparser.y" +#line 282 "./configparser.y" { if (buffer_is_empty(yymsp[0].minor.yy41->key) || NULL == array_get_element(yymsp[-2].minor.yy40, yymsp[0].minor.yy41->key->ptr)) { @@ -1014,37 +1021,37 @@ static void yy_reduce( yygotominor.yy40 = yymsp[-2].minor.yy40; yymsp[-2].minor.yy40 = NULL; } -#line 1017 "configparser.c" +#line 1024 "configparser.c" yy_destructor(10,&yymsp[-1].minor); break; case 20: -#line 292 "./configparser.y" +#line 299 "./configparser.y" { yygotominor.yy40 = yymsp[-1].minor.yy40; yymsp[-1].minor.yy40 = NULL; } -#line 1026 "configparser.c" +#line 1033 "configparser.c" yy_destructor(10,&yymsp[0].minor); break; case 21: -#line 297 "./configparser.y" +#line 304 "./configparser.y" { yygotominor.yy40 = array_init(); array_insert_unique(yygotominor.yy40, yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } -#line 1036 "configparser.c" +#line 1043 "configparser.c" break; case 22: -#line 303 "./configparser.y" +#line 310 "./configparser.y" { yygotominor.yy41 = yymsp[0].minor.yy41; yymsp[0].minor.yy41 = NULL; } -#line 1044 "configparser.c" +#line 1051 "configparser.c" break; case 23: -#line 307 "./configparser.y" +#line 314 "./configparser.y" { buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43); buffer_free(yymsp[-2].minor.yy43); @@ -1053,7 +1060,7 @@ static void yy_reduce( yygotominor.yy41 = yymsp[0].minor.yy41; yymsp[0].minor.yy41 = NULL; } -#line 1056 "configparser.c" +#line 1063 "configparser.c" yy_destructor(11,&yymsp[-1].minor); break; case 24: @@ -1062,18 +1069,18 @@ static void yy_reduce( case 25: break; case 26: -#line 319 "./configparser.y" +#line 326 "./configparser.y" { data_config *dc; dc = (data_config *)array_get_element(ctx->srv->config_context, "global"); assert(dc); configparser_push(ctx, dc, 0); } -#line 1072 "configparser.c" +#line 1079 "configparser.c" yy_destructor(12,&yymsp[0].minor); break; case 27: -#line 326 "./configparser.y" +#line 333 "./configparser.y" { data_config *cur; @@ -1084,14 +1091,14 @@ static void yy_reduce( yygotominor.yy0 = cur; } -#line 1087 "configparser.c" +#line 1094 "configparser.c" /* No destructor defined for globalstart */ yy_destructor(13,&yymsp[-2].minor); /* No destructor defined for metalines */ yy_destructor(14,&yymsp[0].minor); break; case 28: -#line 337 "./configparser.y" +#line 344 "./configparser.y" { assert(yymsp[-3].minor.yy78->context_ndx < yymsp[0].minor.yy78->context_ndx); yymsp[0].minor.yy78->prev = yymsp[-3].minor.yy78; @@ -1100,20 +1107,20 @@ static void yy_reduce( yymsp[-3].minor.yy78 = NULL; yymsp[0].minor.yy78 = NULL; } -#line 1103 "configparser.c" +#line 1110 "configparser.c" /* No destructor defined for eols */ yy_destructor(15,&yymsp[-1].minor); break; case 29: -#line 346 "./configparser.y" +#line 353 "./configparser.y" { yygotominor.yy78 = yymsp[0].minor.yy78; yymsp[0].minor.yy78 = NULL; } -#line 1113 "configparser.c" +#line 1120 "configparser.c" break; case 30: -#line 351 "./configparser.y" +#line 358 "./configparser.y" { data_config *cur; @@ -1124,14 +1131,14 @@ static void yy_reduce( yygotominor.yy78 = cur; } -#line 1127 "configparser.c" +#line 1134 "configparser.c" /* No destructor defined for context */ yy_destructor(13,&yymsp[-2].minor); /* No destructor defined for metalines */ yy_destructor(14,&yymsp[0].minor); break; case 31: -#line 362 "./configparser.y" +#line 369 "./configparser.y" { data_config *dc; buffer *b, *rvalue, *op; @@ -1183,6 +1190,7 @@ static void yy_reduce( { COMP_HTTP_USERAGENT, CONST_STR_LEN("HTTP[\"useragent\"]" ) }, { COMP_HTTP_COOKIE, CONST_STR_LEN("HTTP[\"cookie\"]" ) }, { COMP_HTTP_REMOTEIP, CONST_STR_LEN("HTTP[\"remoteip\"]" ) }, + { COMP_HTTP_QUERYSTRING, CONST_STR_LEN("HTTP[\"querystring\"]") }, { COMP_UNSET, NULL, 0 }, }; size_t i; @@ -1266,45 +1274,45 @@ static void yy_reduce( yymsp[0].minor.yy41->free(yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } -#line 1269 "configparser.c" +#line 1277 "configparser.c" yy_destructor(16,&yymsp[-6].minor); yy_destructor(18,&yymsp[-4].minor); yy_destructor(19,&yymsp[-2].minor); break; case 32: -#line 496 "./configparser.y" +#line 504 "./configparser.y" { yygotominor.yy27 = CONFIG_COND_EQ; } -#line 1279 "configparser.c" +#line 1287 "configparser.c" yy_destructor(20,&yymsp[0].minor); break; case 33: -#line 499 "./configparser.y" +#line 507 "./configparser.y" { yygotominor.yy27 = CONFIG_COND_MATCH; } -#line 1287 "configparser.c" +#line 1295 "configparser.c" yy_destructor(21,&yymsp[0].minor); break; case 34: -#line 502 "./configparser.y" +#line 510 "./configparser.y" { yygotominor.yy27 = CONFIG_COND_NE; } -#line 1295 "configparser.c" +#line 1303 "configparser.c" yy_destructor(22,&yymsp[0].minor); break; case 35: -#line 505 "./configparser.y" +#line 513 "./configparser.y" { yygotominor.yy27 = CONFIG_COND_NOMATCH; } -#line 1303 "configparser.c" +#line 1311 "configparser.c" yy_destructor(23,&yymsp[0].minor); break; case 36: -#line 509 "./configparser.y" +#line 517 "./configparser.y" { yygotominor.yy43 = NULL; if (ctx->ok) { @@ -1321,10 +1329,10 @@ static void yy_reduce( yymsp[0].minor.yy41->free(yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } -#line 1324 "configparser.c" +#line 1332 "configparser.c" break; case 37: -#line 526 "./configparser.y" +#line 534 "./configparser.y" { if (ctx->ok) { if (0 != config_parse_file(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) { @@ -1334,11 +1342,11 @@ static void yy_reduce( yymsp[0].minor.yy43 = NULL; } } -#line 1337 "configparser.c" +#line 1345 "configparser.c" yy_destructor(24,&yymsp[-1].minor); break; case 38: -#line 536 "./configparser.y" +#line 544 "./configparser.y" { if (ctx->ok) { if (0 != config_parse_cmd(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) { @@ -1348,7 +1356,7 @@ static void yy_reduce( yymsp[0].minor.yy43 = NULL; } } -#line 1351 "configparser.c" +#line 1359 "configparser.c" yy_destructor(25,&yymsp[-1].minor); break; }; @@ -1378,11 +1386,11 @@ static void yy_parse_failed( while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser fails */ -#line 125 "./configparser.y" +#line 107 "./configparser.y" ctx->ok = 0; -#line 1385 "configparser.c" +#line 1393 "configparser.c" configparserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } diff --git a/src/configparser.y b/src/configparser.y index ef65061..2e9c819 100644 --- a/src/configparser.y +++ b/src/configparser.y @@ -33,40 +33,22 @@ static data_config *configparser_pop(config_t *ctx) { /* return a copied variable */ static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) { - if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) { - char *env; - - if (NULL != (env = getenv(key->ptr + 4))) { - data_string *ds; - ds = data_string_init(); - buffer_append_string(ds->value, env); - return (data_unset *)ds; - } - - fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4); - ctx->ok = 0; - - return NULL; - } else { - data_unset *du; - data_config *dc; + data_unset *du; + data_config *dc; #if 0 - fprintf(stderr, "get var %s\n", key->ptr); + fprintf(stderr, "get var %s\n", key->ptr); #endif - for (dc = ctx->current; dc; dc = dc->parent) { + for (dc = ctx->current; dc; dc = dc->parent) { #if 0 - fprintf(stderr, "get var on block: %s\n", dc->key->ptr); - array_print(dc->value, 0); + fprintf(stderr, "get var on block: %s\n", dc->key->ptr); + array_print(dc->value, 0); #endif - if (NULL != (du = array_get_element(dc->value, key->ptr))) { - return du->copy(du); - } + if (NULL != (du = array_get_element(dc->value, key->ptr))) { + return du->copy(du); } - fprintf(stderr, "Undefined config variable: %s\n", key->ptr); - ctx->ok = 0; - return NULL; } + return NULL; } /* op1 is to be eat/return by this function, op1->key is not cared @@ -161,7 +143,12 @@ metaline ::= EOL. varline ::= key(A) ASSIGN expression(B). { buffer_copy_string_buffer(B->key, A); - if (NULL == array_get_element(ctx->current->value, B->key->ptr)) { + if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) { + fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n", + ctx->current->context_ndx, + ctx->current->key->ptr, A->ptr); + ctx->ok = 0; + } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) { array_insert_unique(ctx->current->value, B); B = NULL; } else { @@ -180,7 +167,12 @@ varline ::= key(A) APPEND expression(B). { array *vars = ctx->current->value; data_unset *du; - if (NULL != (du = array_get_element(vars, A->ptr))) { + if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) { + fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n", + ctx->current->context_ndx, + ctx->current->key->ptr, A->ptr); + ctx->ok = 0; + } else if (NULL != (du = array_get_element(vars, A->ptr))) { /* exists in current block */ du = configparser_merge_data(du, B); if (NULL == du) { @@ -190,6 +182,7 @@ varline ::= key(A) APPEND expression(B). { buffer_copy_string_buffer(du->key, A); array_replace(vars, du); } + B->free(B); } else if (NULL != (du = configparser_get_variable(ctx, A))) { du = configparser_merge_data(du, B); if (NULL == du) { @@ -199,15 +192,13 @@ varline ::= key(A) APPEND expression(B). { buffer_copy_string_buffer(du->key, A); array_insert_unique(ctx->current->value, du); } + B->free(B); } else { - fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n", - ctx->current->context_ndx, - ctx->current->key->ptr, A->ptr); - ctx->ok = 0; + buffer_copy_string_buffer(B->key, A); + array_insert_unique(ctx->current->value, B); } buffer_free(A); A = NULL; - B->free(B); B = NULL; } @@ -239,7 +230,23 @@ expression(A) ::= value(B). { } value(A) ::= key(B). { - A = configparser_get_variable(ctx, B); + if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) { + char *env; + + if (NULL != (env = getenv(B->ptr + 4))) { + data_string *ds; + ds = data_string_init(); + buffer_append_string(ds->value, env); + A = (data_unset *)ds; + } + else { + fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4); + ctx->ok = 0; + } + } else if (NULL == (A = configparser_get_variable(ctx, B))) { + fprintf(stderr, "Undefined config variable: %s\n", B->ptr); + ctx->ok = 0; + } if (!A) { /* make a dummy so it won't crash */ A = (data_unset *)data_string_init(); @@ -410,6 +417,7 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio { COMP_HTTP_USERAGENT, CONST_STR_LEN("HTTP[\"useragent\"]" ) }, { COMP_HTTP_COOKIE, CONST_STR_LEN("HTTP[\"cookie\"]" ) }, { COMP_HTTP_REMOTEIP, CONST_STR_LEN("HTTP[\"remoteip\"]" ) }, + { COMP_HTTP_QUERYSTRING, CONST_STR_LEN("HTTP[\"querystring\"]") }, { COMP_UNSET, NULL, 0 }, }; size_t i; diff --git a/src/http-header-glue.c b/src/http-header-glue.c index 4771a5e..b40f374 100644 --- a/src/http-header-glue.c +++ b/src/http-header-glue.c @@ -262,26 +262,11 @@ int http_response_handle_cachable(server *srv, connection *con, buffer *mtime) { return HANDLER_FINISHED; } else { char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")]; + time_t t_header, t_file; + struct tm tm; - /* convert to timestamp */ - if (used_len < sizeof(buf)) { - time_t t_header, t_file; - struct tm tm; - - strncpy(buf, con->request.http_if_modified_since, used_len); - buf[used_len] = '\0'; - - strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm); - t_header = mktime(&tm); - - strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm); - t_file = mktime(&tm); - - if (t_file > t_header) { - con->http_status = 304; - return HANDLER_FINISHED; - } - } else { + /* check if we can safely copy the string */ + if (used_len >= sizeof(buf)) { log_error_write(srv, __FILE__, __LINE__, "ssdd", "DEBUG: Last-Modified check failed as the received timestamp was too long:", con->request.http_if_modified_since, used_len, sizeof(buf) - 1); @@ -289,6 +274,21 @@ int http_response_handle_cachable(server *srv, connection *con, buffer *mtime) { con->http_status = 412; return HANDLER_FINISHED; } + + + strncpy(buf, con->request.http_if_modified_since, used_len); + buf[used_len] = '\0'; + + strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm); + t_header = mktime(&tm); + + strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm); + t_file = mktime(&tm); + + if (t_file > t_header) return HANDLER_GO_ON; + + con->http_status = 304; + return HANDLER_FINISHED; } } else { con->http_status = 304; @@ -302,7 +302,7 @@ int http_response_handle_cachable(server *srv, connection *con, buffer *mtime) { } else if (con->request.http_if_modified_since) { size_t used_len; char *semicolon; - + if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) { used_len = strlen(con->request.http_if_modified_since); } else { @@ -310,6 +310,27 @@ int http_response_handle_cachable(server *srv, connection *con, buffer *mtime) { } if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) { + con->http_status = 304; + return HANDLER_FINISHED; + } else { + char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")]; + time_t t_header, t_file; + struct tm tm; + + /* convert to timestamp */ + if (used_len >= sizeof(buf)) return HANDLER_GO_ON; + + strncpy(buf, con->request.http_if_modified_since, used_len); + buf[used_len] = '\0'; + + strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm); + t_header = mktime(&tm); + + strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm); + t_file = mktime(&tm); + + if (t_file > t_header) return HANDLER_GO_ON; + con->http_status = 304; return HANDLER_FINISHED; } diff --git a/src/mod_flv_streaming.c b/src/mod_flv_streaming.c index c557bd4..d1f467a 100644 --- a/src/mod_flv_streaming.c +++ b/src/mod_flv_streaming.c @@ -138,7 +138,7 @@ static int mod_flv_streaming_patch_connection(server *srv, connection *con, plug } #undef PATCH -static int split_get_params(server *srv, connection *con, array *get_params, buffer *qrystr) { +static int split_get_params(array *get_params, buffer *qrystr) { size_t is_key = 1; size_t i; char *key = NULL, *val = NULL; @@ -167,7 +167,7 @@ static int split_get_params(server *srv, connection *con, array *get_params, buf /* terminate the value */ qrystr->ptr[i] = '\0'; - if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) { + if (NULL == (ds = (data_string *)array_get_unused_element(get_params, TYPE_STRING))) { ds = data_string_init(); } buffer_copy_string_len(ds->key, key, strlen(key)); @@ -217,7 +217,7 @@ URIHANDLER_FUNC(mod_flv_streaming_path_handler) { array_reset(p->get_params); buffer_copy_string_buffer(p->query_str, con->uri.query); - split_get_params(srv, con, p->get_params, p->query_str); + split_get_params(p->get_params, p->query_str); if (NULL == (get_param = (data_string *)array_get_element(p->get_params, "start"))) { return HANDLER_GO_ON; diff --git a/src/mod_staticfile.c b/src/mod_staticfile.c index 6fac65b..f5308cd 100644 --- a/src/mod_staticfile.c +++ b/src/mod_staticfile.c @@ -397,6 +397,19 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) { } /* we only handline regular files */ +#ifdef HAVE_LSTAT + if ((sce->is_symlink == 1) && !con->conf.follow_symlink) { + con->http_status = 403; + + if (con->conf.log_request_handling) { + log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied due symlink restriction"); + log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); + } + + buffer_reset(con->physical.path); + return HANDLER_FINISHED; + } +#endif if (!S_ISREG(sce->st.st_mode)) { con->http_status = 404; diff --git a/src/network.c b/src/network.c index c7abf90..6ba2743 100644 --- a/src/network.c +++ b/src/network.c @@ -329,6 +329,24 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { ERR_error_string(ERR_get_error(), NULL)); return -1; } + + if (!s->ssl_use_sslv2) { + /* disable SSLv2 */ + if (SSL_OP_NO_SSLv2 != SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2)) { + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + } + + if (!buffer_is_empty(s->ssl_cipher_list)) { + /* Disable support for low encryption ciphers */ + if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) { + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + } if (buffer_is_empty(s->ssl_pemfile)) { log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set"); diff --git a/src/proc_open.c b/src/proc_open.c index ecea815..ad2650d 100644 --- a/src/proc_open.c +++ b/src/proc_open.c @@ -148,11 +148,14 @@ int proc_open(proc_handler_t *proc, const char *command) { STARTUPINFO si; BOOL procok; SECURITY_ATTRIBUTES security; - const char *shell; + const char *shell = NULL; + const char *windir = NULL; buffer *cmdline; - if (NULL == (shell = getenv(SHELLENV))) { - fprintf(stderr, "env %s is required", SHELLENV); + if (NULL == (shell = getenv(SHELLENV)) && + NULL == (windir = getenv("SystemRoot")) && + NULL == (windir = getenv("windir"))) { + fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV); return -1; } @@ -177,17 +180,23 @@ int proc_open(proc_handler_t *proc, const char *command) { memset(&pi, 0, sizeof(pi)); cmdline = buffer_init(); - buffer_append_string(cmdline, shell); + if (shell) { + buffer_append_string(cmdline, shell); + } else { + buffer_append_string(cmdline, windir); + buffer_append_string(cmdline, "\\system32\\cmd.exe"); + } buffer_append_string_len(cmdline, CONST_STR_LEN(" /c ")); buffer_append_string(cmdline, command); procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); - buffer_free(cmdline); if (FALSE == procok) { - fprintf(stderr, "failed to CreateProcess"); + fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr); + buffer_free(cmdline); return -1; } + buffer_free(cmdline); proc->child = pi.hProcess; CloseHandle(pi.hThread); @@ -226,8 +235,7 @@ int proc_open(proc_handler_t *proc, const char *command) { const char *shell; if (NULL == (shell = getenv(SHELLENV))) { - fprintf(stderr, "env %s is required", SHELLENV); - return -1; + shell = "/bin/sh"; } if (proc_open_pipes(proc) != 0) { diff --git a/src/response.c b/src/response.c index 4f23ea9..45a1782 100644 --- a/src/response.c +++ b/src/response.c @@ -261,7 +261,13 @@ handler_t http_response_prepare(server *srv, connection *con) { */ config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */ - + config_patch_connection(srv, con, COMP_HTTP_QUERYSTRING); /* HTTPqs */ + + /* do we have to downgrade to 1.0 ? */ + if (!con->conf.allow_http11) { + con->request.http_version = HTTP_VERSION_1_0; + } + switch(r = plugins_call_handle_uri_clean(srv, con)) { case HANDLER_GO_ON: break; @@ -451,7 +457,7 @@ handler_t http_response_prepare(server *srv, connection *con) { log_error_write(srv, __FILE__, __LINE__, "s", "-- handling physical path"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } - + if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) { /* file exists */ @@ -459,7 +465,19 @@ handler_t http_response_prepare(server *srv, connection *con) { log_error_write(srv, __FILE__, __LINE__, "s", "-- file found"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } - +#ifdef HAVE_LSTAT + if ((sce->is_symlink != 0) && !con->conf.follow_symlink) { + con->http_status = 403; + + if (con->conf.log_request_handling) { + log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied due symlink restriction"); + log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); + } + + buffer_reset(con->physical.path); + return HANDLER_FINISHED; + }; +#endif if (S_ISDIR(sce->st.st_mode)) { if (con->physical.path->ptr[con->physical.path->used - 2] != '/') { /* redirect to .../ */ @@ -468,7 +486,11 @@ handler_t http_response_prepare(server *srv, connection *con) { return HANDLER_FINISHED; } +#ifdef HAVE_LSTAT + } else if (!S_ISREG(sce->st.st_mode) && !sce->is_symlink) { +#else } else if (!S_ISREG(sce->st.st_mode)) { +#endif /* any special handling of non-reg files ?*/ diff --git a/src/server.c b/src/server.c index d4f9eba..5a29a75 100644 --- a/src/server.c +++ b/src/server.c @@ -861,22 +861,29 @@ int main (int argc, char **argv) { } } } - + + if (srv->config_unsupported) { + log_error_write(srv, __FILE__, __LINE__, "s", + "Configuration contains unsupported keys. Going down."); + } + if (srv->config_deprecated) { log_error_write(srv, __FILE__, __LINE__, "s", "Configuration contains deprecated keys. Going down."); - + } + + if (srv->config_unsupported || srv->config_deprecated) { plugins_free(srv); network_close(srv); server_free(srv); - + return -1; } - + if (-1 == log_error_open(srv)) { log_error_write(srv, __FILE__, __LINE__, "s", "opening errorlog failed, dying"); - + plugins_free(srv); network_close(srv); server_free(srv); diff --git a/src/stat_cache.c b/src/stat_cache.c index 148f4c8..623e5ea 100644 --- a/src/stat_cache.c +++ b/src/stat_cache.c @@ -39,7 +39,7 @@ #define lstat stat #endif -#if 0 +#if 1 /* enables debug code for testing if all nodes in the stat-cache as accessable */ #define DEBUG_STAT_CACHE #endif @@ -328,6 +328,20 @@ static int buffer_copy_dirname(buffer *dst, buffer *file) { } #endif +#ifdef HAVE_LSTAT +static int stat_cache_lstat(server *srv, char *dname, struct stat *lst) { + if (lstat(dname, lst) == 0) { + return S_ISLNK(lst->st_mode) ? 0 : 1; + } + else { + log_error_write(srv, __FILE__, __LINE__, "sss", + "lstat failed for:", + dname, strerror(errno)); + }; + return -1; +} +#endif + /*** * * @@ -450,10 +464,9 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ /* * *lol* * - open() + fstat() on a named-pipe results in a (intended) hang. - * - stat() if regualar file + open() to see if we can read from it is better + * - stat() if regular file + open() to see if we can read from it is better * * */ - if (-1 == stat(name->ptr, &st)) { return HANDLER_ERROR; } @@ -509,11 +522,52 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ * and keeping the file open for the rest of the time. But this can * only be done at network level. * ++ * per default it is not a symlink * */ - if (S_ISLNK(st.st_mode) && !con->conf.follow_symlink) { - return HANDLER_ERROR; +#ifdef HAVE_LSTAT + sce->is_symlink = 0; + struct stat lst; + if (stat_cache_lstat(srv, name->ptr, &lst) == 0) { +#ifdef DEBUG_STAT_CACHE + log_error_write(srv, __FILE__, __LINE__, "sb", + "found symlink", name); +#endif + sce->is_symlink = 1; } + /* + * we assume "/" can not be symlink, so + * skip the symlink stuff if our path is / + **/ + else if ((name->used > 2)) { + char *dname, *s_cur; + + dname = strndup(name->ptr, name->used); + while ((s_cur = strrchr(dname,'/'))) { + *s_cur = '\0'; + if (dname == s_cur) { +#ifdef DEBUG_STAT_CACHE + log_error_write(srv, __FILE__, __LINE__, "s", "reached /"); +#endif + break; + } +#ifdef DEBUG_STAT_CACHE + log_error_write(srv, __FILE__, __LINE__, "sss", + "checking if", dname, "is a symlink"); +#endif + if (stat_cache_lstat(srv, dname, &lst) == 0) { + sce->is_symlink = 1; +#ifdef DEBUG_STAT_CACHE + log_error_write(srv, __FILE__, __LINE__, "ss", + "found symlink", dname); +#endif + break; + }; + }; + free(dname); + }; +#endif + if (S_ISREG(st.st_mode)) { /* determine mimetype */ buffer_reset(sce->content_type); -- cgit v1.2.3