[PATCH 0 of 1] Patch to fix a small "bug" and improve support for custom auth extensions.

Sune Foldager cryo at cyanite.org
Mon Feb 9 06:52:49 CST 2009


Dirkjan wrote:

>> So why do this? Well, I have an extension (actually a patch right now) which wraps check_perms and does some
>> custom authorization. For that I need to send back 401 challenges. With this patch it's as simple as raising
>> an ErrorResponse with the correct WWW-Authenticate header :-).

> I'm curious to hear a little more about your authn/authz needs, as I'm
> thinking about abstracting hgweb's model in that department a bit.

I'll describe how our current authn/authz system works. It involves patching hgweb_mod (to hack check_perms, although it could probably just be wrapped instead) and url.py.

Authentication is done by a separate program, which obtains sends username and password to a webservice and obtains a token (a string). It writes it into a file in my homedir called .hgauth containing lines like "<hostname> = <username>:<password>", which in this case will be "<our repository host> = edlauth:<the token>", where 'edlauth' is a just a magic user name. This file is then [the Windows version of] chmod 600'ed.

url.py is patched to look for the .hgauth file if no password is given on the command line, look for a matching host, and use that username/password pair for HTTP auth. On the server, check_perms is patched/wrapped to check the token (via a local webservice), and send back 401 errors or challenges as appropriate.

I'd like to have the .hgauth patch included in some form upstream, but I don't know how people feel about it. I have included the current version of the patch below, although I am not claiming that it's suitable as a final-form or anything. Notice that I also patch url.py to include the auth information the first time around, instead of waiting for a challenge; urllib2 can't do that, so I set the header myself. It seems a waste of network time to wait for a challenge when the user provided auth information; it must be assumed that it will be needed! :-).

Comments and critique welcome :-).

-- 
Sune.




---- PATCH for url.py ------------

--- a/mercurial/url.py
+++ b/mercurial/url.py
@@ -7,7 +7,7 @@
 # This software may be used and distributed according to the terms
 # of the GNU General Public License, incorporated herein by reference.
 
-import urllib, urllib2, urlparse, httplib, os, re
+import urllib, urllib2, urlparse, httplib, os, re, base64
 from i18n import _
 import keepalive, util
 
@@ -246,6 +246,22 @@
                 return
             raise
 
+def readauthtoken(url):
+    try:
+        url = url[url.index('://')+3:]
+        lines = file(os.path.expanduser('~/.hgauth')).readlines()
+        for line in lines:
+            if not line or line[0] == '#':
+                continue
+            prefix, token = line.split('=')
+            prefix = prefix.strip()
+            if prefix == '*' or url.startswith(prefix):
+                user, passwd = token.strip().split(':')
+                return user, passwd
+        return None, None
+    except:
+        return None, None
+
 def getauthinfo(path):
     scheme, netloc, urlpath, query, frag = urlparse.urlsplit(path)
     if not urlpath:
@@ -261,6 +277,8 @@
     # urllib cannot handle URLs with embedded user or passwd
     url = urlparse.urlunsplit((scheme, netlocunsplit(host, port),
                               urlpath, query, frag))
+    if not user:
+        user, passwd = readauthtoken(url)
     if user:
         netloc = host
         if port:
@@ -296,6 +314,11 @@
     # 1.0 here is the _protocol_ version
     opener.addheaders = [('User-agent', 'mercurial/proto-1.0')]
     opener.addheaders.append(('Accept', 'application/mercurial-0.1'))
+
+    # pre-emptively send auth header to reduce roundtrips
+    if authinfo:
+        opener.addheaders.append(('Authorization', 'Basic ' +
+                                   base64.b64encode(user + ':' + passwd)))
     return opener
 
 scheme_re = re.compile(r'^([a-zA-Z0-9+-.]+)://')





More information about the Mercurial-devel mailing list