--- a/.hgtags Fri Dec 18 13:25:45 2009 +0000
+++ b/.hgtags Sat Dec 19 19:21:41 2009 +0000
@@ -6,4 +6,6 @@
1e4050abb96e72c6324b93709e56a3e135e63ce1 debian_0.8-1
d42d3f5311c55cab668d6962a61d44ba98645e release_0.9
b6887a9b8792bb2b69b428448102140fce121e29 debian_0.9-1
+8ce190faa5c2b50f63cc5b11e28daf98836498d8 release_1.0
60c2d676a754e02f1f7656a4b137399438b2ed35 debian_1.0-1
+92cb6640a6417edaf52870c8a97000e11bb8b138 release_1.0.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CREDITS Sat Dec 19 19:21:41 2009 +0000
@@ -0,0 +1,22 @@
+mercurial-server is by Paul Crowley <paul@lshift.net>
+
+Thanks to:
+
+Thomas Arendsen Hein <thomas@intevation.de>
+Mathieu PASQUET <kiorky@cryptelium.net>
+Vadim Gelfer <vadim.gelfer@gmail.com>
+Hubert Plociniczak <hubert@lshift.net>
+Christoph Junghans <kleiner_otti@gmx.de>
+Steve Kemp <steve@steve.org.uk>
+Cédric Boutillier <cedric.boutillier@gmail.com>
+Justin B Rye <jbr@edlug.org.uk>
+Wolfgang Karall <office@karall-edv.at>
+Helge Kreutzmann <debian@helgefjell.de>
+"Hideki Yamane \(Debian-JP\)" <henrich@debian.or.jp>
+Michal Simunek <michal.simunek@gmail.com>
+Martin Bagge <brother@bsnet.se>
+Vincenzo Campanella <vinz65@gmail.com>
+Ji ZhengYu <zhengyuji@gmail.com>
+
+This credits file may be incomplete - please remind me about people I
+should add!
--- a/NEWS Fri Dec 18 13:25:45 2009 +0000
+++ b/NEWS Sat Dec 19 19:21:41 2009 +0000
@@ -1,3 +1,17 @@
+======================
+mercurial-server 1.0.1
+======================
+
+* Fix HGRCPATH brokenness - potential security issue
+* Fix rule matching to properly handle the case where we don't know for sure
+* Fix error in documentation
+* Remove whitespace around paths, said to help with TortoiseHG
+* Small refactor of access.py
+* Tidy up file prologues; move credits to CREDITS
+
+Upgrading: repositories whose paths begin or end in white space will no longer
+be accessible; if they exist they must be moved to new names.
+
====================
mercurial-server 1.0
====================
--- a/doc/manual.docbook Fri Dec 18 13:25:45 2009 +0000
+++ b/doc/manual.docbook Sat Dec 19 19:21:41 2009 +0000
@@ -147,7 +147,7 @@
class='directory'>keys/users</filename>. To grant this key access, we must give mercurial-server a new access rule, so we create a file in <filename
class='directory'>hgadmin</filename> called <filename>access.conf</filename>, with the following contents:</para>
<programlisting># Give Pat access to the "widget" repository
-write repo=widget user=pat
+write repo=widget user=pat/*
</programlisting>
<para>
Pat will have read and write access to the <filename
--- a/setup.py Fri Dec 18 13:25:45 2009 +0000
+++ b/setup.py Sat Dec 19 19:21:41 2009 +0000
@@ -7,7 +7,7 @@
name="mercurial-server",
description="Centralized Mercurial repository manager",
url="http://www.lshift.net/mercurial-server.html",
- version="0.9", # FIXME: infer this
+ version="1.0.1", # FIXME: infer this
package_dir = {'': 'src'},
packages = ["mercurialserver"],
requires = ["mercurial"], # FIXME: what version?
--- a/src/hg-ssh Fri Dec 18 13:25:45 2009 +0000
+++ b/src/hg-ssh Sat Dec 19 19:21:41 2009 +0000
@@ -1,14 +1,4 @@
#!/usr/bin/env python
-#
-# Copyright 2008-2009 LShift Ltd
-# Copyright 2005-2007 by Intevation GmbH <intevation@intevation.de>
-# Authors:
-# Paul Crowley <paul@lshift.net>
-# Thomas Arendsen Hein <thomas@intevation.de>
-# with ideas from Mathieu PASQUET <kiorky@cryptelium.net>
-#
-# This software may be used and distributed according to the terms
-# of the GNU General Public License, incorporated herein by reference.
"""
hg-ssh - limit access to hg repositories reached via ssh. Part of
@@ -55,7 +45,7 @@
def getrepo(op, repo):
# First canonicalise, then check the string, then the rules
# and finally the filesystem.
- repo = repo.rstrip("/")
+ repo = repo.strip().rstrip("/")
if len(repo) == 0:
fail("path to repository seems to be empty")
if repo.startswith("/"):
@@ -69,6 +59,9 @@
config.initExe()
+for k,v in config.getEnv():
+ os.environ[k.upper()] = v
+
if len(sys.argv) == 3 and sys.argv[1] == "--base64":
ruleset.rules.set(user = base64.b64decode(sys.argv[2]))
elif len(sys.argv) == 2:
@@ -77,9 +70,6 @@
fail("hg-ssh wrongly called, is authorized_keys corrupt? (%s)"
% sys.argv)
-for k,v in config.getEnv():
- os.environ[k] = v
-
os.chdir(config.getReposPath())
for f in config.getAccessPaths():
--- a/src/mercurialserver/access.py Fri Dec 18 13:25:45 2009 +0000
+++ b/src/mercurialserver/access.py Sat Dec 19 19:21:41 2009 +0000
@@ -1,12 +1,4 @@
-# Copyright 2008-2009 LShift Ltd
-# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
-#
-# Authors:
-# Paul Crowley <paul@lshift.net>
-# Vadim Gelfer <vadim.gelfer@gmail.com>
-#
-# This software may be used and distributed according to the terms
-# of the GNU General Public License, incorporated herein by reference.
+"""Mercurial access control hook"""
from mercurial.i18n import _
import mercurial.util
@@ -16,32 +8,21 @@
from mercurialserver import ruleset
from mercurialserver import changes
-class Checker(object):
- '''acl checker.'''
-
- def __init__(self, ui, repo):
- self.ui = ui
- self.repo = repo
-
- def allow(self, ctx):
- branch = ctx.branch()
- if not ruleset.rules.allow("write", branch=branch, file=None):
+def allow(ctx):
+ branch = ctx.branch()
+ if not ruleset.rules.allow("write", branch=branch, file=None):
+ return False
+ for f in ctx.files():
+ if not ruleset.rules.allow("write", branch=branch, file=f):
return False
- for f in ctx.files():
- if not ruleset.rules.allow("write", branch=branch, file=f):
- return False
- return True
-
- def check(self, ctx):
- '''return if access allowed, raise exception if not.'''
- if not self.allow(ctx):
- raise mercurial.util.Abort(_('%s: access denied for changeset %s') %
- (__name__, mercurial.node.short(ctx.node())))
+ return True
def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
if hooktype != 'pretxnchangegroup':
raise mercurial.util.Abort(_('config error - hook type "%s" cannot stop '
'incoming changesets') % hooktype)
- c = Checker(ui, repo)
for ctx in changes.changes(repo, node):
- c.check(ctx)
+ if not allow(ctx):
+ raise mercurial.util.Abort(_('%s: access denied for changeset %s') %
+ (__name__, mercurial.node.short(ctx.node())))
+
--- a/src/mercurialserver/changes.py Fri Dec 18 13:25:45 2009 +0000
+++ b/src/mercurialserver/changes.py Sat Dec 19 19:21:41 2009 +0000
@@ -1,12 +1,6 @@
-# Copyright 2008-2009 LShift Ltd
-# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
-#
-# Authors:
-# Paul Crowley <paul@lshift.net>
-# Vadim Gelfer <vadim.gelfer@gmail.com>
-#
-# This software may be used and distributed according to the terms
-# of the GNU General Public License, incorporated herein by reference.
+"""
+Find all the changes in a node in a way portable across Mercurial versions
+"""
def changes(repo, node):
start = repo.changectx(node).rev()
--- a/src/mercurialserver/config.py Fri Dec 18 13:25:45 2009 +0000
+++ b/src/mercurialserver/config.py Sat Dec 19 19:21:41 2009 +0000
@@ -1,4 +1,6 @@
-# Copyright 2008-2009 LShift Ltd
+"""
+Fix $HOME and read ~/.mercurial-server
+"""
import sys
import os
--- a/src/mercurialserver/refreshauth.py Fri Dec 18 13:25:45 2009 +0000
+++ b/src/mercurialserver/refreshauth.py Sat Dec 19 19:21:41 2009 +0000
@@ -1,9 +1,6 @@
-# Copyright 2008-2009 LShift Ltd
-
-# WARNING
-# This hook completely destroys your ~/.ssh/authorized_keys
-# file every time it is run
-# WARNING
+"""
+Rewrite ~/.ssh/authorized_keys by recursing through key directories
+"""
import re
import base64
--- a/src/mercurialserver/ruleset.py Fri Dec 18 13:25:45 2009 +0000
+++ b/src/mercurialserver/ruleset.py Sat Dec 19 19:21:41 2009 +0000
@@ -1,29 +1,31 @@
-# Copyright 2008-2009 LShift Ltd
-# Author(s):
-# Paul Crowley <paul@lshift.net>
-#
-# This software may be used and distributed according to the terms
-# of the GNU General Public License, incorporated herein by reference.
+"""
+Glob-based, order-based rules matcher that can answer "maybe"
+where the inputs make clear that something is unknown.
+"""
import sys
import re
import os
import os.path
-allowedchars = "A-Za-z0-9_-"
-
def globmatcher(pattern):
p = "[^/]*".join(re.escape(c) for c in pattern.split("*"))
# ** means "match recursively" ie "ignore directories"
- rex = re.compile(p.replace("[^/]*[^/]*", ".*") + "$")
- # None matches everything
- return lambda x: x is None or rex.match(x) is not None
+ return re.compile(p.replace("[^/]*[^/]*", ".*") + "$")
+# Returns True for a definite match
+# False for a definite non-match
+# None where we can't be sure because a key is None
def rule(pairs):
matchers = [(k, globmatcher(v)) for k, v in pairs]
def c(kw):
for k, m in matchers:
- if k not in kw or not m(kw[k]):
+ if k not in kw:
+ return False
+ kkw = kw[k]
+ if kkw is None:
+ return None
+ if m.match(kkw) is None:
return False
return True
return c
@@ -46,32 +48,39 @@
def get(self, k):
return self.preset.get(k, None)
- def matchrule(self, kw):
+ def matchrules(self, kw):
d = self.preset.copy()
d.update(kw)
+ res = set()
for a, c in self.rules:
- if c(d):
- return a
- return None
+ m = c(d)
+ if m is None:
+ # "Maybe match" - add it and carry on
+ res.add(a)
+ elif m:
+ # Definite match - add it and stop
+ res.add(a)
+ break
+ return res
def allow(self, level, **kw):
- a = self.matchrule(kw)
- return a in self.levels and self.levels.index(a) <= self.levels.index(level)
+ for a in self.matchrules(kw):
+ if a in self.levels:
+ if self.levels.index(a) <= self.levels.index(level):
+ return True
+ return False
def readfile(self, fn):
+ f = open(fn)
try:
- f = open(fn)
- try:
- for l in f:
- l = l.strip()
- if len(l) == 0 or l.startswith("#"):
- continue
- l = l.split()
- self.add(l[0], rule([c.split("=", 1) for c in l[1:]]))
- finally:
- f.close()
- except Exception, e:
- print >> sys.stderr, "Failure reading rules file:", e
+ for l in f:
+ l = l.strip()
+ if len(l) == 0 or l.startswith("#"):
+ continue
+ l = l.split()
+ self.add(l[0], rule([c.split("=", 1) for c in l[1:]]))
+ finally:
+ f.close()
rules = Ruleset()
--- a/src/mercurialserver/servelog.py Fri Dec 18 13:25:45 2009 +0000
+++ b/src/mercurialserver/servelog.py Sat Dec 19 19:21:41 2009 +0000
@@ -1,10 +1,6 @@
-# Copyright 2008-2009 LShift Ltd
-#
-# Authors:
-# Paul Crowley <paul@lshift.net>
-#
-# This software may be used and distributed according to the terms
-# of the GNU General Public License, incorporated herein by reference.
+"""
+Hook to log changesets pushed and pulled
+"""
from mercurial.i18n import _
import mercurial.util
--- a/src/refresh-auth Fri Dec 18 13:25:45 2009 +0000
+++ b/src/refresh-auth Sat Dec 19 19:21:41 2009 +0000
@@ -1,10 +1,7 @@
#!/usr/bin/env python
-# Copyright 2008-2009 LShift Ltd
-
-# WARNING
-# This script completely destroys your ~/.ssh/authorized_keys
-# file every time it is run
-# WARNING
+"""
+Rewrite ~/.ssh/authorized_keys by recursing through key directories
+"""
import sys
import os