2
* Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003
3
* Inferno Nettverk A/S, Norway. All rights reserved.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
8
* 1. The above copyright notice, this list of conditions and the following
9
* disclaimer must appear in all copies of the software, derivative works
10
* or modified versions, and any portions thereof, aswell as in all
11
* supporting documentation.
12
* 2. All advertising materials mentioning features or use of this software
13
* must display the following acknowledgement:
14
* This product includes software developed by
15
* Inferno Nettverk A/S, Norway.
16
* 3. The name of the author may not be used to endorse or promote products
17
* derived from this software without specific prior written permission.
19
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
* Inferno Nettverk A/S requests users of this software to return to
32
* Software Distribution Coordinator or sdc@inet.no
33
* Inferno Nettverk A/S
39
* any improvements or extensions that they make and grant Inferno Nettverk A/S
40
* the rights to redistribute these changes.
46
static const char rcsid[] =
47
"$Id: httpproxy.c,v 1.12 2003/07/01 13:21:29 michaels Exp $";
50
httpproxy_negotiate(s, packet)
52
struct socks_t *packet;
54
const char *function = "httpproxy_negotiate()";
55
char buf[MAXHOSTNAMELEN + 512]; /* +512 for httpbabble. */
56
char host[MAXSOCKSHOSTSTRING];
62
slog(LOG_DEBUG, function);
64
sockshost2string(&packet->req.host, host, sizeof(host));
67
* replace the dot that sockshost2string uses to separate port from host
70
*strrchr(host, '.') = ':';
72
len = snprintfn(buf, sizeof(buf),
73
"CONNECT %s HTTP/1.0\r\n"
74
"User-agent: %s/client v%s\r\n"
76
host, PACKAGE, VERSION);
78
if ((rc = writen(s, buf, (size_t)len, NULL)) != len) {
79
swarn("%s: wrote %d/%d bytes", function, rc, len);
83
slog(LOG_DEBUG, "%s: sending: %s", function, buf);
85
eof = checked = len = 0;
88
char *eol, *terminator = "\r\n";
90
/* -1 so we can always NUL-terminate. */
92
switch(rc = read(s, &buf[len], sizeof(buf) - len - 1)) {
94
swarn("%s: read()", function);
102
SASSERTX((size_t)len < sizeof(buf));
106
while ((eol = strstr(buf, terminator)) != NULL) { /* new line. */
108
slog(LOG_DEBUG, "%s: read: %s", function, buf);
113
switch (packet->req.version) {
115
const char *offset = "HTTP/1.0 ";
117
if (strncmp(buf, offset, strlen(offset)) != 0) {
122
if (!isdigit(buf[strlen(offset)])) {
127
packet->res.version = packet->req.version;
130
* XXX we've assumed that a reply is the size of a socks
131
* reply, http replies can however be bigger. :-/
135
packet->res.reply = (unsigned char)(atoi(&buf[strlen(offset)])
136
== HTTP_SUCCESS ? HTTP_SUCCESS : !HTTP_SUCCESS);
140
* we don't know what address the server will use on
141
* our behalf, set it to what we use, better than nothing.
143
addrlen = sizeof(addr);
144
if (getsockname(s, &addr, &addrlen) != 0)
146
sockaddr2sockshost(&addr, &packet->res.host);
153
SERRX(packet->req.version);
157
swarnx("%s: unknown response: \"%s\"", function, buf);
162
len -= (eol + strlen(terminator)) - buf;
164
SASSERTX((size_t)len < sizeof(buf));
165
memmove(buf, eol + strlen(terminator), (size_t)len);
168
if (strncmp(buf, terminator, strlen(terminator)) == 0)
169
eof = 1; /* empty line, all done. */
172
if (eof && !checked) { /* won't get any new line, dump what we have. */
173
slog(LOG_DEBUG, "%s: read: %s", function, buf);
177
} while (len > 0 || !eof);
182
slog(LOG_DEBUG, "%s: not checked?", function);
183
return -1; /* proxyserver doing something strange/unknown. */