| | @@ -173,10 +173,57 @@ |
| 173 | 173 | if( iBio!=NULL ){ |
| 174 | 174 | (void)BIO_reset(iBio); |
| 175 | 175 | BIO_free_all(iBio); |
| 176 | 176 | } |
| 177 | 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 | +} |
| 178 | 225 | |
| 179 | 226 | /* |
| 180 | 227 | ** Open an SSL connection. The identify of the server is determined |
| 181 | 228 | ** by global variables that are set using url_parse(): |
| 182 | 229 | ** |
| | @@ -201,40 +248,67 @@ |
| 201 | 248 | X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), cert); |
| 202 | 249 | X509_free(cert); |
| 203 | 250 | hasSavedCertificate = 1; |
| 204 | 251 | } |
| 205 | 252 | |
| 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 | + } |
| 207 | 283 | BIO_get_ssl(iBio, &ssl); |
| 208 | 284 | |
| 209 | 285 | #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) ){ |
| 211 | 287 | fossil_warning("WARNING: failed to set server name indication (SNI), " |
| 212 | 288 | "continuing without it.\n"); |
| 213 | 289 | } |
| 214 | 290 | #endif |
| 215 | 291 | |
| 216 | 292 | 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 | + } |
| 231 | 303 | } |
| 232 | 304 | |
| 233 | 305 | if( BIO_do_handshake(iBio)<=0 ) { |
| 234 | 306 | 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())); |
| 236 | 310 | ssl_close(); |
| 237 | 311 | return 1; |
| 238 | 312 | } |
| 239 | 313 | /* Check if certificate is valid */ |
| 240 | 314 | cert = SSL_get_peer_certificate(ssl); |
| 241 | 315 | |