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