# Chapter 4: The Configuration System ## How Apache Configuration Works Apache's configuration system is one of its most powerful features. The familiar `httpd.conf` syntax is processed by a sophisticated system that: 1. Parses configuration files 2. Calls modules to handle directives they registered 3. Builds configuration structures at multiple scopes 4. Merges configurations from different contexts ## Configuration Contexts Apache configuration operates at multiple nesting levels. Each level can override settings from the level above: ``` ┌─────────────────────────────────────────────────────────────────┐ │ Server (Global) Context │ │ ServerRoot, Listen, LoadModule, ErrorLog │ │ ┌───────────────────────────────────────────────────────────┐ │ │ │ Virtual Host Context │ │ │ │ │ │ │ │ ServerName www.example.com │ │ │ │ ┌───────────────────────────────────────────────────┐ │ │ │ │ │ Directory Context │ │ │ │ │ │ │ │ │ │ │ │ Options Indexes │ │ │ │ │ │ ┌───────────────────────────────────────────┐ │ │ │ │ │ │ │ Location Context │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ SetHandler my-handler │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └───────────────────────────────────────────┘ │ │ │ │ │ │ │ │ │ │ │ └───────────────────────────────────────────────────┘ │ │ │ │ │ │ │ └───────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ ``` The key insight is that this nesting is not just syntactic -- it controls **when and how configuration is applied**. Server-level directives are processed once at startup. Virtual host directives are selected based on the incoming request's `Host` header and IP:port. Directory directives are matched against the filesystem path. Location directives are matched against the URL path. ## Configuration Scopes ### Server Config ({httpd}`RSRC_CONF`) - Global settings - Virtual host settings - Directives: `ServerRoot`, `Listen`, `LoadModule`, `ErrorLog` ### Per-Directory Config ({httpd}`ACCESS_CONF`) - Settings that can vary by directory/location - Applies within ``, ``, ``, `.htaccess` - Directives: `Options`, `Require`, `SetHandler` ### Per-Request Merge When a request arrives, Apache walks the configuration tree and merges applicable configurations in a specific order. Each merge can override the previous: ```mermaid sequenceDiagram participant R as Incoming Request participant S as Server Config participant V as VirtualHost Config participant D1 as participant D2 as participant L as R->>S: Start with server-level config S->>V: Merge virtual host config V->>D1: Merge /var/www directory D1->>D2: Merge /var/www/special directory D2->>L: Merge /api location Note over L: Final merged config
used by handler ``` The merging order is: server config -> virtual host -> `` sections (most general first) -> `.htaccess` files -> `` sections -> `` sections (most general first). This means `` always wins over ``, which is a common source of confusion. ```{note} **Fuzzing note**: The fuzzing configs (like `pwn.conf`, `crypto-fuzz.conf`) are deliberately simple -- usually a single `` block that matches everything. This avoids complex merging and ensures every request reaches the target module. ``` ```{important} **Configuration directives control code paths.** Every directive a module handles is a branch point - different values activate different internal logic. For example, enabling `SessionCryptoPassphrase` pulls in encryption code paths that are completely dormant without it. Varying configuration directives across fuzzing runs is a practical way to increase code coverage and reach parser/handler logic that a default config never exercises. ``` ## Module Configuration Structures Modules define their own configuration structures: ```c // Server-level config (one per virtual host) typedef struct { int enabled; const char *log_path; apr_array_header_t *allowed_methods; } my_server_config_t; // Per-directory config (can vary by path) typedef struct { int options; const char *handler_name; int max_connections; } my_dir_config_t; ``` Apache stores module configs in a "module config vector" -- essentially an array indexed by module number. Each module gets one slot. The {httpd}`ap_get_module_config` and {httpd}`ap_set_module_config` functions are thin wrappers around array indexing. ## Registering Configuration Directives Modules register the directives they handle in a command table. Each entry specifies the directive name, the handler function, where it's valid, and a help string: ```c // Directive handler functions static const char *set_enabled(cmd_parms *cmd, void *cfg, int on) { my_server_config_t *conf = ap_get_module_config( cmd->server->module_config, &my_module); conf->enabled = on; return NULL; // NULL = success } static const char *set_max_conn(cmd_parms *cmd, void *cfg, const char *arg) { my_dir_config_t *conf = cfg; conf->max_connections = atoi(arg); if (conf->max_connections < 1) { return "MaxConnections must be positive"; } return NULL; } // Directive registration table static const command_rec my_commands[] = { AP_INIT_FLAG("MyModuleEnabled", set_enabled, NULL, RSRC_CONF, "Enable or disable MyModule"), AP_INIT_TAKE1("MaxConnections", set_max_conn, NULL, ACCESS_CONF, "Maximum concurrent connections per directory"), { NULL } // Table terminator }; ``` Note the return convention: `NULL` means success, and a non-NULL string is an error message that Apache will report with the config file name and line number. ## Directive Types Apache provides macros for common directive patterns: ````{dropdown} AP_INIT_FLAG Boolean on/off directive: ```c // Config: MyModuleEnabled On AP_INIT_FLAG("MyModuleEnabled", handler, data, where, help) // Handler signature: const char *handler(cmd_parms *cmd, void *cfg, int on); ``` ```` ````{dropdown} AP_INIT_NO_ARGS Directive with no arguments: ```c // Config: EnableFeature AP_INIT_NO_ARGS("EnableFeature", handler, data, where, help) // Handler signature: const char *handler(cmd_parms *cmd, void *cfg); ``` ```` ````{dropdown} AP_INIT_TAKE1 Directive with one argument: ```c // Config: LogLevel debug AP_INIT_TAKE1("LogLevel", handler, data, where, help) // Handler signature: const char *handler(cmd_parms *cmd, void *cfg, const char *arg); ``` ```` ````{dropdown} AP_INIT_TAKE2 Directive with two arguments: ```c // Config: Header set X-Custom "value" AP_INIT_TAKE2("Header", handler, data, where, help) // Handler signature: const char *handler(cmd_parms *cmd, void *cfg, const char *arg1, const char *arg2); ``` ```` ````{dropdown} AP_INIT_TAKE3 Three arguments: ```c // Handler signature: const char *handler(cmd_parms *cmd, void *cfg, const char *arg1, const char *arg2, const char *arg3); ``` ```` ````{dropdown} AP_INIT_ITERATE Repeatable single argument (called once per arg): ```c // Config: AddLanguage en fr de AP_INIT_ITERATE("AddLanguage", handler, data, where, help) // Handler called 3 times with "en", "fr", "de" const char *handler(cmd_parms *cmd, void *cfg, const char *arg); ``` ```` ````{dropdown} AP_INIT_RAW_ARGS Everything after directive name as raw string: ```c // Config: RewriteRule ^/old/(.*) /new/$1 [R=301,L] AP_INIT_RAW_ARGS("RewriteRule", handler, data, where, help) // Handler signature: const char *handler(cmd_parms *cmd, void *cfg, const char *args); ``` ```` ## The `cmd_parms` Structure The {httpd}`cmd_parms` structure passed to directive handlers contains: ```c struct cmd_parms { void *info; // Your 'data' from AP_INIT_* apr_pool_t *pool; // Pool for this config phase apr_pool_t *temp_pool; // Temporary pool (cleared after config) server_rec *server; // Current server being configured const char *path; // Current path (if any) const command_rec *cmd; // The directive being processed const char *directive; // The directive name string // For error messages const char *config_file; // Current config file int line_num; // Line number in file }; ``` ## Configuration Contexts (where parameter) The `where` parameter in `AP_INIT_*` controls where directive is valid: ```c // Context flags (can be OR'd together) RSRC_CONF // Server config, ACCESS_CONF // , , OR_AUTHCFG // + .htaccess with AuthConfig OR_LIMIT // + .htaccess with Limit OR_OPTIONS // + .htaccess with Options OR_FILEINFO // + .htaccess with FileInfo OR_INDEXES // + .htaccess with Indexes OR_ALL // Everywhere including .htaccess // Examples: RSRC_CONF // Only in server/.conf files ACCESS_CONF // Only in , etc. RSRC_CONF | ACCESS_CONF // Both contexts OR_ALL // Anywhere ACCESS_CONF | OR_AUTHCFG // + .htaccess w/AuthConfig ``` ## Section Containers Apache supports nested configuration containers: ```apache # - filesystem path Options Indexes # - regex on filesystem path Options -Indexes # - URL path Require user admin # - regex on URL SetHandler api-handler # - filename pattern SetHandler php-handler # - regex on filename Header set Cache-Control "max-age=3600" # - expression-based Redirect "/" "https://www.example.com/" # - virtual host ServerName www.example.com ``` ## Writing a Module For a complete walkthrough of writing a module with configuration directives, create/merge functions, and hook registration, see Apache's official guide: [Developing modules for Apache HTTP Server 2.4](https://httpd.apache.org/docs/2.4/developer/modguide.html). ## Summary - Configuration operates at multiple **scopes**: server ({httpd}`RSRC_CONF`) and per-directory ({httpd}`ACCESS_CONF`) - Apache **merges** configs per-request: server -> vhost -> `` -> `.htaccess` -> `` -> `` - Modules register directives using `AP_INIT_*` macros with a `where` parameter controlling valid contexts - The {httpd}`cmd_parms` structure provides the pool, server, and path context to directive handlers - For a hands-on guide to implementing all of this, see the [Apache module development guide](https://httpd.apache.org/docs/2.4/developer/modguide.html)