]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ipfilter/lib/load_http.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ipfilter / lib / load_http.c
1 /* $FreeBSD$ */
2
3 /*
4  * Copyright (C) 2012 by Darren Reed.
5  *
6  * See the IPFILTER.LICENCE file for details on licencing.
7  *
8  * $Id: load_http.c,v 1.5.2.5 2012/07/22 08:04:24 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         size_t avail;
37         int error;
38
39         /*
40          * More than this would just be absurd.
41          */
42         if (strlen(url) > MAX_URL_LEN) {
43                 fprintf(stderr, "load_http has a URL > %d bytes?!\n",
44                         MAX_URL_LEN);
45                 return NULL;
46         }
47
48         fd = -1;
49         rtop = NULL;
50         rbot = NULL;
51
52         avail = sizeof(buffer);
53         error = snprintf(buffer, avail, "GET %s HTTP/1.0\r\n", url);
54
55         /*
56          * error is always less then avail due to the constraint on
57          * the url length above.
58          */
59         avail -= error;
60
61         myurl = strdup(url);
62         if (myurl == NULL)
63                 goto done;
64
65         s = myurl + 7;                  /* http:// */
66         t = strchr(s, '/');
67         if (t == NULL) {
68                 fprintf(stderr, "load_http has a malformed URL '%s'\n", url);
69                 free(myurl);
70                 return NULL;
71         }
72         *t++ = '\0';
73
74         /*
75          * 10 is the length of 'Host: \r\n\r\n' below.
76          */
77         if (strlen(s) + strlen(buffer) + 10 > sizeof(buffer)) {
78                 fprintf(stderr, "load_http has a malformed URL '%s'\n", url);
79                 free(myurl);
80                 return NULL;
81         }
82
83         u = strchr(s, '@');
84         if (u != NULL)
85                 s = u + 1;              /* AUTH */
86
87         error = snprintf(buffer + strlen(buffer), avail, "Host: %s\r\n\r\n", s);
88         if (error >= avail) {
89                 fprintf(stderr, "URL is too large: %s\n", url);
90                 goto done;
91         }
92
93         u = strchr(s, ':');
94         if (u != NULL) {
95                 *u++ = '\0';
96                 port = atoi(u);
97                 if (port < 0 || port > 65535)
98                         goto done;
99         } else {
100                 port = 80;
101         }
102
103
104         fd = connecttcp(s, port);
105         if (fd == -1)
106                 goto done;
107
108
109         len = strlen(buffer);
110         if (write(fd, buffer, len) != len)
111                 goto done;
112
113         s = buffer;
114         endhdr = 0;
115         left = sizeof(buffer) - 1;
116
117         while ((len = read(fd, s, left)) > 0) {
118                 s[len] = '\0';
119                 left -= len;
120                 s += len;
121
122                 if (endhdr >= 0) {
123                         if (endhdr == 0) {
124                                 t = strchr(buffer, ' ');
125                                 if (t == NULL)
126                                         continue;
127                                 t++;
128                                 if (*t != '2')
129                                         break;
130                         }
131
132                         u = buffer;
133                         while ((t = strchr(u, '\r')) != NULL) {
134                                 if (t == u) {
135                                         if (*(t + 1) == '\n') {
136                                                 u = t + 2;
137                                                 endhdr = -1;
138                                                 break;
139                                         } else
140                                                 t++;
141                                 } else if (*(t + 1) == '\n') {
142                                         endhdr++;
143                                         u = t + 2;
144                                 } else
145                                         u = t + 1;
146                         }
147                         if (endhdr >= 0)
148                                 continue;
149                         removed = (u - buffer) + 1;
150                         memmove(buffer, u, (sizeof(buffer) - left) - removed);
151                         s -= removed;
152                         left += removed;
153                 }
154
155                 do {
156                         t = strchr(buffer, '\n');
157                         if (t == NULL)
158                                 break;
159
160                         linenum++;
161                         *t = '\0';
162
163                         /*
164                          * Remove comment and continue to the next line if
165                          * the comment is at the start of the line.
166                          */
167                         u = strchr(buffer, '#');
168                         if (u != NULL) {
169                                 *u = '\0';
170                                 if (u == buffer)
171                                         continue;
172                         }
173
174                         /*
175                          * Trim off tailing white spaces, will include \r
176                          */
177                         for (u = t - 1; (u >= buffer) && ISSPACE(*u); u--)
178                                 *u = '\0';
179
180                         a = alist_new(AF_UNSPEC, buffer);
181                         if (a != NULL) {
182                                 if (rbot != NULL)
183                                         rbot->al_next = a;
184                                 else
185                                         rtop = a;
186                                 rbot = a;
187                         } else {
188                                 fprintf(stderr,
189                                         "%s:%d unrecognised content:%s\n",
190                                         url, linenum, buffer);
191                         }
192
193                         t++;
194                         removed = t - buffer;
195                         memmove(buffer, t, sizeof(buffer) - left - removed);
196                         s -= removed;
197                         left += removed;
198
199                 } while (1);
200         }
201
202 done:
203         if (myurl != NULL)
204                 free(myurl);
205         if (fd != -1)
206                 close(fd);
207         return rtop;
208 }