filters.c
上传用户:qunlip
上传日期:2007-01-04
资源大小:203k
文件大小:14k
源码类别:

代理服务器

开发平台:

Visual C++

  1. char *filters_rcs = "$Id: filters.c,v 1.15 1998/10/23 01:54:03 ACJC Exp $";
  2. /* Written and copyright 1997 Anonymous Coders and Junkbusters Corporation.
  3.  * Distributed under the GNU General Public License; see the README file.
  4.  * This code comes with NO WARRANTY. http://www.junkbusters.com/ht/en/gpl.html
  5.  */
  6. #include <stdio.h>
  7. #include <sys/types.h>
  8. #include <stdlib.h>
  9. #include <ctype.h>
  10. #include <string.h>
  11. #ifndef _WIN32
  12. #include <unistd.h>
  13. #endif
  14. #ifdef REGEX
  15. #include <gnu_regex.h>
  16. #endif
  17. #include "jcc.h"
  18. #define URL(X) url_encode(url_code_map, (X))
  19. char CBLOCK[] = "HTTP/1.0 202 Request for blocked URLn"
  20.  "Pragma: no-cachen"
  21.  "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMTn"
  22.  "Expires:       Thu Jul 31, 1997 07:42:22 pm GMTn"
  23.  "Content-Type: text/htmlnn"
  24.  "<html>n"
  25.  "<head>n"
  26.  "<title>Internet Junkbuster: Request for blocked URL</title>n"
  27.  "</head>n"
  28.  WHITEBG
  29.  "<center>"
  30.  "<a href=http://internet.junkbuster.com/ij-blocked-url?%s+%s+%s>"
  31.  BANNER
  32.  "</a>"
  33.  "</center>"
  34.  "</body>n"
  35.  "</html>n"
  36.  ;
  37. char CTRUST[] = "HTTP/1.0 202 Request for untrusted URLn"
  38.  "Pragma: no-cachen"
  39.  "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMTn"
  40.  "Expires:       Thu Jul 31, 1997 07:42:22 pm GMTn"
  41.  "Content-Type: text/htmlnn"
  42.  "<html>n"
  43.  "<head>n"
  44.  "<title>Internet Junkbuster: Request for untrusted URL</title>n"
  45.  "</head>n"
  46.  WHITEBG
  47.  "<center>"
  48.  "<a href=http://internet.junkbuster.com/ij-untrusted-url?%s+%s+%s>"
  49.  BANNER
  50.  "</a>"
  51.  "</center>"
  52.  "</body>n"
  53.  "</html>n"
  54.  ;
  55. char *
  56. block_url(struct http_request *http, struct client_state *csp)
  57. {
  58. struct file_list *fl;
  59. struct block_spec *b;
  60. struct url_spec url[1];
  61. char *p;
  62. char *hostport, *path, *spec;
  63. int n;
  64. if(((fl = csp->blist) == NULL) || ((b  = fl->f) == NULL)) {
  65. return(NULL);
  66. }
  67. *url = dsplit(http->host);
  68. /* if splitting the domain fails, punt */
  69. if(url->dbuf == NULL) return(NULL);
  70. for(b = b->next; b ; b = b->next) {
  71. if((b->url->port == 0) || (b->url->port == http->port)) {
  72. if((b->url->domain[0] == '') || (domaincmp(b->url, url) == 0)) {
  73. if((b->url->path == NULL) ||
  74. #ifdef REGEX
  75.    (regexec(b->url->preg, http->path, 0, NULL, 0) == 0)
  76. #else
  77.    (strncmp(b->url->path, http->path, b->url->pathlen) == 0)
  78. #endif
  79. ) {
  80. freez(url->dbuf);
  81. freez(url->dvec);
  82. if(b->reject == 0) return(NULL);
  83. hostport = URL(http->hostport);
  84. path     = URL(http->path);
  85. spec     = URL(b->url->spec);
  86. n  = strlen(CBLOCK);
  87. n += strlen(hostport);
  88. n += strlen(path);
  89. n += strlen(spec);
  90. p = malloc(n);
  91. sprintf(p, CBLOCK,
  92. hostport, path, spec);
  93. freez(hostport);
  94. freez(path);
  95. freez(spec);
  96. return(p);
  97. }
  98. }
  99. }
  100. }
  101. freez(url->dbuf);
  102. freez(url->dvec);
  103. return(NULL);
  104. }
  105. char *
  106. trust_url(struct http_request *http, struct client_state *csp)
  107. {
  108. struct file_list *fl;
  109. struct block_spec *b;
  110. struct url_spec url[1], **tl, *t;
  111. char *p, *h;
  112. char *hostport, *path, *referrer;
  113. struct http_request rhttp[1];
  114. int n;
  115. if(((fl = csp->tlist) == NULL) || ((b  = fl->f) == NULL)) {
  116. return(NULL);
  117. }
  118. *url = dsplit(http->host);
  119. /* if splitting the domain fails, punt */
  120. if(url->dbuf == NULL) return(NULL);
  121. memset(rhttp, '', sizeof(*rhttp));
  122. for(b = b->next; b ; b = b->next) {
  123. if((b->url->port == 0) || (b->url->port == http->port)) {
  124. if((b->url->domain[0] == '') || (domaincmp(b->url, url) == 0)) {
  125. if((b->url->path == NULL) ||
  126. #ifdef REGEX
  127.    (regexec(b->url->preg, http->path, 0, NULL, 0) == 0)
  128. #else
  129.    (strncmp(b->url->path, http->path, b->url->pathlen) == 0)
  130. #endif
  131. ) {
  132. freez(url->dbuf);
  133. freez(url->dvec);
  134. if(b->reject == 0) return(NULL);
  135. hostport = URL(http->hostport);
  136. path     = URL(http->path);
  137. if(csp->referrer) {
  138. referrer = URL(csp->referrer);
  139. } else {
  140. referrer = URL("undefined");
  141. }
  142. n  = strlen(CTRUST);
  143. n += strlen(hostport);
  144. n += strlen(path);
  145. n += strlen(referrer);
  146. p = malloc(n);
  147. sprintf(p, CTRUST,
  148. hostport, path, referrer);
  149. freez(hostport);
  150. freez(path);
  151. freez(referrer);
  152. return(p);
  153. }
  154. }
  155. }
  156. }
  157. freez(url->dbuf);
  158. freez(url->dvec);
  159. if((csp->referrer == NULL)|| (strlen(csp->referrer) <= 9)) {
  160. /* no referrer was supplied */
  161. goto trust_url_not_trusted;
  162. }
  163. /* forge a URL from the referrer so we can use
  164.  * convert_url() to parse it into its components.
  165.  */
  166. p = NULL;
  167. p = strsav(p, "GET ");
  168. p = strsav(p, csp->referrer + 9); /* skip over "Referer: " */
  169. p = strsav(p, " HTTP/1.0");
  170. parse_http_request(p, rhttp, csp);
  171. if(rhttp->cmd == NULL) {
  172. freez(p);
  173. goto trust_url_not_trusted;
  174. }
  175. freez(p);
  176. *url = dsplit(rhttp->host);
  177. /* if splitting the domain fails, punt */
  178. if(url->dbuf == NULL) goto trust_url_not_trusted;
  179. for(tl = trust_list; (t = *tl) ; tl++) {
  180. if((t->port == 0) || (t->port == rhttp->port)) {
  181. if((t->domain[0] == '') || domaincmp(t, url) == 0) {
  182. if((t->path == NULL) ||
  183. #ifdef REGEX
  184.    (regexec(t->preg, rhttp->path, 0, NULL, 0) == 0)
  185. #else
  186.    (strncmp(t->path, rhttp->path, t->pathlen) == 0)
  187. #endif
  188. ) {
  189. /* if the URL's referrer is from a trusted referrer, then
  190.  * add the target spec to the trustfile as an unblocked
  191.  * domain and return NULL (which means it's OK).
  192.  */
  193. FILE *fp;
  194. freez(url->dbuf);
  195. freez(url->dvec);
  196. if((fp = fopen(trustfile, "a"))) {
  197. h = NULL;
  198. h = strsav(h, "~");
  199. h = strsav(h, http->hostport);
  200. p = http->path;
  201. if((*p++ == '/')
  202. && (*p++ == '~')) {
  203. /* since this path points into a user's home space
  204.  * be sure to include this spec in the trustfile.
  205.  */
  206. if((p = strchr(p, '/'))) {
  207. *p = '';
  208. h = strsav(h, http->path);
  209. h = strsav(h, "/");
  210. }
  211. }
  212. free_http_request(rhttp);
  213. fprintf(fp, "%sn", h);
  214. freez(h);
  215. fclose(fp);
  216. }
  217. return(NULL);
  218. }
  219. }
  220. }
  221. }
  222. trust_url_not_trusted:
  223. free_http_request(rhttp);
  224. hostport = URL(http->hostport);
  225. path     = URL(http->path);
  226. if(csp->referrer) {
  227. referrer = URL(csp->referrer);
  228. } else {
  229. referrer = URL("undefined");
  230. }
  231. n  = strlen(CTRUST);
  232. n += strlen(hostport);
  233. n += strlen(path);
  234. n += strlen(referrer);
  235. p = malloc(n);
  236. sprintf(p, CTRUST, hostport, path, referrer);
  237. freez(hostport);
  238. freez(path);
  239. freez(referrer);
  240. return(p);
  241. }
  242. /* intercept_url() checks the URL `basename' against a list of URLs
  243.  * to snarf.  If it matches, it calls the associated function which
  244.  * returns an HTML page to send back to the client.
  245.  */
  246. char *
  247. intercept_url(struct http_request *http, struct client_state *csp)
  248. {
  249. char *basename;
  250. struct interceptors *v;
  251. basename = strrchr(http->path, '/');
  252. if(basename == NULL) return(NULL);
  253. basename++; /* first char past the last slash */
  254. if(*basename) {
  255. for(v = intercept_patterns; v->str; v++) {
  256. if(strncmp(basename, v->str, v->len) == 0) {
  257. return((v->interceptor)(http, csp));
  258. }
  259. }
  260. }
  261. return(NULL);
  262. }
  263. struct cookie_spec *
  264. cookie_url(struct http_request *http, struct client_state *csp)
  265. {
  266. struct file_list *fl;
  267. struct cookie_spec *b;
  268. struct url_spec url[1];
  269. if(((fl = csp->clist) == NULL) || ((b  = fl->f) == NULL)) {
  270. return(NULL);
  271. }
  272. *url = dsplit(http->host);
  273. /* if splitting the domain fails, punt */
  274. if(url->dbuf == NULL) return(NULL);
  275. for(b = b->next; b ; b = b->next) {
  276. if((b->url->port == 0) || (b->url->port == http->port)) {
  277. if((b->url->domain[0] == '') || (domaincmp(b->url, url) == 0)) {
  278. if((b->url->path == NULL) ||
  279. #ifdef REGEX
  280.    (regexec(b->url->preg, http->path, 0, NULL, 0) == 0)
  281. #else
  282.    (strncmp(b->url->path, http->path, b->url->pathlen) == 0)
  283. #endif
  284. ) {
  285. freez(url->dbuf);
  286. freez(url->dvec);
  287. return(b);
  288. }
  289. }
  290. }
  291. }
  292. freez(url->dbuf);
  293. freez(url->dvec);
  294. return(NULL);
  295. }
  296. struct gateway *
  297. forward_url(struct http_request *http, struct client_state *csp)
  298. {
  299. struct file_list *fl;
  300. struct forward_spec *b;
  301. struct url_spec url[1];
  302. if(((fl = csp->flist) == NULL) || ((b  = fl->f) == NULL)) {
  303. return(gw_default);
  304. }
  305. *url = dsplit(http->host);
  306. /* if splitting the domain fails, punt */
  307. if(url->dbuf == NULL) return(gw_default);
  308. for(b = b->next; b ; b = b->next) {
  309. if((b->url->port == 0) || (b->url->port == http->port)) {
  310. if((b->url->domain[0] == '') || (domaincmp(b->url, url) == 0)) {
  311. if((b->url->path == NULL) ||
  312. #ifdef REGEX
  313.    (regexec(b->url->preg, http->path, 0, NULL, 0) == 0)
  314. #else
  315.    (strncmp(b->url->path, http->path, b->url->pathlen) == 0)
  316. #endif
  317. ) {
  318. freez(url->dbuf);
  319. freez(url->dvec);
  320. return(b->gw);
  321. }
  322. }
  323. }
  324. }
  325. freez(url->dbuf);
  326. freez(url->dvec);
  327. return(gw_default);
  328. }
  329. /* dsplit() takes a domain and returns a pointer to a url_spec
  330.  * structure populated with dbuf, dcnt and dvec.  the other fields
  331.  * in the structure that is returned are zero.
  332.  *
  333.  */
  334. struct url_spec
  335. dsplit(char *domain)
  336. {
  337. struct url_spec ret[1];
  338. char *v[BUFSIZ];
  339. int size;
  340. char *p;
  341. memset(ret, '', sizeof(*ret));
  342. if((p = strrchr(domain, '.'))) {
  343. if(*(++p) == '') {
  344. ret->toplevel = 1;
  345. }
  346. }
  347. ret->dbuf = strdup(domain);
  348. /* map to lower case */
  349. for(p = ret->dbuf; *p ; p++) *p = tolower(*p);
  350. /* split the domain name into components */
  351. ret->dcnt = ssplit(ret->dbuf, ".", v, SZ(v), 1, 1);
  352. if(ret->dcnt <= 0) {
  353. memset(ret, '', sizeof(ret));
  354. return(*ret);
  355. }
  356. /* save a copy of the pointers in dvec */
  357. size = ret->dcnt * sizeof(*ret->dvec);
  358. if((ret->dvec = malloc(size))) {
  359. memcpy(ret->dvec, v, size);
  360. }
  361. return(*ret);
  362. }
  363. /* the "pattern" is a domain that may contain a '*' as a wildcard.
  364.  * the "fqdn" is the domain name against which the patterns are compared.
  365.  *
  366.  * domaincmp("a.b.c" , "a.b.c") => 0 (MATCH)
  367.  * domaincmp("a*.b.c", "a.b.c") => 0 (MATCH)
  368.  * domaincmp("b.c"   , "a.b.c") => 0 (MATCH)
  369.  * domaincmp(""      , "a.b.c") => 0 (MATCH)
  370.  */
  371. int
  372. domaincmp(struct url_spec *pattern, struct url_spec *fqdn)
  373. {
  374. char **pv, **fv; /* vectors  */
  375. int    pn,   fn; /* counters */
  376. char  *p,   *f; /* chars    */
  377. pv = pattern->dvec;
  378. pn = pattern->dcnt;
  379. fv = fqdn->dvec;
  380. fn = fqdn->dcnt;
  381. while((pn > 0) && (fn > 0)) {
  382. p = pv[--pn];
  383. f = fv[--fn];
  384. while(*p && *f && (*p == tolower(*f))) {
  385. p++, f++;
  386. }
  387. if((*p != tolower(*f)) && (*p != '*')) return(1);
  388. }
  389. if(pn > 0) return(1);
  390. return(0);
  391. }
  392. /* intercept functions */
  393. char *
  394. show_proxy_args(struct http_request *http, struct client_state *csp)
  395. {
  396. char *s = NULL;
  397. s = strsav(s, proxy_args->header);
  398. s = strsav(s, proxy_args->invocation);
  399. s = strsav(s, proxy_args->gateways);
  400. if(csp->blist) {
  401. s = strsav(s, csp->blist->proxy_args);
  402. }
  403. if(csp->clist) {
  404. s = strsav(s, csp->clist->proxy_args);
  405. }
  406. if(csp->tlist) {
  407. s = strsav(s, csp->tlist->proxy_args);
  408. }
  409. if(csp->flist) {
  410. s = strsav(s, csp->flist->proxy_args);
  411. }
  412. s = strsav(s, proxy_args->trailer);
  413. return(s);
  414. }
  415. char *
  416. ij_blocked_url(struct http_request *http, struct client_state *csp)
  417. {
  418. int n;
  419. char *hostport, *path, *pattern, *p, *v[9];
  420. char *template =
  421. "HTTP/1.0 200 OKrn"
  422. "Pragma: no-cachen"
  423. "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMTn"
  424. "Expires:       Thu Jul 31, 1997 07:42:22 pm GMTn"
  425. "Content-Type: text/htmlnn"
  426. "<html>n"
  427. "<head>n"
  428. "<title>Internet Junkbuster: Request for blocked URL</title>n"
  429. "</head>n"
  430. BODY
  431. "<center><h1>"
  432. BANNER
  433. "</h1></center>"
  434. "The " BANNER " Proxy "
  435. "<A href="http://internet.junkbuster.com">"
  436. "(http://internet.junkbuster.com) </A>"
  437. "intercepted the request for %s%sn"
  438. "because the URL matches the following pattern "
  439. "in the blockfile: %sn"
  440. "</body>n"
  441. "</html>n"
  442. ;
  443. if((n = ssplit(http->path, "?+", v, SZ(v), 0, 0)) == 4) {
  444. hostport = url_decode(v[1]);
  445. path     = url_decode(v[2]);
  446. pattern  = url_decode(v[3]);
  447. } else {
  448. hostport = strdup("undefined_host");
  449. path     = strdup("/undefined_path");
  450. pattern  = strdup("undefined_pattern");
  451. }
  452. n  = strlen(template);
  453. n += strlen(hostport);
  454. n += strlen(path    );
  455. n += strlen(pattern );
  456. if((p = malloc(n))) {
  457. sprintf(p, template, hostport, path, pattern);
  458. }
  459. freez(hostport);
  460. freez(path    );
  461. freez(pattern );
  462. return(p);
  463. }
  464. char *
  465. ij_untrusted_url(struct http_request *http, struct client_state *csp)
  466. {
  467. int n;
  468. char *hostport, *path, *p, *v[9];
  469. char buf[BUFSIZ];
  470. struct url_spec **tl, *t;
  471. char *template =
  472. "HTTP/1.0 200 OKrn"
  473. "Pragma: no-cachen"
  474. "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMTn"
  475. "Expires:       Thu Jul 31, 1997 07:42:22 pm GMTn"
  476. "Content-Type: text/htmlnn"
  477. "<html>n"
  478. "<head>n"
  479. "<title>Internet Junkbuster: Request for untrusted URL</title>n"
  480. "</head>n"
  481. BODY
  482. "<center><h1>"
  483. BANNER
  484. "</h1></center>"
  485. "The " BANNER " Proxy "
  486. "<A href="http://internet.junkbuster.com">"
  487. "(http://internet.junkbuster.com) </A>"
  488. "intercepted the request for %s%sn"
  489. "because the URL is not trusted.n"
  490. "<br><br>n"
  491. ;
  492. if((n = ssplit(http->path, "?+", v, SZ(v), 0, 0)) == 4) {
  493. hostport = url_decode(v[1]);
  494. path     = url_decode(v[2]);
  495. referrer = url_decode(v[3]);
  496. } else {
  497. hostport = strdup("undefined_host");
  498. path     = strdup("/undefined_path");
  499. referrer = strdup("undefined");
  500. }
  501. n  = strlen(template);
  502. n += strlen(hostport);
  503. n += strlen(path    );
  504. if((p = malloc(n))) {
  505. sprintf(p, template, hostport, path);
  506. }
  507. freez(hostport);
  508. freez(path    );
  509. strsav(p, "The referrer in this request was <strong>");
  510. strsav(p, referrer);
  511. strsav(p, "</strong><br>n");
  512. p = strsav(p, "<h3>The following referrers are trusted</h3>n");
  513. for(tl = trust_list; (t = *tl) ; tl++) {
  514. sprintf(buf, "%s<br>n", t->spec);
  515. p = strsav(p, buf);
  516. }
  517. if(trust_info->next) {
  518. struct list *l;
  519. strcpy(buf,
  520. "<p>"
  521. "You can learn more about what this means "
  522. "and what you may be able to do about it by "
  523. "reading the following documents:<br>n"
  524. "<ol>n"
  525. );
  526. p = strsav(p, buf);
  527. for(l = trust_info->next; l ; l = l->next) {
  528. sprintf(buf,
  529. "<li> <a href=%s>%s</a><br>n",
  530. l->str, l->str);
  531. p = strsav(p, buf);
  532. }
  533. p = strsav(p, "</ol>n");
  534. }
  535. p = strsav(p, "</body>n" "</html>n");
  536. return(p);
  537. }