diff options
Diffstat (limited to 'contrib/ipfilter/lib/load_http.c')
-rw-r--r-- | contrib/ipfilter/lib/load_http.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/contrib/ipfilter/lib/load_http.c b/contrib/ipfilter/lib/load_http.c new file mode 100644 index 0000000..88fc1e3 --- /dev/null +++ b/contrib/ipfilter/lib/load_http.c @@ -0,0 +1,208 @@ +/* $FreeBSD$ */ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: load_http.c,v 1.5.2.5 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" +#include <ctype.h> + +/* + * Because the URL can be included twice into the buffer, once as the + * full path for the "GET" and once as the "Host:", the buffer it is + * put in needs to be larger than 512*2 to make room for the supporting + * text. Why not just use snprintf and truncate? The warning about the + * URL being too long tells you something is wrong and does not fetch + * any data - just truncating the URL (with snprintf, etc) and sending + * that to the server is allowing an unknown and unintentioned action + * to happen. + */ +#define MAX_URL_LEN 512 +#define LOAD_BUFSIZE (MAX_URL_LEN * 2 + 128) + +/* + * Format expected is one addres per line, at the start of each line. + */ +alist_t * +load_http(char *url) +{ + int fd, len, left, port, endhdr, removed, linenum = 0; + char *s, *t, *u, buffer[LOAD_BUFSIZE], *myurl; + alist_t *a, *rtop, *rbot; + size_t avail; + int error; + + /* + * More than this would just be absurd. + */ + if (strlen(url) > MAX_URL_LEN) { + fprintf(stderr, "load_http has a URL > %d bytes?!\n", + MAX_URL_LEN); + return NULL; + } + + fd = -1; + rtop = NULL; + rbot = NULL; + + avail = sizeof(buffer); + error = snprintf(buffer, avail, "GET %s HTTP/1.0\r\n", url); + + /* + * error is always less then avail due to the constraint on + * the url length above. + */ + avail -= error; + + myurl = strdup(url); + if (myurl == NULL) + goto done; + + s = myurl + 7; /* http:// */ + t = strchr(s, '/'); + if (t == NULL) { + fprintf(stderr, "load_http has a malformed URL '%s'\n", url); + free(myurl); + return NULL; + } + *t++ = '\0'; + + /* + * 10 is the length of 'Host: \r\n\r\n' below. + */ + if (strlen(s) + strlen(buffer) + 10 > sizeof(buffer)) { + fprintf(stderr, "load_http has a malformed URL '%s'\n", url); + free(myurl); + return NULL; + } + + u = strchr(s, '@'); + if (u != NULL) + s = u + 1; /* AUTH */ + + error = snprintf(buffer + strlen(buffer), avail, "Host: %s\r\n\r\n", s); + if (error >= avail) { + fprintf(stderr, "URL is too large: %s\n", url); + goto done; + } + + u = strchr(s, ':'); + if (u != NULL) { + *u++ = '\0'; + port = atoi(u); + if (port < 0 || port > 65535) + goto done; + } else { + port = 80; + } + + + fd = connecttcp(s, port); + if (fd == -1) + goto done; + + + len = strlen(buffer); + if (write(fd, buffer, len) != len) + goto done; + + s = buffer; + endhdr = 0; + left = sizeof(buffer) - 1; + + while ((len = read(fd, s, left)) > 0) { + s[len] = '\0'; + left -= len; + s += len; + + if (endhdr >= 0) { + if (endhdr == 0) { + t = strchr(buffer, ' '); + if (t == NULL) + continue; + t++; + if (*t != '2') + break; + } + + u = buffer; + while ((t = strchr(u, '\r')) != NULL) { + if (t == u) { + if (*(t + 1) == '\n') { + u = t + 2; + endhdr = -1; + break; + } else + t++; + } else if (*(t + 1) == '\n') { + endhdr++; + u = t + 2; + } else + u = t + 1; + } + if (endhdr >= 0) + continue; + removed = (u - buffer) + 1; + memmove(buffer, u, (sizeof(buffer) - left) - removed); + s -= removed; + left += removed; + } + + do { + t = strchr(buffer, '\n'); + if (t == NULL) + break; + + linenum++; + *t = '\0'; + + /* + * Remove comment and continue to the next line if + * the comment is at the start of the line. + */ + u = strchr(buffer, '#'); + if (u != NULL) { + *u = '\0'; + if (u == buffer) + continue; + } + + /* + * Trim off tailing white spaces, will include \r + */ + for (u = t - 1; (u >= buffer) && ISSPACE(*u); u--) + *u = '\0'; + + a = alist_new(AF_UNSPEC, buffer); + if (a != NULL) { + if (rbot != NULL) + rbot->al_next = a; + else + rtop = a; + rbot = a; + } else { + fprintf(stderr, + "%s:%d unrecognised content:%s\n", + url, linenum, buffer); + } + + t++; + removed = t - buffer; + memmove(buffer, t, sizeof(buffer) - left - removed); + s -= removed; + left += removed; + + } while (1); + } + +done: + if (myurl != NULL) + free(myurl); + if (fd != -1) + close(fd); + return rtop; +} |