Unmerged patch from David Bolen to add --ignore-case.
[rsync/rsync-patches.git] / proxy-auth.diff
CommitLineData
6d97842d
MP
1Hi all,
2
3I have put together a patch for supporting "Basic" HTTP
4Proxy Authentication. The patch changes the interpretation
5of the RSYNC_PROXY environment variable so that the syntax
6
7 user:pass@proxy.foo:port
8
9may be used instead of just
10
11 proxy.foo:port
12
13(the old syntax is of course still supported).
14The patch has only been tested lightly, but it should(TM)
15work.
16
17The patch (and future versions of it) is available at:
18
19 http://www.imada.sdu.dk/~bardur/personal/patches.html
20
21(and i've attached the rsync-2.5.5 version). Any comments
22and suggestions are welcome, but please CC them to my
23email, as I am not a member of the list.
24
25--
26Bardur Arantsson
27<bardur@imada.sdu.dk>
28<bardur@odense.kollegienet.dk>
29
30- "Information wants to be tied up and spanked..."
31 - Faulty Dreamer on kuro5hin.org
32diff -u rsync-2.5.5.orig/authenticate.c rsync-2.5.5/authenticate.c
33--- rsync-2.5.5.orig/authenticate.c 2002-01-24 03:33:45.000000000 +0100
34+++ rsync-2.5.5/authenticate.c 2002-04-04 12:32:58.000000000 +0200
35@@ -24,7 +24,7 @@
36 encode a buffer using base64 - simple and slow algorithm. null terminates
37 the result.
38 ***************************************************************************/
39-static void base64_encode(char *buf, int len, char *out)
40+void base64_encode(char *buf, int len, char *out)
41 {
42 char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
43 int bit_offset, byte_offset, idx, i;
44diff -u rsync-2.5.5.orig/socket.c rsync-2.5.5/socket.c
45--- rsync-2.5.5.orig/socket.c 2002-03-16 10:00:44.000000000 +0100
46+++ rsync-2.5.5/socket.c 2002-04-04 12:32:58.000000000 +0200
47@@ -33,15 +33,52 @@
48
49 #include "rsync.h"
50
51+/* declare the base64_encode function from authenticate.c */
52+void base64_encode(char *buf, int len, char *out);
53
54-/* Establish a proxy connection on an open socket to a web roxy by
55- * using the CONNECT method. */
56-static int establish_proxy_connection(int fd, char *host, int port)
57+/* Establish a proxy connection on an open socket to a web proxy by
58+ * using the CONNECT method. If proxy_user and proxy_pass are not NULL,
59+ * they are used to authenticate to the proxy using the "Basic"
60+ * proxy authorization protocol */
61+static int establish_proxy_connection(int fd, char *host, int port,
62+ char *proxy_user, char *proxy_pass)
63 {
64 char buffer[1024];
65+ char authbuf[1024];
66+ size_t authlen;
67 char *cp;
68
69- snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
70+ /* use the proxy_user and proxy_pass
71+ * variables to determine authentication string */
72+ if ((proxy_user != NULL) &&
73+ (proxy_pass != NULL)) {
74+ /* copy "user:pass" into buffer */
75+ strlcpy(buffer, proxy_user, sizeof(buffer));
76+ strlcat(buffer, ":", sizeof(buffer));
77+ strlcat(buffer, proxy_pass, sizeof(buffer));
78+
79+ /* how long will the base64 encoded string be? */
80+ authlen = (strlen(buffer)*8 + 5)/6;
81+ if (authlen>sizeof(authbuf)+1) {
82+ rprintf(FERROR,
83+ "authentication information too long\n");
84+ return -1;
85+ }
86+
87+ /* encode in base64 into authbuf */
88+ base64_encode(buffer, strlen(buffer), authbuf);
89+
90+ /* request */
91+ snprintf(buffer, sizeof(buffer),
92+ "CONNECT %s:%d HTTP/1.0\r\n"
93+ "Proxy-Authorization: Basic %s\r\n\r\n",
94+ host, port, authbuf);
95+ } else {
96+ /* request */
97+ snprintf(buffer, sizeof(buffer),
98+ "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
99+ }
100+
101 if (write(fd, buffer, strlen(buffer)) != (int) strlen(buffer)) {
102 rprintf(FERROR, "failed to write to proxy: %s\n",
103 strerror(errno));
104@@ -166,6 +203,9 @@
105 int proxied = 0;
106 char buffer[1024];
107 char *cp;
108+ char *proxy_user = NULL;
109+ char *proxy_pass = NULL;
110+ char *buffer_hostpart;
111
112 /* if we have a RSYNC_PROXY env variable then redirect our
113 * connetcion via a web proxy at the given address. The format
114@@ -175,7 +215,34 @@
115
116 if (proxied) {
117 strlcpy(buffer, h, sizeof(buffer));
118- cp = strchr(buffer, ':');
119+
120+ /* authentication information present? */
121+ cp = strchr(buffer, '@');
122+ if (cp != NULL) {
123+ /* rest of buffer points past the '@' */
124+ buffer_hostpart = cp+1;
125+ /* null separate auth portion from host:port */
126+ *cp = '\0';
127+ /* find a ':' in the auth portion */
128+ cp = strchr(buffer, ':');
129+ if (cp == NULL) {
130+ rprintf(FERROR,
131+ "invalid proxy specification: should be USER:PASS@HOST:PORT\n");
132+ return -1;
133+ };
134+
135+ /* null separate USER from PASS */
136+ *cp++ = '\0';
137+
138+ /* set up pointers to USER and PASS */
139+ proxy_user = buffer;
140+ proxy_pass = cp;
141+ } else {
142+ /* whole buffer is the host part */
143+ buffer_hostpart = buffer;
144+ }
145+
146+ cp = strchr(buffer_hostpart, ':');
147 if (cp == NULL) {
148 rprintf(FERROR,
149 "invalid proxy specification: should be HOST:PORT\n");
150@@ -183,7 +250,7 @@
151 }
152 *cp++ = '\0';
153 strcpy(portbuf, cp);
154- h = buffer;
155+ h = buffer_hostpart;
156 if (verbose >= 2) {
157 rprintf(FINFO, "connection via http proxy %s port %s\n",
158 h, portbuf);
159@@ -227,7 +294,8 @@
160 continue;
161 }
162 if (proxied &&
163- establish_proxy_connection(s, host, port) != 0) {
164+ establish_proxy_connection(s, host, port,
165+ proxy_user, proxy_pass) != 0) {
166 close(s);
167 s = -1;
168 continue;