static void normalise(unsigned int flags, char *str) { char *p; if (flags & NORM_LC) for (p = str; *p; ++p) if (isupper(*p)) *p = tolower(*p); if (flags & NORM_MSSLASH) for (p = ap_strchr(str, '\\'); p; p = ap_strchr(p+1, '\\')) *p = '/'; }
/** * Log an AJP message * * @param request The current request * @param msg AJP Message to dump * @param err error string to display * @return APR_SUCCESS or error */ apr_status_t ajp_msg_log(request_rec *r, ajp_msg_t *msg, char *err) { int level; apr_size_t count; char *buf, *next; apr_status_t rc = APR_SUCCESS; if (APLOGrtrace7(r)) { level = APLOG_TRACE7; count = 1024; if (APLOGrtrace8(r)) { level = APLOG_TRACE8; count = AJP_MAX_BUFFER_SZ; } rc = ajp_msg_dump(r->pool, msg, err, count, &buf); if (rc == APR_SUCCESS) { while ((next = ap_strchr(buf, '\n'))) { *next = '\0'; /* Intentional no APLOGNO */ ap_log_rerror(APLOG_MARK, level, 0, r, "%s", buf); buf = next + 1; } /* Intentional no APLOGNO */ ap_log_rerror(APLOG_MARK, level, 0, r, "%s", buf); } } return rc; }
static authn_status get_dbm_realm_hash(request_rec *r, const char *user, const char *realm, char **rethash) { authn_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config, &authn_dbm_module); apr_status_t rv; char *dbm_hash; char *colon_hash; rv = fetch_dbm_value(conf->dbmtype, conf->pwfile, apr_pstrcat(r->pool, user, ":", realm, NULL), &dbm_hash, r->pool); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01755) "Could not open dbm (type %s) hash file: %s", conf->dbmtype, conf->pwfile); return AUTH_GENERAL_ERROR; } if (!dbm_hash) { return AUTH_USER_NOT_FOUND; } colon_hash = ap_strchr(dbm_hash, ':'); if (colon_hash) { *colon_hash = '\0'; } *rethash = dbm_hash; AUTHN_CACHE_STORE(r, user, realm, dbm_hash); return AUTH_USER_FOUND; }
/* * Canonicalize scgi-like URLs. */ static int scgi_canon(request_rec *r, char *url) { char *host, sport[sizeof(":65535")]; const char *err, *path; apr_port_t port = SCGI_DEFAULT_PORT; if (strncasecmp(url, SCHEME "://", sizeof(SCHEME) + 2)) { return DECLINED; } url += sizeof(SCHEME); /* Keep slashes */ err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port); if (err) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "error parsing URL %s: %s", url, err); return HTTP_BAD_REQUEST; } apr_snprintf(sport, sizeof(sport), ":%u", port); if (ap_strchr(host, ':')) { /* if literal IPv6 address */ host = apr_pstrcat(r->pool, "[", host, "]", NULL); } path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0, r->proxyreq); if (!path) { return HTTP_BAD_REQUEST; } r->filename = apr_pstrcat(r->pool, "proxy:" SCHEME "://", host, sport, "/", path, NULL); r->path_info = apr_pstrcat(r->pool, "/", path, NULL); return OK; }
/** * find certain header line, return copy of first part (up to first ";") * @param p pool to allocate from * @param name name of the header * @param string input: pointer to pointer string where to find the header; * output: pointer to the ";" or "\n" after the copied value * @param end pointer where to stop searching * @note string must be NUL-terminated (but the NUL may be after *end) * @return copy of the header value or NULL if not found */ static char *mbox_mime_get_header(apr_pool_t *p, const char *name, char **string, const char *end) { char *ptr; int namelen = strlen(name); for (ptr = *string; ptr && *ptr && ptr < end ; ptr = ap_strchr(ptr + 1, '\n') + 1) { int l; if (strncasecmp(ptr, name, namelen) != 0) continue; ptr += namelen; if (*ptr != ':') continue; ptr++; while (*ptr == ' ') ptr++; if (ptr >= end) break; l = strcspn(ptr, ";\n"); *string = ptr + l; while (apr_isspace(ptr[l]) && l > 0) l--; return apr_pstrndup(p, ptr, l); } return NULL; }
static const char* interpolate_env(request_rec *r, const char *str) { /* Interpolate an env str in a configuration string * Syntax ${var} --> value_of(var) * Method: replace one var, and recurse on remainder of string * Nothing clever here, and crap like nested vars may do silly things * but we'll at least avoid sending the unwary into a loop */ const char *start; const char *end; const char *var; const char *val; const char *firstpart; start = ap_strstr(str, "${"); if (start == NULL) { return str; } end = ap_strchr(start+2, '}'); if (end == NULL) { return str; } /* OK, this is syntax we want to interpolate. Is there such a var ? */ var = apr_pstrndup(r->pool, start+2, end-(start+2)); val = apr_table_get(r->subprocess_env, var); firstpart = apr_pstrndup(r->pool, str, (start-str)); if (val == NULL) { return apr_pstrcat(r->pool, firstpart, interpolate_env(r, end+1), NULL); } else { return apr_pstrcat(r->pool, firstpart, val, interpolate_env(r, end+1), NULL); } }
static const char *rpaf_set_proxy_ip(cmd_parms *cmd, void *dummy, const char *proxy_ip) { char *ip, *mask; apr_ipsubnet_t **sub; apr_status_t rv; server_rec *s = cmd->server; rpaf_server_cfg *cfg = (rpaf_server_cfg *)ap_get_module_config(s->module_config, &rpaf_module); if (rpaf_looks_like_ip(proxy_ip)) { ip = apr_pstrdup(cmd->temp_pool, proxy_ip); if (mask = ap_strchr(ip, '/')) { *mask++ = '\0'; } sub = (apr_ipsubnet_t **)apr_array_push(cfg->proxy_ips); rv = apr_ipsubnet_create(sub, ip, mask, cmd->pool); if (rv != APR_SUCCESS) { char msgbuf[128]; apr_strerror(rv, msgbuf, sizeof(msgbuf)); return apr_pstrcat(cmd->pool, "mod_rpaf: Error parsing IP ", proxy_ip, " in ", cmd->cmd->name, ". ", msgbuf, NULL); } } else { return apr_pstrcat(cmd->pool, "mod_rpaf: Error parsing IP \"", proxy_ip, "\" in ", cmd->cmd->name, ". Failed basic parsing.", NULL); } return NULL; }
static apr_table_t *parse_headers(apr_array_header_t *hlines, apr_pool_t *pool) { if (hlines) { apr_table_t *headers = apr_table_make(pool, hlines->nelts); int i; for (i = 0; i < hlines->nelts; ++i) { char *hline = ((char **)hlines->elts)[i]; char *sep = ap_strchr(hline, ':'); if (!sep) { ap_log_perror(APLOG_MARK, APLOG_WARNING, APR_EINVAL, pool, APLOGNO(02955) "h2_response: invalid header[%d] '%s'", i, (char*)hline); /* not valid format, abort */ return NULL; } (*sep++) = '\0'; while (*sep == ' ' || *sep == '\t') { ++sep; } if (!h2_util_ignore_header(hline)) { apr_table_merge(headers, hline, sep); } } return headers; } else { return apr_table_make(pool, 0); } }
static authn_status get_mongodb_realm_hash(request_rec *r, const char *user, const char *realm, char **rethash) { authn_mongodb_config_rec *conf = ap_get_module_config(r->per_dir_config, &authn_mongodb_module); apr_status_t rv; char *dbm_hash; char *colon_hash; rv = fetch_mongodb_value(conf->host, conf->port, conf->userfield, conf->passwdfield, conf->collection, apr_pstrcat(r->pool, user, ":", realm, NULL), &dbm_hash, r->pool); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "Could not open mongoDB (host %s) port : %d", conf->host, conf->port); return AUTH_GENERAL_ERROR; } if (!dbm_hash) { return AUTH_USER_NOT_FOUND; } colon_hash = ap_strchr(dbm_hash, ':'); if (colon_hash) { *colon_hash = '\0'; } *rethash = dbm_hash; return AUTH_USER_FOUND; }
/** * Parse the RewriteIPAllow directive */ static const char *allow_config_cmd(cmd_parms *cmd, void *dv, const char *where_c) { my_config *d = ap_get_module_config(cmd->server->module_config, &myfixip_module); accesslist *a; char *where = apr_pstrdup(cmd->pool, where_c); char *s; char msgbuf[120]; apr_status_t rv; a = (accesslist *) apr_array_push(d->allows); if ((s = ap_strchr(where, '/'))) { *s++ = '\0'; rv = apr_ipsubnet_create(&a->ip, where, s, cmd->pool); if (APR_STATUS_IS_EINVAL(rv)) { /* looked nothing like an IP address */ return "An IP address was expected"; } else if (rv != APR_SUCCESS) { apr_strerror(rv, msgbuf, sizeof msgbuf); return apr_pstrdup(cmd->pool, msgbuf); } } else if (!APR_STATUS_IS_EINVAL(rv = apr_ipsubnet_create(&a->ip, where, NULL, cmd->pool))) { if (rv != APR_SUCCESS) { apr_strerror(rv, msgbuf, sizeof msgbuf); return apr_pstrdup(cmd->pool, msgbuf); } } else { /* no slash, didn't look like an IP address => must be a host */ return "An IP address was expected"; } return NULL; }
static const char *ip_parse_config(cmd_parms *cmd, const char *require_line, const void **parsed_require_line) { const char *t, *w; int count = 0; apr_ipsubnet_t **ip; apr_pool_t *ptemp = cmd->temp_pool; apr_pool_t *p = cmd->pool; /* The 'ip' provider will allow the configuration to specify a list of ip addresses to check rather than a single address. This is different from the previous host based syntax. */ t = require_line; while ((w = ap_getword_conf(ptemp, &t)) && w[0]) count++; if (count == 0) return "'require ip' requires an argument"; ip = apr_pcalloc(p, sizeof(apr_ipsubnet_t *) * (count + 1)); *parsed_require_line = ip; t = require_line; while ((w = ap_getword_conf(ptemp, &t)) && w[0]) { char *addr = apr_pstrdup(ptemp, w); char *mask; apr_status_t rv; if (parsed_subnets && (*ip = apr_hash_get(parsed_subnets, w, APR_HASH_KEY_STRING)) != NULL) { /* we already have parsed this subnet */ ip++; continue; } if ((mask = ap_strchr(addr, '/'))) *mask++ = '\0'; rv = apr_ipsubnet_create(ip, addr, mask, p); if(APR_STATUS_IS_EINVAL(rv)) { /* looked nothing like an IP address */ return apr_psprintf(p, "ip address '%s' appears to be invalid", w); } else if (rv != APR_SUCCESS) { return apr_psprintf(p, "ip address '%s' appears to be invalid: %pm", w, &rv); } if (parsed_subnets) apr_hash_set(parsed_subnets, w, APR_HASH_KEY_STRING, *ip); ip++; } return NULL; }
h2_response *h2_response_create(int stream_id, const char *http_status, apr_array_header_t *hlines, apr_pool_t *pool) { apr_table_t *header; h2_response *response = apr_pcalloc(pool, sizeof(h2_response)); int i; if (response == NULL) { return NULL; } response->stream_id = stream_id; response->status = http_status; response->content_length = -1; if (hlines) { header = apr_table_make(pool, hlines->nelts); for (i = 0; i < hlines->nelts; ++i) { char *hline = ((char **)hlines->elts)[i]; char *sep = ap_strchr(hline, ':'); if (!sep) { ap_log_perror(APLOG_MARK, APLOG_WARNING, APR_EINVAL, pool, APLOGNO(02955) "h2_response(%d): invalid header[%d] '%s'", response->stream_id, i, (char*)hline); /* not valid format, abort */ return NULL; } (*sep++) = '\0'; while (*sep == ' ' || *sep == '\t') { ++sep; } if (ignore_header(hline)) { /* never forward, ch. 8.1.2.2 */ } else { apr_table_merge(header, hline, sep); if (*sep && H2_HD_MATCH_LIT_CS("content-length", hline)) { char *end; response->content_length = apr_strtoi64(sep, &end, 10); if (sep == end) { ap_log_perror(APLOG_MARK, APLOG_WARNING, APR_EINVAL, pool, APLOGNO(02956) "h2_response(%d): content-length" " value not parsed: %s", response->stream_id, sep); response->content_length = -1; } } } } } else { header = apr_table_make(pool, 0); } response->rheader = header; return response; }
static const char *proxies_set(cmd_parms *cmd, void *cfg, const char *arg) { remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, &remoteip_module); remoteip_proxymatch_t *match; apr_status_t rv; char *ip = apr_pstrdup(cmd->temp_pool, arg); char *s = ap_strchr(ip, '/'); if (s) { *s++ = '\0'; } if (!config->proxymatch_ip) { config->proxymatch_ip = apr_array_make(cmd->pool, 1, sizeof(*match)); } match = (remoteip_proxymatch_t *) apr_array_push(config->proxymatch_ip); match->internal = cmd->info; if (looks_like_ip(ip)) { /* Note s may be null, that's fine (explicit host) */ rv = apr_ipsubnet_create(&match->ip, ip, s, cmd->pool); } else { apr_sockaddr_t *temp_sa; if (s) { return apr_pstrcat(cmd->pool, "RemoteIP: Error parsing IP ", arg, " the subnet /", s, " is invalid for ", cmd->cmd->name, NULL); } rv = apr_sockaddr_info_get(&temp_sa, ip, APR_UNSPEC, 0, APR_IPV4_ADDR_OK, cmd->temp_pool); while (rv == APR_SUCCESS) { apr_sockaddr_ip_get(&ip, temp_sa); rv = apr_ipsubnet_create(&match->ip, ip, NULL, cmd->pool); if (!(temp_sa = temp_sa->next)) { break; } match = (remoteip_proxymatch_t *) apr_array_push(config->proxymatch_ip); match->internal = cmd->info; } } if (rv != APR_SUCCESS) { char msgbuf[128]; apr_strerror(rv, msgbuf, sizeof(msgbuf)); return apr_pstrcat(cmd->pool, "RemoteIP: Error parsing IP ", arg, " (", msgbuf, " error) for ", cmd->cmd->name, NULL); } return NULL; }
static const char *allow_cmd(cmd_parms *cmd, void *dv, const char *from, const char *where_c) { access_compat_dir_conf *d = (access_compat_dir_conf *) dv; allowdeny *a; char *where = apr_pstrdup(cmd->pool, where_c); char *s; apr_status_t rv; if (strcasecmp(from, "from")) return "allow and deny must be followed by 'from'"; a = (allowdeny *) apr_array_push(cmd->info ? d->allows : d->denys); a->x.from = where; a->limited = cmd->limited; if (!strncasecmp(where, "env=!", 5)) { a->type = T_NENV; a->x.from += 5; } else if (!strncasecmp(where, "env=", 4)) { a->type = T_ENV; a->x.from += 4; } else if (!strcasecmp(where, "all")) { a->type = T_ALL; } else if ((s = ap_strchr(where, '/'))) { *s++ = '\0'; rv = apr_ipsubnet_create(&a->x.ip, where, s, cmd->pool); if(APR_STATUS_IS_EINVAL(rv)) { /* looked nothing like an IP address */ return "An IP address was expected"; } else if (rv != APR_SUCCESS) { return apr_psprintf(cmd->pool, "%pm", &rv); } a->type = T_IP; } else if (!APR_STATUS_IS_EINVAL(rv = apr_ipsubnet_create(&a->x.ip, where, NULL, cmd->pool))) { if (rv != APR_SUCCESS) return apr_psprintf(cmd->pool, "%pm", &rv); a->type = T_IP; } else { /* no slash, didn't look like an IP address => must be a host */ a->type = T_HOST; } return NULL; }
/* return -1 means error */ static int parse_url (request_rec *r, const char *remote_url, char **hostname, apr_int64_t *p_port_num, char **filepath) { apr_pool_t *rp = r->pool; char *p_port_str; char *p_tmp; *hostname = apr_pstrdup (rp, remote_url); if (!strncasecmp (*hostname, "http://", 7)) { *hostname += 7; } p_tmp = ap_strchr (*hostname, '/'); if (p_tmp) { *filepath = apr_pstrdup (rp, p_tmp); *p_tmp = '\0'; } else { *filepath = apr_pstrdup (rp, "/"); } *p_port_num = DEF_PORT_NUM; if (p_port_str = ap_strchr (*hostname, ':')) { *p_port_str = '\0'; p_port_str++; *p_port_num = apr_atoi64 (p_port_str); } if (errno == ERANGE) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "port number overflow"); return -1; } return 0; }
static apr_status_t get_dbm_grp(request_rec *r, char *key1, char *key2, const char *dbmgrpfile, const char *dbtype, const char ** out) { char *grp_colon, *val; apr_status_t retval; apr_dbm_t *f; retval = apr_dbm_open_ex(&f, dbtype, dbmgrpfile, APR_DBM_READONLY, APR_OS_DEFAULT, r->pool); if (retval != APR_SUCCESS) { return retval; } /* Try key2 only if key1 failed */ if (!(val = get_dbm_entry_as_str(r->pool, f, key1))) { val = get_dbm_entry_as_str(r->pool, f, key2); } apr_dbm_close(f); if (val && (grp_colon = ap_strchr(val, ':')) != NULL) { char *grp_colon2 = ap_strchr(++grp_colon, ':'); if (grp_colon2) { *grp_colon2 = '\0'; } *out = grp_colon; } else { *out = val; } return retval; }
/* output:p_ipsubnet_list */ static void get_ipsubnet_list_from_file_content (request_rec *r, apr_pool_t *mp, char *file_content, apr_int64_t file_len, apr_array_header_t **p_ipsubnet_list) { int i, j, k; int cr = 0, cn = 0; apr_status_t rv; char *tp; apr_ipsubnet_t **pip; char errmsg_buf[120]; *p_ipsubnet_list = apr_array_make (mp, 0, sizeof(apr_ipsubnet_t*)); for (i = j = 0; i <= file_len; i++) { if (file_content[i] == '\r' || file_content[i] == '\n') { file_content[i] == '\r' ? cr++ : cn++; for (k = j; k < i; k++) { if (file_content[i] != ' ') break; } /*be sure not a blank line */ if (k < i) { pip = apr_array_push (*p_ipsubnet_list); file_content[i] = '\0'; if (tp = ap_strchr (file_content + j, '/')) { *tp++ = '\0'; rv = apr_ipsubnet_create (pip, file_content + j, tp, mp); } else { rv = apr_ipsubnet_create (pip, file_content + j, NULL, mp); } if (rv != APR_SUCCESS) { apr_array_pop (*p_ipsubnet_list); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "invalid ipsubnet address at line %d", MAX (cr, cn)); #ifdef DEBUG apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf)); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "%s", errmsg_buf); #endif } } j = i + 1; } } }
/* Sets basic connection info */ static const char *set_log_sql_info(cmd_parms *cmd, void *dummy, const char *host, const char *user, const char *pwd) { if (!user) { /* user is null, so only one arg passed */ /* TODO: to more error checking/force all params to be set */ apr_uri_t uri; apr_uri_parse(cmd->pool, host, &uri); if (uri.scheme) { set_dbparam(cmd, NULL, "driver", uri.scheme); } if (uri.hostname) { set_dbparam(cmd, NULL, "hostname", uri.hostname); } if (uri.user) { set_dbparam(cmd, NULL, "username", uri.user); } if (uri.password) { set_dbparam(cmd, NULL, "password", uri.password); } if (uri.port_str) { set_dbparam(cmd, NULL, "port", uri.port_str); } if (uri.path) { /* extract Database name */ char *off = ap_strchr(++uri.path,'/'); if (off) *off='\0'; set_dbparam(cmd, NULL, "database", uri.path); } } else { if (*host != '.') { set_dbparam(cmd, NULL, "hostname", host); } if (*user != '.') { set_dbparam(cmd, NULL, "username", user); } if (*pwd != '.') { set_dbparam(cmd, NULL, "password", pwd); } } return NULL; }
static apr_status_t set_cf_default_proxies(apr_pool_t *p, reverseproxy_config_t *config) { apr_status_t rv; reverseproxy_proxymatch_t *match; int i; char *proxies[] = AB_DEFAULT_TRUSTED_PROXY; for (i=0; i<AB_DEFAULT_TRUSTED_PROXY_COUNT; i++) { char *ip = apr_pstrdup(p, proxies[i]); char *s = ap_strchr(ip, '/'); if (s) { *s++ = '\0'; } if (!config->proxymatch_ip) { config->proxymatch_ip = apr_array_make(p, 1, sizeof(*match)); } match = (reverseproxy_proxymatch_t *) apr_array_push(config->proxymatch_ip); rv = apr_ipsubnet_create(&match->ip, ip, s, p); } return rv; }
static authn_status check_dbm_pw(request_rec *r, const char *user, const char *password) { authn_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config, &authn_dbm_module); apr_status_t rv; char *dbm_password; char *colon_pw; rv = fetch_dbm_value(conf->dbmtype, conf->pwfile, user, &dbm_password, r->pool); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01754) "could not open dbm (type %s) auth file: %s", conf->dbmtype, conf->pwfile); return AUTH_GENERAL_ERROR; } if (!dbm_password) { return AUTH_USER_NOT_FOUND; } colon_pw = ap_strchr(dbm_password, ':'); if (colon_pw) { *colon_pw = '\0'; } AUTHN_CACHE_STORE(r, user, NULL, dbm_password); rv = apr_password_validate(password, dbm_password); if (rv != APR_SUCCESS) { return AUTH_DENIED; } return AUTH_GRANTED; }
AP_DECLARE(void) ap_add_common_vars(request_rec *r) { apr_table_t *e; server_rec *s = r->server; conn_rec *c = r->connection; core_dir_config *conf = (core_dir_config *)ap_get_core_module_config(r->per_dir_config); const char *env_temp; const apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in); const apr_table_entry_t *hdrs = (const apr_table_entry_t *) hdrs_arr->elts; int i; apr_port_t rport; char *q; /* use a temporary apr_table_t which we'll overlap onto * r->subprocess_env later * (exception: if r->subprocess_env is empty at the start, * write directly into it) */ if (apr_is_empty_table(r->subprocess_env)) { e = r->subprocess_env; } else { e = apr_table_make(r->pool, 25 + hdrs_arr->nelts); } /* First, add environment vars from headers... this is as per * CGI specs, though other sorts of scripting interfaces see * the same vars... */ for (i = 0; i < hdrs_arr->nelts; ++i) { if (!hdrs[i].key) { continue; } /* A few headers are special cased --- Authorization to prevent * rogue scripts from capturing passwords; content-type and -length * for no particular reason. */ if (!strcasecmp(hdrs[i].key, "Content-type")) { apr_table_addn(e, "CONTENT_TYPE", hdrs[i].val); } else if (!strcasecmp(hdrs[i].key, "Content-length")) { apr_table_addn(e, "CONTENT_LENGTH", hdrs[i].val); } /* * You really don't want to disable this check, since it leaves you * wide open to CGIs stealing passwords and people viewing them * in the environment with "ps -e". But, if you must... */ #ifndef SECURITY_HOLE_PASS_AUTHORIZATION else if (!strcasecmp(hdrs[i].key, "Authorization") || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) { if (conf->cgi_pass_auth == AP_CGI_PASS_AUTH_ON) { add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val); } } #endif else add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val); } env_temp = apr_table_get(r->subprocess_env, "PATH"); if (env_temp == NULL) { env_temp = getenv("PATH"); } if (env_temp == NULL) { env_temp = DEFAULT_PATH; } apr_table_addn(e, "PATH", apr_pstrdup(r->pool, env_temp)); #if defined(WIN32) env2env(e, "SystemRoot"); env2env(e, "COMSPEC"); env2env(e, "PATHEXT"); env2env(e, "WINDIR"); #elif defined(OS2) env2env(e, "COMSPEC"); env2env(e, "ETC"); env2env(e, "DPATH"); env2env(e, "PERLLIB_PREFIX"); #elif defined(BEOS) env2env(e, "LIBRARY_PATH"); #elif defined(DARWIN) env2env(e, "DYLD_LIBRARY_PATH"); #elif defined(_AIX) env2env(e, "LIBPATH"); #elif defined(__HPUX__) /* HPUX PARISC 2.0W knows both, otherwise redundancy is harmless */ env2env(e, "SHLIB_PATH"); env2env(e, "LD_LIBRARY_PATH"); #else /* Some Unix */ env2env(e, "LD_LIBRARY_PATH"); #endif apr_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r)); apr_table_addn(e, "SERVER_SOFTWARE", ap_get_server_banner()); apr_table_addn(e, "SERVER_NAME", ap_escape_html(r->pool, ap_get_server_name_for_url(r))); apr_table_addn(e, "SERVER_ADDR", r->connection->local_ip); /* Apache */ apr_table_addn(e, "SERVER_PORT", apr_psprintf(r->pool, "%u", ap_get_server_port(r))); add_unless_null(e, "REMOTE_HOST", ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST, NULL)); apr_table_addn(e, "REMOTE_ADDR", r->useragent_ip); apr_table_addn(e, "DOCUMENT_ROOT", ap_document_root(r)); /* Apache */ apr_table_setn(e, "REQUEST_SCHEME", ap_http_scheme(r)); apr_table_addn(e, "CONTEXT_PREFIX", ap_context_prefix(r)); apr_table_addn(e, "CONTEXT_DOCUMENT_ROOT", ap_context_document_root(r)); apr_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */ if (apr_table_get(r->notes, "proxy-noquery") && (q = ap_strchr(r->filename, '?'))) { *q = '\0'; apr_table_addn(e, "SCRIPT_FILENAME", apr_pstrdup(r->pool, r->filename)); *q = '?'; } else { apr_table_addn(e, "SCRIPT_FILENAME", r->filename); /* Apache */ } rport = c->client_addr->port; apr_table_addn(e, "REMOTE_PORT", apr_itoa(r->pool, rport)); if (r->user) { apr_table_addn(e, "REMOTE_USER", r->user); } else if (r->prev) { request_rec *back = r->prev; while (back) { if (back->user) { apr_table_addn(e, "REDIRECT_REMOTE_USER", back->user); break; } back = back->prev; } } add_unless_null(e, "AUTH_TYPE", r->ap_auth_type); env_temp = ap_get_remote_logname(r); if (env_temp) { apr_table_addn(e, "REMOTE_IDENT", apr_pstrdup(r->pool, env_temp)); } /* Apache custom error responses. If we have redirected set two new vars */ if (r->prev) { /* PR#57785: reconstruct full URL here */ apr_uri_t *uri = &r->prev->parsed_uri; if (!uri->scheme) { uri->scheme = (char*)ap_http_scheme(r->prev); } if (!uri->port) { uri->port = ap_get_server_port(r->prev); uri->port_str = apr_psprintf(r->pool, "%u", uri->port); } if (!uri->hostname) { uri->hostname = (char*)ap_get_server_name_for_url(r->prev); } add_unless_null(e, "REDIRECT_QUERY_STRING", r->prev->args); add_unless_null(e, "REDIRECT_URL", apr_uri_unparse(r->pool, uri, 0)); } if (e != r->subprocess_env) { apr_table_overlap(r->subprocess_env, e, APR_OVERLAP_TABLES_SET); } }
static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r, apr_pool_t *temp_pool, apr_uint16_t request_id) { const apr_array_header_t *envarr; const apr_table_entry_t *elts; struct iovec vec[2]; ap_fcgi_header header; unsigned char farray[AP_FCGI_HEADER_LEN]; char *body; apr_status_t rv; apr_size_t avail_len, len, required_len; int next_elem, starting_elem; char *proxyfilename = r->filename; fcgi_req_config_t *rconf = ap_get_module_config(r->request_config, &proxy_fcgi_module); if (rconf) { if (rconf->need_dirwalk) { ap_directory_walk(r); } } /* Strip balancer prefix */ if (r->filename && !strncmp(r->filename, "proxy:balancer://", 17)) { char *newfname = apr_pstrdup(r->pool, r->filename+17); newfname = ap_strchr(newfname, '/'); r->filename = newfname; } ap_add_common_vars(r); ap_add_cgi_vars(r); r->filename = proxyfilename; /* XXX are there any FastCGI specific env vars we need to send? */ /* XXX mod_cgi/mod_cgid use ap_create_environment here, which fills in * the TZ value specially. We could use that, but it would mean * parsing the key/value pairs back OUT of the allocated env array, * not to mention allocating a totally useless array in the first * place, which would suck. */ envarr = apr_table_elts(r->subprocess_env); elts = (const apr_table_entry_t *) envarr->elts; if (APLOGrtrace8(r)) { int i; for (i = 0; i < envarr->nelts; ++i) { ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, APLOGNO(01062) "sending env var '%s' value '%s'", elts[i].key, elts[i].val); } } /* Send envvars over in as many FastCGI records as it takes, */ next_elem = 0; /* starting with the first one */ avail_len = 16 * 1024; /* our limit per record, which could have been up * to AP_FCGI_MAX_CONTENT_LEN */ while (next_elem < envarr->nelts) { starting_elem = next_elem; required_len = ap_fcgi_encoded_env_len(r->subprocess_env, avail_len, &next_elem); if (!required_len) { if (next_elem < envarr->nelts) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02536) "couldn't encode envvar '%s' in %" APR_SIZE_T_FMT " bytes", elts[next_elem].key, avail_len); /* skip this envvar and continue */ ++next_elem; continue; } /* only an unused element at the end of the array */ break; } body = apr_palloc(temp_pool, required_len); rv = ap_fcgi_encode_env(r, r->subprocess_env, body, required_len, &starting_elem); /* we pre-compute, so we can't run out of space */ ap_assert(rv == APR_SUCCESS); /* compute and encode must be in sync */ ap_assert(starting_elem == next_elem); ap_fcgi_fill_in_header(&header, AP_FCGI_PARAMS, request_id, (apr_uint16_t)required_len, 0); ap_fcgi_header_to_array(&header, farray); vec[0].iov_base = (void *)farray; vec[0].iov_len = sizeof(farray); vec[1].iov_base = body; vec[1].iov_len = required_len; rv = send_data(conn, vec, 2, &len); apr_pool_clear(temp_pool); if (rv) { return rv; } } /* Envvars sent, so say we're done */ ap_fcgi_fill_in_header(&header, AP_FCGI_PARAMS, request_id, 0, 0); ap_fcgi_header_to_array(&header, farray); vec[0].iov_base = (void *)farray; vec[0].iov_len = sizeof(farray); return send_data(conn, vec, 1, &len); }
/* * Canonicalise http-like URLs. * scheme is the scheme for the URL * url is the URL starting with the first '/' * def_port is the default port for this scheme. */ static int proxy_fcgi_canon(request_rec *r, char *url) { char *host, sport[7]; const char *err; char *path; apr_port_t port, def_port; fcgi_req_config_t *rconf = NULL; const char *pathinfo_type = NULL; if (strncasecmp(url, "fcgi:", 5) == 0) { url += 5; } else { return DECLINED; } port = def_port = ap_proxy_port_of_scheme("fcgi"); ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "canonicalising URL %s", url); err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port); if (err) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01059) "error parsing URL %s: %s", url, err); return HTTP_BAD_REQUEST; } if (port != def_port) apr_snprintf(sport, sizeof(sport), ":%d", port); else sport[0] = '\0'; if (ap_strchr_c(host, ':')) { /* if literal IPv6 address */ host = apr_pstrcat(r->pool, "[", host, "]", NULL); } if (apr_table_get(r->notes, "proxy-nocanon")) { path = url; /* this is the raw path */ } else { path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0, r->proxyreq); } if (path == NULL) return HTTP_BAD_REQUEST; r->filename = apr_pstrcat(r->pool, "proxy:fcgi://", host, sport, "/", path, NULL); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01060) "set r->filename to %s", r->filename); rconf = ap_get_module_config(r->request_config, &proxy_fcgi_module); if (rconf == NULL) { rconf = apr_pcalloc(r->pool, sizeof(fcgi_req_config_t)); ap_set_module_config(r->request_config, &proxy_fcgi_module, rconf); } if (NULL != (pathinfo_type = apr_table_get(r->subprocess_env, "proxy-fcgi-pathinfo"))) { /* It has to be on disk for this to work */ if (!strcasecmp(pathinfo_type, "full")) { rconf->need_dirwalk = 1; ap_unescape_url_keep2f(path, 0); } else if (!strcasecmp(pathinfo_type, "first-dot")) { char *split = ap_strchr(path, '.'); if (split) { char *slash = ap_strchr(split, '/'); if (slash) { r->path_info = apr_pstrdup(r->pool, slash); ap_unescape_url_keep2f(r->path_info, 0); *slash = '\0'; /* truncate path */ } } } else if (!strcasecmp(pathinfo_type, "last-dot")) { char *split = ap_strrchr(path, '.'); if (split) { char *slash = ap_strchr(split, '/'); if (slash) { r->path_info = apr_pstrdup(r->pool, slash); ap_unescape_url_keep2f(r->path_info, 0); *slash = '\0'; /* truncate path */ } } } else { /* before proxy-fcgi-pathinfo had multi-values. This requires the * the FCGI server to fixup PATH_INFO because it's the entire path */ r->path_info = apr_pstrcat(r->pool, "/", path, NULL); if (!strcasecmp(pathinfo_type, "unescape")) { ap_unescape_url_keep2f(r->path_info, 0); } ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01061) "set r->path_info to %s", r->path_info); } } return OK; }
/* Read the OCSP response from the socket 'sd', using temporary memory * BIO 'bio', and return the decoded OCSP response object, or NULL on * error. */ static OCSP_RESPONSE *read_response(apr_socket_t *sd, BIO *bio, conn_rec *c, apr_pool_t *p) { apr_bucket_brigade *bb, *tmpbb; OCSP_RESPONSE *response; char *line; apr_size_t count; apr_int64_t code; /* Using brigades for response parsing is much simpler than using * apr_socket_* directly. */ bb = apr_brigade_create(p, c->bucket_alloc); tmpbb = apr_brigade_create(p, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_socket_create(sd, c->bucket_alloc)); line = get_line(tmpbb, bb, c, p); if (!line || strncmp(line, "HTTP/", 5) || (line = ap_strchr(line, ' ')) == NULL || (code = apr_atoi64(++line)) < 200 || code > 299) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01980) "bad response from OCSP server: %s", line ? line : "(none)"); return NULL; } /* Read till end of headers; don't have to even bother parsing the * Content-Length since the server is obliged to close the * connection after the response anyway for HTTP/1.0. */ count = 0; while ((line = get_line(tmpbb, bb, c, p)) != NULL && line[0] && ++count < MAX_HEADERS) { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01981) "OCSP response header: %s", line); } if (count == MAX_HEADERS) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01982) "could not read response headers from OCSP server, " "exceeded maximum count (%u)", MAX_HEADERS); return NULL; } else if (!line) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01983) "could not read response header from OCSP server"); return NULL; } /* Read the response body into the memory BIO. */ count = 0; while (!APR_BRIGADE_EMPTY(bb)) { const char *data; apr_size_t len; apr_status_t rv; apr_bucket *e = APR_BRIGADE_FIRST(bb); rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ); if (rv == APR_EOF) { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01984) "OCSP response: got EOF"); break; } if (rv != APR_SUCCESS) { ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01985) "error reading response from OCSP server"); return NULL; } if (len == 0) { /* Ignore zero-length buckets (possible side-effect of * line splitting). */ apr_bucket_delete(e); continue; } count += len; if (count > MAX_CONTENT) { ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01986) "OCSP response size exceeds %u byte limit", MAX_CONTENT); return NULL; } ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01987) "OCSP response: got %" APR_SIZE_T_FMT " bytes, %" APR_SIZE_T_FMT " total", len, count); BIO_write(bio, data, (int)len); apr_bucket_delete(e); } apr_brigade_destroy(bb); apr_brigade_destroy(tmpbb); /* Finally decode the OCSP response from what's stored in the * bio. */ response = d2i_OCSP_RESPONSE_bio(bio, NULL); if (response == NULL) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01988) "failed to decode OCSP response data"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, mySrvFromConn(c)); } return response; }
/* Manages the loadfactors and member status */ static int balancer_handler(request_rec *r) { void *sconf = r->server->module_config; proxy_server_conf *conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); proxy_balancer *balancer, *bsel = NULL; proxy_worker *worker, *wsel = NULL; apr_table_t *params = apr_table_make(r->pool, 10); int access_status; int i, n; const char *name; /* is this for us? */ if (strcmp(r->handler, "balancer-manager")) return DECLINED; r->allowed = (AP_METHOD_BIT << M_GET); if (r->method_number != M_GET) return DECLINED; if (r->args) { char *args = apr_pstrdup(r->pool, r->args); char *tok, *val; while (args && *args) { if ((val = ap_strchr(args, '='))) { *val++ = '\0'; if ((tok = ap_strchr(val, '&'))) *tok++ = '\0'; /* * Special case: workers are allowed path information */ if ((access_status = ap_unescape_url(val)) != OK) if (strcmp(args, "w") || (access_status != HTTP_NOT_FOUND)) return access_status; apr_table_setn(params, args, val); args = tok; } else return HTTP_BAD_REQUEST; } } /* Check that the supplied nonce matches this server's nonce; * otherwise ignore all parameters, to prevent a CSRF attack. */ if ((name = apr_table_get(params, "nonce")) == NULL || strcmp(balancer_nonce, name) != 0) { apr_table_clear(params); } if ((name = apr_table_get(params, "b"))) bsel = ap_proxy_get_balancer(r->pool, conf, apr_pstrcat(r->pool, "balancer://", name, NULL)); if ((name = apr_table_get(params, "w"))) { proxy_worker *ws; ws = ap_proxy_get_worker(r->pool, conf, name); if (bsel && ws) { worker = (proxy_worker *)bsel->workers->elts; for (n = 0; n < bsel->workers->nelts; n++) { if (strcasecmp(worker->name, ws->name) == 0) { wsel = worker; break; } ++worker; } } } /* First set the params */ /* * Note that it is not possible set the proxy_balancer because it is not * in shared memory. */ if (wsel) { const char *val; if ((val = apr_table_get(params, "lf"))) { int ival = atoi(val); if (ival >= 1 && ival <= 100) { wsel->s->lbfactor = ival; if (bsel) recalc_factors(bsel); } } if ((val = apr_table_get(params, "wr"))) { if (strlen(val) && strlen(val) < PROXY_WORKER_MAX_ROUTE_SIZ) strcpy(wsel->s->route, val); else *wsel->s->route = '\0'; } if ((val = apr_table_get(params, "rr"))) { if (strlen(val) && strlen(val) < PROXY_WORKER_MAX_ROUTE_SIZ) strcpy(wsel->s->redirect, val); else *wsel->s->redirect = '\0'; } if ((val = apr_table_get(params, "dw"))) { if (!strcasecmp(val, "Disable")) wsel->s->status |= PROXY_WORKER_DISABLED; else if (!strcasecmp(val, "Enable")) wsel->s->status &= ~PROXY_WORKER_DISABLED; } if ((val = apr_table_get(params, "ls"))) { int ival = atoi(val); if (ival >= 0 && ival <= 99) { wsel->s->lbset = ival; } } } if (apr_table_get(params, "xml")) { ap_set_content_type(r, "text/xml"); ap_rputs("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n", r); ap_rputs("<httpd:manager xmlns:httpd=\"http://httpd.apache.org\">\n", r); ap_rputs(" <httpd:balancers>\n", r); balancer = (proxy_balancer *)conf->balancers->elts; for (i = 0; i < conf->balancers->nelts; i++) { ap_rputs(" <httpd:balancer>\n", r); ap_rvputs(r, " <httpd:name>", balancer->name, "</httpd:name>\n", NULL); ap_rputs(" <httpd:workers>\n", r); worker = (proxy_worker *)balancer->workers->elts; for (n = 0; n < balancer->workers->nelts; n++) { ap_rputs(" <httpd:worker>\n", r); ap_rvputs(r, " <httpd:scheme>", worker->scheme, "</httpd:scheme>\n", NULL); ap_rvputs(r, " <httpd:hostname>", worker->hostname, "</httpd:hostname>\n", NULL); ap_rprintf(r, " <httpd:loadfactor>%d</httpd:loadfactor>\n", worker->s->lbfactor); ap_rputs(" </httpd:worker>\n", r); ++worker; } ap_rputs(" </httpd:workers>\n", r); ap_rputs(" </httpd:balancer>\n", r); ++balancer; } ap_rputs(" </httpd:balancers>\n", r); ap_rputs("</httpd:manager>", r); } else { ap_set_content_type(r, "text/html; charset=ISO-8859-1"); ap_rputs(DOCTYPE_HTML_3_2 "<html><head><title>Balancer Manager</title></head>\n", r); ap_rputs("<body><h1>Load Balancer Manager for ", r); ap_rvputs(r, ap_get_server_name(r), "</h1>\n\n", NULL); ap_rvputs(r, "<dl><dt>Server Version: ", ap_get_server_description(), "</dt>\n", NULL); ap_rvputs(r, "<dt>Server Built: ", ap_get_server_built(), "\n</dt></dl>\n", NULL); balancer = (proxy_balancer *)conf->balancers->elts; for (i = 0; i < conf->balancers->nelts; i++) { ap_rputs("<hr />\n<h3>LoadBalancer Status for ", r); ap_rvputs(r, balancer->name, "</h3>\n\n", NULL); ap_rputs("\n\n<table border=\"0\" style=\"text-align: left;\"><tr>" "<th>StickySession</th><th>Timeout</th><th>FailoverAttempts</th><th>Method</th>" "</tr>\n<tr>", r); if (balancer->sticky) { ap_rvputs(r, "<td>", balancer->sticky, NULL); } else { ap_rputs("<td> - ", r); } ap_rprintf(r, "</td><td>%" APR_TIME_T_FMT "</td>", apr_time_sec(balancer->timeout)); ap_rprintf(r, "<td>%d</td>\n", balancer->max_attempts); ap_rprintf(r, "<td>%s</td>\n", balancer->lbmethod->name); ap_rputs("</table>\n<br />", r); ap_rputs("\n\n<table border=\"0\" style=\"text-align: left;\"><tr>" "<th>Worker URL</th>" "<th>Route</th><th>RouteRedir</th>" "<th>Factor</th><th>Set</th><th>Status</th>" "<th>Elected</th><th>To</th><th>From</th>" "</tr>\n", r); worker = (proxy_worker *)balancer->workers->elts; for (n = 0; n < balancer->workers->nelts; n++) { char fbuf[50]; ap_rvputs(r, "<tr>\n<td><a href=\"", r->uri, "?b=", balancer->name + sizeof("balancer://") - 1, "&w=", ap_escape_uri(r->pool, worker->name), "&nonce=", balancer_nonce, "\">", NULL); ap_rvputs(r, worker->name, "</a></td>", NULL); ap_rvputs(r, "<td>", ap_escape_html(r->pool, worker->s->route), NULL); ap_rvputs(r, "</td><td>", ap_escape_html(r->pool, worker->s->redirect), NULL); ap_rprintf(r, "</td><td>%d</td>", worker->s->lbfactor); ap_rprintf(r, "<td>%d</td><td>", worker->s->lbset); if (worker->s->status & PROXY_WORKER_DISABLED) ap_rputs("Dis ", r); if (worker->s->status & PROXY_WORKER_IN_ERROR) ap_rputs("Err ", r); if (worker->s->status & PROXY_WORKER_STOPPED) ap_rputs("Stop ", r); if (worker->s->status & PROXY_WORKER_HOT_STANDBY) ap_rputs("Stby ", r); if (PROXY_WORKER_IS_USABLE(worker)) ap_rputs("Ok", r); if (!PROXY_WORKER_IS_INITIALIZED(worker)) ap_rputs("-", r); ap_rputs("</td>", r); ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td><td>", worker->s->elected); ap_rputs(apr_strfsize(worker->s->transferred, fbuf), r); ap_rputs("</td><td>", r); ap_rputs(apr_strfsize(worker->s->read, fbuf), r); ap_rputs("</td></tr>\n", r); ++worker; } ap_rputs("</table>\n", r); ++balancer; } ap_rputs("<hr />\n", r); if (wsel && bsel) { ap_rputs("<h3>Edit worker settings for ", r); ap_rvputs(r, wsel->name, "</h3>\n", NULL); ap_rvputs(r, "<form method=\"GET\" action=\"", NULL); ap_rvputs(r, r->uri, "\">\n<dl>", NULL); ap_rputs("<table><tr><td>Load factor:</td><td><input name=\"lf\" type=text ", r); ap_rprintf(r, "value=\"%d\"></td></tr>\n", wsel->s->lbfactor); ap_rputs("<tr><td>LB Set:</td><td><input name=\"ls\" type=text ", r); ap_rprintf(r, "value=\"%d\"></td></tr>\n", wsel->s->lbset); ap_rputs("<tr><td>Route:</td><td><input name=\"wr\" type=text ", r); ap_rvputs(r, "value=\"", ap_escape_html(r->pool, wsel->s->route), NULL); ap_rputs("\"></td></tr>\n", r); ap_rputs("<tr><td>Route Redirect:</td><td><input name=\"rr\" type=text ", r); ap_rvputs(r, "value=\"", ap_escape_html(r->pool, wsel->s->redirect), NULL); ap_rputs("\"></td></tr>\n", r); ap_rputs("<tr><td>Status:</td><td>Disabled: <input name=\"dw\" value=\"Disable\" type=radio", r); if (wsel->s->status & PROXY_WORKER_DISABLED) ap_rputs(" checked", r); ap_rputs("> | Enabled: <input name=\"dw\" value=\"Enable\" type=radio", r); if (!(wsel->s->status & PROXY_WORKER_DISABLED)) ap_rputs(" checked", r); ap_rputs("></td></tr>\n", r); ap_rputs("<tr><td colspan=2><input type=submit value=\"Submit\"></td></tr>\n", r); ap_rvputs(r, "</table>\n<input type=hidden name=\"w\" ", NULL); ap_rvputs(r, "value=\"", ap_escape_uri(r->pool, wsel->name), "\">\n", NULL); ap_rvputs(r, "<input type=hidden name=\"b\" ", NULL); ap_rvputs(r, "value=\"", bsel->name + sizeof("balancer://") - 1, "\">\n", NULL); ap_rvputs(r, "<input type=hidden name=\"nonce\" value=\"", balancer_nonce, "\">\n", NULL); ap_rvputs(r, "</form>\n", NULL); ap_rputs("<hr />\n", r); } ap_rputs(ap_psignature("",r), r); ap_rputs("</body></html>\n", r); } return OK; }
/* * This function will configure on the fly the php like php.ini will do */ static void vhx_php_config(request_rec * r, vhx_config_rec * vhr, char *path, char *phpoptstr) { /* * Some Basic PHP stuff, thank to Igor Popov module */ apr_table_set(r->subprocess_env, "PHP_DOCUMENT_ROOT", path); //zend_alter_ini_entry("doc_root", sizeof("doc_root"), path, strlen(path), 4, 1); zend_alter_ini_entry("doc_root", sizeof("doc_root"), path, strlen(path), ZEND_INI_SYSTEM, ZEND_INI_STAGE_ACTIVATE); /* * vhx_PHPopt_fromdb */ if (vhr->phpopt_fromdb) { VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "vhx_php_config: PHP from DB engaged"); char *retval; char *state; char *myphpoptions; myphpoptions = apr_pstrdup(r->pool, phpoptstr); if(myphpoptions != NULL) { VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "vhx_php_config: DB => %s", myphpoptions); if ((ap_strchr(myphpoptions, '=') != NULL)) { /* Getting values for PHP there so we can proceed */ retval = apr_strtok(myphpoptions, ";", &state); while (retval != NULL) { char *key = NULL; char *val = NULL; char *strtokstate = NULL; key = apr_strtok(retval, "=", &strtokstate); val = apr_strtok(NULL, "=", &strtokstate); if(key != NULL && val != NULL) { key = trimwhitespace(key); val = trimwhitespace(val); VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "vhx_php_config: Zend PHP option => %s => %s", key, val); //zend_alter_ini_entry(key, strlen(key) + 1, val, strlen(val), 4, 16); zend_alter_ini_entry(key, strlen(key) + 1, val, strlen(val), ZEND_INI_SYSTEM, ZEND_INI_STAGE_RUNTIME); if(apr_strnatcasecmp(key, "display_errors") == 0) { vhr->display_errors = atoi(val); } } else if( key != NULL && val == NULL) { VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "vhx_php_config: PHP option key '%s' had empty value, skipping...", key); } retval = apr_strtok(NULL, ";", &state); } } } else { VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "vhx_php_config: no PHP options found in DB"); } } /* * vhx_PHPopen_baserdir \ vhx_append_open_basedir | support * vhx_open_basedir_path / */ if (vhr->open_basedir) { if (vhr->append_basedir && vhr->openbdir_path) { /* * There is a default open_basedir path and * configuration allow appending them */ char *obasedir_path; if (vhr->path_prefix) { obasedir_path = apr_pstrcat(r->pool, vhr->openbdir_path, ":", vhr->path_prefix, path, NULL); } else { obasedir_path = apr_pstrcat(r->pool, vhr->openbdir_path, ":", path, NULL); } //zend_alter_ini_entry("open_basedir", 13, obasedir_path, strlen(obasedir_path), 4, 16); zend_alter_ini_entry("open_basedir", 13, obasedir_path, strlen(obasedir_path), ZEND_INI_SYSTEM, ZEND_INI_STAGE_RUNTIME); VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "vhx_php_config: PHP open_basedir set to %s (appending mode)", obasedir_path); } else { //zend_alter_ini_entry("open_basedir", 13, path, strlen(path), 4, 16); zend_alter_ini_entry("open_basedir", 13, path, strlen(path), ZEND_INI_SYSTEM, ZEND_INI_STAGE_RUNTIME); VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "vhx_php_config: PHP open_basedir set to %s", path); } } else { VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "vhx_php_config: PHP open_basedir inactive defaulting to php.ini values"); } /* * vhx_PHPdisplay_errors support */ if (vhr->display_errors) { VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "vhx_php_config: PHP display_errors engaged"); //zend_alter_ini_entry("display_errors", 10, "1", 1, 4, 16); zend_alter_ini_entry("display_errors", 10, "1", 1, ZEND_INI_SYSTEM, ZEND_INI_STAGE_RUNTIME); } else { VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "vhx_php_config: PHP display_errors inactive defaulting to php.ini values"); } }
static authn_status check_mongodb_pw(request_rec *r, const char *user, const char *password) { authn_mongodb_config_rec *conf = ap_get_module_config(r->per_dir_config, &authn_mongodb_module); apr_status_t rv; char *password_hash; char *colon_pw; rv = fetch_mongodb_value(conf->host, conf->port, conf->userfield, conf->passwdfield, conf->collection, user, &password_hash, r->pool); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "could not open mongoDB (host %s) port: %d", conf->host, conf->port); return AUTH_GENERAL_ERROR; } if (!password_hash) { return AUTH_USER_NOT_FOUND; } if ( conf->password_format != NULL) { if ( strcasecmp( conf->password_format,"django")==0) { char *token; char *alg; char *salt; char *hsh; char *saltpass; alg= apr_strtok( password_hash, "$",&token); salt = apr_strtok( NULL, "$",&token); hsh = apr_strtok( NULL, "$",&token); //ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,"password_hash=%s ALG=%s salt=%s hsh=%s", password_hash,alg,salt,hsh ); saltpass= apr_pstrcat(r->pool, salt, password, NULL); //char hash[APR_SHA1_DIGESTSIZE+APR_SHA1PW_IDLEN]; apr_byte_t hash[APR_SHA1_DIGESTSIZE+1]; apr_sha1_ctx_t context; apr_sha1_init(&context); apr_sha1_update(&context, saltpass, strlen(saltpass)); apr_sha1_final(hash, &context); hash[APR_SHA1_DIGESTSIZE]='\0'; int i=0; int j=0; for (i=0,j=0; i < APR_SHA1_DIGESTSIZE ;i+=1, j+=2 ) { if ( hash[i] != parse_hexpair(&(hsh[j]))) { return AUTH_DENIED; } } return AUTH_GRANTED; } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,"unrecognized password format %s", conf->password_format); return AUTH_DENIED; } } else { colon_pw = ap_strchr(password_hash, ':'); if (colon_pw) { *colon_pw = '\0'; } rv = apr_password_validate(password, password_hash); } if (rv != APR_SUCCESS) { return AUTH_DENIED; } return AUTH_GRANTED; }
static const char *allow_cmd (cmd_parms *cmd, void *dv, const char *from, const char *where_c) { auth_remote_dir_conf *d = (auth_remote_dir_conf *) dv; allowdeny *a; char *where = apr_pstrdup(cmd->pool, where_c); char *s; char msgbuf[120]; apr_status_t rv; if (strcasecmp(from, "from")) return "remote_allow and remote_deny must be followed by 'from'"; a = (allowdeny *) apr_array_push(cmd->info ? d->allows : d->denys); a->x.from = where; a->limited = cmd->limited; if (!strncasecmp(where, "env=!", 5)) { a->type = T_NENV; a->x.from += 5; } else if (!strncasecmp(where, "env=", 4)) { a->type = T_ENV; a->x.from += 4; } else if (!strcasecmp(where, "all")) { a->type = T_ALL; } else if (!strncasecmp (where, "uri=", 4)) { if (!strncasecmp (where, "uri=file://", 11)) { a->type = T_FILE; a->x.local_file_info.last_update_time = 0; a->x.local_file_info.last_update_file = NULL; a->x.local_file_info.local_file = where + 11; a->x.local_file_info.p_ipsubnet_list = NULL; #if APR_HAS_THREADS a->x.local_file_info.rwlock = NULL; #endif } else if (!strncasecmp (where, "uri=http://", 11) || !strncasecmp (where, "uri=", 4)){ a->type = T_URL; a->x.remote_info.last_contact_time = 0; a->x.remote_info.last_update_time = NULL; a->x.remote_info.last_update_url = NULL; a->x.remote_info.remote_url = where + 4; a->x.remote_info.subpool = NULL; a->x.remote_info.p_ipsubnet_list = NULL; #if APR_HAS_THREADS a->x.remote_info.rwlock = NULL; #endif } } else if ((s = ap_strchr(where, '/'))) { *s++ = '\0'; rv = apr_ipsubnet_create(&a->x.ip, where, s, cmd->pool); if(APR_STATUS_IS_EINVAL(rv)) { /* looked nothing like an IP address */ return "An IP address was expected"; } else if (rv != APR_SUCCESS) { apr_strerror(rv, msgbuf, sizeof msgbuf); return apr_pstrdup(cmd->pool, msgbuf); } a->type = T_IP; } else if (!APR_STATUS_IS_EINVAL(rv = apr_ipsubnet_create(&a->x.ip, where, NULL, cmd->pool))) { if (rv != APR_SUCCESS) { apr_strerror(rv, msgbuf, sizeof msgbuf); return apr_pstrdup(cmd->pool, msgbuf); } a->type = T_IP; } else { /* no slash, didn't look like an IP address => must be a host */ a->type = T_HOST; } return NULL; }
static authz_status forward_dns_check_authorization(request_rec *r, const char *require_line, const void *parsed_require_line) { const char *err = NULL; const ap_expr_info_t *expr = parsed_require_line; const char *require, *t; char *w; /* the require line is an expression, which is evaluated now. */ require = ap_expr_str_exec(r, expr, &err); if (err) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(03354) "authz_host authorize: require forward-dns: " "Can't evaluate require expression: %s", err); return AUTHZ_DENIED; } /* tokenize expected list of names */ t = require; while ((w = ap_getword_conf(r->pool, &t)) && w[0]) { apr_sockaddr_t *sa; apr_status_t rv; char *hash_ptr; /* stop on apache configuration file comments */ if ((hash_ptr = ap_strchr(w, '#'))) { if (hash_ptr == w) { break; } *hash_ptr = '\0'; } /* does the client ip match one of the names? */ rv = apr_sockaddr_info_get(&sa, w, APR_UNSPEC, 0, 0, r->pool); if (rv == APR_SUCCESS) { while (sa) { int match = apr_sockaddr_equal(sa, r->useragent_addr); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03355) "access check for %s as '%s': %s", r->useragent_ip, w, match? "yes": "no"); if (match) { return AUTHZ_GRANTED; } sa = sa->next; } } else { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(03356) "No sockaddr info for \"%s\"", w); } /* stop processing, we are in a comment */ if (hash_ptr) { break; } } return AUTHZ_DENIED; }
static authn_status authn_dbd_password(request_rec *r, const char *user, const char *password) { apr_status_t rv; const char *dbd_password = NULL; apr_dbd_prepared_t *statement; apr_dbd_results_t *res = NULL; apr_dbd_row_t *row = NULL; authn_dbd_conf *conf = ap_get_module_config(r->per_dir_config, &authn_dbd_module); ap_dbd_t *dbd = authn_dbd_acquire_fn(r); char *digest_colon = NULL; if (dbd == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Failed to acquire database connection to look up " "user '%s'", user); return AUTH_GENERAL_ERROR; } if (conf->user == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "No AuthDBDUserPWQuery has been specified"); return AUTH_GENERAL_ERROR; } statement = apr_hash_get(dbd->prepared, conf->user, APR_HASH_KEY_STRING); if (statement == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "A prepared statement could not be found for " "AuthDBDUserPWQuery with the key '%s'", conf->user); return AUTH_GENERAL_ERROR; } if (apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res, statement, 0, user, NULL) != 0) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Query execution error looking up '%s' " "in database", user); return AUTH_GENERAL_ERROR; } for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1); rv != -1; rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) { if (rv != 0) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "Error retrieving results while looking up '%s' " "in database", user); return AUTH_GENERAL_ERROR; } if (dbd_password == NULL) { #if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 3) /* add the rest of the columns to the environment */ int i = 1; const char *name; for (name = apr_dbd_get_name(dbd->driver, res, i); name != NULL; name = apr_dbd_get_name(dbd->driver, res, i)) { char *str = apr_pstrcat(r->pool, AUTHN_PREFIX, name, NULL); int j = sizeof(AUTHN_PREFIX)-1; /* string length of "AUTHENTICATE_", excluding the trailing NIL */ while (str[j]) { if (!apr_isalnum(str[j])) { str[j] = '_'; } else { str[j] = apr_toupper(str[j]); } j++; } apr_table_set(r->subprocess_env, str, apr_dbd_get_entry(dbd->driver, row, i)); i++; } #endif dbd_password = apr_dbd_get_entry(dbd->driver, row, 0); } /* we can't break out here or row won't get cleaned up */ } if (!dbd_password) { return AUTH_USER_NOT_FOUND; } if ((digest_colon = ap_strchr(dbd_password, ':'))) { const char *realm = NULL, *exp_hash = NULL; const char *act_hash = NULL; realm = apr_pstrndup(r->pool, dbd_password, digest_colon - dbd_password); exp_hash = digest_colon + 1; act_hash = ap_md5(r->pool, (unsigned char*) apr_pstrcat(r->pool, user, ":", realm, ":", password, NULL)); if (strcmp(act_hash, exp_hash)) { return AUTH_DENIED; } else { return AUTH_GRANTED; } } rv = apr_password_validate(password, dbd_password); if (rv != APR_SUCCESS) { return AUTH_DENIED; } return AUTH_GRANTED; }