Mercurial > public > mercurial-scm > hg-stable
diff mercurial/url.py @ 8847:7951f385fcb7
url: support client certificate files over HTTPS (issue643)
This extends the httpshandler with the means to utilise the auth
section to provide it with a PEM encoded certificate key file and
certificate chain file. This works also with sites that both require
client certificate authentication and basic or digest password
authentication, although the latter situation may require the user to
enter the PEM password multiple times.
author | Henrik Stuart <hg@hstuart.dk> |
---|---|
date | Sat, 20 Jun 2009 10:58:57 +0200 |
parents | 59acb9c7d90f |
children | 89b71acdac9a |
line wrap: on
line diff
--- a/mercurial/url.py Sun Jun 07 20:31:38 2009 +0200 +++ b/mercurial/url.py Sat Jun 20 10:58:57 2009 +0200 @@ -109,7 +109,9 @@ return (user, passwd) if not user: - user, passwd = self._readauthtoken(authuri) + auth = self.readauthtoken(authuri) + if auth: + user, passwd = auth.get('username'), auth.get('password') if not user or not passwd: if not self.ui.interactive(): raise util.Abort(_('http authorization required')) @@ -132,7 +134,7 @@ msg = _('http auth: user %s, password %s\n') self.ui.debug(msg % (user, passwd and '*' * len(passwd) or 'not set')) - def _readauthtoken(self, uri): + def readauthtoken(self, uri): # Read configuration config = dict() for key, val in self.ui.configitems('auth'): @@ -143,7 +145,7 @@ # Find the best match scheme, hostpath = uri.split('://', 1) bestlen = 0 - bestauth = None, None + bestauth = None for auth in config.itervalues(): prefix = auth.get('prefix') if not prefix: continue @@ -155,7 +157,7 @@ if (prefix == '*' or hostpath.startswith(prefix)) and \ len(prefix) > bestlen and scheme in schemes: bestlen = len(prefix) - bestauth = auth.get('username'), auth.get('password') + bestauth = auth return bestauth class proxyhandler(urllib2.ProxyHandler): @@ -411,8 +413,32 @@ send = _gen_sendfile(httplib.HTTPSConnection) class httpshandler(keepalive.KeepAliveHandler, urllib2.HTTPSHandler): + def __init__(self, ui): + keepalive.KeepAliveHandler.__init__(self) + urllib2.HTTPSHandler.__init__(self) + self.ui = ui + self.pwmgr = passwordmgr(self.ui) + def https_open(self, req): - return self.do_open(httpsconnection, req) + self.auth = self.pwmgr.readauthtoken(req.get_full_url()) + return self.do_open(self._makeconnection, req) + + def _makeconnection(self, host, port=443, *args, **kwargs): + keyfile = None + certfile = None + + if args: # key_file + keyfile = args.pop(0) + if args: # cert_file + certfile = args.pop(0) + + # if the user has specified different key/cert files in + # hgrc, we prefer these + if self.auth and 'key' in self.auth and 'cert' in self.auth: + keyfile = self.auth['key'] + certfile = self.auth['cert'] + + return httpsconnection(host, port, keyfile, certfile, *args, **kwargs) # In python < 2.5 AbstractDigestAuthHandler raises a ValueError if # it doesn't know about the auth type requested. This can happen if @@ -460,7 +486,7 @@ ''' handlers = [httphandler()] if has_https: - handlers.append(httpshandler()) + handlers.append(httpshandler(ui)) handlers.append(proxyhandler(ui))