Fossil SCM

Support for tunneling https through http proxy.

jan 2013-10-07 13:27 trunk
Commit c039efde8375b1c3c76b922ec03d37e02d362aba
+91 -17
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -173,10 +173,57 @@
173173
if( iBio!=NULL ){
174174
(void)BIO_reset(iBio);
175175
BIO_free_all(iBio);
176176
}
177177
}
178
+
179
+static int establish_proxy_tunnel(BIO *bio){
180
+ int rc, httpVerMin;
181
+ char *connStr, *bbuf;
182
+ Blob reply;
183
+ int done=0,end=0;
184
+ if( !g.urlProxyAuth ){
185
+ connStr = mprintf("CONNECT %s:%d HTTP/1.1\r\n"
186
+ "Host: %s:%d\r\n\r\n", g.urlHostname, g.proxyOrigPort,
187
+ g.urlHostname, g.proxyOrigPort);
188
+ }else{
189
+ connStr = mprintf("CONNECT %s:%d HTTP/1.1\r\n"
190
+ "Host: %s:%d\r\n"
191
+ "Proxy-Authorization: %s\r\n\r\n", g.urlHostname, g.proxyOrigPort,
192
+ g.urlHostname, g.proxyOrigPort, g.urlProxyAuth);
193
+ }
194
+ BIO_write(bio, connStr, strlen(connStr));
195
+ free(connStr);
196
+
197
+ /* Wait for end of reply */
198
+ blob_zero(&reply);
199
+ do{
200
+ int len;
201
+ char buf[256];
202
+ len = BIO_read(bio, buf, sizeof(buf));
203
+ blob_append(&reply, buf, len);
204
+
205
+ bbuf = blob_buffer(&reply);
206
+ len = blob_size(&reply);
207
+ while(end < len) {
208
+ if(bbuf[end] == '\r') {
209
+ if(len - end < 4) {
210
+ /* need more data */
211
+ break;
212
+ }
213
+ if(memcmp(&bbuf[end], "\r\n\r\n", 4) == 0) {
214
+ done = 1;
215
+ break;
216
+ }
217
+ }
218
+ end++;
219
+ }
220
+ }while(!done);
221
+ sscanf(bbuf, "HTTP/1.%d %d", &httpVerMin, &rc);
222
+ blob_reset(&reply);
223
+ return rc;
224
+}
178225
179226
/*
180227
** Open an SSL connection. The identify of the server is determined
181228
** by global variables that are set using url_parse():
182229
**
@@ -201,40 +248,67 @@
201248
X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), cert);
202249
X509_free(cert);
203250
hasSavedCertificate = 1;
204251
}
205252
206
- iBio = BIO_new_ssl_connect(sslCtx);
253
+ if( g.useProxy ){
254
+ int rc;
255
+ BIO *sBio;
256
+ char *connStr;
257
+ connStr = mprintf("%s:%d", g.urlName, g.urlPort);
258
+ sBio = BIO_new_connect(connStr);
259
+ free(connStr);
260
+ if( BIO_do_connect(sBio)<=0 ){
261
+ ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)",
262
+ g.urlName, g.urlPort, ERR_reason_error_string(ERR_get_error()));
263
+ ssl_close();
264
+ return 1;
265
+ }
266
+ rc = establish_proxy_tunnel(sBio);
267
+ if( rc!= 200 ){
268
+ return 1;
269
+ }
270
+
271
+ g.urlPath = g.proxyUrlPath;
272
+
273
+ iBio = BIO_new_ssl(sslCtx, 1);
274
+ BIO_push(iBio, sBio);
275
+ }else{
276
+ iBio = BIO_new_ssl_connect(sslCtx);
277
+ }
278
+ if( iBio==NULL ) {
279
+ ssl_set_errmsg("SSL: cannot open SSL (%s)",
280
+ ERR_reason_error_string(ERR_get_error()));
281
+ return 1;
282
+ }
207283
BIO_get_ssl(iBio, &ssl);
208284
209285
#if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
210
- if( !SSL_set_tlsext_host_name(ssl, g.urlName) ){
286
+ if( !SSL_set_tlsext_host_name(ssl, g.urlHostname) ){
211287
fossil_warning("WARNING: failed to set server name indication (SNI), "
212288
"continuing without it.\n");
213289
}
214290
#endif
215291
216292
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
217
- if( iBio==NULL ) {
218
- ssl_set_errmsg("SSL: cannot open SSL (%s)",
219
- ERR_reason_error_string(ERR_get_error()));
220
- return 1;
221
- }
222
-
223
- BIO_set_conn_hostname(iBio, g.urlName);
224
- BIO_set_conn_int_port(iBio, &g.urlPort);
225
-
226
- if( BIO_do_connect(iBio)<=0 ){
227
- ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
228
- g.urlName, g.urlPort, ERR_reason_error_string(ERR_get_error()));
229
- ssl_close();
230
- return 1;
293
+
294
+ if( !g.useProxy ){
295
+ BIO_set_conn_hostname(iBio, g.urlName);
296
+ BIO_set_conn_int_port(iBio, &g.urlPort);
297
+ if( BIO_do_connect(iBio)<=0 ){
298
+ ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
299
+ g.urlName, g.urlPort, ERR_reason_error_string(ERR_get_error()));
300
+ ssl_close();
301
+ return 1;
302
+ }
231303
}
232304
233305
if( BIO_do_handshake(iBio)<=0 ) {
234306
ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
235
- g.urlName, g.urlPort, ERR_reason_error_string(ERR_get_error()));
307
+ g.useProxy?g.urlHostname:g.urlName,
308
+ g.useProxy?g.proxyOrigPort:g.urlPort,
309
+ ERR_reason_error_string(ERR_get_error()));
236310
ssl_close();
237311
return 1;
238312
}
239313
/* Check if certificate is valid */
240314
cert = SSL_get_peer_certificate(ssl);
241315
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -173,10 +173,57 @@
173 if( iBio!=NULL ){
174 (void)BIO_reset(iBio);
175 BIO_free_all(iBio);
176 }
177 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
179 /*
180 ** Open an SSL connection. The identify of the server is determined
181 ** by global variables that are set using url_parse():
182 **
@@ -201,40 +248,67 @@
201 X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), cert);
202 X509_free(cert);
203 hasSavedCertificate = 1;
204 }
205
206 iBio = BIO_new_ssl_connect(sslCtx);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207 BIO_get_ssl(iBio, &ssl);
208
209 #if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
210 if( !SSL_set_tlsext_host_name(ssl, g.urlName) ){
211 fossil_warning("WARNING: failed to set server name indication (SNI), "
212 "continuing without it.\n");
213 }
214 #endif
215
216 SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
217 if( iBio==NULL ) {
218 ssl_set_errmsg("SSL: cannot open SSL (%s)",
219 ERR_reason_error_string(ERR_get_error()));
220 return 1;
221 }
222
223 BIO_set_conn_hostname(iBio, g.urlName);
224 BIO_set_conn_int_port(iBio, &g.urlPort);
225
226 if( BIO_do_connect(iBio)<=0 ){
227 ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
228 g.urlName, g.urlPort, ERR_reason_error_string(ERR_get_error()));
229 ssl_close();
230 return 1;
231 }
232
233 if( BIO_do_handshake(iBio)<=0 ) {
234 ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
235 g.urlName, g.urlPort, ERR_reason_error_string(ERR_get_error()));
 
 
236 ssl_close();
237 return 1;
238 }
239 /* Check if certificate is valid */
240 cert = SSL_get_peer_certificate(ssl);
241
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -173,10 +173,57 @@
173 if( iBio!=NULL ){
174 (void)BIO_reset(iBio);
175 BIO_free_all(iBio);
176 }
177 }
178
179 static int establish_proxy_tunnel(BIO *bio){
180 int rc, httpVerMin;
181 char *connStr, *bbuf;
182 Blob reply;
183 int done=0,end=0;
184 if( !g.urlProxyAuth ){
185 connStr = mprintf("CONNECT %s:%d HTTP/1.1\r\n"
186 "Host: %s:%d\r\n\r\n", g.urlHostname, g.proxyOrigPort,
187 g.urlHostname, g.proxyOrigPort);
188 }else{
189 connStr = mprintf("CONNECT %s:%d HTTP/1.1\r\n"
190 "Host: %s:%d\r\n"
191 "Proxy-Authorization: %s\r\n\r\n", g.urlHostname, g.proxyOrigPort,
192 g.urlHostname, g.proxyOrigPort, g.urlProxyAuth);
193 }
194 BIO_write(bio, connStr, strlen(connStr));
195 free(connStr);
196
197 /* Wait for end of reply */
198 blob_zero(&reply);
199 do{
200 int len;
201 char buf[256];
202 len = BIO_read(bio, buf, sizeof(buf));
203 blob_append(&reply, buf, len);
204
205 bbuf = blob_buffer(&reply);
206 len = blob_size(&reply);
207 while(end < len) {
208 if(bbuf[end] == '\r') {
209 if(len - end < 4) {
210 /* need more data */
211 break;
212 }
213 if(memcmp(&bbuf[end], "\r\n\r\n", 4) == 0) {
214 done = 1;
215 break;
216 }
217 }
218 end++;
219 }
220 }while(!done);
221 sscanf(bbuf, "HTTP/1.%d %d", &httpVerMin, &rc);
222 blob_reset(&reply);
223 return rc;
224 }
225
226 /*
227 ** Open an SSL connection. The identify of the server is determined
228 ** by global variables that are set using url_parse():
229 **
@@ -201,40 +248,67 @@
248 X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), cert);
249 X509_free(cert);
250 hasSavedCertificate = 1;
251 }
252
253 if( g.useProxy ){
254 int rc;
255 BIO *sBio;
256 char *connStr;
257 connStr = mprintf("%s:%d", g.urlName, g.urlPort);
258 sBio = BIO_new_connect(connStr);
259 free(connStr);
260 if( BIO_do_connect(sBio)<=0 ){
261 ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)",
262 g.urlName, g.urlPort, ERR_reason_error_string(ERR_get_error()));
263 ssl_close();
264 return 1;
265 }
266 rc = establish_proxy_tunnel(sBio);
267 if( rc!= 200 ){
268 return 1;
269 }
270
271 g.urlPath = g.proxyUrlPath;
272
273 iBio = BIO_new_ssl(sslCtx, 1);
274 BIO_push(iBio, sBio);
275 }else{
276 iBio = BIO_new_ssl_connect(sslCtx);
277 }
278 if( iBio==NULL ) {
279 ssl_set_errmsg("SSL: cannot open SSL (%s)",
280 ERR_reason_error_string(ERR_get_error()));
281 return 1;
282 }
283 BIO_get_ssl(iBio, &ssl);
284
285 #if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
286 if( !SSL_set_tlsext_host_name(ssl, g.urlHostname) ){
287 fossil_warning("WARNING: failed to set server name indication (SNI), "
288 "continuing without it.\n");
289 }
290 #endif
291
292 SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
293
294 if( !g.useProxy ){
295 BIO_set_conn_hostname(iBio, g.urlName);
296 BIO_set_conn_int_port(iBio, &g.urlPort);
297 if( BIO_do_connect(iBio)<=0 ){
298 ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
299 g.urlName, g.urlPort, ERR_reason_error_string(ERR_get_error()));
300 ssl_close();
301 return 1;
302 }
 
 
 
 
303 }
304
305 if( BIO_do_handshake(iBio)<=0 ) {
306 ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
307 g.useProxy?g.urlHostname:g.urlName,
308 g.useProxy?g.proxyOrigPort:g.urlPort,
309 ERR_reason_error_string(ERR_get_error()));
310 ssl_close();
311 return 1;
312 }
313 /* Check if certificate is valid */
314 cert = SSL_get_peer_certificate(ssl);
315
+3
--- src/main.c
+++ src/main.c
@@ -177,10 +177,13 @@
177177
int urlDfltPort; /* The default port for the given protocol */
178178
char *urlPath; /* Pathname for http: */
179179
char *urlUser; /* User id for http: */
180180
char *urlPasswd; /* Password for http: */
181181
char *urlCanonical; /* Canonical representation of the URL */
182
+ int useProxy; /* Used to remember that a proxy is in use */
183
+ char *proxyUrlPath;
184
+ int proxyOrigPort; /* Tunneled port number for https through proxy */
182185
char *urlProxyAuth; /* Proxy-Authorizer: string */
183186
char *urlFossil; /* The fossil query parameter on ssh: */
184187
char *urlShell; /* The shell query parameter on ssh: */
185188
unsigned urlFlags; /* Boolean flags controlling URL processing */
186189
187190
--- src/main.c
+++ src/main.c
@@ -177,10 +177,13 @@
177 int urlDfltPort; /* The default port for the given protocol */
178 char *urlPath; /* Pathname for http: */
179 char *urlUser; /* User id for http: */
180 char *urlPasswd; /* Password for http: */
181 char *urlCanonical; /* Canonical representation of the URL */
 
 
 
182 char *urlProxyAuth; /* Proxy-Authorizer: string */
183 char *urlFossil; /* The fossil query parameter on ssh: */
184 char *urlShell; /* The shell query parameter on ssh: */
185 unsigned urlFlags; /* Boolean flags controlling URL processing */
186
187
--- src/main.c
+++ src/main.c
@@ -177,10 +177,13 @@
177 int urlDfltPort; /* The default port for the given protocol */
178 char *urlPath; /* Pathname for http: */
179 char *urlUser; /* User id for http: */
180 char *urlPasswd; /* Password for http: */
181 char *urlCanonical; /* Canonical representation of the URL */
182 int useProxy; /* Used to remember that a proxy is in use */
183 char *proxyUrlPath;
184 int proxyOrigPort; /* Tunneled port number for https through proxy */
185 char *urlProxyAuth; /* Proxy-Authorizer: string */
186 char *urlFossil; /* The fossil query parameter on ssh: */
187 char *urlShell; /* The shell query parameter on ssh: */
188 unsigned urlFlags; /* Boolean flags controlling URL processing */
189
190
+8
--- src/url.c
+++ src/url.c
@@ -90,10 +90,11 @@
9090
char *zLogin;
9191
char *zExe;
9292
char cQuerySep = '?';
9393
9494
g.urlIsFile = 0;
95
+ g.useProxy = 0;
9596
if( zUrl[4]=='s' ){
9697
g.urlIsHttps = 1;
9798
g.urlProtocol = "https";
9899
g.urlDfltPort = 443;
99100
iStart = 8;
@@ -328,13 +329,16 @@
328329
}
329330
}
330331
if( zProxy && zProxy[0] && !is_false(zProxy)
331332
&& !g.urlIsSsh && !g.urlIsFile ){
332333
char *zOriginalUrl = g.urlCanonical;
334
+ int fOriginalIsHttps = g.urlIsHttps;
333335
char *zOriginalHost = g.urlHostname;
334336
char *zOriginalUser = g.urlUser;
335337
char *zOriginalPasswd = g.urlPasswd;
338
+ char *zOriginalUrlPath = g.urlPath;
339
+ int iOriginalPort = g.urlPort;
336340
unsigned uOriginalFlags = g.urlFlags;
337341
g.urlUser = 0;
338342
g.urlPasswd = "";
339343
url_parse(zProxy, 0);
340344
if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
@@ -346,10 +350,14 @@
346350
g.urlProxyAuth = mprintf("Basic %z", zCredentials2);
347351
free(zCredentials1);
348352
}
349353
g.urlUser = zOriginalUser;
350354
g.urlPasswd = zOriginalPasswd;
355
+ g.urlIsHttps = fOriginalIsHttps;
356
+ g.useProxy = 1;
357
+ g.proxyUrlPath = zOriginalUrlPath;
358
+ g.proxyOrigPort = iOriginalPort;
351359
g.urlFlags = uOriginalFlags;
352360
}
353361
}
354362
355363
#if INTERFACE
356364
--- src/url.c
+++ src/url.c
@@ -90,10 +90,11 @@
90 char *zLogin;
91 char *zExe;
92 char cQuerySep = '?';
93
94 g.urlIsFile = 0;
 
95 if( zUrl[4]=='s' ){
96 g.urlIsHttps = 1;
97 g.urlProtocol = "https";
98 g.urlDfltPort = 443;
99 iStart = 8;
@@ -328,13 +329,16 @@
328 }
329 }
330 if( zProxy && zProxy[0] && !is_false(zProxy)
331 && !g.urlIsSsh && !g.urlIsFile ){
332 char *zOriginalUrl = g.urlCanonical;
 
333 char *zOriginalHost = g.urlHostname;
334 char *zOriginalUser = g.urlUser;
335 char *zOriginalPasswd = g.urlPasswd;
 
 
336 unsigned uOriginalFlags = g.urlFlags;
337 g.urlUser = 0;
338 g.urlPasswd = "";
339 url_parse(zProxy, 0);
340 if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
@@ -346,10 +350,14 @@
346 g.urlProxyAuth = mprintf("Basic %z", zCredentials2);
347 free(zCredentials1);
348 }
349 g.urlUser = zOriginalUser;
350 g.urlPasswd = zOriginalPasswd;
 
 
 
 
351 g.urlFlags = uOriginalFlags;
352 }
353 }
354
355 #if INTERFACE
356
--- src/url.c
+++ src/url.c
@@ -90,10 +90,11 @@
90 char *zLogin;
91 char *zExe;
92 char cQuerySep = '?';
93
94 g.urlIsFile = 0;
95 g.useProxy = 0;
96 if( zUrl[4]=='s' ){
97 g.urlIsHttps = 1;
98 g.urlProtocol = "https";
99 g.urlDfltPort = 443;
100 iStart = 8;
@@ -328,13 +329,16 @@
329 }
330 }
331 if( zProxy && zProxy[0] && !is_false(zProxy)
332 && !g.urlIsSsh && !g.urlIsFile ){
333 char *zOriginalUrl = g.urlCanonical;
334 int fOriginalIsHttps = g.urlIsHttps;
335 char *zOriginalHost = g.urlHostname;
336 char *zOriginalUser = g.urlUser;
337 char *zOriginalPasswd = g.urlPasswd;
338 char *zOriginalUrlPath = g.urlPath;
339 int iOriginalPort = g.urlPort;
340 unsigned uOriginalFlags = g.urlFlags;
341 g.urlUser = 0;
342 g.urlPasswd = "";
343 url_parse(zProxy, 0);
344 if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
@@ -346,10 +350,14 @@
350 g.urlProxyAuth = mprintf("Basic %z", zCredentials2);
351 free(zCredentials1);
352 }
353 g.urlUser = zOriginalUser;
354 g.urlPasswd = zOriginalPasswd;
355 g.urlIsHttps = fOriginalIsHttps;
356 g.useProxy = 1;
357 g.proxyUrlPath = zOriginalUrlPath;
358 g.proxyOrigPort = iOriginalPort;
359 g.urlFlags = uOriginalFlags;
360 }
361 }
362
363 #if INTERFACE
364

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button