# include "first.h"
# include "base.h"
# include "burl.h"
# include "fdevent.h"
# include "keyvalue.h"
# include "log.h"
# include "stream.h"
# include "configparser.h"
# include "configfile.h"
# include "plugin.h"
# include "stat_cache.h"
# include "sys-crypto.h"
# include <sys/stat.h>
# include <sys/wait.h>
# include <stdlib.h>
# include <fcntl.h>
# include <unistd.h>
# include <errno.h>
# include <string.h>
# include <ctype.h>
# include <limits.h>
# include <glob.h>
# ifndef PATH_MAX
# define PATH_MAX 4096
# endif
typedef struct {
PLUGIN_DATA ;
specific_config defaults ;
} config_data_base ;
static void config_free_config ( void * const p_d ) {
plugin_data_base * const p = p_d ;
if ( NULL = = p ) return ;
if ( NULL = = p - > cvlist ) { free ( p ) ; return ; }
/* (init i to 0 if global context; to 1 to skip empty global context) */
for ( int i = ! p - > cvlist [ 0 ] . v . u2 [ 1 ] , used = p - > nconfig ; i < used ; + + i ) {
config_plugin_value_t * cpv = p - > cvlist + p - > cvlist [ i ] . v . u2 [ 0 ] ;
for ( ; - 1 ! = cpv - > k_id ; + + cpv ) {
switch ( cpv - > k_id ) {
case 18 : /* server.kbytes-per-second */
if ( cpv - > vtype = = T_CONFIG_LOCAL ) free ( cpv - > v . v ) ;
break ;
default :
break ;
}
}
}
free ( p - > cvlist ) ;
free ( p ) ;
}
void config_reset_config_bytes_sec ( void * const p_d ) {
plugin_data_base * const p = p_d ;
if ( NULL = = p - > cvlist ) return ;
/* (init i to 0 if global context; to 1 to skip empty global context) */
for ( int i = ! p - > cvlist [ 0 ] . v . u2 [ 1 ] , used = p - > nconfig ; i < used ; + + i ) {
config_plugin_value_t * cpv = p - > cvlist + p - > cvlist [ i ] . v . u2 [ 0 ] ;
for ( ; - 1 ! = cpv - > k_id ; + + cpv ) {
switch ( cpv - > k_id ) {
case 18 : /* server.kbytes-per-second */
if ( cpv - > vtype = = T_CONFIG_LOCAL ) ( ( off_t * ) cpv - > v . v ) [ 0 ] = 0 ;
break ;
default :
break ;
}
}
}
}
static void config_merge_config_cpv ( specific_config * const pconf , const config_plugin_value_t * const cpv ) {
switch ( cpv - > k_id ) { /* index into static config_plugin_keys_t cpk[] */
case 0 : /* server.document-root */
pconf - > document_root = cpv - > v . b ;
break ;
case 1 : /* server.name */
pconf - > server_name = cpv - > v . b ;
break ;
case 2 : /* server.tag */
pconf - > server_tag = cpv - > v . b ;
break ;
case 3 : /* server.max-request-size */
pconf - > max_request_size = cpv - > v . u ;
break ;
case 4 : /* server.max-keep-alive-requests */
pconf - > max_keep_alive_requests = cpv - > v . shrt ;
break ;
case 5 : /* server.max-keep-alive-idle */
pconf - > max_keep_alive_idle = cpv - > v . shrt ;
break ;
case 6 : /* server.max-read-idle */
pconf - > max_read_idle = cpv - > v . shrt ;
break ;
case 7 : /* server.max-write-idle */
pconf - > max_write_idle = cpv - > v . shrt ;
break ;
case 8 : /* server.errorfile-prefix */
pconf - > errorfile_prefix = cpv - > v . b ;
break ;
case 9 : /* server.error-handler */
pconf - > error_handler = cpv - > v . b ;
break ;
case 10 : /* server.error-handler-404 */
pconf - > error_handler_404 = cpv - > v . b ;
break ;
case 11 : /* server.error-intercept */
pconf - > error_intercept = ( 0 ! = cpv - > v . u ) ;
break ;
case 12 : /* server.force-lowercase-filenames */
pconf - > force_lowercase_filenames = ( 0 ! = cpv - > v . u ) ;
break ;
case 13 : /* server.follow-symlink */
pconf - > follow_symlink = ( 0 ! = cpv - > v . u ) ;
break ;
case 14 : /* server.protocol-http11 */
pconf - > allow_http11 = ( 0 ! = cpv - > v . u ) ;
break ;
case 15 : /* server.range-requests */
pconf - > range_requests = ( 0 ! = cpv - > v . u ) ;
break ;
case 16 : /* server.stream-request-body */
pconf - > stream_request_body = cpv - > v . shrt ;
break ;
case 17 : /* server.stream-response-body */
pconf - > stream_response_body = cpv - > v . shrt ;
break ;
case 18 : /* server.kbytes-per-second */
pconf - > global_bytes_per_second = ( unsigned int ) ( ( off_t * ) cpv - > v . v ) [ 1 ] ;
pconf - > global_bytes_per_second_cnt_ptr = cpv - > v . v ;
break ;
case 19 : /* connection.kbytes-per-second */
pconf - > bytes_per_second = ( unsigned int ) cpv - > v . shrt < < 10 ; /* (*=1024) */
break ;
case 20 : /* mimetype.assign */
pconf - > mimetypes = cpv - > v . a ;
break ;
case 21 : /* mimetype.use-xattr */
pconf - > use_xattr = ( 0 ! = cpv - > v . u ) ;
break ;
case 22 : /* etag.use-inode */
cpv - > v . u
? ( pconf - > etag_flags | = ETAG_USE_INODE )
: ( pconf - > etag_flags & = ~ ETAG_USE_INODE ) ;
break ;
case 23 : /* etag.use-mtime */
cpv - > v . u
? ( pconf - > etag_flags | = ETAG_USE_MTIME )
: ( pconf - > etag_flags & = ~ ETAG_USE_MTIME ) ;
break ;
case 24 : /* etag.use-size */
cpv - > v . u
? ( pconf - > etag_flags | = ETAG_USE_SIZE )
: ( pconf - > etag_flags & = ~ ETAG_USE_SIZE ) ;
break ;
case 25 : /* debug.log-condition-handling */
pconf - > log_condition_handling = ( 0 ! = cpv - > v . u ) ;
break ;
case 26 : /* debug.log-file-not-found */
pconf - > log_file_not_found = ( 0 ! = cpv - > v . u ) ;
break ;
case 27 : /* debug.log-request-handling */
pconf - > log_request_handling = ( 0 ! = cpv - > v . u ) ;
break ;
case 28 : /* debug.log-request-header */
pconf - > log_request_header = ( 0 ! = cpv - > v . u ) ;
break ;
case 29 : /* debug.log-response-header */
pconf - > log_response_header = ( 0 ! = cpv - > v . u ) ;
break ;
case 30 : /* debug.log-timeouts */
pconf - > log_timeouts = ( 0 ! = cpv - > v . u ) ;
break ;
default : /* should not happen */
return ;
}
}
static void config_merge_config ( specific_config * const pconf , const config_plugin_value_t * cpv ) {
do {
config_merge_config_cpv ( pconf , cpv ) ;
} while ( ( + + cpv ) - > k_id ! = - 1 ) ;
}
void config_patch_config ( server * const srv , connection * const con ) {
config_data_base * const p = srv - > config_data_base ;
/* performed by config_reset_config() */
/*memcpy(&con->conf, &p->defaults, sizeof(specific_config));*/
for ( int i = 1 , used = p - > nconfig ; i < used ; + + i ) {
if ( config_check_cond ( con , ( uint32_t ) p - > cvlist [ i ] . k_id ) )
config_merge_config ( & con - > conf , p - > cvlist + p - > cvlist [ i ] . v . u2 [ 0 ] ) ;
}
}
void config_reset_config ( server * const srv , connection * const con ) {
/* initialize specific_config (con->conf) from top-level specific_config */
config_data_base * const p = srv - > config_data_base ;
con - > server_name = p - > defaults . server_name ;
memcpy ( & con - > conf , & p - > defaults , sizeof ( specific_config ) ) ;
}
static int config_burl_normalize_cond ( server * srv ) {
for ( uint32_t i = 0 ; i < srv - > config_context - > used ; + + i ) {
data_config * const config = ( data_config * ) srv - > config_context - > data [ i ] ;
if ( COMP_HTTP_QUERY_STRING ! = config - > comp ) continue ;
switch ( config - > cond ) {
case CONFIG_COND_NE :
case CONFIG_COND_EQ :
/* (can use this routine as long as it does not perform
* any regex - specific normalization of first arg ) */
pcre_keyvalue_burl_normalize_key ( & config - > string , srv - > tmp_buf ) ;
break ;
case CONFIG_COND_NOMATCH :
case CONFIG_COND_MATCH :
pcre_keyvalue_burl_normalize_key ( & config - > string , srv - > tmp_buf ) ;
if ( ! data_config_pcre_compile ( config ) ) return 0 ;
break ;
default :
break ;
}
}
return 1 ;
}
# if defined(HAVE_MYSQL) || (defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER))
static void config_warn_authn_module ( server * srv , const char * module , size_t len ) {
for ( size_t i = 0 ; i < srv - > config_context - > used ; + + i ) {
const data_config * config = ( data_config const * ) srv - > config_context - > data [ i ] ;
const data_unset * du = array_get_element_klen ( config - > value , CONST_STR_LEN ( " auth.backend " ) ) ;
if ( NULL ! = du & & du - > type = = TYPE_STRING ) {
data_string * ds = ( data_string * ) du ;
if ( buffer_is_equal_string ( & ds - > value , module , len ) ) {
buffer_copy_string_len ( srv - > tmp_buf , CONST_STR_LEN ( " mod_authn_ " ) ) ;
buffer_append_string_len ( srv - > tmp_buf , module , len ) ;
array_insert_value ( srv - > srvconf . modules , CONST_BUF_LEN ( srv - > tmp_buf ) ) ;
log_error_write ( srv , __FILE__ , __LINE__ , " SSSsSSS " , " Warning: please add \" mod_authn_ " , module , " \" to server.modules list in lighttpd.conf. A future release of lighttpd 1.4.x will not automatically load mod_authn_ " , module , " and lighttpd will fail to start up since your lighttpd.conf uses auth.backend = \" " , module , " \" . " ) ;
return ;
}
}
}
}
# endif
# ifdef USE_OPENSSL_CRYPTO
static void config_warn_openssl_module ( server * srv ) {
for ( size_t i = 0 ; i < srv - > config_context - > used ; + + i ) {
const data_config * config = ( data_config const * ) srv - > config_context - > data [ i ] ;
for ( size_t j = 0 ; j < config - > value - > used ; + + j ) {
data_unset * du = config - > value - > data [ j ] ;
if ( 0 = = strncmp ( du - > key . ptr , " ssl. " , sizeof ( " ssl. " ) - 1 ) ) {
/* mod_openssl should be loaded after mod_extforward */
array_insert_value ( srv - > srvconf . modules , CONST_STR_LEN ( " mod_openssl " ) ) ;
log_error_write ( srv , __FILE__ , __LINE__ , " S " , " Warning: please add \" mod_openssl \" to server.modules list in lighttpd.conf. A future release of lighttpd 1.4.x *will not* automatically load mod_openssl and lighttpd *will not* use SSL/TLS where your lighttpd.conf contains ssl.* directives " ) ;
return ;
}
}
}
}
# endif
static void config_compat_module_load ( server * srv ) {
int prepend_mod_indexfile = 1 ;
int append_mod_dirlisting = 1 ;
int append_mod_staticfile = 1 ;
int append_mod_authn_file = 1 ;
int append_mod_authn_ldap = 1 ;
int append_mod_authn_mysql = 1 ;
int append_mod_openssl = 1 ;
int contains_mod_auth = 0 ;
for ( uint32_t i = 0 ; i < srv - > srvconf . modules - > used ; + + i ) {
buffer * m = & ( ( data_string * ) srv - > srvconf . modules - > data [ i ] ) - > value ;
if ( buffer_eq_slen ( m , CONST_STR_LEN ( " mod_indexfile " ) ) )
prepend_mod_indexfile = 0 ;
else if ( buffer_eq_slen ( m , CONST_STR_LEN ( " mod_staticfile " ) ) )
append_mod_staticfile = 0 ;
else if ( buffer_eq_slen ( m , CONST_STR_LEN ( " mod_dirlisting " ) ) )
append_mod_dirlisting = 0 ;
else if ( buffer_eq_slen ( m , CONST_STR_LEN ( " mod_openssl " ) ) )
append_mod_openssl = 0 ;
else if ( buffer_eq_slen ( m , CONST_STR_LEN ( " mod_authn_file " ) ) )
append_mod_authn_file = 0 ;
else if ( buffer_eq_slen ( m , CONST_STR_LEN ( " mod_authn_ldap " ) ) )
append_mod_authn_ldap = 0 ;
else if ( buffer_eq_slen ( m , CONST_STR_LEN ( " mod_authn_mysql " ) ) )
append_mod_authn_mysql = 0 ;
else if ( buffer_eq_slen ( m , CONST_STR_LEN ( " mod_auth " ) ) )
contains_mod_auth = 1 ;
if ( 0 = = prepend_mod_indexfile & &
0 = = append_mod_dirlisting & &
0 = = append_mod_staticfile & &
0 = = append_mod_openssl & &
0 = = append_mod_authn_file & &
0 = = append_mod_authn_ldap & &
0 = = append_mod_authn_mysql & &
1 = = contains_mod_auth ) {
break ;
}
}
/* prepend default modules */
if ( prepend_mod_indexfile ) {
/* mod_indexfile has to be loaded before mod_fastcgi and friends */
array * modules = array_init ( ) ;
array_insert_value ( modules , CONST_STR_LEN ( " mod_indexfile " ) ) ;
for ( uint32_t i = 0 ; i < srv - > srvconf . modules - > used ; + + i ) {
data_string * ds = ( data_string * ) srv - > srvconf . modules - > data [ i ] ;
array_insert_value ( modules , CONST_BUF_LEN ( & ds - > value ) ) ;
}
array_free ( srv - > srvconf . modules ) ;
srv - > srvconf . modules = modules ;
}
/* append default modules */
if ( append_mod_dirlisting ) {
array_insert_value ( srv - > srvconf . modules , CONST_STR_LEN ( " mod_dirlisting " ) ) ;
}
if ( append_mod_staticfile ) {
array_insert_value ( srv - > srvconf . modules , CONST_STR_LEN ( " mod_staticfile " ) ) ;
}
if ( append_mod_openssl ) {
# ifdef USE_OPENSSL_CRYPTO
config_warn_openssl_module ( srv ) ;
# endif
}
/* mod_auth.c,http_auth.c auth backends were split into separate modules
* Automatically load auth backend modules for compatibility with
* existing lighttpd 1.4 . x configs */
if ( contains_mod_auth ) {
if ( append_mod_authn_file ) {
array_insert_value ( srv - > srvconf . modules , CONST_STR_LEN ( " mod_authn_file " ) ) ;
}
if ( append_mod_authn_ldap ) {
# if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
config_warn_authn_module ( srv , CONST_STR_LEN ( " ldap " ) ) ;
# endif
}
if ( append_mod_authn_mysql ) {
# if defined(HAVE_MYSQL)
config_warn_authn_module ( srv , CONST_STR_LEN ( " mysql " ) ) ;
# endif
}
}
}
static int config_http_parseopts ( server * srv , const array * a ) {
unsigned short int opts = srv - > srvconf . http_url_normalize ;
unsigned short int decode_2f = 1 ;
int rc = 1 ;
if ( ! array_is_kvstring ( a ) ) {
log_error ( srv - > errh , __FILE__ , __LINE__ ,
" unexpected value for server.http-parseopts; "
" expected list of \" key \" => \" [enable|disable] \" " ) ;
return 0 ;
}
for ( size_t i = 0 ; i < a - > used ; + + i ) {
const data_string * const ds = ( const data_string * ) a - > data [ i ] ;
const buffer * k = & ds - > key ;
const buffer * v = & ds - > value ;
unsigned short int opt ;
int val = 0 ;
if ( buffer_eq_slen ( v , CONST_STR_LEN ( " enable " ) ) )
val = 1 ;
else if ( buffer_eq_slen ( v , CONST_STR_LEN ( " disable " ) ) )
val = 0 ;
else {
log_error ( srv - > errh , __FILE__ , __LINE__ ,
" unrecognized value for server.http-parseopts: "
" %s => %s (expect \" [enable|disable] \" ) " , k - > ptr , v - > ptr ) ;
rc = 0 ;
}
if ( buffer_eq_slen ( k , CONST_STR_LEN ( " url-normalize " ) ) )
opt = HTTP_PARSEOPT_URL_NORMALIZE ;
else if ( buffer_eq_slen ( k , CONST_STR_LEN ( " url-normalize-unreserved " ) ) )
opt = HTTP_PARSEOPT_URL_NORMALIZE_UNRESERVED ;
else if ( buffer_eq_slen ( k , CONST_STR_LEN ( " url-normalize-required " ) ) )
opt = HTTP_PARSEOPT_URL_NORMALIZE_REQUIRED ;
else if ( buffer_eq_slen ( k , CONST_STR_LEN ( " url-ctrls-reject " ) ) )
opt = HTTP_PARSEOPT_URL_NORMALIZE_CTRLS_REJECT ;
else if ( buffer_eq_slen ( k , CONST_STR_LEN ( " url-path-backslash-trans " ) ) )
opt = HTTP_PARSEOPT_URL_NORMALIZE_PATH_BACKSLASH_TRANS ;
else if ( buffer_eq_slen ( k , CONST_STR_LEN ( " url-path-2f-decode " ) ) )
opt = HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_DECODE ;
else if ( buffer_eq_slen ( k , CONST_STR_LEN ( " url-path-2f-reject " ) ) )
opt = HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_REJECT ;
else if ( buffer_eq_slen ( k , CONST_STR_LEN ( " url-path-dotseg-remove " ) ) )
opt = HTTP_PARSEOPT_URL_NORMALIZE_PATH_DOTSEG_REMOVE ;
else if ( buffer_eq_slen ( k , CONST_STR_LEN ( " url-path-dotseg-reject " ) ) )
opt = HTTP_PARSEOPT_URL_NORMALIZE_PATH_DOTSEG_REJECT ;
else if ( buffer_eq_slen ( k , CONST_STR_LEN ( " url-query-20-plus " ) ) )
opt = HTTP_PARSEOPT_URL_NORMALIZE_QUERY_20_PLUS ;
else if ( buffer_eq_slen ( k , CONST_STR_LEN ( " header-strict " ) ) ) {
srv - > srvconf . http_header_strict = val ;
continue ;
}
else if ( buffer_eq_slen ( k , CONST_STR_LEN ( " host-strict " ) ) ) {
srv - > srvconf . http_host_strict = val ;
continue ;
}
else if ( buffer_eq_slen ( k , CONST_STR_LEN ( " host-normalize " ) ) ) {
srv - > srvconf . http_host_normalize = val ;
continue ;
}
else if ( buffer_eq_slen ( k , CONST_STR_LEN ( " method-get-body " ) ) ) {
srv - > srvconf . http_method_get_body = val ;
continue ;
}
else {
log_error ( srv - > errh , __FILE__ , __LINE__ ,
" unrecognized key for server.http-parseopts: %s " , k - > ptr ) ;
rc = 0 ;
continue ;
}
if ( val )
opts | = opt ;
else {
opts & = ~ opt ;
if ( opt = = HTTP_PARSEOPT_URL_NORMALIZE ) {
opts = 0 ;
break ;
}
if ( opt = = HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_DECODE ) {
decode_2f = 0 ;
}
}
}
if ( opts ! = 0 ) {
opts | = HTTP_PARSEOPT_URL_NORMALIZE ;
if ( ( opts & ( HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_DECODE
| HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_REJECT ) )
= = ( HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_DECODE
| HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_REJECT ) ) {
log_error ( srv - > errh , __FILE__ , __LINE__ ,
" conflicting options in server.http-parseopts: "
" url-path-2f-decode, url-path-2f-reject " ) ;
rc = 0 ;
}
if ( ( opts & ( HTTP_PARSEOPT_URL_NORMALIZE_PATH_DOTSEG_REMOVE
| HTTP_PARSEOPT_URL_NORMALIZE_PATH_DOTSEG_REJECT ) )
= = ( HTTP_PARSEOPT_URL_NORMALIZE_PATH_DOTSEG_REMOVE
| HTTP_PARSEOPT_URL_NORMALIZE_PATH_DOTSEG_REJECT ) ) {
log_error ( srv - > errh , __FILE__ , __LINE__ ,
" conflicting options in server.http-parseopts: "
" url-path-dotseg-remove, url-path-dotseg-reject " ) ;
rc = 0 ;
}
if ( ! ( opts & ( HTTP_PARSEOPT_URL_NORMALIZE_UNRESERVED
| HTTP_PARSEOPT_URL_NORMALIZE_REQUIRED ) ) ) {
opts | = HTTP_PARSEOPT_URL_NORMALIZE_UNRESERVED ;
if ( decode_2f
& & ! ( opts & HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_REJECT ) )
opts | = HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_DECODE ;
}
}
srv - > srvconf . http_url_normalize = opts ;
return rc ;
}
static int config_insert_srvconf ( server * srv ) {
static const config_plugin_keys_t cpk [ ] = {
{ CONST_STR_LEN ( " server.modules " ) ,
T_CONFIG_ARRAY ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.compat-module-load " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.systemd-socket-activation " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.port " ) ,
T_CONFIG_SHORT ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.bind " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.network-backend " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.chroot " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.username " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.groupname " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.errorlog " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.breakagelog " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.errorlog-use-syslog " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.syslog-facility " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.core-files " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.event-handler " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.pid-file " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.max-worker " ) ,
T_CONFIG_SHORT ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.max-fds " ) ,
T_CONFIG_SHORT ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.max-connections " ) ,
T_CONFIG_SHORT ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.max-request-field-size " ) ,
T_CONFIG_INT ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.chunkqueue-chunk-sz " ) ,
T_CONFIG_INT ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.upload-temp-file-size " ) ,
T_CONFIG_INT ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.upload-dirs " ) ,
T_CONFIG_ARRAY ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.http-parseopts " ) ,
T_CONFIG_ARRAY ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.http-parseopt-header-strict " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.http-parseopt-host-strict " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.http-parseopt-host-normalize " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.reject-expect-100-with-417 " ) , /*(ignored)*/
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " server.stat-cache-engine " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " mimetype.xattr-name " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " ssl.engine " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " debug.log-request-header-on-error " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_SERVER }
, { CONST_STR_LEN ( " debug.log-state-handling " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_SERVER }
, { NULL , 0 ,
T_CONFIG_UNSET ,
T_CONFIG_SCOPE_UNSET }
} ;
if ( 0 ! = stat_cache_choose_engine ( srv , NULL ) ) /*(set initial default)*/
return HANDLER_ERROR ;
int rc = 0 ;
plugin_data_base srvplug ;
memset ( & srvplug , 0 , sizeof ( srvplug ) ) ;
plugin_data_base * const p = & srvplug ;
if ( ! config_plugin_values_init ( srv , p , cpk , " global " ) )
return HANDLER_ERROR ;
int ssl_enabled = 0 ; /*(directive checked here only to set default port)*/
/* process and validate T_CONFIG_SCOPE_SERVER config directives */
if ( p - > cvlist [ 0 ] . v . u2 [ 1 ] ) {
config_plugin_value_t * cpv = p - > cvlist + p - > cvlist [ 0 ] . v . u2 [ 0 ] ;
for ( ; - 1 ! = cpv - > k_id ; + + cpv ) {
switch ( cpv - > k_id ) {
case 0 : /* server.modules */
if ( ! array_is_vlist ( cpv - > v . a ) ) {
log_error ( srv - > errh , __FILE__ , __LINE__ ,
" unexpected value for %s; "
" expected list of \" mod_xxxxxx \" strings " ,
cpk [ cpv - > k_id ] . k ) ;
rc = HANDLER_ERROR ;
break ;
}
array_copy_array ( srv - > srvconf . modules , cpv - > v . a ) ;
break ;
case 1 : /* server.compat-module-load */
srv - > srvconf . compat_module_load = ( unsigned short ) cpv - > v . u ;
break ;
case 2 : /* server.systemd-socket-activation */
srv - > srvconf . systemd_socket_activation = ( unsigned short ) cpv - > v . u ;
break ;
case 3 : /* server.port */
srv - > srvconf . port = cpv - > v . shrt ;
break ;
case 4 : /* server.bind */
srv - > srvconf . bindhost = cpv - > v . b ;
break ;
case 5 : /* server.network-backend */
srv - > srvconf . network_backend = cpv - > v . b ;
break ;
case 6 : /* server.chroot */
srv - > srvconf . changeroot = cpv - > v . b ;
break ;
case 7 : /* server.username */
srv - > srvconf . username = cpv - > v . b ;
break ;
case 8 : /* server.groupname */
srv - > srvconf . groupname = cpv - > v . b ;
break ;
case 9 : /* server.errorlog */
srv - > srvconf . errorlog_file = cpv - > v . b ;
break ;
case 10 : /* server.breakagelog */
srv - > srvconf . breakagelog_file = cpv - > v . b ;
break ;
case 11 : /* server.errorlog-use-syslog */
srv - > srvconf . errorlog_use_syslog = ( unsigned short ) cpv - > v . u ;
break ;
case 12 : /* server.syslog-facility */
srv - > srvconf . syslog_facility = cpv - > v . b ;
break ;
case 13 : /* server.core-files */
srv - > srvconf . enable_cores = ( unsigned short ) cpv - > v . u ;
break ;
case 14 : /* server.event-handler */
srv - > srvconf . event_handler = cpv - > v . b - > ptr ;
break ;
case 15 : /* server.pid-file */
* ( const buffer * * ) & srv - > srvconf . pid_file = cpv - > v . b ;
break ;
case 16 : /* server.max-worker */
srv - > srvconf . max_worker = ( unsigned short ) cpv - > v . u ;
break ;
case 17 : /* server.max-fds */
srv - > srvconf . max_fds = ( unsigned short ) cpv - > v . u ;
break ;
case 18 : /* server.max-connections */
srv - > srvconf . max_conns = ( unsigned short ) cpv - > v . u ;
break ;
case 19 : /* server.max-request-field-size */
srv - > srvconf . max_request_field_size = cpv - > v . u ;
break ;
case 20 : /* server.chunkqueue-chunk-sz */
chunkqueue_set_chunk_size ( cpv - > v . u ) ;
break ;
case 21 : /* server.upload-temp-file-size */
srv - > srvconf . upload_temp_file_size = cpv - > v . u ;
break ;
case 22 : /* server.upload-dirs */
if ( ! array_is_vlist ( cpv - > v . a ) ) {
log_error ( srv - > errh , __FILE__ , __LINE__ ,
" unexpected value for %s; "
" expected list of \" path \" strings " , cpk [ cpv - > k_id ] . k ) ;
rc = HANDLER_ERROR ;
break ;
}
array_copy_array ( srv - > srvconf . upload_tempdirs , cpv - > v . a ) ;
break ;
case 23 : /* server.http-parseopts */
if ( ! config_http_parseopts ( srv , cpv - > v . a ) )
rc = HANDLER_ERROR ;
break ;
case 24 : /* server.http-parseopt-header-strict */
srv - > srvconf . http_header_strict = ( 0 ! = cpv - > v . u ) ;
break ;
case 25 : /* server.http-parseopt-host-strict */
srv - > srvconf . http_host_strict = ( 0 ! = cpv - > v . u ) ;
break ;
case 26 : /* server.http-parseopt-host-normalize */
srv - > srvconf . http_host_normalize = ( 0 ! = cpv - > v . u ) ;
break ;
case 27 : /* server.reject-expect-100-with-417 */ /*(ignored)*/
break ;
case 28 : /* server.stat-cache-engine */
if ( 0 ! = stat_cache_choose_engine ( srv , cpv - > v . b ) )
rc = HANDLER_ERROR ;
break ;
case 29 : /* mimetype.xattr-name */
srv - > srvconf . xattr_name = cpv - > v . b - > ptr ;
break ;
case 30 : /* ssl.engine */
ssl_enabled = ( 0 ! = cpv - > v . u ) ;
# ifndef USE_OPENSSL_CRYPTO
if ( ssl_enabled ) {
log_error ( srv - > errh , __FILE__ , __LINE__ ,
" ssl support is missing; "
" recompile with e.g. --with-openssl " ) ;
rc = HANDLER_ERROR ;
break ;
}
# endif
break ;
case 31 : /* debug.log-request-header-on-error */
srv - > srvconf . log_request_header_on_error = ( 0 ! = cpv - > v . u ) ;
break ;
case 32 : /* debug.log-state-handling */
srv - > srvconf . log_state_handling = ( 0 ! = cpv - > v . u ) ;
break ;
default : /* should not happen */
break ;
}
}
}
if ( 0 = = srv - > srvconf . port )
srv - > srvconf . port = ssl_enabled ? 443 : 80 ;
if ( srv - > srvconf . compat_module_load )
config_compat_module_load ( srv ) ;
if ( srv - > srvconf . http_url_normalize & & ! config_burl_normalize_cond ( srv ) )
rc = HANDLER_ERROR ;
free ( srvplug . cvlist ) ;
return rc ;
}
static int config_insert ( server * srv ) {
static const config_plugin_keys_t cpk [ ] = {
{ CONST_STR_LEN ( " server.document-root " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.name " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.tag " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.max-request-size " ) ,
T_CONFIG_INT ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.max-keep-alive-requests " ) ,
T_CONFIG_SHORT ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.max-keep-alive-idle " ) ,
T_CONFIG_SHORT ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.max-read-idle " ) ,
T_CONFIG_SHORT ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.max-write-idle " ) ,
T_CONFIG_SHORT ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.errorfile-prefix " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.error-handler " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.error-handler-404 " ) ,
T_CONFIG_STRING ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.error-intercept " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.force-lowercase-filenames " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.follow-symlink " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.protocol-http11 " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.range-requests " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.stream-request-body " ) ,
T_CONFIG_SHORT ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.stream-response-body " ) ,
T_CONFIG_SHORT ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " server.kbytes-per-second " ) ,
T_CONFIG_SHORT ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " connection.kbytes-per-second " ) ,
T_CONFIG_SHORT ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " mimetype.assign " ) ,
T_CONFIG_ARRAY ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " mimetype.use-xattr " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " etag.use-inode " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " etag.use-mtime " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " etag.use-size " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " debug.log-condition-handling " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " debug.log-file-not-found " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " debug.log-request-handling " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " debug.log-request-header " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " debug.log-response-header " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { CONST_STR_LEN ( " debug.log-timeouts " ) ,
T_CONFIG_BOOL ,
T_CONFIG_SCOPE_CONNECTION }
, { NULL , 0 ,
T_CONFIG_UNSET ,
T_CONFIG_SCOPE_UNSET }
} ;
int rc = 0 ;
config_data_base * const p = calloc ( 1 , sizeof ( config_data_base ) ) ;
force_assert ( p ) ;
srv - > config_data_base = p ;
if ( ! config_plugin_values_init ( srv , p , cpk , " base " ) )
return HANDLER_ERROR ;
/* process and validate T_CONFIG_SCOPE_CONNECTION config directives
* ( init i to 0 if global context ; to 1 to skip empty global context ) */
for ( int i = ! p - > cvlist [ 0 ] . v . u2 [ 1 ] ; i < p - > nconfig ; + + i ) {
config_plugin_value_t * cpv = p - > cvlist + p - > cvlist [ i ] . v . u2 [ 0 ] ;
for ( ; - 1 ! = cpv - > k_id ; + + cpv ) {
switch ( cpv - > k_id ) {