proxy_util.c revision 88d088222c12b626d76069ecef91057b2a26122b
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* ====================================================================
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * The Apache Software License, Version 1.1
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * reserved.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Redistribution and use in source and binary forms, with or without
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * modification, are permitted provided that the following conditions
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * are met:
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 1. Redistributions of source code must retain the above copyright
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * notice, this list of conditions and the following disclaimer.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 2. Redistributions in binary form must reproduce the above copyright
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * notice, this list of conditions and the following disclaimer in
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * the documentation and/or other materials provided with the
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * distribution.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 3. The end-user documentation included with the redistribution,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * if any, must include the following acknowledgment:
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * "This product includes software developed by the
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Apache Software Foundation (http://www.apache.org/)."
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Alternately, this acknowledgment may appear in the software itself,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * if and wherever such third-party acknowledgments normally appear.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 4. The names "Apache" and "Apache Software Foundation" must
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * not be used to endorse or promote products derived from this
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * software without prior written permission. For written
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * permission, please contact apache@apache.org.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 5. Products derived from this software may not be called "Apache",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * nor may "Apache" appear in their name, without prior written
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * permission of the Apache Software Foundation.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * SUCH DAMAGE.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * ====================================================================
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * This software consists of voluntary contributions made by many
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * individuals on behalf of the Apache Software Foundation. For more
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * information on the Apache Software Foundation, please see
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Portions of this software are based upon public domain software
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * originally written at the National Center for Supercomputing Applications,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * University of Illinois, Urbana-Champaign.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* Utility routines for Apache proxy */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic int proxy_match_hostname(struct dirconn_entry *This, request_rec *r);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic int proxy_match_word(struct dirconn_entry *This, request_rec *r);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic struct per_thread_data *get_per_thread_data(void);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* already called in the knowledge that the characters are hex digits */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbint ap_proxy_hex2c(const char *x)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#else /*APR_CHARSET_EBCDIC*/
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return (1 == sscanf(x, "%2x", &i)) ? os_toebcdic[i&0xFF] : 0;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#endif /*APR_CHARSET_EBCDIC*/
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz if (i >= 10)
a2a0abd88b19e042a3eb2a9fa1702c25ad51303dwrowe if (i >= 10)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#else /*APR_CHARSET_EBCDIC*/
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb x[0] = '%';
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#endif /*APR_CHARSET_EBCDIC*/
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * canonicalise a URL-encoded string
c2cf53a40a9814eb91db2cdf820f97d943f21628coar * Convert a URL-encoded string to canonical form.
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * It decodes characters which need not be encoded,
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * and encodes those which must be encoded, and does not touch
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * those which must not be touched.
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoarchar *ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe int i, j, ch;
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe char *allowed; /* characters which should not be encoded */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe char *reserved; /* characters which much not be en/de-coded */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe/* N.B. in addition to :@&=, this allows ';' in an http path
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * and '?' in an ftp path -- this may be revised
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * Also, it makes a '+' character in a search string reserved, as
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * it may be form-encoded. (Although RFC 1738 doesn't allow this -
ea512a4af20e6b6e6931de4929d54d93f03a0139ianh * it only permits ; / ? : @ = & as reserved chars.)
ea512a4af20e6b6e6931de4929d54d93f03a0139ianh else if (t == enc_search)
ea512a4af20e6b6e6931de4929d54d93f03a0139ianh else if (t == enc_user)
ea512a4af20e6b6e6931de4929d54d93f03a0139ianh else if (t == enc_fpath)
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe else /* if (t == enc_parm) */
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz else if (t == enc_search)
3e392a5afd51526de3cb15d57ee46d8cb160ae65gregames for (i = 0, j = 0; i < len; i++, j++) {
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe/* always handle '/' first */
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe/* decode it if not already done */
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe if (ch != 0 && strchr(reserved, ch)) { /* keep it encoded */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe/* recode it, if necessary */
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe y[j] = '\0';
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * Parses network-location.
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * urlp on input the URL; on output the path, after the leading /
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * user NULL if no user/password permitted
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * password holder for password
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * host holder for host
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * port port number; only set if one is supplied.
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe * Returns an error string.
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe return "Malformed URL";
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe /* find _last_ '@' since it might occur in user/password part */
c2cf53a40a9814eb91db2cdf820f97d943f21628coar/* find password */
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz password = ap_proxy_canonenc(p, strp + 1, strlen(strp + 1), enc_user, 1);
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe return "Bad %-escape in URL (password)";
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe user = ap_proxy_canonenc(p, user, strlen(user), enc_user, 1);
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz return "Bad %-escape in URL (username)";
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz /* if (i == 0) the no port was given; keep default */
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz return "Bad port number in URL";
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe } else if (i > 0) {
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe return "Port number in URL > 65535";
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe ap_str_tolower(host); /* DNS names are case-insensitive */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe return "Missing host in URL";
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe/* check hostname syntax */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe /* must be an IP address */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe#if defined(WIN32) || defined(NETWARE) || defined(TPF) || defined(BEOS)
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1))
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe return "Bad IP address in URL";
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe/* if (strchr(host,'.') == NULL && domain != NULL)
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe host = pstrcat(p, host, domain, NULL);
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe * If the date is a valid RFC 850 date or asctime() date, then it
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe * is converted to the RFC 1123 format, otherwise it is not modified.
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe * This routine is not very fast at doing conversions, as it uses
0f6fdc73136a064819585afe03bc3503826ee592wrowe * sscanf and sprintf. However, if the date is already correctly
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe * formatted, then it exits very quickly.
cc9582e53aead2a044077c4a92f3dfc3605590b3wroweconst char *
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe /* check for RFC 850 date */
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp return x; /* not a valid date */
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp if (q[4] != '-' || q[8] != '-' || q[11] != ' ' || q[14] != ':' ||
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp if (sscanf(q + 2, "%u-%3s-%u %u:%u:%u %3s", &mday, month, &year,
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe/* check for acstime() date */
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe if (x[3] != ' ' || x[7] != ' ' || x[10] != ' ' || x[13] != ':' ||
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp if (sscanf(x, "%3s %3s %u %u:%u:%u %u", week, month, &mday, &hour,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* check date */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb apr_snprintf(q, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", ap_day_snames[wk],
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe rp->request_config = ap_create_request_config(rp->pool);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe req_cfg = apr_pcalloc(rp->pool, sizeof(core_request_config));
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe ap_set_module_config(rp->request_config, &core_module, req_cfg);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe * Reads headers from a buffer and returns an array of headers.
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe * Returns NULL on file error
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe * This routine tries to deal with too long lines and continuation lines.
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe * @@@: XXX: FIXME: currently the headers are passed thru un-merged.
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe * Is that okay, or should they be collapsed where possible?
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwroweapr_table_t *ap_proxy_read_headers(request_rec *r, request_rec *rr, char *buffer, int size, conn_rec *c)
11fb2f3611e6ff9a541e10b13e3108934f828141gregames * Read header lines until we get the empty separator line, a read error,
11fb2f3611e6ff9a541e10b13e3108934f828141gregames * the connection closes (EOF), or we timeout.
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* Buggy MS IIS servers sometimes return invalid headers
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe * (an extra "HTTP/1.0 200, OK" line sprinkled in between
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * the usual MIME headers). Try to deal with it in a sensible
2f1949bb0e3c209db94c8d521cba7380b9d11421trawick * way, but log the fact.
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * XXX: The mask check is buggy if we ever see an HTTP/1.10 */
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar /* Nope, it wasn't even an extra HTTP header. Give up. */
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe "proxy: Ignoring duplicate HTTP header "
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* XXX: RFC2068 defines only SP and HT as whitespace, this test is
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe * wrong... and so are many others probably.
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* should strip trailing whitespace as well */
8aefbd756763807188d2e3ce336a8680e4893066wrowe for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* the header was too long; at the least we should skip extra data */
8aefbd756763807188d2e3ce336a8680e4893066wrowe while ((len = ap_getline(field, MAX_STRING_LEN, rr, 1))
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* soak up the extra data */
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (len == 0) /* time to exit the larger loop as well */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe * list is a comma-separated list of case-insensitive tokens, with
8aefbd756763807188d2e3ce336a8680e4893066wrowe * optional whitespace around the tokens.
8aefbd756763807188d2e3ce336a8680e4893066wrowe * The return returns 1 if the token val is found in the list, or 0
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe * otherwise.
8aa5ca8ff2a4d8e56f62ea3d461e2799136da085trawickint ap_proxy_liststr(const char *list, const char *val)
23c6309e36a63b13b61c35999c978017521993d6wrowe const char *p;
23c6309e36a63b13b61c35999c978017521993d6wrowe if (p != NULL) {
cf6ef072483172309861d06e85b1aeff4573c060wrowe while (apr_isspace(*p));
cf6ef072483172309861d06e85b1aeff4573c060wrowe * list is a comma-separated list of case-insensitive tokens, with
cf6ef072483172309861d06e85b1aeff4573c060wrowe * optional whitespace around the tokens.
8aefbd756763807188d2e3ce336a8680e4893066wrowe * The return returns 1 if the token val is found in the list, or 0
cf6ef072483172309861d06e85b1aeff4573c060wrowe * otherwise.
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianpchar *ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val)
cf6ef072483172309861d06e85b1aeff4573c060wrowe const char *p;
cf6ef072483172309861d06e85b1aeff4573c060wrowe if (p != NULL) {
cf6ef072483172309861d06e85b1aeff4573c060wrowe while (apr_isspace(*p));
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* do nothing */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe new = apr_pstrcat(pool, new, ",", apr_pstrndup(pool, list, i), NULL);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe * Converts 8 hex digits to a time integer
a9a4544168a37b43bd180b3703ccee995f27a80awroweint ap_proxy_hex2sec(const char *x)
a9a4544168a37b43bd180b3703ccee995f27a80awrowe unsigned int j;
a9a4544168a37b43bd180b3703ccee995f27a80awrowe for (i = 0, j = 0; i < 8; i++) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (j == 0xffffffff)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe * Converts a time integer to 8 hex digits
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowevoid ap_proxy_sec2hex(int t, char *y)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe unsigned int j = t;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe for (i = 7; i >= 0; i--) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wroweint ap_proxyerror(request_rec *r, int statuscode, const char *message)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "The proxy server could not handle the request "
8aefbd756763807188d2e3ce336a8680e4893066wrowe "Reason: <STRONG>",
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* Allow "error-notes" string to be printed by ap_send_error_response() */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe apr_table_setn(r->notes, "verbose-error-to", apr_pstrdup(r->pool, "*"));
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe r->status_line = apr_psprintf(r->pool, "%3.3u Proxy Error", statuscode);
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe * This routine returns its own error message
1b315ee865b0f11e582beb64127ca3a99a319d2fwroweconst char *ap_proxy_host2addr(const char *host, struct hostent *reqhp)
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe return "Host not found";
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe hp = gethostbyaddr((char *) &ptd->ipaddr, sizeof(ptd->ipaddr), AF_INET);
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowestatic const char *
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe char *url, *user = NULL, *password = NULL, *err, *host;
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* Set url to the first char after "scheme://" */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe url = apr_pstrdup(r->pool, &url[1]); /* make it point to "//", which is what proxy_canon_netloc expects */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe err = ap_proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port);
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe/* Return TRUE if addr represents an IP address (or an IP network address) */
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantzint ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p)
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* if the address is given with an explicit netmask, use that */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* Due to a deficiency in ap_inet_addr(), it is impossible to parse */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* "partial" addresses (with less than 4 quads) correctly, i.e. */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* 192.168.123 is parsed as 192.168.0.123, which is not what I want. */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* I therefore have to parse the IP address manually: */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /*if (proxy_readmask(This->name, &This->addr.s_addr, &This->mask.s_addr) == 0) */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* addr and mask were set by proxy_readmask() */
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz /*return 1; */
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz /* Parse IP addr manually, optionally allowing */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* abbreviated net addresses like 192.168. */
cf6ef072483172309861d06e85b1aeff4573c060wrowe /* Iterate over up to 4 (dotted) quads. */
8aefbd756763807188d2e3ce336a8680e4893066wrowe for (quads = 0; quads < 4 && *addr != '\0'; ++quads) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (*addr == '/' && quads > 0) /* netmask starts here. */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe return 0; /* no digit at start of quad */
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz if (tmp == addr) /* expected a digit, found something else */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* invalid octet */
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz ++addr; /* after the 4th quad, a dot would be illegal */
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz for (This->addr.s_addr = 0, i = 0; i < quads; ++i)
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (addr[0] == '/' && apr_isdigit(addr[1])) { /* net mask follows: */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (tmp == addr) /* expected a digit, found something else */
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar if (bits < 0 || bits > 32) /* netmask must be between 0 and 32 */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* Determine (i.e., "guess") netmask by counting the */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* number of trailing .0's; reduce #quads appropriately */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* (so that 192.168.0.0 is equivalent to 192.168.) */
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz /* "IP Address should be given in dotted-quad form, optionally followed by a netmask (e.g., 192.168.111.0/24)"; */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* every zero-byte counts as 8 zero-bits */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (bits != 32) /* no warning for fully qualified IP address */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld\n",
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe This->mask.s_addr = htonl(APR_INADDR_NONE << (32 - bits));
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "Warning: NetMask and IP-Addr disagree in %s/%ld\n",
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe " Set to %s/%ld\n",
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe return (*addr == '\0'); /* okay iff we've parsed the whole string */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe/* Return TRUE if addr represents an IP address (or an IP network address) */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowestatic int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe const char *found;
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz if (4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3])) {
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr)) {
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz "1)IP-Match: %s[%s] <-> ", host, inet_ntoa(addr));
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* Try to deal with multiple IP addr's for a host */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe for (ip_listptr = the_host.h_addr_list; *ip_listptr; ++ip_listptr) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (This->addr.s_addr == (ip_list->s_addr & This->mask.s_addr)) {
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz "3)IP-Match: %s[%s] <-> ", found, inet_ntoa(*ip_list));
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "3)IP-NoMatch: %s[%s] <-> ", found, inet_ntoa(*ip_list));
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
2787ef5edc27fa4f6777ba8d51aa48fd9fdf54bbwrowe/* Return TRUE if addr represents a domain name */
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantzint ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p)
2787ef5edc27fa4f6777ba8d51aa48fd9fdf54bbwrowe /* Domain name must start with a '.' */
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
2787ef5edc27fa4f6777ba8d51aa48fd9fdf54bbwrowe for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "@@@@ handle optional port in proxy_is_domainname()");
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* @@@@ handle optional port */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* Strip trailing dots */
8aefbd756763807188d2e3ce336a8680e4893066wrowe for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe/* Return TRUE if host "host" is in domain "domain" */
8aefbd756763807188d2e3ce336a8680e4893066wrowestatic int proxy_match_domainname(struct dirconn_entry *This, request_rec *r)
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz const char *host = proxy_get_host_of_request(r);
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz if (host == NULL) /* some error was logged already */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* @@@ do this within the setup? */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* Ignore trailing dots in domain comparison: */
8aefbd756763807188d2e3ce336a8680e4893066wrowe && strncasecmp(&host[h_len - d_len], This->name, d_len) == 0;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe/* Create a copy of a "struct hostent" record; it was presumably returned
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe * from a call to gethostbyname() and lives in static storage.
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe * By creating a copy we can tuck it away for later use.
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowestatic struct hostent * pduphostent(apr_pool_t *p, const struct hostent *hp)
cf6ef072483172309861d06e85b1aeff4573c060wrowe int i = 0, j = 0;
cf6ef072483172309861d06e85b1aeff4573c060wrowe /* Count number of alias entries */
69adb3d949e3dd17c0492a01fc2cf298832c7eefwrowe /* Count number of in_addr entries */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* Allocate hostent structure, alias ptrs, addr ptrs, addrs */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe newent = (struct hostent *) apr_palloc(p, sizeof(*hp));
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe aliases = (char **) apr_palloc(p, (j+1) * sizeof(char*));
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ptrs = (char **) apr_palloc(p, (i+1) * sizeof(char*));
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe addrs = (struct in_addr *) apr_palloc(p, (i+1) * sizeof(struct in_addr));
c2cf53a40a9814eb91db2cdf820f97d943f21628coar /* Copy Alias Names: */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* Copy address entries */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe/* Return TRUE if addr represents a host name */
e4a3f3c2f080cac75a15a6454cca429b8161c050wroweint ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* Host names must not start with a '.' */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
cf6ef072483172309861d06e85b1aeff4573c060wrowe for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (addr[i] != '\0' || ap_proxy_host2addr(addr, &host) != NULL)
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz /* Strip trailing dots */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe/* Return TRUE if host "host" is equal to host2 "host2" */
c2cf53a40a9814eb91db2cdf820f97d943f21628coarstatic int proxy_match_hostname(struct dirconn_entry *This, request_rec *r)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe return 0; /* oops! */
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz unsigned long *ip_list;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* Try to deal with multiple IP addr's for a host */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe for (ip_list = *This->hostentry->h_addr_list; *ip_list != 0UL; ++ip_list)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (*ip_list == ? ? ? ? ? ? ? ? ? ? ? ? ?)
cf6ef072483172309861d06e85b1aeff4573c060wrowe /* Ignore trailing dots in host2 comparison: */
cf6ef072483172309861d06e85b1aeff4573c060wrowe/* Return TRUE if addr is to be matched as a word */
cf6ef072483172309861d06e85b1aeff4573c060wroweint ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p)
cf6ef072483172309861d06e85b1aeff4573c060wrowe/* Return TRUE if string "str2" occurs literally in "str1" */
cf6ef072483172309861d06e85b1aeff4573c060wrowestatic int proxy_match_word(struct dirconn_entry *This, request_rec *r)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe return host != NULL && ap_strstr_c(host, This->name) != NULL;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe/* checks whether a host in uri_addr matches proxyblock */
e4a3f3c2f080cac75a15a6454cca429b8161c050wroweint ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* XXX FIXME: conf->noproxies->elts is part of an opaque structure */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar "proxy: checking remote machine [%s] against [%s]", uri_addr->hostname, npent[j].name);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if ((npent[j].name && ap_strstr_c(uri_addr->hostname, npent[j].name))
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "proxy: connect to remote machine %s blocked: name %s matched", uri_addr->hostname, npent[j].name);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "proxy: ProxyBlock comparing %s and %s", conf_ip, uri_ip);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "proxy: connect to remote machine %s blocked: IP %s matched", uri_addr->hostname, conf_ip);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe/* set up the minimal filter set */
e4a3f3c2f080cac75a15a6454cca429b8161c050wroweint ap_proxy_pre_http_connection(conn_rec *c, request_rec *r)
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar/* converts a series of buckets into a string */
e4a3f3c2f080cac75a15a6454cca429b8161c050wroweapr_status_t ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen)
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* start with an empty string */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* get line-at-a-time */
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe /* loop through each brigade */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* get brigade from network */
c2cf53a40a9814eb91db2cdf820f97d943f21628coar if (APR_SUCCESS != (rv = ap_get_brigade(c->input_filters, bb, AP_MODE_BLOCKING))) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* loop through each bucket */
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (APR_SUCCESS != apr_bucket_read(e, (const char **)&response, &len, APR_BLOCK_READ)) {
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* is string LF terminated? */
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar /* concat strings until buff is full - then throw the data away */
0540a0b469147b52e858587270dba31c2aaa9e09wrowe if (len > 0) {
0540a0b469147b52e858587270dba31c2aaa9e09wroweBOOL WINAPI DllMain (HINSTANCE dllhandle, DWORD reason, LPVOID reserved)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb TlsSetValue (tls_index, malloc (sizeof (struct per_thread_data)));
948096a99010fccf648814fecf38f75c689172d7wrowestatic struct per_thread_data *get_per_thread_data(void)