load_http.c revision 1.1 1 1.1 christos /* $NetBSD: load_http.c,v 1.1 2012/03/23 21:20:09 christos Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Copyright (C) 2010 by Darren Reed.
5 1.1 christos *
6 1.1 christos * See the IPFILTER.LICENCE file for details on licencing.
7 1.1 christos *
8 1.1 christos * Id: load_http.c,v 1.5.2.3 2012/01/26 05:44:26 darren_r Exp
9 1.1 christos */
10 1.1 christos
11 1.1 christos #include "ipf.h"
12 1.1 christos #include <ctype.h>
13 1.1 christos
14 1.1 christos /*
15 1.1 christos * Because the URL can be included twice into the buffer, once as the
16 1.1 christos * full path for the "GET" and once as the "Host:", the buffer it is
17 1.1 christos * put in needs to be larger than 512*2 to make room for the supporting
18 1.1 christos * text. Why not just use snprintf and truncate? The warning about the
19 1.1 christos * URL being too long tells you something is wrong and does not fetch
20 1.1 christos * any data - just truncating the URL (with snprintf, etc) and sending
21 1.1 christos * that to the server is allowing an unknown and unintentioned action
22 1.1 christos * to happen.
23 1.1 christos */
24 1.1 christos #define MAX_URL_LEN 512
25 1.1 christos #define LOAD_BUFSIZE (MAX_URL_LEN * 2 + 128)
26 1.1 christos
27 1.1 christos /*
28 1.1 christos * Format expected is one addres per line, at the start of each line.
29 1.1 christos */
30 1.1 christos alist_t *
31 1.1 christos load_http(char *url)
32 1.1 christos {
33 1.1 christos int fd, len, left, port, endhdr, removed, linenum = 0;
34 1.1 christos char *s, *t, *u, buffer[LOAD_BUFSIZE], *myurl;
35 1.1 christos alist_t *a, *rtop, *rbot;
36 1.1 christos
37 1.1 christos /*
38 1.1 christos * More than this would just be absurd.
39 1.1 christos */
40 1.1 christos if (strlen(url) > MAX_URL_LEN) {
41 1.1 christos fprintf(stderr, "load_http has a URL > %d bytes?!\n",
42 1.1 christos MAX_URL_LEN);
43 1.1 christos return NULL;
44 1.1 christos }
45 1.1 christos
46 1.1 christos fd = -1;
47 1.1 christos rtop = NULL;
48 1.1 christos rbot = NULL;
49 1.1 christos
50 1.1 christos sprintf(buffer, "GET %s HTTP/1.0\r\n", url);
51 1.1 christos
52 1.1 christos myurl = strdup(url);
53 1.1 christos if (myurl == NULL)
54 1.1 christos goto done;
55 1.1 christos
56 1.1 christos s = myurl + 7; /* http:// */
57 1.1 christos t = strchr(s, '/');
58 1.1 christos if (t == NULL) {
59 1.1 christos fprintf(stderr, "load_http has a malformed URL '%s'\n", url);
60 1.1 christos free(myurl);
61 1.1 christos return NULL;
62 1.1 christos }
63 1.1 christos *t++ = '\0';
64 1.1 christos
65 1.1 christos /*
66 1.1 christos * 10 is the length of 'Host: \r\n\r\n' below.
67 1.1 christos */
68 1.1 christos if (strlen(s) + strlen(buffer) + 10 > sizeof(buffer)) {
69 1.1 christos fprintf(stderr, "load_http has a malformed URL '%s'\n", url);
70 1.1 christos free(myurl);
71 1.1 christos return NULL;
72 1.1 christos }
73 1.1 christos
74 1.1 christos u = strchr(s, '@');
75 1.1 christos if (u != NULL)
76 1.1 christos s = u + 1; /* AUTH */
77 1.1 christos
78 1.1 christos sprintf(buffer + strlen(buffer), "Host: %s\r\n\r\n", s);
79 1.1 christos
80 1.1 christos u = strchr(s, ':');
81 1.1 christos if (u != NULL) {
82 1.1 christos *u++ = '\0';
83 1.1 christos port = atoi(u);
84 1.1 christos if (port < 0 || port > 65535)
85 1.1 christos goto done;
86 1.1 christos } else {
87 1.1 christos port = 80;
88 1.1 christos }
89 1.1 christos
90 1.1 christos
91 1.1 christos fd = connecttcp(s, port);
92 1.1 christos if (fd == -1)
93 1.1 christos goto done;
94 1.1 christos
95 1.1 christos
96 1.1 christos len = strlen(buffer);
97 1.1 christos if (write(fd, buffer, len) != len) {
98 1.1 christos close(fd);
99 1.1 christos goto done;
100 1.1 christos }
101 1.1 christos
102 1.1 christos s = buffer;
103 1.1 christos endhdr = 0;
104 1.1 christos left = sizeof(buffer) - 1;
105 1.1 christos
106 1.1 christos while ((len = read(fd, s, left)) > 0) {
107 1.1 christos s[len] = '\0';
108 1.1 christos left -= len;
109 1.1 christos s += len;
110 1.1 christos
111 1.1 christos if (endhdr >= 0) {
112 1.1 christos if (endhdr == 0) {
113 1.1 christos t = strchr(buffer, ' ');
114 1.1 christos if (t == NULL)
115 1.1 christos continue;
116 1.1 christos t++;
117 1.1 christos if (*t != '2')
118 1.1 christos break;
119 1.1 christos }
120 1.1 christos
121 1.1 christos u = buffer;
122 1.1 christos while ((t = strchr(u, '\r')) != NULL) {
123 1.1 christos if (t == u) {
124 1.1 christos if (*(t + 1) == '\n') {
125 1.1 christos u = t + 2;
126 1.1 christos endhdr = -1;
127 1.1 christos break;
128 1.1 christos } else
129 1.1 christos t++;
130 1.1 christos } else if (*(t + 1) == '\n') {
131 1.1 christos endhdr++;
132 1.1 christos u = t + 2;
133 1.1 christos } else
134 1.1 christos u = t + 1;
135 1.1 christos }
136 1.1 christos if (endhdr >= 0)
137 1.1 christos continue;
138 1.1 christos removed = (u - buffer) + 1;
139 1.1 christos memmove(buffer, u, (sizeof(buffer) - left) - removed);
140 1.1 christos s -= removed;
141 1.1 christos left += removed;
142 1.1 christos }
143 1.1 christos
144 1.1 christos do {
145 1.1 christos t = strchr(buffer, '\n');
146 1.1 christos if (t == NULL)
147 1.1 christos break;
148 1.1 christos
149 1.1 christos linenum++;
150 1.1 christos *t = '\0';
151 1.1 christos
152 1.1 christos /*
153 1.1 christos * Remove comment and continue to the next line if
154 1.1 christos * the comment is at the start of the line.
155 1.1 christos */
156 1.1 christos u = strchr(buffer, '#');
157 1.1 christos if (u != NULL) {
158 1.1 christos *u = '\0';
159 1.1 christos if (u == buffer);
160 1.1 christos continue;
161 1.1 christos }
162 1.1 christos
163 1.1 christos /*
164 1.1 christos * Trim off tailing white spaces, will include \r
165 1.1 christos */
166 1.1 christos for (u = t - 1; (u >= buffer) && ISSPACE(*u); u--)
167 1.1 christos *u = '\0';
168 1.1 christos
169 1.1 christos a = alist_new(AF_UNSPEC, buffer);
170 1.1 christos if (a != NULL) {
171 1.1 christos if (rbot != NULL)
172 1.1 christos rbot->al_next = a;
173 1.1 christos else
174 1.1 christos rtop = a;
175 1.1 christos rbot = a;
176 1.1 christos } else {
177 1.1 christos fprintf(stderr,
178 1.1 christos "%s:%d unrecognised content:%s\n",
179 1.1 christos url, linenum, buffer);
180 1.1 christos }
181 1.1 christos
182 1.1 christos t++;
183 1.1 christos removed = t - buffer;
184 1.1 christos memmove(buffer, t, sizeof(buffer) - left - removed);
185 1.1 christos s -= removed;
186 1.1 christos left += removed;
187 1.1 christos
188 1.1 christos } while (1);
189 1.1 christos }
190 1.1 christos
191 1.1 christos done:
192 1.1 christos if (myurl != NULL)
193 1.1 christos free(myurl);
194 1.1 christos if (fd != -1)
195 1.1 christos close(fd);
196 1.1 christos return rtop;
197 1.1 christos }
198