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