9 #include "configfile.h"
14 #include <arpa/inet.h>
18 * like all glue code this file contains functions which
19 * are the external interface of lighttpd. The functions
20 * are used by the server itself and the plugins.
22 * The main-goal is to have a small library in the end
23 * which is linked against both and which will define
24 * the interface itself in the end.
29 /* handle global options */
31 /* parse config array */
32 int config_insert_values_internal(server
*srv
, array
*ca
, const config_values_t cv
[], config_scope_type_t scope
) {
36 for (i
= 0; cv
[i
].key
; i
++) {
38 if (NULL
== (du
= array_get_element(ca
, cv
[i
].key
))) {
44 if ((T_CONFIG_SCOPE_SERVER
== cv
[i
].scope
)
45 && (T_CONFIG_SCOPE_SERVER
!= scope
)) {
46 /* server scope options should only be set in server scope, not in conditionals */
47 log_error_write(srv
, __FILE__
, __LINE__
, "ss",
48 "DEPRECATED: don't set server options in conditionals, variable:",
54 if (du
->type
== TYPE_ARRAY
) {
56 data_array
*da
= (data_array
*)du
;
58 for (j
= 0; j
< da
->value
->used
; j
++) {
59 if (da
->value
->data
[j
]->type
== TYPE_STRING
) {
60 data_string
*ds
= data_string_init();
62 buffer_copy_buffer(ds
->value
, ((data_string
*)(da
->value
->data
[j
]))->value
);
63 if (!((data_string
*)(da
->value
->data
[j
]))->is_index_key
) {
64 /* the id's were generated automaticly, as we copy now we might have to renumber them
65 * this is used to prepend server.modules by mod_indexfile as it has to be loaded
66 * before mod_fastcgi and friends */
67 buffer_copy_buffer(ds
->key
, ((data_string
*)(da
->value
->data
[j
]))->key
);
70 array_insert_unique(cv
[i
].destination
, (data_unset
*)ds
);
72 log_error_write(srv
, __FILE__
, __LINE__
, "sssbsd",
73 "the value of an array can only be a string, variable:",
74 cv
[i
].key
, "[", da
->value
->data
[j
]->key
, "], type:", da
->value
->data
[j
]->type
);
80 log_error_write(srv
, __FILE__
, __LINE__
, "ss", cv
[i
].key
, "should have been a array of strings like ... = ( \"...\" )");
86 if (du
->type
== TYPE_STRING
) {
87 data_string
*ds
= (data_string
*)du
;
89 buffer_copy_buffer(cv
[i
].destination
, ds
->value
);
91 log_error_write(srv
, __FILE__
, __LINE__
, "ssss", cv
[i
].key
, "should have been a string like ... = \"...\"");
99 data_integer
*di
= (data_integer
*)du
;
101 *((unsigned short *)(cv
[i
].destination
)) = di
->value
;
105 data_string
*ds
= (data_string
*)du
;
107 /* If the value came from an environment variable, then it is a
108 * data_string, although it may contain a number in ASCII
109 * decimal format. We try to interpret the string as a decimal
110 * short before giving up, in order to support setting numeric
111 * values with environment variables (eg, port number).
113 if (ds
->value
->ptr
&& *ds
->value
->ptr
) {
115 long l
= strtol(ds
->value
->ptr
, &e
, 10);
116 if (e
!= ds
->value
->ptr
&& !*e
&& l
>=0 && l
<= 65535) {
117 *((unsigned short *)(cv
[i
].destination
)) = l
;
122 log_error_write(srv
, __FILE__
, __LINE__
, "ssb", "got a string but expected a short:", cv
[i
].key
, ds
->value
);
127 log_error_write(srv
, __FILE__
, __LINE__
, "ssds", "unexpected type for key:", cv
[i
].key
, du
->type
, "expected a short integer, range 0 ... 65535");
134 data_integer
*di
= (data_integer
*)du
;
136 *((unsigned int *)(cv
[i
].destination
)) = di
->value
;
140 data_string
*ds
= (data_string
*)du
;
142 if (ds
->value
->ptr
&& *ds
->value
->ptr
) {
144 long l
= strtol(ds
->value
->ptr
, &e
, 10);
145 if (e
!= ds
->value
->ptr
&& !*e
&& l
>= 0) {
146 *((unsigned int *)(cv
[i
].destination
)) = l
;
151 log_error_write(srv
, __FILE__
, __LINE__
, "ssb", "got a string but expected an integer:", cv
[i
].key
, ds
->value
);
156 log_error_write(srv
, __FILE__
, __LINE__
, "ssds", "unexpected type for key:", cv
[i
].key
, du
->type
, "expected an integer, range 0 ... 4294967295");
160 case T_CONFIG_BOOLEAN
:
161 if (du
->type
== TYPE_STRING
) {
162 data_string
*ds
= (data_string
*)du
;
164 if (buffer_is_equal_string(ds
->value
, CONST_STR_LEN("enable"))) {
165 *((unsigned short *)(cv
[i
].destination
)) = 1;
166 } else if (buffer_is_equal_string(ds
->value
, CONST_STR_LEN("disable"))) {
167 *((unsigned short *)(cv
[i
].destination
)) = 0;
169 log_error_write(srv
, __FILE__
, __LINE__
, "ssbs", "ERROR: unexpected value for key:", cv
[i
].key
, ds
->value
, "(enable|disable)");
174 log_error_write(srv
, __FILE__
, __LINE__
, "ssss", "ERROR: unexpected type for key:", cv
[i
].key
, "(string)", "\"(enable|disable)\"");
182 case T_CONFIG_UNSUPPORTED
:
183 log_error_write(srv
, __FILE__
, __LINE__
, "ssss", "ERROR: found unsupported key:", cv
[i
].key
, "-", (char *)(cv
[i
].destination
));
185 srv
->config_unsupported
= 1;
188 case T_CONFIG_DEPRECATED
:
189 log_error_write(srv
, __FILE__
, __LINE__
, "ssss", "ERROR: found deprecated key:", cv
[i
].key
, "-", (char *)(cv
[i
].destination
));
191 srv
->config_deprecated
= 1;
200 int config_insert_values_global(server
*srv
, array
*ca
, const config_values_t cv
[], config_scope_type_t scope
) {
204 for (i
= 0; cv
[i
].key
; i
++) {
205 data_string
*touched
;
207 if (NULL
== (du
= array_get_element(ca
, cv
[i
].key
))) {
214 touched
= data_string_init();
216 buffer_copy_string_len(touched
->value
, CONST_STR_LEN(""));
217 buffer_copy_buffer(touched
->key
, du
->key
);
219 array_insert_unique(srv
->config_touched
, (data_unset
*)touched
);
222 return config_insert_values_internal(srv
, ca
, cv
, scope
);
225 static unsigned short sock_addr_get_port(sock_addr
*addr
) {
227 return ntohs(addr
->plain
.sa_family
? addr
->ipv6
.sin6_port
: addr
->ipv4
.sin_port
);
229 return ntohs(addr
->ipv4
.sin_port
);
233 static const char* cond_result_to_string(cond_result_t cond_result
) {
234 switch (cond_result
) {
235 case COND_RESULT_UNSET
: return "unset";
236 case COND_RESULT_SKIP
: return "skipped";
237 case COND_RESULT_FALSE
: return "false";
238 case COND_RESULT_TRUE
: return "true";
239 default: return "invalid cond_result_t";
243 static int config_addrstr_eq_remote_ip_mask(server
*srv
, const char *addrstr
, int nm_bits
, sock_addr
*rmt
) {
244 /* special-case 0 == nm_bits to mean "all bits of the address" in addrstr */
246 #ifdef HAVE_INET_PTON
247 if (1 == inet_pton(AF_INET
, addrstr
, &val
.ipv4
.sin_addr
))
249 if (INADDR_NONE
!= (val
.ipv4
.sin_addr
= inet_addr(addrstr
)))
255 log_error_write(srv
, __FILE__
, __LINE__
, "sd", "ERROR: ipv4 netmask too large:", nm_bits
);
258 nm
= htonl(~((1u << (32 - (0 != nm_bits
? nm_bits
: 32))) - 1));
260 if (rmt
->plain
.sa_family
== AF_INET
) {
261 return ((val
.ipv4
.sin_addr
.s_addr
& nm
) == (rmt
->ipv4
.sin_addr
.s_addr
& nm
));
263 } else if (rmt
->plain
.sa_family
== AF_INET6
264 && IN6_IS_ADDR_V4MAPPED(&rmt
->ipv6
.sin6_addr
)) {
265 in_addr_t x
= *(in_addr_t
*)(rmt
->ipv6
.sin6_addr
.s6_addr
+12);
266 return ((val
.ipv4
.sin_addr
.s_addr
& nm
) == (x
& nm
));
271 #if defined(HAVE_INET_PTON) && defined(HAVE_IPV6)
272 } else if (1 == inet_pton(AF_INET6
, addrstr
, &val
.ipv6
.sin6_addr
)) {
274 log_error_write(srv
, __FILE__
, __LINE__
, "sd", "ERROR: ipv6 netmask too large:", nm_bits
);
277 if (rmt
->plain
.sa_family
== AF_INET6
) {
278 uint8_t *a
= (uint8_t *)&val
.ipv6
.sin6_addr
.s6_addr
[0];
279 uint8_t *b
= (uint8_t *)&rmt
->ipv6
.sin6_addr
.s6_addr
[0];
282 match
= (nm_bits
>= 8)
284 : (*a
>> (8 - nm_bits
)) == (*b
>> (8 - nm_bits
));
285 } while (match
&& (nm_bits
-= 8) > 0);
287 } else if (rmt
->plain
.sa_family
== AF_INET
288 && IN6_IS_ADDR_V4MAPPED(&val
.ipv6
.sin6_addr
)) {
289 in_addr_t x
= *(in_addr_t
*)(val
.ipv6
.sin6_addr
.s6_addr
+12);
291 htonl(~((1u << (32 - (0 != nm_bits
? (nm_bits
> 96 ? nm_bits
- 96 : 0) : 32))) - 1));
292 return ((x
& nm
) == (rmt
->ipv4
.sin_addr
.s_addr
& nm
));
298 log_error_write(srv
, __FILE__
, __LINE__
, "ss", "ERROR: ip addr is invalid:", addrstr
);
303 static int config_addrbuf_eq_remote_ip_mask(server
*srv
, buffer
*string
, char *nm_slash
, sock_addr
*rmt
) {
305 int nm_bits
= strtol(nm_slash
+ 1, &err
, 10);
306 size_t addrstrlen
= (size_t)(nm_slash
- string
->ptr
);
307 char addrstr
[64]; /*(larger than INET_ADDRSTRLEN and INET6_ADDRSTRLEN)*/
310 log_error_write(srv
, __FILE__
, __LINE__
, "sbs", "ERROR: non-digit found in netmask:", string
, err
);
315 if (*(nm_slash
+1) == '\0') {
316 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "ERROR: no number after / ", string
);
318 log_error_write(srv
, __FILE__
, __LINE__
, "sbs", "ERROR: invalid netmask <= 0:", string
, err
);
323 if (addrstrlen
>= sizeof(addrstr
)) {
324 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "ERROR: address string too long:", string
);
328 memcpy(addrstr
, string
->ptr
, addrstrlen
);
329 addrstr
[addrstrlen
] = '\0';
331 return config_addrstr_eq_remote_ip_mask(srv
, addrstr
, nm_bits
, rmt
);
334 static cond_result_t
config_check_cond_cached(server
*srv
, connection
*con
, data_config
*dc
);
336 static cond_result_t
config_check_cond_nocache(server
*srv
, connection
*con
, data_config
*dc
) {
338 server_socket
*srv_sock
= con
->srv_socket
;
339 cond_cache_t
*cache
= &con
->cond_cache
[dc
->context_ndx
];
341 /* check parent first */
342 if (dc
->parent
&& dc
->parent
->context_ndx
) {
344 * a nested conditional
346 * if the parent is not decided yet or false, we can't be true either
348 if (con
->conf
.log_condition_handling
) {
349 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "go parent", dc
->parent
->key
);
352 switch (config_check_cond_cached(srv
, con
, dc
->parent
)) {
353 case COND_RESULT_UNSET
:
355 return COND_RESULT_UNSET
;
356 case COND_RESULT_SKIP
:
357 case COND_RESULT_FALSE
:
358 /* failed precondition */
359 return COND_RESULT_SKIP
;
360 case COND_RESULT_TRUE
:
368 * a else branch; can only be executed if the previous branch
369 * was evaluated as "false" (not unset/skipped/true)
371 if (con
->conf
.log_condition_handling
) {
372 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "go prev", dc
->prev
->key
);
375 /* make sure prev is checked first */
376 switch (config_check_cond_cached(srv
, con
, dc
->prev
)) {
377 case COND_RESULT_UNSET
:
379 return COND_RESULT_UNSET
;
380 case COND_RESULT_SKIP
:
381 case COND_RESULT_TRUE
:
382 /* failed precondition */
383 return COND_RESULT_SKIP
;
384 case COND_RESULT_FALSE
:
390 if (!con
->conditional_is_valid
[dc
->comp
]) {
391 if (con
->conf
.log_condition_handling
) {
392 log_error_write(srv
, __FILE__
, __LINE__
, "dss",
395 "not available yet");
398 return COND_RESULT_UNSET
;
401 /* if we had a real result before and weren't cleared just return it */
402 switch (cache
->local_result
) {
403 case COND_RESULT_TRUE
:
404 case COND_RESULT_FALSE
:
405 return cache
->local_result
;
413 case COMP_HTTP_HOST
: {
414 char *ck_colon
= NULL
, *val_colon
= NULL
;
416 if (!buffer_string_is_empty(con
->uri
.authority
)) {
419 * append server-port to the HTTP_POST if necessary
422 l
= con
->uri
.authority
;
427 ck_colon
= strchr(dc
->string
->ptr
, ':');
428 val_colon
= strchr(l
->ptr
, ':');
430 if (NULL
!= ck_colon
&& NULL
== val_colon
) {
431 /* condition "host:port" but client send "host" */
432 buffer_copy_buffer(srv
->cond_check_buf
, l
);
433 buffer_append_string_len(srv
->cond_check_buf
, CONST_STR_LEN(":"));
434 buffer_append_int(srv
->cond_check_buf
, sock_addr_get_port(&(srv_sock
->addr
)));
435 l
= srv
->cond_check_buf
;
436 } else if (NULL
!= val_colon
&& NULL
== ck_colon
) {
437 /* condition "host" but client send "host:port" */
438 buffer_copy_string_len(srv
->cond_check_buf
, l
->ptr
, val_colon
- l
->ptr
);
439 l
= srv
->cond_check_buf
;
445 #if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
446 } else if (!buffer_string_is_empty(con
->tlsext_server_name
)) {
447 l
= con
->tlsext_server_name
;
450 l
= srv
->empty_string
;
454 case COMP_HTTP_REMOTE_IP
: {
456 /* handle remoteip limitations
458 * "10.0.0.1" is provided for all comparisions
460 * only for == and != we support
465 if ((dc
->cond
== CONFIG_COND_EQ
||
466 dc
->cond
== CONFIG_COND_NE
) &&
467 (NULL
!= (nm_slash
= strchr(dc
->string
->ptr
, '/')))) {
468 switch (config_addrbuf_eq_remote_ip_mask(srv
, dc
->string
, nm_slash
, &con
->dst_addr
)) {
469 case 1: return (dc
->cond
== CONFIG_COND_EQ
) ? COND_RESULT_TRUE
: COND_RESULT_FALSE
;
470 case 0: return (dc
->cond
== CONFIG_COND_EQ
) ? COND_RESULT_FALSE
: COND_RESULT_TRUE
;
471 case -1: return COND_RESULT_FALSE
; /*(error parsing configfile entry)*/
474 l
= con
->dst_addr_buf
;
477 case COMP_HTTP_SCHEME
:
485 case COMP_HTTP_QUERY_STRING
:
489 case COMP_SERVER_SOCKET
:
490 l
= srv_sock
->srv_token
;
493 case COMP_HTTP_REFERER
: {
496 if (NULL
!= (ds
= (data_string
*)array_get_element(con
->request
.headers
, "Referer"))) {
499 l
= srv
->empty_string
;
503 case COMP_HTTP_COOKIE
: {
505 if (NULL
!= (ds
= (data_string
*)array_get_element(con
->request
.headers
, "Cookie"))) {
508 l
= srv
->empty_string
;
512 case COMP_HTTP_USER_AGENT
: {
514 if (NULL
!= (ds
= (data_string
*)array_get_element(con
->request
.headers
, "User-Agent"))) {
517 l
= srv
->empty_string
;
521 case COMP_HTTP_REQUEST_METHOD
: {
522 const char *method
= get_http_method_name(con
->request
.http_method
);
524 /* we only have the request method as const char but we need a buffer for comparing */
526 buffer_copy_string(srv
->tmp_buf
, method
);
532 case COMP_HTTP_LANGUAGE
: {
534 if (NULL
!= (ds
= (data_string
*)array_get_element(con
->request
.headers
, "Accept-Language"))) {
537 l
= srv
->empty_string
;
542 return COND_RESULT_FALSE
;
546 if (con
->conf
.log_condition_handling
) {
547 log_error_write(srv
, __FILE__
, __LINE__
, "bsbs", dc
->comp_key
,
548 "(", l
, ") compare to NULL");
550 return COND_RESULT_FALSE
;
553 if (con
->conf
.log_condition_handling
) {
554 log_error_write(srv
, __FILE__
, __LINE__
, "bsbsb", dc
->comp_key
,
555 "(", l
, ") compare to ", dc
->string
);
560 if (buffer_is_equal(l
, dc
->string
)) {
561 return (dc
->cond
== CONFIG_COND_EQ
) ? COND_RESULT_TRUE
: COND_RESULT_FALSE
;
563 return (dc
->cond
== CONFIG_COND_EQ
) ? COND_RESULT_FALSE
: COND_RESULT_TRUE
;
567 case CONFIG_COND_NOMATCH
:
568 case CONFIG_COND_MATCH
: {
572 #define elementsof(x) (sizeof(x) / sizeof(x[0]))
574 n
= pcre_exec(dc
->regex
, dc
->regex_study
, CONST_BUF_LEN(l
), 0, 0,
575 cache
->matches
, elementsof(cache
->matches
));
577 cache
->patterncount
= n
;
579 cache
->comp_value
= l
;
580 return (dc
->cond
== CONFIG_COND_MATCH
) ? COND_RESULT_TRUE
: COND_RESULT_FALSE
;
582 /* cache is already cleared */
583 return (dc
->cond
== CONFIG_COND_MATCH
) ? COND_RESULT_FALSE
: COND_RESULT_TRUE
;
593 return COND_RESULT_FALSE
;
596 static cond_result_t
config_check_cond_cached(server
*srv
, connection
*con
, data_config
*dc
) {
597 cond_cache_t
*caches
= con
->cond_cache
;
599 if (COND_RESULT_UNSET
== caches
[dc
->context_ndx
].result
) {
600 caches
[dc
->context_ndx
].result
= config_check_cond_nocache(srv
, con
, dc
);
601 switch (caches
[dc
->context_ndx
].result
) {
602 case COND_RESULT_FALSE
:
603 case COND_RESULT_TRUE
:
604 /* remember result of local condition for a partial reset */
605 caches
[dc
->context_ndx
].local_result
= caches
[dc
->context_ndx
].result
;
611 if (con
->conf
.log_condition_handling
) {
612 log_error_write(srv
, __FILE__
, __LINE__
, "dss",
614 "(uncached) result:",
615 cond_result_to_string(caches
[dc
->context_ndx
].result
));
618 if (con
->conf
.log_condition_handling
) {
619 log_error_write(srv
, __FILE__
, __LINE__
, "dss",
622 cond_result_to_string(caches
[dc
->context_ndx
].result
));
625 return caches
[dc
->context_ndx
].result
;
628 /* if we reset the cache result for a node, we also need to clear all
629 * child nodes and else-branches*/
630 static void config_cond_clear_node(server
*srv
, connection
*con
, data_config
*dc
) {
631 /* if a node is "unset" all children are unset too */
632 if (con
->cond_cache
[dc
->context_ndx
].result
!= COND_RESULT_UNSET
) {
635 con
->cond_cache
[dc
->context_ndx
].patterncount
= 0;
636 con
->cond_cache
[dc
->context_ndx
].comp_value
= NULL
;
637 con
->cond_cache
[dc
->context_ndx
].result
= COND_RESULT_UNSET
;
639 for (i
= 0; i
< dc
->children
.used
; ++i
) {
640 data_config
*dc_child
= dc
->children
.data
[i
];
641 if (NULL
== dc_child
->prev
) {
642 /* only call for first node in if-else chain */
643 config_cond_clear_node(srv
, con
, dc_child
);
646 if (NULL
!= dc
->next
) config_cond_clear_node(srv
, con
, dc
->next
);
651 * reset the config-cache for a named item
653 * if the item is COND_LAST_ELEMENT we reset all items
655 void config_cond_cache_reset_item(server
*srv
, connection
*con
, comp_key_t item
) {
658 for (i
= 0; i
< srv
->config_context
->used
; i
++) {
659 data_config
*dc
= (data_config
*)srv
->config_context
->data
[i
];
661 if (item
== dc
->comp
) {
662 /* clear local_result */
663 con
->cond_cache
[i
].local_result
= COND_RESULT_UNSET
;
664 /* clear result in subtree (including the node itself) */
665 config_cond_clear_node(srv
, con
, dc
);
671 * reset the config cache to its initial state at connection start
673 void config_cond_cache_reset(server
*srv
, connection
*con
) {
676 /* resetting all entries; no need to follow children as in config_cond_cache_reset_item */
677 for (i
= 0; i
< srv
->config_context
->used
; i
++) {
678 con
->cond_cache
[i
].result
= COND_RESULT_UNSET
;
679 con
->cond_cache
[i
].local_result
= COND_RESULT_UNSET
;
680 con
->cond_cache
[i
].patterncount
= 0;
681 con
->cond_cache
[i
].comp_value
= NULL
;
684 for (i
= 0; i
< COMP_LAST_ELEMENT
; i
++) {
685 con
->conditional_is_valid
[i
] = 0;
689 int config_check_cond(server
*srv
, connection
*con
, data_config
*dc
) {
690 if (con
->conf
.log_condition_handling
) {
691 log_error_write(srv
, __FILE__
, __LINE__
, "s", "=== start of condition block ===");
693 return (config_check_cond_cached(srv
, con
, dc
) == COND_RESULT_TRUE
);
696 int config_append_cond_match_buffer(connection
*con
, data_config
*dc
, buffer
*buf
, int n
)
698 cond_cache_t
*cache
= &con
->cond_cache
[dc
->context_ndx
];
699 if (n
>= cache
->patterncount
) {
703 n
<<= 1; /* n *= 2 */
704 buffer_append_string_len(buf
,
705 cache
->comp_value
->ptr
+ cache
->matches
[n
],
706 cache
->matches
[n
+ 1] - cache
->matches
[n
]);