Commit | Line | Data |
---|---|---|
6d97842d MP |
1 | Hi all, |
2 | ||
3 | I have put together a patch for supporting "Basic" HTTP | |
4 | Proxy Authentication. The patch changes the interpretation | |
5 | of the RSYNC_PROXY environment variable so that the syntax | |
6 | ||
7 | user:pass@proxy.foo:port | |
8 | ||
9 | may be used instead of just | |
10 | ||
11 | proxy.foo:port | |
12 | ||
13 | (the old syntax is of course still supported). | |
14 | The patch has only been tested lightly, but it should(TM) | |
15 | work. | |
16 | ||
17 | The 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 | |
22 | and suggestions are welcome, but please CC them to my | |
23 | email, as I am not a member of the list. | |
24 | ||
25 | -- | |
26 | Bardur 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 | |
32 | diff -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; | |
44 | diff -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; |