summaryrefslogtreecommitdiffstats
path: root/contrib/ipfilter/lib/load_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ipfilter/lib/load_http.c')
-rw-r--r--contrib/ipfilter/lib/load_http.c208
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;
+}
OpenPOWER on IntegriCloud