Basic HTTP Proxy Authentication: patch update

Bardur Arantsson bardur at odense.kollegienet.dk
Wed May 14 19:24:26 EST 2003


Hi all,

My patch for supporting "Basic" HTTP Proxy Authentication
has been updated for rsync 2.5.6 by Martin Ehmsen. The
patch changes the interpretation of the RSYNC_PROXY
environment variable so that the syntax

   user:pass at proxy.foo.com:port

may be used instead of just

   proxy.foo.com:port

(the old syntax is, of course, still supported).  

The updated patch is available at:

    http://www.imada.sdu.dk/~bardur/personal/patches.html

(and i've attached the rsync-2.5.6 version). Any comments
and suggestions are welcome, but please CC them to my
email, as I am not subscribed to the rsync list.

Please note that the version in the current rsync-2.5.6
tarball does NOT apply cleanly, and it should probably be
updated by one of the maintainers. (Or this updated patch
could perhaps be applied to the trunk :-?)

Cheers,

-- 
Bardur Arantsson
<bardur at imada.sdu.dk>
<bardur at odense.kollegienet.dk>
-------------- next part --------------
diff -u rsync-2.5.6.orig/authenticate.c rsync-2.5.6/authenticate.c
--- rsync-2.5.6.orig/authenticate.c	Sun Jan 26 20:37:54 2003
+++ rsync-2.5.6/authenticate.c	Tue May 13 13:18:50 2003
@@ -24,7 +24,7 @@
 encode a buffer using base64 - simple and slow algorithm. null terminates
 the result.
   ***************************************************************************/
-static void base64_encode(char *buf, int len, char *out)
+void base64_encode(char *buf, int len, char *out)
 {
 	char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 	int bit_offset, byte_offset, idx, i;
diff -u rsync-2.5.6.orig/socket.c rsync-2.5.6/socket.c
--- rsync-2.5.6.orig/socket.c	Mon Jan 27 04:35:09 2003
+++ rsync-2.5.6/socket.c	Tue May 13 13:18:55 2003
@@ -33,17 +33,56 @@
 
 #include "rsync.h"
 
+/**
+ *declare the base64_encode function from authenticate.c
+ **/
+void base64_encode(char *buf, int len, char *out);
 
 /**
  * Establish a proxy connection on an open socket to a web proxy by
- * using the HTTP CONNECT method.
+ * using the CONNECT method. If proxy_user and proxy_pass are not NULL,
+ * they are used to authenticate to the proxy using the "Basic"
+ * proxy authorization protocol
  **/
-static int establish_proxy_connection(int fd, char *host, int port)
+static int establish_proxy_connection(int fd, char *host, int port,
+                                     char *proxy_user, char *proxy_pass)
 {
 	char buffer[1024];
+        char authbuf[1024];
+        size_t authlen;
 	char *cp;
 
-	snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
+	/* use the proxy_user and proxy_pass
+	 * variables to determine authentication string */
+	if ((proxy_user != NULL) &&
+	    (proxy_pass != NULL)) {
+		/* copy "user:pass" into buffer */
+		strlcpy(buffer, proxy_user, sizeof(buffer));
+		strlcat(buffer, ":", sizeof(buffer));
+		strlcat(buffer, proxy_pass, sizeof(buffer));
+		
+		/* how long will the base64 encoded string be? */
+		authlen = (strlen(buffer)*8 + 5)/6;
+		if (authlen>sizeof(authbuf)+1) {
+			rprintf(FERROR,
+				"authentication information too long\n");
+			return -1;
+		}
+		
+		/* encode in base64 into authbuf */
+		base64_encode(buffer, strlen(buffer), authbuf);
+		
+		/* request */
+		snprintf(buffer, sizeof(buffer), 
+			 "CONNECT %s:%d HTTP/1.0\r\n"
+			 "Proxy-Authorization: Basic %s\r\n\r\n", 
+			 host, port, authbuf);
+	} else {
+		/* request */
+		snprintf(buffer, sizeof(buffer), 
+			 "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
+	}
+
 	if (write(fd, buffer, strlen(buffer)) != (int) strlen(buffer)) {
 		rprintf(FERROR, "failed to write to proxy: %s\n",
 			strerror(errno));
@@ -168,6 +207,9 @@
 	int proxied = 0;
 	char buffer[1024];
 	char *cp;
+	char *proxy_user = NULL;
+	char *proxy_pass = NULL;
+	char *buffer_hostpart;
 
 	/* if we have a RSYNC_PROXY env variable then redirect our
 	 * connetcion via a web proxy at the given address. The format
@@ -177,7 +219,35 @@
 
 	if (proxied) {
 		strlcpy(buffer, h, sizeof(buffer));
-		cp = strchr(buffer, ':');
+
+		/* authentication information present? */
+		cp = strchr(buffer, '@');
+		if (cp != NULL) {
+			/* rest of buffer points past the '@' */ 
+			buffer_hostpart = cp+1;
+			/* null separate auth portion from host:port */
+			*cp = '\0';
+			/* find a ':' in the auth portion */
+			cp = strchr(buffer, ':');
+			if (cp == NULL) {
+				rprintf(FERROR,
+					"invalid proxy specification: should be USER:PASS at HOST:PORT\n");
+				return -1;
+			};
+
+			/* null separate USER from PASS */
+		        *cp++ = '\0';
+			
+			/* set up pointers to USER and PASS */
+			proxy_user = buffer;
+			proxy_pass = cp;
+		} else {
+			/* whole buffer is the host part */
+			buffer_hostpart = buffer;
+		}
+
+		cp = strchr(buffer_hostpart, ':');
+
 		if (cp == NULL) {
 			rprintf(FERROR,
 				"invalid proxy specification: should be HOST:PORT\n");
@@ -185,7 +255,7 @@
 		}
 		*cp++ = '\0';
 		strcpy(portbuf, cp);
-		h = buffer;
+		h = buffer_hostpart;
 		if (verbose >= 2) {
 			rprintf(FINFO, "connection via http proxy %s port %s\n",
 				h, portbuf);
@@ -229,7 +299,8 @@
 			continue;
 		}
 		if (proxied &&
-		    establish_proxy_connection(s, host, port) != 0) {
+		    establish_proxy_connection(s, host, port, 
+					       proxy_user, proxy_pass) != 0) {
 			close(s);
 			s = -1;
 			continue;


More information about the rsync mailing list