📄 jcc.c
字号:
char *jcc_rcs = "$Id: jcc.c,v 3.42 1998/10/29 03:11:21 ACJC Exp $";/* Written and copyright 1997 Anonymous Coders and Junkbusters Corporation. * Distributed under the GNU General Public License; see the README file. * This code comes with NO WARRANTY. http://www.junkbusters.com/ht/en/gpl.html */#include <stdio.h>#include <sys/types.h>#include <stdlib.h>#include <ctype.h>#include <string.h>#include <signal.h>#include <fcntl.h>#include <errno.h>#ifdef _WIN32#include <sys/timeb.h>#include <windows.h>#include <io.h>#include <process.h>#else#include <unistd.h>#include <sys/time.h>#include <sys/wait.h>#include <sys/stat.h>#ifdef __BEOS__#include <socket.h> /* BeOS has select() for sockets only. */#include <OS.h> /* declarations for threads and stuff. */#endif#ifndef FD_ZERO#include <select.h>#endif#endif#ifdef REGEX#include <gnu_regex.h>#endif#include "jcc.h"char *prog;#define BODY "<body bgcolor=\"#f8f8f0\" link=\"#000078\" alink=\"#ff0022\" vlink=\"#787878\">\n"char CFAIL[] = "HTTP/1.0 503 Connect failed\n" "Content-Type: text/html\n\n" "<html>\n" "<head>\n" "<title>Internet Junkbuster: Connect failed</title>\n" "</head>\n" BODY "<h1><center>" BANNER "</center></h1>" "TCP connection to '%s' failed: %s.\n<br>" "</body>\n" "</html>\n" ;char CNXDOM[] = "HTTP/1.0 404 Non-existent domain\n" "Content-Type: text/html\n\n" "<html>\n" "<head>\n" "<title>Internet Junkbuster: Non-existent domain</title>\n" "</head>\n" BODY "<h1><center>" BANNER "</center></h1>" "No such domain: %s\n" "</body>\n" "</html>\n" ;char CSUCCEED[] = "HTTP/1.0 200 Connection established\n" "Proxy-Agent: IJ/" VERSION "\n\n" ;char CHEADER[] = "HTTP/1.0 400 Invalid header received from browser\n\n";char SHEADER[] = "HTTP/1.0 502 Invalid header received from server\n\n";char VANILLA_WAFER[] = "NOTICE=TO_WHOM_IT_MAY_CONCERN_" "Do_not_send_me_any_copyrighted_information_other_than_the_" "document_that_I_am_requesting_or_any_of_its_necessary_components._" "In_particular_do_not_send_me_any_cookies_that_" "are_subject_to_a_claim_of_copyright_by_anybody._" "Take_notice_that_I_refuse_to_be_bound_by_any_license_condition_" "(copyright_or_otherwise)_applying_to_any_cookie._";char DEFAULT_USER_AGENT[] ="User-Agent: Mozilla/3.01Gold (Macintosh; I; 68K)";int debug = 0;int multi_threaded = 1;int hideConsole = 0;#ifdef _WIN32#define sleep(N) Sleep(((N) * 1000))#endifchar *logfile = NULL;FILE *logfp;char *blockfile = NULL;char *cookiefile = NULL;char *trustfile = NULL;char *forwardfile = NULL;char *aclfile = NULL;char *jarfile = NULL;FILE *jar;char *referrer = NULL;char *uagent = NULL;char *from = NULL;int suppress_vanilla_wafer = 0;int add_forwarded = 0;struct client_state clients[1];struct file_list files[1];struct list wafer_list[1];struct list xtra_list[1];struct list trust_info[1];struct url_spec * trust_list[64];int (*loaders[NLOADERS])();struct gateway gateways[] = {/* type function gw type/host/port, fw host/port*/{ "direct", direct_connect, 0, NULL, 0, NULL, 0 },{ ".", direct_connect, 0, NULL, 0, NULL, 0 },{ "socks", socks4_connect, SOCKS_4, NULL, 1080, NULL, 0 },{ "socks4", socks4_connect, SOCKS_4, NULL, 1080, NULL, 0 },{ "socks4a", socks4_connect, SOCKS_4A, NULL, 1080, NULL, 0 },{ NULL, NULL, 0, NULL, 0, NULL, 0 }};struct gateway *gw_default = gateways;char *haddr = "127.0.0.1"; /* default binding to localhost */int hport = 8000;struct proxy_args proxy_args[1];intwrite_socket(int fd, char *buf, int n){ if(n <= 0) return(0); if(DEBUG(LOG)) fwrite(buf, n, 1, logfp);#if defined(_WIN32) || defined(__BEOS__) return send(fd, buf, n, 0);#else return write(fd, buf, n);#endif}intread_socket(int fd, char *buf, int n){ if(n <= 0) return(0);#if defined(_WIN32) || defined(__BEOS__) return recv(fd, buf, n, 0);#else return read(fd, buf, n);#endif}voidclose_socket(int fd){#if defined(_WIN32) || defined(__BEOS__) closesocket(fd);#else close(fd);#endif}voidchat(struct client_state *csp){ char buf[BUFSIZ], *hdr, *p, *req; char *err = NULL; char *eno; fd_set rfds; int n, maxfd, server_body; struct cookie_spec *cs; struct gateway *gw; struct http_request *http; http = csp->http; /* read the client's request. * note that since we're not using select() * we could get blocked here if a client * connected, then didn't say anything! */ for(;;) { n = read_socket(csp->cfd, buf, sizeof(buf)); if(n <= 0) break; /* error! */ add_to_iob(csp, buf, n); req = get_header(csp); if(req == NULL) break; /* no HTTP request! */ if(*req == '\0') continue; /* more to come! */ parse_http_request(req, http, csp); freez(req); break; } if(http->cmd == NULL) { strcpy(buf, CHEADER); write_socket(csp->cfd, buf, strlen(buf)); return; } /* decide how to route the HTTP request */ if((gw = forward_url(http, csp)) == NULL) { fprintf(logfp, "%s: gateway spec is NULL!?!? This can't happen!\n", prog); abort(); } /* build the http request to send to the server * we have to do one of the following: * * create = use the original HTTP request to create a new * HTTP request that has only the path component * without the http://domainspec * pass = pass the original HTTP request unchanged * * drop = drop the HTTP request * * here's the matrix: * SSL * 0 1 * +--------+--------+ * | | | * 0 | create | drop | * | | | * Forwarding +--------+--------+ * | | | * 1 | pass | pass | * | | | * +--------+--------+ * */ if(gw->forward_host) { /* if forwarding, just pass the request as is */ enlist(csp->headers, http->cmd); } else { if(http->ssl == 0) { /* otherwise elide the host information from the url */ p = NULL; p = strsav(p, http->gpc); p = strsav(p, " "); p = strsav(p, http->path); p = strsav(p, " "); p = strsav(p, http->ver); enlist(csp->headers, p); freez(p); } } /* decide what we're to do with cookies */ if((cs = cookie_url(http, csp))) { csp->accept_server_cookie = cs->accept_server_cookie; csp->send_user_cookie = cs->send_user_cookie; } else { csp->accept_server_cookie = 0; csp->send_user_cookie = 0; } /* grab the rest of the client's headers */ for(;;) { if(( p = get_header(csp)) && (*p == '\0')) { n = read_socket(csp->cfd, buf, sizeof(buf)); if(n <= 0) { fprintf(logfp, "%s: read from client failed: ", prog); fperror(logfp, ""); return; } add_to_iob(csp, buf, n); continue; } if(p == NULL) break; enlist(csp->headers, p); freez(p); } /* filter it as required */ hdr = sed(client_patterns, add_client_headers, csp); destroy_list(csp->headers); if((p = intercept_url(http, csp)) || (p = block_url(http, csp)) || (p = trust_url(http, csp))) { if(DEBUG(GPC)) { fprintf(logfp, "%s: GPC\t%s%s crunch!\n", prog, http->hostport, http->path); } write_socket(csp->cfd, p, strlen(p)); if(DEBUG(LOG)) fwrite(p, strlen(p), 1, logfp); freez(p); freez(hdr); return; } if(DEBUG(GPC)) { fprintf(logfp, "%s: GPC\t%s%s\n", prog, http->hostport, http->path); } if(DEBUG(CON)) { if(gw->forward_host) { fprintf(logfp, "%s: connect via %s:%d to: %s ... ", prog, gw->forward_host, gw->forward_port, http->hostport); } else { fprintf(logfp, "%s: connect to: %s ... ", prog, http->hostport); } } /* here we connect to the server, gateway, or the forwarder */ csp->sfd = (gw->conn)(gw, http, csp); if(csp->sfd < 0) { if(DEBUG(CON)) { fprintf(logfp, "%s: connect to: %s failed: ", prog, http->hostport); fperror(logfp, ""); } if(errno == EINVAL) { err = zalloc(strlen(CNXDOM) + strlen(http->host)); sprintf(err, CNXDOM, http->host); } else { eno = safe_strerror(errno); err = zalloc(strlen(CFAIL) + strlen(http->hostport) + strlen(eno)); sprintf(err, CFAIL, http->hostport, eno); } write_socket(csp->cfd, err, strlen(err)); if(DEBUG(LOG)) fwrite(err, strlen(err), 1, logfp); freez(err); freez(hdr); return; } if(DEBUG(CON)) { fprintf(logfp, "OK\n"); } if(gw->forward_host || (http->ssl == 0)) { /* write the client's (modified) header to the server * (along with anything else that may be in the buffer) */ n = strlen(hdr); if((write_socket(csp->sfd, hdr, n) != n) || (flush_socket(csp->sfd, csp ) < 0)) { if(DEBUG(CON)) { fprintf(logfp, "%s: write header to: %s failed: ", prog, http->hostport); fperror(logfp, ""); } eno = safe_strerror(errno); err = zalloc(strlen(CFAIL) + strlen(http->hostport) + strlen(eno)); sprintf(err, CFAIL, http->hostport, eno); write_socket(csp->cfd, err, strlen(err)); freez(err); freez(hdr); return; } } else { /* we're running an SSL tunnel and we're not * forwarding, so just send the "connect succeeded" * message to the client, flush the rest, and * get out of the way. */ if(write_socket(csp->cfd, CSUCCEED, sizeof(CSUCCEED)-1) < 0) { freez(hdr); return; } IOB_RESET(csp); } /* we're finished with the client's header */ freez(hdr); maxfd = ( csp->cfd > csp->sfd ) ? csp->cfd : csp->sfd; /* pass data between the client and server * until one or the other shuts down the connection. */ server_body = 0; for(;;) { FD_ZERO(&rfds); FD_SET(csp->cfd, &rfds); FD_SET(csp->sfd, &rfds); n = select(maxfd+1, &rfds, NULL, NULL, NULL); if(n < 0) { fprintf(logfp, "%s: select() failed!: ", prog); fperror(logfp, ""); return; } /* this is the body of the browser's request * just read it and write it. */ if(FD_ISSET(csp->cfd, &rfds)) { n = read_socket(csp->cfd, buf, sizeof(buf)); if(n <= 0) break; /* "game over, man" */ if(write_socket(csp->sfd, buf, n) != n) { fprintf(logfp, "%s: write to: %s failed: ", prog, http->host); fperror(logfp, ""); return; } continue; } /* the server wants to talk. * it could be the header or the body. * if `hdr' is null, then it's the header * otherwise it's the body */ if(FD_ISSET(csp->sfd, &rfds)) { n = read_socket(csp->sfd, buf, sizeof(buf)); if(n < 0) { fprintf(logfp, "%s: read from: %s failed: ", prog, http->host); fperror(logfp, ""); eno = safe_strerror(errno); sprintf(buf, CFAIL, http->hostport, eno); freez(eno); write_socket(csp->cfd, buf, strlen(buf)); return; } if(n == 0) break; /* "game over, man" */ /* if this is an SSL connection or we're in the body * of the server document, just write it to the client. */ if(server_body || http->ssl) { /* just write */ if(write_socket(csp->cfd, buf, n) != n) { fprintf(logfp, "%s: write to client failed: ", prog); fperror(logfp, ""); return; } continue; } else { /* we're still looking for the end of the * server's header ... (does that make header * parsing an "out of body experience" ? */ /* buffer up the data we just read */ add_to_iob(csp, buf, n); /* get header lines from the iob */ while((p = get_header(csp))) { if(*p == '\0') { /* see following note */ break; } enlist(csp->headers, p); freez(p); } /* NOTE: there are no "empty" headers so * if the pointer `p' is not NULL we must * assume that we reached the end of the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -