-
-
Notifications
You must be signed in to change notification settings - Fork 905
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for authenticated proxies #1129
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
from .Custom_httplib27 import httplib | ||
import ssl | ||
|
||
from base64 import b64encode | ||
from logging import debug | ||
from threading import Semaphore | ||
from time import time | ||
|
@@ -26,7 +27,7 @@ | |
|
||
from .Config import Config | ||
from .Exceptions import ParameterError, S3SSLCertificateError | ||
from .Utils import getBucketFromHostname | ||
from .Utils import getBucketFromHostname, deunicodise_s, unicodise_s | ||
|
||
|
||
|
||
|
@@ -229,14 +230,22 @@ def __init__(self, id, hostname, ssl, cfg): | |
self.c = httplib.HTTPConnection(self.hostname, self.port) | ||
debug(u'non-proxied HTTPConnection(%s, %s)', self.hostname, self.port) | ||
else: | ||
headers = {} | ||
proxy_hostname = cfg.proxy_host | ||
if '@' in cfg.proxy_host: | ||
credential, proxy_hostname = cfg.proxy_host.split('@') | ||
# FIXME: Following line can't handle username or password including colon | ||
proxy_username, proxy_password = credential.split(':') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same a previous, split(':', 1) |
||
headers['Proxy-Authorization'] = 'Basic ' + \ | ||
unicodise_s(b64encode(deunicodise_s(('%s:%s' % (proxy_username, proxy_password))))) | ||
if ssl: | ||
self.c = http_connection._https_connection(cfg.proxy_host, cfg.proxy_port) | ||
self.c = http_connection._https_connection(proxy_hostname, cfg.proxy_port) | ||
debug(u'proxied HTTPSConnection(%s, %s)', cfg.proxy_host, cfg.proxy_port) | ||
port = self.port and self.port or 443 | ||
self.c.set_tunnel(self.hostname, port) | ||
self.c.set_tunnel(self.hostname, port, headers) | ||
debug(u'tunnel to %s, %s', self.hostname, port) | ||
else: | ||
self.c = httplib.HTTPConnection(cfg.proxy_host, cfg.proxy_port) | ||
self.c = httplib.HTTPConnection(proxy_hostname, cfg.proxy_port) | ||
debug(u'proxied HTTPConnection(%s, %s)', cfg.proxy_host, cfg.proxy_port) | ||
# No tunnel here for the moment | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,6 +68,12 @@ except ImportError: | |
# python2 fallback code | ||
from distutils.spawn import find_executable as which | ||
|
||
try: | ||
# python 3 support | ||
from urlparse import urlparse | ||
except ImportError: | ||
from urllib.parse import urlparse | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is a detail, but you can probably exchange the imports and have the python3 "from urlib.parse import urlparse" case first as it should now be the default case. |
||
|
||
|
||
def output(message): | ||
sys.stdout.write(message + "\n") | ||
|
@@ -2342,21 +2348,13 @@ def run_configure(config_file, args): | |
("gpg_passphrase", "Encryption password", "Encryption password is used to protect your files from reading\nby unauthorized persons while in transfer to S3"), | ||
("gpg_command", "Path to GPG program"), | ||
("use_https", "Use HTTPS protocol", "When using secure HTTPS protocol all communication with Amazon S3\nservers is protected from 3rd party eavesdropping. This method is\nslower than plain HTTP, and can only be proxied with Python 2.7 or newer"), | ||
("proxy_host", "HTTP Proxy server name", "On some networks all internet access must go through a HTTP proxy.\nTry setting it here if you can't connect to S3 directly"), | ||
("proxy_host", "username:[email protected]", "HTTP Proxy server name", "On some networks all internet access must go through a HTTP proxy.\nTry setting it here if you can't connect to S3 directly"), | ||
("proxy_port", "HTTP Proxy server port"), | ||
] | ||
## Option-specfic defaults | ||
if getattr(cfg, "gpg_command") == "": | ||
setattr(cfg, "gpg_command", which("gpg")) | ||
|
||
if getattr(cfg, "proxy_host") == "" and os.getenv("http_proxy"): | ||
autodetected_encoding = locale.getpreferredencoding() or "UTF-8" | ||
re_match=re.match(r"(http://)?([^:]+):(\d+)", | ||
unicodise_s(os.getenv("http_proxy"), autodetected_encoding)) | ||
if re_match: | ||
setattr(cfg, "proxy_host", re_match.groups()[1]) | ||
setattr(cfg, "proxy_port", re_match.groups()[2]) | ||
|
||
try: | ||
# Support for python3 | ||
# raw_input only exists in py2 and was renamed to input in py3 | ||
|
@@ -2372,12 +2370,16 @@ def run_configure(config_file, args): | |
for option in options: | ||
prompt = option[1] | ||
## Option-specific handling | ||
if option[0] == 'proxy_host' and getattr(cfg, 'use_https') == True and sys.hexversion < 0x02070000: | ||
setattr(cfg, option[0], "") | ||
continue | ||
if option[0] == 'proxy_port' and getattr(cfg, 'proxy_host') == "": | ||
setattr(cfg, option[0], 0) | ||
continue | ||
if option[0] == "proxy_host": | ||
autodetected_encoding = locale.getpreferredencoding() or "UTF-8" | ||
key = "https_proxy" if getattr(cfg, 'use_https') else "http_proxy" | ||
url = urlparse(unicodise_s(os.getenv(key), autodetected_encoding)) | ||
if url.port is None: | ||
port = 80 if url.scheme == "http" else 443 # httplib supports HTTP(S) proxy only | ||
else: | ||
port = url.port | ||
setattr(cfg, "proxy_host", "%s:%s@%s" % (url.username, url.password, url.hostname)) | ||
setattr(cfg, "proxy_port", port) | ||
|
||
try: | ||
val = getattr(cfg, option[0]) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is probably better to use split('@', 1) to avoid unexpected issues.