Patch from Marco d'Itri that sketches a --soften-links option.
[rsync-patches.git] / proxy-auth.diff
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;