proxy_util.c revision a6fc1f3e5f9a478080cea4715aba49d17a7ccbf8
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*/
b45c1c292ff1fa635004ae81fa691f8cb3cdda85rbb x[0] = '%';
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (i >= 10)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (i >= 10)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#else /*APR_CHARSET_EBCDIC*/
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb x[0] = '%';
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#endif /*APR_CHARSET_EBCDIC*/
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * canonicalise a URL-encoded string
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Convert a URL-encoded string to canonical form.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * It decodes characters which need not be encoded,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * and encodes those which must be encoded, and does not touch
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * those which must not be touched.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbchar *ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb int i, j, ch;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb char *allowed; /* characters which should not be encoded */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb char *reserved; /* characters which much not be en/de-coded */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* N.B. in addition to :@&=, this allows ';' in an http path
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * and '?' in an ftp path -- this may be revised
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Also, it makes a '+' character in a search string reserved, as
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * it may be form-encoded. (Although RFC 1738 doesn't allow this -
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * it only permits ; / ? : @ = & as reserved chars.)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb else if (t == enc_search)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb else if (t == enc_user)
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe else if (t == enc_fpath)
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe else /* if (t == enc_parm) */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe else if (t == enc_search)
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe for (i = 0, j = 0; i < len; i++, j++) {
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe/* always handle '/' first */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe/* decode it if not already done */
2f1949bb0e3c209db94c8d521cba7380b9d11421trawick if (!ap_isxdigit(x[i + 1]) || !ap_isxdigit(x[i + 2]))
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe if (ch != 0 && strchr(reserved, ch)) { /* keep it encoded */
2f1949bb0e3c209db94c8d521cba7380b9d11421trawick/* recode it, if necessary */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe y[j] = '\0';
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe * Parses network-location.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * urlp on input the URL; on output the path, after the leading /
8aefbd756763807188d2e3ce336a8680e4893066wrowe * user NULL if no user/password permitted
8aefbd756763807188d2e3ce336a8680e4893066wrowe * password holder for password
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * host holder for host
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * port port number; only set if one is supplied.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Returns an error string.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return "Malformed URL";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* find _last_ '@' since it might occur in user/password part */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* find password */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb password = ap_proxy_canonenc(p, strp + 1, strlen(strp + 1), enc_user, 1);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return "Bad %-escape in URL (password)";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb user = ap_proxy_canonenc(p, user, strlen(user), enc_user, 1);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return "Bad %-escape in URL (username)";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* if (i == 0) the no port was given; keep default */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return "Bad port number in URL";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb } else if (i > 0) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return "Port number in URL > 65535";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ap_str_tolower(host); /* DNS names are case-insensitive */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return "Missing host in URL";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* check hostname syntax */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* must be an IP address */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#if defined(WIN32) || defined(NETWARE) || defined(TPF) || defined(BEOS)
4ca6cbe768b4e0917ac0b76333c26a7d5396d454trawick if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1))
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return "Bad IP address in URL";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* if (strchr(host,'.') == NULL && domain != NULL)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb host = pstrcat(p, host, domain, NULL);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * If the date is a valid RFC 850 date or asctime() date, then it
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * is converted to the RFC 1123 format, otherwise it is not modified.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * This routine is not very fast at doing conversions, as it uses
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * sscanf and sprintf. However, if the date is already correctly
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * formatted, then it exits very quickly.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbconst char *
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* check for RFC 850 date */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb *q = '\0';
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return x; /* not a valid date */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (q[4] != '-' || q[8] != '-' || q[11] != ' ' || q[14] != ':' ||
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (sscanf(q + 2, "%u-%3s-%u %u:%u:%u %3s", &mday, month, &year,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* check for acstime() date */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (x[3] != ' ' || x[7] != ' ' || x[10] != ' ' || x[13] != ':' ||
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb 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],
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb rp->request_config = ap_create_request_config(rp->pool);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb req_cfg = apr_pcalloc(rp->pool, sizeof(core_request_config));
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ap_set_module_config(rp->request_config, &core_module, req_cfg);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Reads headers from a buffer and returns an array of headers.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Returns NULL on file error
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * This routine tries to deal with too long lines and continuation lines.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * @@@: XXX: FIXME: currently the headers are passed thru un-merged.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Is that okay, or should they be collapsed where possible?
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbapr_table_t *ap_proxy_read_headers(request_rec *r, request_rec *rr, char *buffer, int size, conn_rec *c)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Read header lines until we get the empty separator line, a read error,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * the connection closes (EOF), or we timeout.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Buggy MS IIS servers sometimes return invalid headers
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * (an extra "HTTP/1.0 200, OK" line sprinkled in between
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * the usual MIME headers). Try to deal with it in a sensible
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * way, but log the fact.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * XXX: The mask check is buggy if we ever see an HTTP/1.10 */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Nope, it wasn't even an extra HTTP header. Give up. */
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "proxy: Ignoring duplicate HTTP header "
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* XXX: RFC2068 defines only SP and HT as whitespace, this test is
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * wrong... and so are many others probably.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* should strip trailing whitespace as well */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* the header was too long; at the least we should skip extra data */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* soak up the extra data */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (len == 0) /* time to exit the larger loop as well */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * list is a comma-separated list of case-insensitive tokens, with
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * optional whitespace around the tokens.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * The return returns 1 if the token val is found in the list, or 0
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * otherwise.
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wroweint ap_proxy_liststr(const char *list, const char *val)
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe const char *p;
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe if (p != NULL) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb while (apr_isspace(*p));
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * list is a comma-separated list of case-insensitive tokens, with
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * optional whitespace around the tokens.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * The return returns 1 if the token val is found in the list, or 0
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * otherwise.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbchar *ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb const char *p;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (p != NULL) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb while (apr_isspace(*p));
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* do nothing */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb new = apr_pstrcat(pool, new, ",", apr_pstrndup(pool, list, i), NULL);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Converts 8 hex digits to a time integer
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbint ap_proxy_hex2sec(const char *x)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb unsigned int j;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb for (i = 0, j = 0; i < 8; i++) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (j == 0xffffffff)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Converts a time integer to 8 hex digits
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbvoid ap_proxy_sec2hex(int t, char *y)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb unsigned int j = t;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb for (i = 7; i >= 0; i--) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbint ap_proxyerror(request_rec *r, int statuscode, const char *message)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "The proxy server could not handle the request "
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "Reason: <STRONG>",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Allow "error-notes" string to be printed by ap_send_error_response() */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb apr_table_setn(r->notes, "verbose-error-to", apr_pstrdup(r->pool, "*"));
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb r->status_line = apr_psprintf(r->pool, "%3.3u Proxy Error", statuscode);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * This routine returns its own error message
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbconst char *ap_proxy_host2addr(const char *host, struct hostent *reqhp)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return "Host not found";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb hp = gethostbyaddr((char *) &ptd->ipaddr, sizeof(ptd->ipaddr), AF_INET);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic const char *
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Set url to the first char after "scheme://" */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb url = apr_pstrdup(r->pool, &url[1]); /* make it point to "//", which is what proxy_canon_netloc expects */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb err = ap_proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* Return TRUE if addr represents an IP address (or an IP network address) */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbint ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* if the address is given with an explicit netmask, use that */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Due to a deficiency in ap_inet_addr(), it is impossible to parse */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* "partial" addresses (with less than 4 quads) correctly, i.e. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* 192.168.123 is parsed as 192.168.0.123, which is not what I want. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* I therefore have to parse the IP address manually: */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /*if (proxy_readmask(This->name, &This->addr.s_addr, &This->mask.s_addr) == 0) */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* addr and mask were set by proxy_readmask() */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /*return 1; */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Parse IP addr manually, optionally allowing */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* abbreviated net addresses like 192.168. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Iterate over up to 4 (dotted) quads. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (*addr == '/' && quads > 0) /* netmask starts here. */
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe return 0; /* no digit at start of quad */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (tmp == addr) /* expected a digit, found something else */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* invalid octet */
8aefbd756763807188d2e3ce336a8680e4893066wrowe ++addr; /* after the 4th quad, a dot would be illegal */
8aefbd756763807188d2e3ce336a8680e4893066wrowe This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (addr[0] == '/' && apr_isdigit(addr[1])) { /* net mask follows: */
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (tmp == addr) /* expected a digit, found something else */
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (bits < 0 || bits > 32) /* netmask must be between 0 and 32 */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Determine (i.e., "guess") netmask by counting the */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* number of trailing .0's; reduce #quads appropriately */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* (so that 192.168.0.0 is equivalent to 192.168.) */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* "IP Address should be given in dotted-quad form, optionally followed by a netmask (e.g., 192.168.111.0/24)"; */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* every zero-byte counts as 8 zero-bits */
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (bits != 32) /* no warning for fully qualified IP address */
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe "Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld\n",
8aefbd756763807188d2e3ce336a8680e4893066wrowe This->mask.s_addr = htonl(APR_INADDR_NONE << (32 - bits));
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe "Warning: NetMask and IP-Addr disagree in %s/%ld\n",
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe " Set to %s/%ld\n",
8aefbd756763807188d2e3ce336a8680e4893066wrowe return (*addr == '\0'); /* okay iff we've parsed the whole string */
8aefbd756763807188d2e3ce336a8680e4893066wrowe/* Return TRUE if addr represents an IP address (or an IP network address) */
8aefbd756763807188d2e3ce336a8680e4893066wrowestatic int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r)
8aefbd756763807188d2e3ce336a8680e4893066wrowe const char *found;
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3])) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr)) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Try to deal with multiple IP addr's for a host */
8aefbd756763807188d2e3ce336a8680e4893066wrowe for (ip_listptr = the_host.h_addr_list; *ip_listptr; ++ip_listptr) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (This->addr.s_addr == (ip_list->s_addr & This->mask.s_addr)) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe "3)IP-Match: %s[%s] <-> ", found, inet_ntoa(*ip_list));
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe "3)IP-NoMatch: %s[%s] <-> ", found, inet_ntoa(*ip_list));
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe/* Return TRUE if addr represents a domain name */
8aefbd756763807188d2e3ce336a8680e4893066wroweint ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p)
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Domain name must start with a '.' */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
8aefbd756763807188d2e3ce336a8680e4893066wrowe for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i)
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
8aefbd756763807188d2e3ce336a8680e4893066wrowe "@@@@ handle optional port in proxy_is_domainname()");
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* @@@@ handle optional port */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Strip trailing dots */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
8aefbd756763807188d2e3ce336a8680e4893066wrowe/* Return TRUE if host "host" is in domain "domain" */
8aefbd756763807188d2e3ce336a8680e4893066wrowestatic int proxy_match_domainname(struct dirconn_entry *This, request_rec *r)
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* @@@ do this within the setup? */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Ignore trailing dots in domain comparison: */
8aefbd756763807188d2e3ce336a8680e4893066wrowe && strncasecmp(&host[h_len - d_len], This->name, d_len) == 0;
8aefbd756763807188d2e3ce336a8680e4893066wrowe/* Create a copy of a "struct hostent" record; it was presumably returned
8aefbd756763807188d2e3ce336a8680e4893066wrowe * from a call to gethostbyname() and lives in static storage.
8aefbd756763807188d2e3ce336a8680e4893066wrowe * By creating a copy we can tuck it away for later use.
8aefbd756763807188d2e3ce336a8680e4893066wrowestatic struct hostent * pduphostent(apr_pool_t *p, const struct hostent *hp)
8aefbd756763807188d2e3ce336a8680e4893066wrowe int i = 0, j = 0;
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Count number of alias entries */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Count number of in_addr entries */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Allocate hostent structure, alias ptrs, addr ptrs, addrs */
b29f87f4b6c6886a04dccc296177a7033f70dfedtrawick newent = (struct hostent *) apr_palloc(p, sizeof(*hp));
8aefbd756763807188d2e3ce336a8680e4893066wrowe aliases = (char **) apr_palloc(p, (j+1) * sizeof(char*));
8aefbd756763807188d2e3ce336a8680e4893066wrowe ptrs = (char **) apr_palloc(p, (i+1) * sizeof(char*));
8aefbd756763807188d2e3ce336a8680e4893066wrowe addrs = (struct in_addr *) apr_palloc(p, (i+1) * sizeof(struct in_addr));
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Copy Alias Names: */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Copy address entries */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe/* Return TRUE if addr represents a host name */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwroweint ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p)
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Host names must not start with a '.' */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
8aefbd756763807188d2e3ce336a8680e4893066wrowe for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i);
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (addr[i] != '\0' || ap_proxy_host2addr(addr, &host) != NULL)
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* Strip trailing dots */
8aefbd756763807188d2e3ce336a8680e4893066wrowe for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
8aefbd756763807188d2e3ce336a8680e4893066wrowe/* Return TRUE if host "host" is equal to host2 "host2" */
8aefbd756763807188d2e3ce336a8680e4893066wrowestatic int proxy_match_hostname(struct dirconn_entry *This, request_rec *r)
8aefbd756763807188d2e3ce336a8680e4893066wrowe return 0; /* oops! */
8aefbd756763807188d2e3ce336a8680e4893066wrowe unsigned long *ip_list;
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Try to deal with multiple IP addr's for a host */
8aefbd756763807188d2e3ce336a8680e4893066wrowe for (ip_list = *This->hostentry->h_addr_list; *ip_list != 0UL; ++ip_list)
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (*ip_list == ? ? ? ? ? ? ? ? ? ? ? ? ?)
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Ignore trailing dots in host2 comparison: */
8aefbd756763807188d2e3ce336a8680e4893066wrowe/* Return TRUE if addr is to be matched as a word */
8aefbd756763807188d2e3ce336a8680e4893066wroweint ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p)
8aefbd756763807188d2e3ce336a8680e4893066wrowe/* Return TRUE if string "str2" occurs literally in "str1" */
8aefbd756763807188d2e3ce336a8680e4893066wrowestatic int proxy_match_word(struct dirconn_entry *This, request_rec *r)
8aefbd756763807188d2e3ce336a8680e4893066wrowe return host != NULL && ap_strstr_c(host, This->name) != NULL;
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe/* checks whether a host in uri_addr matches proxyblock */
8aefbd756763807188d2e3ce336a8680e4893066wroweint ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf,
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* XXX FIXME: conf->noproxies->elts is part of an opaque structure */
8aefbd756763807188d2e3ce336a8680e4893066wrowe struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
8aefbd756763807188d2e3ce336a8680e4893066wrowe "proxy: checking remote machine [%s] against [%s]", uri_addr->hostname, npent[j].name);
8aefbd756763807188d2e3ce336a8680e4893066wrowe if ((npent[j].name && ap_strstr_c(uri_addr->hostname, npent[j].name))
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
8aefbd756763807188d2e3ce336a8680e4893066wrowe "proxy: connect to remote machine %s blocked: name %s matched", uri_addr->hostname, npent[j].name);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "proxy: ProxyBlock comparing %s and %s", conf_ip, uri_ip);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "proxy: connect to remote machine %s blocked: IP %s matched", uri_addr->hostname, conf_ip);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* set up the minimal filter set */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbint ap_proxy_pre_http_connection(conn_rec *c, request_rec *r)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#if defined WIN32
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbBOOL WINAPI DllMain (HINSTANCE dllhandle, DWORD reason, LPVOID reserved)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb TlsSetValue (tls_index, malloc (sizeof (struct per_thread_data)));