diff -Nru stunnel-3.14-ori/common.h stunnel-3.14/common.h --- stunnel-3.14-ori/common.h Wed Feb 21 16:08:31 2001 +++ stunnel-3.14/common.h Thu Jul 18 14:23:12 2002 @@ -18,14 +18,16 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define OPT_CLIENT 0x01 -#define OPT_CERT 0x02 -#define OPT_DAEMON 0x04 -#define OPT_FOREGROUND 0x08 -#define OPT_PROGRAM 0x10 -#define OPT_REMOTE 0x20 -#define OPT_TRANSPARENT 0x40 -#define OPT_PTY 0x80 +#define OPT_CLIENT 0x0001 +#define OPT_CERT 0x0002 +#define OPT_DAEMON 0x0004 +#define OPT_FOREGROUND 0x0008 +#define OPT_PROGRAM 0x0010 +#define OPT_REMOTE 0x0020 +#define OPT_TRANSPARENT 0x0040 +#define OPT_PTY 0x0080 +#define OPT_WEBPROXY 0x0100 +#define OPT_ADDHEADERS 0x0200 /* Certificate defaults */ @@ -202,6 +204,8 @@ int random_bytes; /* how many random bytes to read */ char *pid_dir; int cert_defaults; + char *finaldest; + char *headers; } server_options; /* Prototypes for stunnel.c */ diff -Nru stunnel-3.14-ori/stunnel.c stunnel-3.14/stunnel.c --- stunnel-3.14-ori/stunnel.c Wed Feb 21 15:55:28 2001 +++ stunnel-3.14/stunnel.c Thu Jul 18 14:25:02 2002 @@ -102,6 +102,8 @@ /* Prototypes */ static void get_options(int, char *[]); static void daemon_loop(); +int connect_to_finaldest(int); + #ifndef USE_WIN32 static void daemonize(); static void create_pid(); @@ -242,8 +244,10 @@ options.rand_file=NULL; options.rand_write=1; options.random_bytes=RANDOM_BYTES; + options.finaldest=NULL; + options.headers=NULL; opterr=0; - while ((c = getopt(argc, argv, "A:a:cp:v:d:fTl:L:r:s:g:t:u:n:N:hC:D:E:R:WB:VP:S:")) != EOF) + while ((c = getopt(argc, argv, "A:a:cp:v:d:fTl:L:r:s:g:t:u:n:N:hC:D:E:R:WB:VP:S:Z:H:")) != EOF) switch (c) { case 'A': safecopy(options.cert_file,optarg); @@ -385,6 +389,18 @@ log(LOG_ERR, "Illegal option: '%c'", optopt); case 'h': print_help(); + case 'Z': + if(!(options.option & OPT_CLIENT)) { + log(LOG_ERR, "webproxy -Z option runs only in client mode"); + fprintf(stderr, "webproxy -Z option runs only in client mode"); + print_help(); + } + options.option |= OPT_WEBPROXY; + options.finaldest = optarg; + break; + case 'H': + options.option |= OPT_ADDHEADERS; + options.headers = optarg; default: log(LOG_ERR, "INTERNAL ERROR: Illegal option: '%c'", c); print_help(); @@ -747,7 +763,8 @@ addr.sin_addr.s_addr=*list; log(LOG_DEBUG, "%s connecting %s:%d", options.servname, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - if(!connect(s, (struct sockaddr *) &addr, sizeof(addr))) + if(!connect(s, (struct sockaddr *) &addr, sizeof(addr)) + && !connect_to_finaldest(s)) return s; /* success */ } sockerror("remote connect"); @@ -1098,6 +1115,8 @@ "\n\t-d [host:]port -r [host:]port" #endif + "\n\t[-Z host:port ] " + "\n\t[-H additional_headers ] " /* Argument notes */ @@ -1106,6 +1125,10 @@ "\n" "\n -d [host:]port daemon mode (host defaults to INADDR_ANY)" "\n -r [host:]port connect to remote service (host defaults to INADDR_LOOPBACK)" + "\n -Z host:port the remote SSL host, if in client mode and using a webproxy" + "\n eg. -c -d localhost:9999 -r proxy:3128 -Z remotehost:443" + "\n -H additional_headers: add specified headers to the http request" + "\n to the proxy, for ex. to give credentials" #ifndef USE_WIN32 "\n -l program\t execute local inetd-type program" "\n -L program\t open local pty and execute program" @@ -1159,6 +1182,51 @@ "\nSee stunnel -V output for default values\n" "\n"); exit(1); +} + +int connect_to_finaldest(int s) { + char buff[STRLEN]; + int len, code; + + if (!(options.option & OPT_WEBPROXY)) + return 0; + +#ifdef HAVE_SNPRINTF + len=snprintf(buff, STRLEN, +#else + len=sprintfxbuff, +#endif + "CONNECT %s HTTP/1.0i\r\n%s\r\n\r\n", options.finaldest, + options.option & OPT_ADDHEADERS ? options.headers : ""); + len=writesocket(s, buff, len); + if(len<0) { + sockerror("writesocket (finaldest)"); + closesocket(s); + return -1; + } + log(LOG_DEBUG, "me ---> proxy: %s", buff); + + len=readsocket(s, buff, STRLEN-1); + if(len<0) { + sockerror("readsocket (finaldest)"); + closesocket(s); + return -1; + } + buff[len]='\0'; + log(LOG_DEBUG, "proxy ---> me: %s", buff); + + code = 0; + if(sscanf(buff, "HTTP/%*s %d %*s", &code) != 1) { + log(LOG_ERR, "error: %s", buff); + return -1; + } + + if(code != 200) { + log(LOG_WARNING, "return code not 200: %s", buff); + return -1; + } + + return 0; } /* End of stunnel.c */