50cfe8bbbaf4279375802531268e2bf0155215fetrawick/* Licensed to the Apache Software Foundation (ASF) under one or more
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * contributor license agreements. See the NOTICE file distributed with
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * this work for additional information regarding copyright ownership.
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * The ASF licenses this file to You under the Apache License, Version 2.0
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * (the "License"); you may not use this file except in compliance with
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * the License. You may obtain a copy of the License at
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * Unless required by applicable law or agreed to in writing, software
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * distributed under the License is distributed on an "AS IS" BASIS,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * See the License for the specific language governing permissions and
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * limitations under the License.
50cfe8bbbaf4279375802531268e2bf0155215fetrawicktypedef struct {
50cfe8bbbaf4279375802531268e2bf0155215fetrawick const char *backend; /* backend address, as configured */
50cfe8bbbaf4279375802531268e2bf0155215fetrawicktypedef struct {
bbb64779da3514ea1fee8b806f5ad30d29ea45abtrawick const char *default_user; /* this is user if authorizer returns
bbb64779da3514ea1fee8b806f5ad30d29ea45abtrawick * success and a user expression yields
bbb64779da3514ea1fee8b806f5ad30d29ea45abtrawick * empty string
bbb64779da3514ea1fee8b806f5ad30d29ea45abtrawick ap_expr_info_t *user_expr; /* expr to evaluate to set r->user */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick char authoritative; /* fail request if user is rejected? */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick char require_basic_auth; /* fail if client didn't send credentials? */
50cfe8bbbaf4279375802531268e2bf0155215fetrawicktypedef struct {
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* If an "authnz" provider successfully authenticates, record
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * the provider name here for checking during authz.
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic apr_hash_t *fcgi_authn_providers, *fcgi_authz_providers;
50cfe8bbbaf4279375802531268e2bf0155215fetrawick/* fcgi://{hostname|IPv4|IPv6}:port[/] */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick#define FCGI_BACKEND_REGEX_STR "m%^fcgi://(.*):(\\d{1,5})/?$%"
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * utility function to connect to a peer; generally useful, but
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * wait for AF_UNIX support in this mod before thinking about how
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * to make it available to other modules
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic apr_status_t connect_to_peer(apr_socket_t **newsock,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick apr_status_t rv = APR_EINVAL; /* returned if no backend addr was provided
50cfe8bbbaf4279375802531268e2bf0155215fetrawick int loglevel = addr->next ? APLOG_DEBUG : APLOG_ERR;
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "for target %s",
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic void log_provider_info(const fcgi_provider_conf *conf, request_rec *r)
50cfe8bbbaf4279375802531268e2bf0155215fetrawick APLOGNO(02496) "name %s, backend %s, host %s, port %d, "
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "first address %pI, %c%c",
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic void setupenv(request_rec *r, const char *password, const char *apache_role)
50cfe8bbbaf4279375802531268e2bf0155215fetrawick apr_table_setn(r->subprocess_env, "FCGI_ROLE", AP_FCGI_AUTHORIZER_STR);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick apr_table_setn(r->subprocess_env, "FCGI_APACHE_ROLE", apache_role);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick apr_table_setn(r->subprocess_env, "REMOTE_PASSWD", password);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* Drop the variables CONTENT_LENGTH, PATH_INFO, PATH_TRANSLATED,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * SCRIPT_NAME and most Hop-By-Hop headers - EXCEPT we will pass
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * PROXY_AUTH to allow CGI to perform proxy auth for httpd
50cfe8bbbaf4279375802531268e2bf0155215fetrawick apr_table_unset(r->subprocess_env, "CONTENT_LENGTH");
50cfe8bbbaf4279375802531268e2bf0155215fetrawick apr_table_unset(r->subprocess_env, "PATH_TRANSLATED");
50cfe8bbbaf4279375802531268e2bf0155215fetrawick apr_table_unset(r->subprocess_env, "HTTP_KEEP_ALIVE");
50cfe8bbbaf4279375802531268e2bf0155215fetrawick apr_table_unset(r->subprocess_env, "HTTP_TRANSFER_ENCODING");
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* Connection hop-by-hop header to prevent the CGI from hanging */
210116e11414ce7a3789652725be298b5f073056jailletc apr_table_setn(r->subprocess_env, "HTTP_CONNECTION", "close");
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic apr_status_t recv_data(const fcgi_provider_conf *conf,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_log_rdata(APLOG_MARK, APLOG_TRACE5, r, "FastCGI data received",
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic apr_status_t recv_data_full(const fcgi_provider_conf *conf,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick rv = recv_data(conf, r, s, buf + cumulative_len, &readlen);
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic apr_status_t sendv_data(const fcgi_provider_conf *conf,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick for (i = 0; i < nvec; i++) {
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_log_rdata(APLOG_MARK, APLOG_TRACE5, r, "FastCGI data sent",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick vec[i].iov_base, vec[i].iov_len, AP_LOG_DATA_SHOW_OFFSET);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick rv = apr_socket_sendv(s, vec + offset, nvec - offset, &n);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick if (n > 0) {
50cfe8bbbaf4279375802531268e2bf0155215fetrawick break; /* short circuit out */
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic apr_status_t send_begin_request(request_rec *r,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_fcgi_fill_in_header(&header, AP_FCGI_BEGIN_REQUEST, request_id,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick sizeof(abrb), 0);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_fcgi_fill_in_request_body(&brb, role, 0 /* *NOT* AP_FCGI_KEEP_CONN */);
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic apr_status_t send_environment(apr_socket_t *s,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "%s: '%s': '%s'",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* Send envvars over in as many FastCGI records as it takes, */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick avail_len = 16 * 1024; /* our limit per record, which could have been up
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * to AP_FCGI_MAX_CONTENT_LEN
50cfe8bbbaf4279375802531268e2bf0155215fetrawick required_len = ap_fcgi_encoded_env_len(r->subprocess_env,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* skip this envvar and continue */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* only an unused element at the end of the array */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick APLOGNO(02500) "required len for encoding envvars: %"
50cfe8bbbaf4279375802531268e2bf0155215fetrawick rv = ap_fcgi_encode_env(r, r->subprocess_env, body, required_len,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* we pre-compute, so we can't run out of space */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* compute and encode must be in sync */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_fcgi_fill_in_header(&header, AP_FCGI_PARAMS, request_id,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* Envvars sent, so say we're done */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_fcgi_fill_in_header(&header, AP_FCGI_PARAMS, request_id, 0, 0);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * This header-state logic is from mod_proxy_fcgi.
50cfe8bbbaf4279375802531268e2bf0155215fetrawick/* Try to find the end of the script headers in the response from the back
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * end fastcgi server. STATE holds the current header parsing state for this
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * Returns 0 if it can't find the end of the headers, and 1 if it found the
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * end of the headers. */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick switch (*state) {
50cfe8bbbaf4279375802531268e2bf0155215fetrawick switch (*state) {
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * handle_response() is based on mod_proxy_fcgi's dispatch()
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic apr_status_t handle_response(const fcgi_provider_conf *conf,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick *rspbuflen = 0; /* unless we actually read something */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ob = apr_brigade_create(r->pool, r->connection->bucket_alloc);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick while (!done && rv == APR_SUCCESS) { /* Keep reading FastCGI records until
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * we get AP_FCGI_END_REQUEST (done)
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * or an error occurs.
50cfe8bbbaf4279375802531268e2bf0155215fetrawick rv = recv_data_full(conf, r, s, (char *)farray, AP_FCGI_HEADER_LEN);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_fcgi_header_fields_from_array(&version, &type, &rid, &clen, &plen,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "request id %d, expected %d",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick recv_again: /* if we need to keep reading more of a record's content */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * Now get the actual content of the record.
50cfe8bbbaf4279375802531268e2bf0155215fetrawick case AP_FCGI_STDOUT: /* Response headers and optional body */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick if (clen != 0) {
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "parsing -> %d/%d",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* should not occur for these bucket types;
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * does not indicate overflow
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "flattening response body",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "script headers from %s",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* We're still looking for the end of the
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * headers, so this part of the data will need
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * to persist. */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* If we didn't read all the data go back and get the
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * rest of it. */
0d0d3ba82362da5eed586c40333c03078cb34571ylavic /* Leave on above switch's inner error. */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * Read/discard any trailing padding.
50cfe8bbbaf4279375802531268e2bf0155215fetrawick APLOGNO(02510) "%s: Never reached end of script headers",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick/* almost from mod_fcgid */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* When the application gives a 200 response, the server ignores response
50cfe8bbbaf4279375802531268e2bf0155215fetrawick headers whose names aren't prefixed with Variable- prefix, and ignores
50cfe8bbbaf4279375802531268e2bf0155215fetrawick any response content */
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic int fix_auth_header(void *vr, const char *key, const char *val)
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "moving %s->%s", key, val);
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic void req_rsp(request_rec *r, const fcgi_provider_conf *conf,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick *rspbuflen = 0; /* unless we actually read something */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick rv = send_begin_request(r, conf, s, AP_FCGI_AUTHORIZER, request_id);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick rv = send_environment(s, conf, r, request_id, temp_pool);
21a7a1304e24c6206608a59ca1f0a3c8b14c3b54trawick /* The responder owns the request body, not the authorizer.
21a7a1304e24c6206608a59ca1f0a3c8b14c3b54trawick * Don't even send an empty AP_FCGI_STDIN block. libfcgi doesn't care,
21a7a1304e24c6206608a59ca1f0a3c8b14c3b54trawick * but it wasn't sent to authorizers by mod_fastcgi or mod_fcgi and
21a7a1304e24c6206608a59ca1f0a3c8b14c3b54trawick * may be unhandled by the app. Additionally, the FastCGI spec does
21a7a1304e24c6206608a59ca1f0a3c8b14c3b54trawick * not mention FCGI_STDIN in the Authorizer description, though it
21a7a1304e24c6206608a59ca1f0a3c8b14c3b54trawick * does describe FCGI_STDIN elsewhere in more general terms than
21a7a1304e24c6206608a59ca1f0a3c8b14c3b54trawick * simply a wrapper for the client's request body.
50cfe8bbbaf4279375802531268e2bf0155215fetrawick rv = handle_response(conf, r, s, temp_pool, request_id, rspbuf,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* some sort of mechanical problem */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* An Authorizer application's 200 response may include headers
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * whose names are prefixed with Variable-, and they should be
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * available to subsequent phases via subprocess_env (and yanked
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * from the client response).
710362cca9d3cd3ec3de8907998598cd6fa79087trawick apr_table_t *vars = apr_table_make(temp_pool, /* not used to allocate
710362cca9d3cd3ec3de8907998598cd6fa79087trawick * any values that end up
710362cca9d3cd3ec3de8907998598cd6fa79087trawick * in r->(anything)
50cfe8bbbaf4279375802531268e2bf0155215fetrawick fcgi_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick char rspbuf[NON200_RESPONSE_BUF_LEN + 1]; /* extra byte for '\0' */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "require-basic %s, user expr? %s type %s",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick conf = apr_hash_get(fcgi_authn_providers, prov, APR_HASH_KEY_STRING);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick APLOGNO(02518) "%s: can't find config for provider %s",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick req_rsp(r, conf, password, AP_FCGI_APACHE_ROLE_AUTHENTICATOR_STR,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick const char *user = ap_expr_str_exec(r, dconf->user_expr,
bbb64779da3514ea1fee8b806f5ad30d29ea45abtrawick r->user = apr_pstrdup(r->pool, dconf->default_user);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick else if (user) {
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "after calling authorizer: user expression "
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "yielded empty string (variable not set?)",
bbb64779da3514ea1fee8b806f5ad30d29ea45abtrawick /* unexpected error, not even an empty string was returned */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "after calling authorizer: %s",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* combined authn/authz phase, so app won't be invoked for authz
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * Remember that the request was successfully authorized by this
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * provider.
50cfe8bbbaf4279375802531268e2bf0155215fetrawick fcgi_request_notes *rnotes = apr_palloc(r->pool, sizeof(*rnotes));
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_set_module_config(r->request_config, &authnz_fcgi_module,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* From the spec:
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * For Authorizer response status values other than "200" (OK), the
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * Web server denies access and sends the response status, headers,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * and content back to the HTTP client.
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * This only makes sense if this authorizer is authoritative.
50cfe8bbbaf4279375802531268e2bf0155215fetrawick APLOGNO(02522) "%s: Ignoring response body from non-"
50cfe8bbbaf4279375802531268e2bf0155215fetrawick else if (rspbuflen > 0) {
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* apr_brigade_flatten() interface :( */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick rspbuf[rspbuflen] = '\0'; /* we reserved an extra byte for '\0' */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_custom_response(r, r->status, rspbuf); /* API makes a copy */
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic authn_status fcgi_check_password(request_rec *r, const char *user,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick const char *password)
50cfe8bbbaf4279375802531268e2bf0155215fetrawick const char *prov = apr_table_get(r->notes, AUTHN_PROVIDER_NAME_NOTE);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick conf = apr_hash_get(fcgi_authn_providers, prov, APR_HASH_KEY_STRING);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick APLOGNO(02526) "%s: can't find config for provider %s",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* combined authn and authz: FCGI_APACHE_ROLE not set */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick conf->is_authz ? NULL : AP_FCGI_APACHE_ROLE_AUTHENTICATOR_STR,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* combined authn/authz phase, so app won't be invoked for authz
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * Remember that the request was successfully authorized by this
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * provider.
50cfe8bbbaf4279375802531268e2bf0155215fetrawick fcgi_request_notes *rnotes = apr_palloc(r->pool, sizeof(*rnotes));
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_set_module_config(r->request_config, &authnz_fcgi_module,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick const char *prov = apr_table_get(r->notes, AUTHZ_PROVIDER_NAME_NOTE);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick conf = apr_hash_get(fcgi_authz_providers, prov, APR_HASH_KEY_STRING);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick APLOGNO(02529) "%s: can't find config for provider %s",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* combined authn/authz phase, so app won't be invoked for authz
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * If the provider already successfully authorized this request,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick fcgi_request_notes *rnotes = ap_get_module_config(r->request_config,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick && !strcmp(rnotes->successful_authnz_provider, conf->name)) {
50cfe8bbbaf4279375802531268e2bf0155215fetrawick req_rsp(r, conf, NULL, AP_FCGI_APACHE_ROLE_AUTHORIZER_STR, NULL, NULL);
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic const char *fcgi_authz_parse(cmd_parms *cmd, const char *require_line,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* Allowed form: Require [not] registered-provider-name<EOS>
50cfe8bbbaf4279375802531268e2bf0155215fetrawick return "mod_authnz_fcgi doesn't support restrictions on providers "
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "(i.e., multiple require args)";
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic const char *fcgi_check_authn_provider(cmd_parms *cmd,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick char *const argv[])
50cfe8bbbaf4279375802531268e2bf0155215fetrawick return apr_pstrcat(cmd->pool, dname, ": No provider given", NULL);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick return "Options aren't supported with \"None\"";
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* at present, everything needs an argument */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick int flags = AP_EXPR_FLAG_DONT_VARY | AP_EXPR_FLAG_RESTRICTED
50cfe8bbbaf4279375802531268e2bf0155215fetrawick return apr_psprintf(cmd->pool, "%s: Error parsing '%s': '%s'",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick return apr_pstrcat(cmd->pool, dname, ": Unexpected option '",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick return apr_pstrcat(cmd->pool, dname, ": Bad argument '",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick/* AuthnzFcgiAuthDefineProvider {authn|authz|authnz} provider-name \
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * fcgi://backendhost:backendport/
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic const char *fcgi_define_provider(cmd_parms *cmd,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick char *const argv[])
50cfe8bbbaf4279375802531268e2bf0155215fetrawick fcgi_provider_conf *conf = apr_pcalloc(cmd->pool, sizeof(*conf));
50cfe8bbbaf4279375802531268e2bf0155215fetrawick fcgi_backend_regex = ap_rxplus_compile(cmd->pool, FCGI_BACKEND_REGEX_STR);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "%s: failed to compile regexec '%s'",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick return apr_pstrcat(cmd->pool, dname, ": No type given", NULL);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ": Invalid provider type ",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick return apr_pstrcat(cmd->pool, dname, ": No provider name given", NULL);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick return apr_pstrcat(cmd->pool, dname, ": No backend-address given",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick rc = ap_rxplus_exec(cmd->pool, fcgi_backend_regex, argv[ca], NULL);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick if (!rc || ap_rxplus_nmatch(fcgi_backend_regex) != 3) {
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "' has invalid form",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick host = ap_rxplus_pmatch(cmd->pool, fcgi_backend_regex, 1);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick if (host[0] == '[' && host[strlen(host) - 1] == ']') {
450a2ff1d5ebc7a2a695bcc1bab1972390415e9arjung port = atoi(ap_rxplus_pmatch(cmd->pool, fcgi_backend_regex, 2));
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "' has invalid port",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick rv = apr_sockaddr_info_get(&conf->backend_addrs, conf->host,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, rv, NULL,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ": Error resolving backend address",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ": Unexpected parameter ",
50cfe8bbbaf4279375802531268e2bf0155215fetrawick apr_hash_set(fcgi_authn_providers, conf->name, APR_HASH_KEY_STRING,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_register_auth_provider(cmd->pool, AUTHN_PROVIDER_GROUP,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick apr_hash_set(fcgi_authz_providers, conf->name, APR_HASH_KEY_STRING,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_register_auth_provider(cmd->pool, AUTHZ_PROVIDER_GROUP,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "Define a FastCGI authn and/or authz provider"),
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "Enable/disable a FastCGI authorizer to handle "
50cfe8bbbaf4279375802531268e2bf0155215fetrawick "check_authn phase"),
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic int fcgi_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
50cfe8bbbaf4279375802531268e2bf0155215fetrawick static const char * const auth_basic_runs_after_me[] =
50cfe8bbbaf4279375802531268e2bf0155215fetrawick {"mod_auth_basic.c", NULL}; /* to allow for custom response */
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_hook_pre_config(fcgi_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
50cfe8bbbaf4279375802531268e2bf0155215fetrawick ap_hook_check_authn(fcgi_check_authn, NULL, auth_basic_runs_after_me,
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic void *create_dir_conf(apr_pool_t *p, char *dummy)
50cfe8bbbaf4279375802531268e2bf0155215fetrawick fcgi_dir_conf *dconf = apr_pcalloc(p, sizeof(fcgi_dir_conf));
50cfe8bbbaf4279375802531268e2bf0155215fetrawickstatic void *merge_dir_conf(apr_pool_t *p, void *basev, void *overridesv)
50cfe8bbbaf4279375802531268e2bf0155215fetrawick fcgi_dir_conf *a = (fcgi_dir_conf *)apr_pcalloc(p, sizeof(*a));
50cfe8bbbaf4279375802531268e2bf0155215fetrawick /* currently we just have a single directive applicable to a
50cfe8bbbaf4279375802531268e2bf0155215fetrawick * directory, so if it is set then grab all fields from fcgi_dir_conf