proxy_util.c revision db3fa7db7c7910f2f23c3e3ffe0cf9f41a1899b9
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl/* ====================================================================
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * The Apache Software License, Version 1.1
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl *
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * Copyright (c) 2000 The Apache Software Foundation. All rights
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * reserved.
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl *
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * Redistribution and use in source and binary forms, with or without
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * modification, are permitted provided that the following conditions
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * are met:
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl *
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * 1. Redistributions of source code must retain the above copyright
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * notice, this list of conditions and the following disclaimer.
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco *
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * 2. Redistributions in binary form must reproduce the above copyright
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * notice, this list of conditions and the following disclaimer in
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * the documentation and/or other materials provided with the
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * distribution.
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco *
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * 3. The end-user documentation included with the redistribution,
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * if any, must include the following acknowledgment:
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * "This product includes software developed by the
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * Apache Software Foundation (http://www.apache.org/)."
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * Alternately, this acknowledgment may appear in the software itself,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * if and wherever such third-party acknowledgments normally appear.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco *
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * 4. The names "Apache" and "Apache Software Foundation" must
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * not be used to endorse or promote products derived from this
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * software without prior written permission. For written
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * permission, please contact apache@apache.org.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco *
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * 5. Products derived from this software may not be called "Apache",
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * nor may "Apache" appear in their name, without prior written
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * permission of the Apache Software Foundation.
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco *
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * SUCH DAMAGE.
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * ====================================================================
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco *
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * This software consists of voluntary contributions made by many
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco * individuals on behalf of the Apache Software Foundation. For more
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * information on the Apache Software Foundation, please see
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * <http://www.apache.org/>.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco *
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Portions of this software are based upon public domain software
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * originally written at the National Center for Supercomputing Applications,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * University of Illinois, Urbana-Champaign.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#define CORE_PRIVATE
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* Utility routines for Apache proxy */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "mod_proxy.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "http_core.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "http_main.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "http_log.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "util_uri.h"
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco#include "util_date.h" /* get ap_checkmask() decl. */
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco#include "apr_md5.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "apr_pools.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int proxy_match_hostname(struct dirconn_entry *This, request_rec *r);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int proxy_match_word(struct dirconn_entry *This, request_rec *r);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic struct per_thread_data *get_per_thread_data(void);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* already called in the knowledge that the characters are hex digits */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescoint ap_proxy_hex2c(const char *x)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int i, ch;
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#if !APR_CHARSET_EBCDIC
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ch = x[0];
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (apr_isdigit(ch))
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco i = ch - '0';
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else if (apr_isupper(ch))
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco i = ch - ('A' - 10);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco i = ch - ('a' - 10);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco i <<= 4;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ch = x[1];
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco if (apr_isdigit(ch))
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco i += ch - '0';
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else if (apr_isupper(ch))
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco i += ch - ('A' - 10);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco i += ch - ('a' - 10);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return i;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#else /*APR_CHARSET_EBCDIC*/
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return (1 == sscanf(x, "%2x", &i)) ? os_toebcdic[i&0xFF] : 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif /*APR_CHARSET_EBCDIC*/
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescovoid ap_proxy_c2hex(int ch, char *x)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco#if !APR_CHARSET_EBCDIC
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int i;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco x[0] = '%';
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco i = (ch & 0xF0) >> 4;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (i >= 10)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco x[1] = ('A' - 10) + i;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco x[1] = '0' + i;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco i = ch & 0x0F;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (i >= 10)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco x[2] = ('A' - 10) + i;
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco else
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco x[2] = '0' + i;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#else /*APR_CHARSET_EBCDIC*/
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco static const char ntoa[] = { "0123456789ABCDEF" };
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ch &= 0xFF;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco x[0] = '%';
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco x[1] = ntoa[(os_toascii[ch]>>4)&0x0F];
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco x[2] = ntoa[os_toascii[ch]&0x0F];
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco x[3] = '\0';
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif /*APR_CHARSET_EBCDIC*/
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/*
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * canonicalise a URL-encoded string
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/*
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Convert a URL-encoded string to canonical form.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * It decodes characters which need not be encoded,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * and encodes those which must be encoded, and does not touch
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * those which must not be touched.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescochar *ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int isenc)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int i, j, ch;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco char *y;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco char *allowed; /* characters which should not be encoded */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco char *reserved; /* characters which much not be en/de-coded */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco/* N.B. in addition to :@&=, this allows ';' in an http path
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * and '?' in an ftp path -- this may be revised
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco *
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Also, it makes a '+' character in a search string reserved, as
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * it may be form-encoded. (Although RFC 1738 doesn't allow this -
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * it only permits ; / ? : @ = & as reserved chars.)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (t == enc_path)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco allowed = "$-_.+!*'(),;:@&=";
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else if (t == enc_search)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco allowed = "$-_.!*'(),;:@&=";
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else if (t == enc_user)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco allowed = "$-_.+!*'(),;@&=";
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else if (t == enc_fpath)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco allowed = "$-_.+!*'(),?:@&=";
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco else /* if (t == enc_parm) */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco allowed = "$-_.+!*'(),?/:@&=";
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (t == enc_path)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco reserved = "/";
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else if (t == enc_search)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco reserved = "+";
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco reserved = "";
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco y = apr_palloc(p, 3 * len + 1);
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (i = 0, j = 0; i < len; i++, j++) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* always handle '/' first */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ch = x[i];
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (strchr(reserved, ch)) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco y[j] = ch;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco continue;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* decode it if not already done */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (isenc && ch == '%') {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (!ap_isxdigit(x[i + 1]) || !ap_isxdigit(x[i + 2]))
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco return NULL;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco ch = ap_proxy_hex2c(&x[i + 1]);
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco i += 2;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco if (ch != 0 && strchr(reserved, ch)) { /* keep it encoded */
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco ap_proxy_c2hex(ch, &y[j]);
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco j += 2;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco continue;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco }
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco/* recode it, if necessary */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (!apr_isalnum(ch) && !strchr(allowed, ch)) {
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco ap_proxy_c2hex(ch, &y[j]);
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco j += 2;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco }
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco else
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco y[j] = ch;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco }
3f8cdebaede9921402318d525b57a9af8f9279d3Adrián Riesco y[j] = '\0';
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return y;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/*
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Parses network-location.
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco * urlp on input the URL; on output the path, after the leading /
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco * user NULL if no user/password permitted
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco * password holder for password
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco * host holder for host
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco * port port number; only set if one is supplied.
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco *
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco * Returns an error string.
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco */
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riescochar *
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco char **passwordp, char **hostp, int *port)
0f593bb6e3f0bc82abf3d6d3c76ef222a43d0476Adrián Riesco{
0f593bb6e3f0bc82abf3d6d3c76ef222a43d0476Adrián Riesco int i;
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco char *strp, *host, *url = *urlp;
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco char *user = NULL, *password = NULL;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco if (url[0] != '/' || url[1] != '/')
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco return "Malformed URL";
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco host = url + 2;
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco url = strchr(host, '/');
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco if (url == NULL)
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco url = "";
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco else
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco *(url++) = '\0'; /* skip seperating '/' */
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco /* find _last_ '@' since it might occur in user/password part */
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco strp = strrchr(host, '@');
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco if (strp != NULL) {
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco *strp = '\0';
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco user = host;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco host = strp + 1;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco/* find password */
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco strp = strchr(user, ':');
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco if (strp != NULL) {
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco *strp = '\0';
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco password = ap_proxy_canonenc(p, strp + 1, strlen(strp + 1), enc_user, 1);
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco if (password == NULL)
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco return "Bad %-escape in URL (password)";
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco }
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco user = ap_proxy_canonenc(p, user, strlen(user), enc_user, 1);
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco if (user == NULL)
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco return "Bad %-escape in URL (username)";
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco }
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco if (userp != NULL) {
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco *userp = user;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco }
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco if (passwordp != NULL) {
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco *passwordp = password;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco }
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco strp = strrchr(host, ':');
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco if (strp != NULL) {
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco *(strp++) = '\0';
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco for (i = 0; strp[i] != '\0'; i++)
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco if (!apr_isdigit(strp[i]))
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco break;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco /* if (i == 0) the no port was given; keep default */
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco if (strp[i] != '\0') {
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco return "Bad port number in URL";
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco } else if (i > 0) {
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco *port = atoi(strp);
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco if (*port > 65535)
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco return "Port number in URL > 65535";
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco }
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco }
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco ap_str_tolower(host); /* DNS names are case-insensitive */
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco if (*host == '\0')
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco return "Missing host in URL";
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco/* check hostname syntax */
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco for (i = 0; host[i] != '\0'; i++)
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco if (!apr_isdigit(host[i]) && host[i] != '.')
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco break;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco /* must be an IP address */
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco#if defined(WIN32) || defined(NETWARE) || defined(TPF) || defined(BEOS)
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco if (host[i] == '\0' && (inet_addr(host) == -1))
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco#else
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1))
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco#endif
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco {
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco return "Bad IP address in URL";
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco }
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco/* if (strchr(host,'.') == NULL && domain != NULL)
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco host = pstrcat(p, host, domain, NULL);
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco */
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco *urlp = url;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco *hostp = host;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco return NULL;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco}
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco
223be434693e8c97e2522ac19155a284b3536035Adrián Riescostatic const char * const lwday[7] =
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco/*
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco * If the date is a valid RFC 850 date or asctime() date, then it
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco * is converted to the RFC 1123 format, otherwise it is not modified.
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco * This routine is not very fast at doing conversions, as it uses
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco * sscanf and sprintf. However, if the date is already correctly
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * formatted, then it exits very quickly.
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco */
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riescoconst char *
0be63c5d4b5e66cc600a0003081ae2bf85be9615Adrián Riesco ap_proxy_date_canon(apr_pool_t *p, const char *x1)
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco{
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco char *x = apr_pstrdup(p, x1);
0be63c5d4b5e66cc600a0003081ae2bf85be9615Adrián Riesco int wk, mday, year, hour, min, sec, mon;
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco char *q, month[4], zone[4], week[4];
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco q = strchr(x, ',');
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco /* check for RFC 850 date */
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco if (q != NULL && q - x > 3 && q[1] == ' ') {
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco *q = '\0';
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco for (wk = 0; wk < 7; wk++)
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco if (strcmp(x, lwday[wk]) == 0)
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco break;
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco *q = ',';
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco if (wk == 7)
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco return x; /* not a valid date */
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco if (q[4] != '-' || q[8] != '-' || q[11] != ' ' || q[14] != ':' ||
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco q[17] != ':' || strcmp(&q[20], " GMT") != 0)
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco return x;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco if (sscanf(q + 2, "%u-%3s-%u %u:%u:%u %3s", &mday, month, &year,
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco &hour, &min, &sec, zone) != 7)
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco return x;
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco if (year < 70)
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco year += 2000;
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco else
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco year += 1900;
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco }
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco else {
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco/* check for acstime() date */
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco if (x[3] != ' ' || x[7] != ' ' || x[10] != ' ' || x[13] != ':' ||
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco x[16] != ':' || x[19] != ' ' || x[24] != '\0')
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco return x;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco if (sscanf(x, "%3s %3s %u %u:%u:%u %u", week, month, &mday, &hour,
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco &min, &sec, &year) != 7)
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco return x;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco for (wk = 0; wk < 7; wk++)
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco if (strcmp(week, ap_day_snames[wk]) == 0)
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco break;
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco if (wk == 7)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco return x;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco/* check date */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco for (mon = 0; mon < 12; mon++)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if (strcmp(month, ap_month_snames[mon]) == 0)
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco break;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco if (mon == 12)
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco return x;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco q = apr_palloc(p, 30);
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco apr_snprintf(q, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", ap_day_snames[wk],
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco mday, ap_month_snames[mon], year, hour, min, sec);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco return q;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco}
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riescostatic request_rec *make_fake_req(conn_rec *c)
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco{
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco request_rec *r = apr_pcalloc(c->pool, sizeof(*r));
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco core_request_config *req_cfg;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco r->pool = c->pool;
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco r->status = HTTP_OK;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco r->headers_in = apr_make_table(r->pool, 50);
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco r->subprocess_env = apr_make_table(r->pool, 50);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco r->headers_out = apr_make_table(r->pool, 12);
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco r->err_headers_out = apr_make_table(r->pool, 5);
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco r->notes = apr_make_table(r->pool, 5);
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco r->read_body = REQUEST_NO_BODY;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco r->connection = c;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco r->output_filters = c->output_filters;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco r->input_filters = c->input_filters;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco r->request_config = ap_create_request_config(r->pool);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco req_cfg = apr_pcalloc(r->pool, sizeof(core_request_config));
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco req_cfg->bb = ap_brigade_create(r->pool);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ap_set_module_config(r->request_config, &core_module, req_cfg);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco return r;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco}
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco/*
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco * Reads headers from a buffer and returns an array of headers.
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * Returns NULL on file error
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * This routine tries to deal with too long lines and continuation lines.
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * @@@: XXX: FIXME: currently the headers are passed thru un-merged.
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * Is that okay, or should they be collapsed where possible?
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riescoapr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, conn_rec *c)
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco{
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco apr_table_t *resp_hdrs;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco int len;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco char *value, *end;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco char field[MAX_STRING_LEN];
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco request_rec *rr = make_fake_req(c);
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco resp_hdrs = ap_make_table(r->pool, 20);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /*
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * Read header lines until we get the empty separator line, a read error,
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * the connection closes (EOF), or we timeout.
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco while ((len = ap_getline(buffer, size, rr, 1)) > 0) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* Buggy MS IIS servers sometimes return invalid headers
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * (an extra "HTTP/1.0 200, OK" line sprinkled in between
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * the usual MIME headers). Try to deal with it in a sensible
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * way, but log the fact.
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco * XXX: The mask check is buggy if we ever see an HTTP/1.10 */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if (!ap_checkmask(buffer, "HTTP/#.# ###*")) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* Nope, it wasn't even an extra HTTP header. Give up. */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco return NULL;
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco "proxy: Ignoring duplicate HTTP header "
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco "returned by %s (%s)", r->uri, r->method);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco continue;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco *value = '\0';
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco ++value;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* XXX: RFC2068 defines only SP and HT as whitespace, this test is
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * wrong... and so are many others probably.
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco while (apr_isspace(*value))
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ++value; /* Skip to start of value */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* should strip trailing whitespace as well */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco *end = '\0';
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ap_table_add(resp_hdrs, buffer, value);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* the header was too long; at the least we should skip extra data */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (len >= size - 1) {
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco while ((len = ap_getline(field, MAX_STRING_LEN, r, 1))
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco >= MAX_STRING_LEN - 1) {
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco /* soak up the extra data */
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (len == 0) /* time to exit the larger loop as well */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco break;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return resp_hdrs;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco}
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riescolong int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r, ap_cache_el *c)
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco{
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco int ok;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco char buf[IOBUFSIZE];
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco long total_bytes_rcvd, in_buffer;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco apr_ssize_t cntr;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco register int n, o;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco conn_rec *con = r->connection;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int alternate_timeouts = 1; /* 1 if we alternate between soft & hard timeouts */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco apr_file_t *cachefp = NULL;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int written = 0, wrote_to_cache;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco total_bytes_rcvd = 0;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco if (c) ap_cache_el_data(c, &cachefp);
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#if 0
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#if APR_CHARSET_EBCDIC
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* The cache copy is ASCII, not EBCDIC, even for text/html) */
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco ap_bsetflag(f, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco if (c != NULL && c->fp != NULL)
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco ap_bsetflag(c->fp, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco ap_bsetflag(con->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco#endif
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Since we are reading from one buffer and writing to another,
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco * it is unsafe to do a soft_timeout here, at least until the proxy
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * has its own timeout handler which can set both buffers to EOUT.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#if defined(WIN32) || defined(TPF) || defined(NETWARE)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* works fine under win32, so leave it */
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco alternate_timeouts = 0;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco#else
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco /* CHECKME! Since hard_timeout won't work in unix on sends with partial
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco * cache completion, we have to alternate between hard_timeout
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco * for reads, and soft_timeout for send. This is because we need
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco * to get a return from ap_bwrite to be able to continue caching.
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco * BUT, if we *can't* continue anyway, just use hard_timeout.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * (Also, if no cache file is written, use hard timeouts)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco if (!completion || completion->content_length > 0
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco || completion->cache_completion == 1.0) {
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco alternate_timeouts = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Loop and ap_bread() while we can successfully read and write,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * or (after the client aborted) while we can successfully
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco * read and finish the configured cache_completion.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (ok = 1; ok; cntr = 0) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Read block from server */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (ap_bread(f, buf, IOBUFSIZE, &cntr) != APR_SUCCESS && !cntr)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (c != NULL) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "proxy: error reading from %s", c->name);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_proxy_cache_error(&c);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco break;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else if(cntr == 0) break;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Write to cache first. */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco /*@@@ XXX FIXME: Assuming that writing the cache file won't time out?!!? */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco wrote_to_cache = cntr;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (cachefp && apr_write(cachefp, &buf[0], &wrote_to_cache) != APR_SUCCESS) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "proxy: error writing to cache");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_proxy_cache_error(&c);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco } else {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco written += n;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco o = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco total_bytes_rcvd += cntr;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco in_buffer = cntr;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Write the block to the client, detect aborted transfers */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco while (!con->aborted && in_buffer > 0) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if ((cntr = ap_rwrite(&buf[o], in_buffer, r))) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (completion) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* when a send failure occurs, we need to decide
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * whether to continue loading and caching the
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * document, or to abort the whole thing
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ok = (completion->content_length > 0) &&
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco (completion->cache_completion > 0) &&
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco (completion->content_length * completion->cache_completion < total_bytes_rcvd);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (!ok)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_proxy_cache_error(&c);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco con->aborted = 1;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco break;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco in_buffer -= cntr;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco o += cntr;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco } /* while client alive and more data to send */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco } /* loop and ap_bread while "ok" */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (!con->aborted)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_rflush(r);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return total_bytes_rcvd;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/*
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Sends response line and headers. Uses the client fd and the
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * headers_out array from the passed request_rec to talk to the client
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * and to properly set the headers it sends for things such as logging.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco *
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * A timeout should be set before calling this routine.
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescovoid ap_proxy_send_headers(request_rec *r, const char *respline, apr_table_t *t)
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int i;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco apr_socket_t *fp = r->connection->client_socket;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco apr_table_entry_t *elts = (apr_table_entry_t *) apr_table_elts(t)->elts;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco char *temp = apr_pstrcat(r->pool, respline, CRLF, NULL);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco apr_size_t len = strlen(temp);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco apr_send(fp, temp, &len);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco for (i = 0; i < ap_table_elts(t)->nelts; ++i) {
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco if (elts[i].key != NULL) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco temp = apr_pstrcat(r->pool, elts[i].key, ": ", elts[i].val, CRLF, NULL);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco apr_send(fp, temp, &len);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco apr_table_addn(r->headers_out, elts[i].key, elts[i].val);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco len = 2;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco apr_send(fp, CRLF, &len);
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/*
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * list is a comma-separated list of case-insensitive tokens, with
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * optional whitespace around the tokens.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * The return returns 1 if the token val is found in the list, or 0
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * otherwise.
3b1e33dd8d2de8301d7a31860dd1819bd3752718Adrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescoint ap_proxy_liststr(const char *list, const char *val)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int len, i;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco const char *p;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco len = strlen(val);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco while (list != NULL) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco p = ap_strchr_c(list, ',');
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (p != NULL) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco i = p - list;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco do
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco p++;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco while (apr_isspace(*p));
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco }
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco else
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco i = strlen(list);
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco while (i > 0 && apr_isspace(list[i - 1]))
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco i--;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (i == len && strncasecmp(list, val, len) == 0)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return 1;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco list = p;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco }
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco return 0;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco}
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco/*
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco * Converts 8 hex digits to a time integer
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco */
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riescoint ap_proxy_hex2sec(const char *x)
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco{
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco int i, ch;
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco unsigned int j;
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco for (i = 0, j = 0; i < 8; i++) {
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco ch = x[i];
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco j <<= 4;
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco if (apr_isdigit(ch))
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco j |= ch - '0';
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco else if (apr_isupper(ch))
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco j |= ch - ('A' - 10);
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco else
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco j |= ch - ('a' - 10);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (j == 0xffffffff)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return -1; /* so that it works with 8-byte ints */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return j;
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/*
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Converts a time integer to 8 hex digits
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescovoid ap_proxy_sec2hex(int t, char *y)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int i, ch;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco unsigned int j = t;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (i = 7; i >= 0; i--) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ch = j & 0xF;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco j >>= 4;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (ch >= 10)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco y[i] = ch + ('A' - 10);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco y[i] = ch + '0';
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco y[8] = '\0';
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescovoid ap_proxy_cache_error(ap_cache_el **c)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (c && *c) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco const char *name = (*c)->name;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_cache_el_finalize((*c));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_cache_remove((*c)->cache, name);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco *c = NULL;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescoint ap_proxyerror(request_rec *r, int statuscode, const char *message)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco apr_table_setn(r->notes, "error-notes",
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco apr_pstrcat(r->pool,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "The proxy server could not handle the request "
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "<EM><A HREF=\"", ap_escape_uri(r->pool, r->uri),
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "\">", ap_escape_html(r->pool, r->method),
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "&nbsp;",
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_escape_html(r->pool, r->uri), "</A></EM>.<P>\n"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "Reason: <STRONG>",
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_escape_html(r->pool, message),
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "</STRONG>", NULL));
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco /* Allow "error-notes" string to be printed by ap_send_error_response() */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco apr_table_setn(r->notes, "verbose-error-to", apr_pstrdup(r->pool, "*"));
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco r->status_line = apr_psprintf(r->pool, "%3.3u Proxy Error", statuscode);
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco return statuscode;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco}
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/*
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * This routine returns its own error message
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescoconst char *ap_proxy_host2addr(const char *host, struct hostent *reqhp)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int i;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco struct hostent *hp;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco struct per_thread_data *ptd = get_per_thread_data();
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco for (i = 0; host[i] != '\0'; i++)
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco if (!apr_isdigit(host[i]) && host[i] != '.')
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco break;
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco if (host[i] != '\0') {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco hp = gethostbyname(host);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (hp == NULL)
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco return "Host not found";
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco else {
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco ptd->ipaddr = ap_inet_addr(host);
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco hp = gethostbyaddr((char *) &ptd->ipaddr, sizeof(ptd->ipaddr), AF_INET);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (hp == NULL) {
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco memset(&ptd->hpbuf, 0, sizeof(ptd->hpbuf));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ptd->hpbuf.h_name = 0;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco ptd->hpbuf.h_addrtype = AF_INET;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ptd->hpbuf.h_length = sizeof(ptd->ipaddr);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ptd->hpbuf.h_addr_list = ptd->charpbuf;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ptd->hpbuf.h_addr_list[0] = (char *) &ptd->ipaddr;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ptd->hpbuf.h_addr_list[1] = 0;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco hp = &ptd->hpbuf;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco }
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco *reqhp = *hp;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco return NULL;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic const char *
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco proxy_get_host_of_request(request_rec *r)
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco{
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco char *url, *user = NULL, *password = NULL, *err, *host;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco int port = -1;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco if (r->hostname != NULL)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return r->hostname;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Set url to the first char after "scheme://" */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if ((url = strchr(r->uri, ':')) == NULL
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco || url[1] != '/' || url[2] != '/')
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return NULL;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco url = apr_pstrdup(r->pool, &url[1]); /* make it point to "//", which is what proxy_canon_netloc expects */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco err = ap_proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (err != NULL)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "%s", err);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco r->hostname = host;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return host; /* ought to return the port, too */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco/* Return TRUE if addr represents an IP address (or an IP network address) */
7474965b2e6323002c96c0b39a59843cde201870Adrián Riescoint ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p)
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco{
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco const char *addr = This->name;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco long ip_addr[4];
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int i, quads;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco long bits;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco /* if the address is given with an explicit netmask, use that */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* Due to a deficiency in ap_inet_addr(), it is impossible to parse */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* "partial" addresses (with less than 4 quads) correctly, i.e. */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* 192.168.123 is parsed as 192.168.0.123, which is not what I want. */
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco /* I therefore have to parse the IP address manually: */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /*if (proxy_readmask(This->name, &This->addr.s_addr, &This->mask.s_addr) == 0) */
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco /* addr and mask were set by proxy_readmask() */
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco /*return 1; */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Parse IP addr manually, optionally allowing */
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco /* abbreviated net addresses like 192.168. */
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* Iterate over up to 4 (dotted) quads. */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco for (quads = 0; quads < 4 && *addr != '\0'; ++quads) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco char *tmp;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco if (*addr == '/' && quads > 0) /* netmask starts here. */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco break;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco if (!apr_isdigit(*addr))
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco return 0; /* no digit at start of quad */
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco ip_addr[quads] = strtol(addr, &tmp, 0);
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco if (tmp == addr) /* expected a digit, found something else */
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco return 0;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco if (ip_addr[quads] < 0 || ip_addr[quads] > 255) {
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco /* invalid octet */
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco return 0;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco }
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco addr = tmp;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco if (*addr == '.' && quads != 3)
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco ++addr; /* after the 4th quad, a dot would be illegal */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco for (This->addr.s_addr = 0, i = 0; i < quads; ++i)
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco if (addr[0] == '/' && apr_isdigit(addr[1])) { /* net mask follows: */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco char *tmp;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco ++addr;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco bits = strtol(addr, &tmp, 0);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if (tmp == addr) /* expected a digit, found something else */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco return 0;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco addr = tmp;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if (bits < 0 || bits > 32) /* netmask must be between 0 and 32 */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco return 0;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco else {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* Determine (i.e., "guess") netmask by counting the */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* number of trailing .0's; reduce #quads appropriately */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* (so that 192.168.0.0 is equivalent to 192.168.) */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco while (quads > 0 && ip_addr[quads - 1] == 0)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco --quads;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* "IP Address should be given in dotted-quad form, optionally followed by a netmask (e.g., 192.168.111.0/24)"; */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if (quads < 1)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco return 0;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* every zero-byte counts as 8 zero-bits */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco bits = 8 * quads;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco if (bits != 32) /* no warning for fully qualified IP address */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco "Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld\n",
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco inet_ntoa(This->addr), bits);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco This->mask.s_addr = htonl(INADDR_NONE << (32 - bits));
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco "Warning: NetMask and IP-Addr disagree in %s/%ld\n",
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco inet_ntoa(This->addr), bits);
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco This->addr.s_addr &= This->mask.s_addr;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco " Set to %s/%ld\n",
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco inet_ntoa(This->addr), bits);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco if (*addr == '\0') {
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco This->matcher = proxy_match_ipaddr;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return 1;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco }
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco else
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco return (*addr == '\0'); /* okay iff we've parsed the whole string */
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco}
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco/* Return TRUE if addr represents an IP address (or an IP network address) */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riescostatic int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco{
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco int i;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco int ip_addr[4];
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco struct in_addr addr;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco struct in_addr *ip_list;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco char **ip_listptr;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco const char *found;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco const char *host = proxy_get_host_of_request(r);
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco if (host == NULL) /* oops! */
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco return 0;
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco memset(&addr, '\0', sizeof addr);
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco memset(ip_addr, '\0', sizeof ip_addr);
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco if (4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3])) {
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco for (addr.s_addr = 0, i = 0; i < 4; ++i)
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr)) {
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco#if DEBUGGING
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "1)IP-Match: %s[%s] <-> ", host, inet_ntoa(addr));
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco "%s/", inet_ntoa(This->addr));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "%s", inet_ntoa(This->mask));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco return 1;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco#if DEBUGGING
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco else {
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "1)IP-NoMatch: %s[%s] <-> ", host, inet_ntoa(addr));
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco "%s/", inet_ntoa(This->addr));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "%s", inet_ntoa(This->mask));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco else {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco struct hostent the_host;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco memset(&the_host, '\0', sizeof the_host);
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco found = ap_proxy_host2addr(host, &the_host);
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco if (found != NULL) {
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco#if DEBUGGING
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco "2)IP-NoMatch: hostname=%s msg=%s", host, found);
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco#endif
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco return 0;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco if (the_host.h_name != NULL)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco found = the_host.h_name;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco found = host;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco /* Try to deal with multiple IP addr's for a host */
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco for (ip_listptr = the_host.h_addr_list; *ip_listptr; ++ip_listptr) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ip_list = (struct in_addr *) *ip_listptr;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (This->addr.s_addr == (ip_list->s_addr & This->mask.s_addr)) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#if DEBUGGING
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco "3)IP-Match: %s[%s] <-> ", found, inet_ntoa(*ip_list));
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco "%s/", inet_ntoa(This->addr));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "%s", inet_ntoa(This->mask));
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco#endif
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return 1;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco }
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco#if DEBUGGING
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco else {
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco "3)IP-NoMatch: %s[%s] <-> ", found, inet_ntoa(*ip_list));
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco "%s/", inet_ntoa(This->addr));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "%s", inet_ntoa(This->mask));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco return 0;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco}
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* Return TRUE if addr represents a domain name */
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riescoint ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p)
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco{
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco char *addr = This->name;
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco int i;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Domain name must start with a '.' */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (addr[0] != '.')
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco continue;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#if 0
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (addr[i] == ':') {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "@@@@ handle optional port in proxy_is_domainname()");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* @@@@ handle optional port */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (addr[i] != '\0')
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Strip trailing dots */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco addr[i] = '\0';
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco This->matcher = proxy_match_domainname;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return 1;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* Return TRUE if host "host" is in domain "domain" */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int proxy_match_domainname(struct dirconn_entry *This, request_rec *r)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco const char *host = proxy_get_host_of_request(r);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int d_len = strlen(This->name), h_len;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco if (host == NULL) /* some error was logged already */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco h_len = strlen(host);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* @@@ do this within the setup? */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Ignore trailing dots in domain comparison: */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco while (d_len > 0 && This->name[d_len - 1] == '.')
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco --d_len;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco while (h_len > 0 && host[h_len - 1] == '.')
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco --h_len;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return h_len > d_len
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco && strncasecmp(&host[h_len - d_len], This->name, d_len) == 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* Create a copy of a "struct hostent" record; it was presumably returned
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * from a call to gethostbyname() and lives in static storage.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * By creating a copy we can tuck it away for later use.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic struct hostent * pduphostent(apr_pool_t *p, const struct hostent *hp)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco struct hostent *newent;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco char **ptrs;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco char **aliases;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco struct in_addr *addrs;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int i = 0, j = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (hp == NULL)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return NULL;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Count number of alias entries */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (hp->h_aliases != NULL)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (; hp->h_aliases[j] != NULL; ++j)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco continue;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Count number of in_addr entries */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (hp->h_addr_list != NULL)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (; hp->h_addr_list[i] != NULL; ++i)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco continue;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Allocate hostent structure, alias ptrs, addr ptrs, addrs */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco newent = (struct hostent *) apr_palloc(p, sizeof(*hp));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco aliases = (char **) apr_palloc(p, (j+1) * sizeof(char*));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ptrs = (char **) apr_palloc(p, (i+1) * sizeof(char*));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco addrs = (struct in_addr *) apr_palloc(p, (i+1) * sizeof(struct in_addr));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco *newent = *hp;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco newent->h_name = apr_pstrdup(p, hp->h_name);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco newent->h_aliases = aliases;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco newent->h_addr_list = (char**) ptrs;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Copy Alias Names: */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (j = 0; hp->h_aliases[j] != NULL; ++j) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco aliases[j] = apr_pstrdup(p, hp->h_aliases[j]);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco aliases[j] = NULL;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Copy address entries */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (i = 0; hp->h_addr_list[i] != NULL; ++i) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ptrs[i] = (char*) &addrs[i];
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco addrs[i] = *(struct in_addr *) hp->h_addr_list[i];
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ptrs[i] = NULL;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return newent;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco}
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco/* Return TRUE if addr represents a host name */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riescoint ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p)
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco{
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco struct hostent host;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco char *addr = This->name;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco int i;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco /* Host names must not start with a '.' */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco if (addr[0] == '.')
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco return 0;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i);
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco#if 0
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco if (addr[i] == ':') {
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco "@@@@ handle optional port in proxy_is_hostname()");
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco /* @@@@ handle optional port */
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco }
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco#endif
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco if (addr[i] != '\0' || ap_proxy_host2addr(addr, &host) != NULL)
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco return 0;
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco This->hostentry = pduphostent (p, &host);
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco /* Strip trailing dots */
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco addr[i] = '\0';
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco This->matcher = proxy_match_hostname;
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco return 1;
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco}
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco/* Return TRUE if host "host" is equal to host2 "host2" */
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riescostatic int proxy_match_hostname(struct dirconn_entry *This, request_rec *r)
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco{
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco char *host = This->name;
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco const char *host2 = proxy_get_host_of_request(r);
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco int h2_len;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco int h1_len;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco if (host == NULL || host2 == NULL)
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco return 0; /* oops! */
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco h2_len = strlen(host2);
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco h1_len = strlen(host);
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco
b3a8ae62887130fd41b91bf2ea1fd66360bd3c29Adrián Riesco#if 0
b3a8ae62887130fd41b91bf2ea1fd66360bd3c29Adrián Riesco unsigned long *ip_list;
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco /* Try to deal with multiple IP addr's for a host */
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco for (ip_list = *This->hostentry->h_addr_list; *ip_list != 0UL; ++ip_list)
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco if (*ip_list == ? ? ? ? ? ? ? ? ? ? ? ? ?)
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco return 1;
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco#endif
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco /* Ignore trailing dots in host2 comparison: */
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco while (h2_len > 0 && host2[h2_len - 1] == '.')
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco --h2_len;
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco while (h1_len > 0 && host[h1_len - 1] == '.')
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco --h1_len;
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco return h1_len == h2_len
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco && strncasecmp(host, host2, h1_len) == 0;
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco}
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco/* Return TRUE if addr is to be matched as a word */
7474965b2e6323002c96c0b39a59843cde201870Adrián Riescoint ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p)
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco{
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco This->matcher = proxy_match_word;
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco return 1;
8b389272b3312c6d3e3c0aee2e94bca6dbdade50Adrián Riesco}
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco
51c15129e8118fed5c33c334f8df82619ce98e7dAdrián Riesco/* Return TRUE if string "str2" occurs literally in "str1" */
static int proxy_match_word(struct dirconn_entry *This, request_rec *r)
{
const char *host = proxy_get_host_of_request(r);
return host != NULL && ap_strstr_c(host, This->name) != NULL;
}
apr_status_t ap_proxy_doconnect(apr_socket_t *sock, char *host, apr_uint32_t port, request_rec *r)
{
apr_status_t rv;
apr_sockaddr_t *destsa;
rv = apr_getaddrinfo(&destsa, host, AF_INET, port, 0, r->pool);
if (rv == APR_SUCCESS) {
rv = apr_connect(sock, destsa);
}
else if (rv != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"proxy connect to %s port %d failed", host, port);
}
return rv;
}
/* This function is called by ap_table_do() for all header lines */
/* (from proxy_http.c and proxy_ftp.c) */
/* It is passed a table_do_args struct pointer and a MIME field and value pair */
int ap_proxy_send_hdr_line(void *p, const char *key, const char *value)
{
struct request_rec *r = (struct request_rec *)p;
if (key == NULL || value == NULL || value[0] == '\0')
return 1;
if (!r->assbackwards)
ap_rvputs(r, key, ": ", value, CRLF, NULL);
return 1; /* tell ap_table_do() to continue calling us for more headers */
}
/* send a text line to one or two BUFF's; return line length */
unsigned ap_proxy_bputs2(const char *data, apr_socket_t *client, ap_cache_el *cache)
{
unsigned len = strlen(data);
apr_file_t *cachefp = NULL;
apr_send(client, data, &len);
if (ap_cache_el_data(cache, &cachefp) == APR_SUCCESS)
apr_puts(data, cachefp);
return len;
}
#if defined WIN32
static DWORD tls_index;
BOOL WINAPI DllMain (HINSTANCE dllhandle, DWORD reason, LPVOID reserved)
{
LPVOID memptr;
switch (reason) {
case DLL_PROCESS_ATTACH:
tls_index = TlsAlloc();
case DLL_THREAD_ATTACH: /* intentional no break */
TlsSetValue (tls_index, malloc (sizeof (struct per_thread_data)));
break;
case DLL_THREAD_DETACH:
memptr = TlsGetValue (tls_index);
if (memptr) {
free (memptr);
TlsSetValue (tls_index, 0);
}
break;
}
return TRUE;
}
#endif
static struct per_thread_data *get_per_thread_data(void)
{
#if 0
#if defined(WIN32)
return (struct per_thread_data *) TlsGetValue (tls_index);
#else
static APACHE_TLS struct per_thread_data sptd;
return &sptd;
#endif
#endif
return NULL;
}
/* This function is completely bogus. This should become a part of the
* cache filter when it is finished. RBB
*/
int ap_proxy_cache_send(request_rec *r, ap_cache_el *c)
{
apr_file_t *cachefp = NULL;
apr_socket_t *fp = r->connection->client_socket;
char buffer[500];
apr_size_t len;
apr_off_t offset = 0;
apr_finfo_t finfo;
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
"Sending cache file for %s", c->name);
if(ap_cache_el_data(c, &cachefp) != APR_SUCCESS)
return HTTP_INTERNAL_SERVER_ERROR;
/* send the response */
if(apr_fgets(buffer, sizeof(buffer), cachefp)) {
len = strlen(buffer);
apr_send(fp, buffer, &len);
offset +=len;
}
/* send headers */
ap_cache_el_header_walk(c, ap_proxy_send_hdr_line, r, NULL);
len = 2;
apr_send(fp, CRLF, &len);
/* send data */
apr_getfileinfo(&finfo, cachefp);
if(!r->header_only && ap_send_fd(cachefp, r, offset, finfo.size, &len))
return HTTP_INTERNAL_SERVER_ERROR;
return OK;
}
int ap_proxy_cache_should_cache(request_rec *r, apr_table_t *resp_hdrs, const int is_HTTP1)
{
const char *expire = apr_table_get(resp_hdrs, "Expires");
time_t expc;
if (expire != NULL)
expc = ap_parseHTTPdate(expire);
else
expc = BAD_DATE;
if((r->status != HTTP_OK && r->status != HTTP_MOVED_PERMANENTLY && r->status != HTTP_NOT_MODIFIED) ||
(r->status == HTTP_NOT_MODIFIED) ||
r->header_only ||
apr_table_get(r->headers_in, "Authorization") != NULL ||
(expire != NULL && expc == BAD_DATE) ||
(r->status == HTTP_OK && !apr_table_get(resp_hdrs, "Last-Modified") && is_HTTP1))
{
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
"proxy: Response is not cacheable: %s", r->unparsed_uri);
return 0;
}
return 1;
}
/*
* what responses should we not cache?
* Unknown status responses and those known to be uncacheable
* 304 HTTP_NOT_MODIFIED response when we have no valid cache file, or
* 200 HTTP_OK response from HTTP/1.0 and up without a Last-Modified header, or
* HEAD requests, or
* requests with an Authorization header, or
* protocol requests nocache (e.g. ftp with user/password)
*/
/* @@@ XXX FIXME: is the test "r->status != HTTP_MOVED_PERMANENTLY" correct?
* or shouldn't it be "ap_is_HTTP_REDIRECT(r->status)" ? -MnKr */
int ap_proxy_cache_update(ap_cache_el *c)
{
ap_cache_handle_t *h = c ? c->cache : NULL;
if(!h) return DECLINED;
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
"proxy: Cache finalized: %s", c->name);
ap_cache_el_finalize(c);
ap_cache_garbage_collect(h);
return DECLINED;
}