Package: stunnel4
Version: 2:4.070-2
Severity: wishlist
Tags: patch
Hello,
Included is the dunbar-proxy-connect patch updated against version 4.07.
Could you include it in your debian package and forward it to upstream?
Thanks in advance, Peter
-- System Information:
Debian Release: 3.1
APT prefers unstable
APT policy: (990, 'unstable'), (500, 'testing')
Architecture: i386 (i686)
Kernel: Linux 2.6.10-my-2
Locale: [EMAIL PROTECTED], LC_CTYPE=it_IT (charmap=ISO-8859-1)
Versions of packages stunnel4 depends on:
ii libc6 2.3.2.ds1-20 GNU C Library: Shared libraries an
ii libssl0.9.7 0.9.7e-3 SSL shared libraries
ii libwrap0 7.6.dbs-6 Wietse Venema's TCP wrappers libra
ii netbase 4.19 Basic TCP/IP networking system
ii openssl 0.9.7e-3 Secure Socket Layer (SSL) binary a
-- no debconf information
diff -ubdNr stunnel4-4.070-original/src/client.c stunnel4-4.070-patched/src/client.c
--- stunnel4-4.070-original/src/client.c 2005-01-02 22:35:22.000000000 +0100
+++ stunnel4-4.070-patched/src/client.c 2005-01-18 11:52:39.000000000 +0100
@@ -75,6 +75,7 @@
static int connect_remote(CLI *c);
static int connect_wait(int, int);
static void reset(int, char *);
+int connect_to_finaldest(CLI *c, int s);
int max_clients;
#ifndef USE_WIN32
@@ -952,7 +953,8 @@
s_ntop(c->connecting_address, &addr);
s_log(LOG_DEBUG, "%s connecting %s",
c->opt->servname, c->connecting_address);
- if(!connect(s, &addr.sa, addr_len(addr)))
+ if(!connect(s, &addr.sa, addr_len(addr))
+ && !connect_to_finaldest(c, s))
return s; /* no error -> success (should not be possible) */
error=get_last_socket_error();
if(error!=EINPROGRESS && error!=EWOULDBLOCK) {
@@ -962,7 +964,11 @@
continue; /* next IP */
}
if(!connect_wait(s, c->opt->timeout_connect))
+ {
+ /* we got a connection */
+ if (!connect_to_finaldest(c, s))
return s; /* success! */
+ }
closesocket(s); /* error -> next IP */
}
return -1;
@@ -1015,4 +1021,292 @@
log_error(LOG_DEBUG, get_last_socket_error(), txt);
}
+/*
+ * Base 64 encoding algorithm from: Bob Deblier <[EMAIL PROTECTED]>
+ * Modified by Daniel Savard <[EMAIL PROTECTED]> to accept char *
+ */
+static const char* to_b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+char* b64enc(const char* data) {
+ int divider = strlen(data) / 3;
+ int remainder = strlen(data) % 3;
+ int chars = divider*4 + remainder + 1;
+ char* string = (char*) malloc(chars + 1);
+
+ if (string) {
+ register char* buf = string;
+ chars = 0;
+ while (divider > 0) {
+ buf[0] = to_b64[ (data[0] >> 2) & 0x3f];
+ buf[1] = to_b64[((data[0] << 4) & 0x30) + ((data[1] >> 4) & 0xf)];
+ buf[2] = to_b64[((data[1] << 2) & 0x3c) + ((data[2] >> 6) & 0x3)];
+ buf[3] = to_b64[ data[2] & 0x3f];
+ data += 3;
+ buf += 4;
+ divider--;
+ chars += 4;
+ }
+
+ switch (remainder) {
+ case 2:
+ buf[0] = to_b64[ (data[0] >> 2) & 0x3f];
+ buf[1] = to_b64[((data[0] << 4) & 0x30) + ((data[1] >> 4) & 0xf)];
+ buf[2] = to_b64[ (data[1] << 2) & 0x3c];
+ buf[3] = '=';
+ buf += 4;
+ chars += 4;
+ break;
+ case 1:
+ buf[0] = to_b64[ (data[0] >> 2) & 0x3f];
+ buf[1] = to_b64[ (data[0] << 4) & 0x30];
+ buf[2] = '=';
+ buf[3] = '=';
+ buf += 4;
+ chars += 4;
+ break;
+ }
+
+ *buf = '\0';
+ }
+
+return string;
+}
+
+/*
+ * Base 64 decoding algorithm from: Bob Deblier <[EMAIL PROTECTED]>
+ * Modified by Daniel Savard <[EMAIL PROTECTED]> to return char *
+ */
+char* b64dec(const char* string)
+{
+ /* return a decoded char string, or a null pointer in case of failure */
+ char* data = NULL;
+
+ if (string) {
+ register int length = strlen(string);
+
+ /* do a format verification first */
+ if (length > 0) {
+ register int count = 0, rem = 0;
+ register const char* tmp = string;
+
+ while (length > 0) {
+ register int skip = strspn(tmp, to_b64);
+ count += skip;
+ length -= skip;
+ tmp += skip;
+ if (length > 0) {
+ register int i, vrfy = strcspn(tmp, to_b64);
+
+ for (i = 0; i < vrfy; i++) {
+ if (isspace(tmp[i]))
+ continue;
+
+ if (tmp[i] == '=') {
+ /* we should check if we're close to the end of the string */
+ rem = count % 4;
+
+ /* rem must be either 2 or 3, otherwise no '=' should be here */
+ if (rem < 2)
+ return NULL;
+
+ /* end-of-message recognized */
+ break;
+ } else {
+ /* Transmission error; RFC tells us to ignore this, but:
+ * - the rest of the message is going to even more corrupt since we're sliding bits out of place
+ * If a message is corrupt, it should be dropped. Period.
+ */
+ return NULL;
+ }
+ }
+
+ length -= vrfy;
+ tmp += vrfy;
+ }
+ }
+
+ data = (unsigned char *)malloc((count / 4) * 3 + (rem ? (rem - 1) : 0));
+
+ if (data) {
+ if (count > 0) {
+ register int i, qw = 0, tw = 0;
+
+ length = strlen(tmp = string);
+
+ for (i = 0; i < length; i++) {
+ register char ch = string[i];
+ register char bits = 0;
+
+ if (isspace(ch))
+ continue;
+
+ if ((ch >= 'A') && (ch <= 'Z')) {
+ bits = (ch - 'A');
+ } else if ((ch >= 'a') && (ch <= 'z')) {
+ bits = (ch - 'a' + 26);
+ } else if ((ch >= '0') && (ch <= '9')) {
+ bits = (ch - '0' + 52);
+ } else if (ch == '=') {
+ break;
+ }
+
+ switch (qw++) {
+ case 0:
+ data[tw+0] = (bits << 2) & 0xfc;
+ break;
+ case 1:
+ data[tw+0] |= (bits >> 4) & 0x03;
+ data[tw+1] = (bits << 4) & 0xf0;
+ break;
+ case 2:
+ data[tw+1] |= (bits >> 2) & 0x0f;
+ data[tw+2] = (bits << 6) & 0xc0;
+ break;
+ case 3:
+ data[tw+2] |= bits & 0x3f;
+ break;
+ }
+
+ if (qw == 4) {
+ qw = 0;
+ tw += 3;
+ }
+ }
+
+ data[tw] = '\0';
+ }
+ }
+ }
+ }
+
+return data;
+}
+
+/*
+ * Original https proxy algorithm from: Tan Swee Heng <[EMAIL PROTECTED]>
+ * Modified by Daniel Savard <[EMAIL PROTECTED]> to support basic authentication
+ */
+ int connect_to_finaldest(CLI *c, int s) {
+ char buff[STRLEN];
+ int len, code,position,num;
+ char httpsproxy_auth[STRLEN] = "";
+ char httpsproxy_useragent[STRLEN] = "";
+
+ if (!c->opt->option.httpsproxy)
+ return 0;
+
+ if (c->opt->httpsproxy_auth != NULL) {
+ if (strchr(c->opt->httpsproxy_auth,':')) {
+ /* httpsproxy_auth in the form name:password' */
+ char *base64_auth = b64enc(c->opt->httpsproxy_auth);
+ s_log(LOG_DEBUG,"proxy: authenticate with '%s' -> '%s'\n",c->opt->httpsproxy_auth,base64_auth);
+ sprintf(httpsproxy_auth,"Proxy-Authorization: Basic %s\r\n",base64_auth);
+ free(base64_auth);
+ } else {
+ /* httpsproxy_auth already base64 encoded */
+ char *normal_auth = b64dec(c->opt->httpsproxy_auth);
+ s_log(LOG_DEBUG,"proxy: authenticate with '%s' -> '%s'\n",normal_auth,c->opt->httpsproxy_auth);
+ sprintf(httpsproxy_auth,"Proxy-Authorization: Basic %s\r\n",c->opt->httpsproxy_auth);
+ free(normal_auth);
+ }
+ } else {
+ s_log(LOG_DEBUG,"proxy: no authentication specified");
+ }
+
+ if (c->opt->httpsproxy_useragent != NULL) {
+ sprintf(httpsproxy_useragent,"User-Agent: %s\r\n",c->opt->httpsproxy_useragent);
+ s_log(LOG_DEBUG,"proxy: useragent '%s' -> '%s'\n",c->opt->httpsproxy_useragent,httpsproxy_useragent);
+ } else {
+ s_log(LOG_DEBUG,"proxy: no useragent specified");
+ }
+
+#ifdef HAVE_SNPRINTF
+ len=snprintf(buff, STRLEN,
+#else
+ len=sprintf(buff,
+#endif
+ "CONNECT %s HTTP/1.0\r\n%s%s\r\n",
+ c->opt->httpsproxy_dest_address,
+ httpsproxy_auth,
+ httpsproxy_useragent);
+
+
+ s_log(LOG_DEBUG, "me ---> proxy: %s", buff);
+ for(position=0;position<len;) {
+ switch(num=writesocket(s, buff+position, len-position)) {
+ case -1: /* error */
+ switch(get_last_socket_error()) {
+ case EINTR:
+ s_log(LOG_DEBUG,
+ "writesocket of proxy connect interrupted by a signal: retrying");
+ break;
+ case EWOULDBLOCK:
+ s_log(LOG_NOTICE, "writesocket would block: retrying");
+ break;
+ default:
+ sockerror("writesocket (httpsproxy)");
+ closesocket(s);
+ return -1;
+ }
+ break;
+ case 0:
+ s_log(LOG_DEBUG, "No data written to the proxy socket: retrying");
+ break;
+ default:
+ position+=num;
+ }
+ }
+ s_log(LOG_DEBUG, "done sending\n");
+
+
+ if(connect_wait(s, c->opt->timeout_busy)) {
+ s_log(LOG_ERR,"timeout while wainting for reply to command '%s'\n",
+ buff);
+ return -1;
+ }
+
+
+ /* get a line */
+ for(position=0; (position == 0) || (buff[position-1] != '\n');) {
+ switch(num=readsocket(s, buff+position, STRLEN-1-position)) {
+ case -1:
+ switch(get_last_socket_error()) {
+ case EINTR:
+ s_log(LOG_DEBUG,
+ "readsocket for proxy interrupted by a signal: retrying");
+ break;
+ case EWOULDBLOCK:
+ buff[position+num]='\0';
+ s_log(LOG_NOTICE, "readsocket for proxy would block: retrying, got: '%s'",buff);
+ break;
+ default:
+ sockerror("readsocket for proxy");
+ closesocket(s);
+ return -1;
+ }
+ break;
+ case 0: /* close */
+ s_log(LOG_DEBUG, "Socket closed on read for proxy");
+ break;
+ default:
+ position+=num;
+ }
+ }
+
+ buff[position]='\0';
+ s_log(LOG_DEBUG, "proxy ---> me: %s", buff);
+
+ code = 0;
+ if(sscanf(buff, "HTTP/%*s %d %*s", &code) != 1) {
+ s_log(LOG_ERR, "error: %s", buff);
+ return -1;
+ }
+
+ if(code != 200) {
+ s_log(LOG_WARNING, "return code not 200: %s", buff);
+ return -1;
+ }
+
+ return 0;
+}
+
/* End of client.c */
diff -ubdNr stunnel4-4.070-original/src/options.c stunnel4-4.070-patched/src/options.c
--- stunnel4-4.070-original/src/options.c 2004-12-31 09:53:40.000000000 +0100
+++ stunnel4-4.070-patched/src/options.c 2005-01-18 11:15:18.000000000 +0100
@@ -788,6 +788,84 @@
}
#endif
+ /* Daniel Savard <[EMAIL PROTECTED]>
+ * httpsproxy_auth
+ * Optional parameter to httpsproxy_dest to specify authentication
+ * credential to the https proxy. Value must be in form name:password
+ * or the base64 encoded value of the preceding form.
+ */
+ switch(cmd) {
+ case CMD_INIT:
+ section->httpsproxy_auth=NULL;
+ break;
+ case CMD_EXEC:
+ if(strcasecmp(opt, "httpsproxy_auth"))
+ break;
+ section->httpsproxy_auth=stralloc(arg);
+ return NULL; /* OK */
+ case CMD_DEFAULT:
+ break;
+ case CMD_HELP:
+ log_raw("%-15s = authentication for 'httpsproxy' must be userid:password",
+ "httpsproxy_auth");
+ break;
+ }
+
+ /* Daniel Savard <[EMAIL PROTECTED]>
+ * httpsproxy_dest
+ * When specified, the connect parameter will specify the name of a https
+ * proxy server and this parameter will be the final destination.
+ */
+ switch(cmd) {
+ case CMD_INIT:
+ section->option.httpsproxy=0;
+ section->httpsproxy_dest_address=NULL;
+ memset(§ion->httpsproxy_dest_names, 0, sizeof(SOCKADDR_LIST));
+ section->httpsproxy_dest_names.addr[0].in.sin_family=AF_INET;
+ section->httpsproxy_dest_port=0;
+ break;
+ case CMD_EXEC:
+ if(strcasecmp(opt, "httpsproxy_dest"))
+ break;
+ section->option.httpsproxy=1;
+ section->httpsproxy_dest_address=stralloc(arg);
+
+ if(!section->option.delayed_lookup &&
+ !name2addrlist(§ion->httpsproxy_dest_names, arg, DEFAULT_LOOPBACK)) {
+ log_raw("Cannot resolve '%s' - delaying DNS lookup", arg);
+ section->option.delayed_lookup=1;
+ }
+ return NULL; /* OK */
+ case CMD_DEFAULT:
+ break;
+ case CMD_HELP:
+ log_raw("%-15s = [host:]port https proxy connect destination host:port",
+ "httpsproxy_dest");
+ break;
+ }
+
+ /* Daniel Savard <[EMAIL PROTECTED]>
+ * httpsproxy_useragent
+ * Optional parameter to httpsproxy_dest. When specified, the specified
+ * user-agent will be sent to the proxy
+ */
+ switch(cmd) {
+ case CMD_INIT:
+ section->httpsproxy_useragent=NULL;
+ break;
+ case CMD_EXEC:
+ if(strcasecmp(opt, "httpsproxy_useragent"))
+ break;
+ section->httpsproxy_useragent=stralloc(arg);
+ return NULL; /* OK */
+ case CMD_DEFAULT:
+ break;
+ case CMD_HELP:
+ log_raw("%-15s = useragent for 'httpsproxy'",
+ "httpsproxy_useragent");
+ break;
+ }
+
/* ident */
switch(cmd) {
case CMD_INIT:
diff -ubdNr stunnel4-4.070-original/src/prototypes.h stunnel4-4.070-patched/src/prototypes.h
--- stunnel4-4.070-original/src/prototypes.h 2005-01-02 23:43:23.000000000 +0100
+++ stunnel4-4.070-patched/src/prototypes.h 2005-01-18 11:10:13.000000000 +0100
@@ -181,10 +181,12 @@
/* service-specific data for client.c */
int fd; /* file descriptor accepting connections for this service */
char *execname, **execargs; /* program name and arguments for local mode */
- SOCKADDR_LIST local_addr, remote_addr;
+ SOCKADDR_LIST local_addr, remote_addr, httpsproxy_dest_names;
SOCKADDR_LIST source_addr;
char *username;
char *remote_address;
+ char *httpsproxy_auth, *httpsproxy_useragent, *httpsproxy_dest_address;
+ unsigned short httpsproxy_dest_port;
int timeout_busy; /* Maximum waiting for data time */
int timeout_close; /* Maximum close_notify time */
int timeout_connect; /* Maximum connect() time */
@@ -198,6 +200,43 @@
unsigned int delayed_lookup:1;
unsigned int accept:1;
unsigned int remote:1;
+ unsigned int httpsproxy:1;
#ifndef USE_WIN32
unsigned int program:1;
unsigned int pty:1;