src/ruleset.py
author Paul Crowley <paul@lshift.net>
Mon, 16 Jun 2008 17:24:53 +0100
changeset 36 b3237aabd0fe
parent 33 18e93dbdaf12
child 39 f5055ce263c7
permissions -rw-r--r--
Change the name to mercurial-server
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
18
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
     1
# Copyright 2008 LShift Ltd
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
     2
# Author(s):
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
     3
# Paul Crowley <paul@lshift.net>
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
     4
#
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
     6
# of the GNU General Public License, incorporated herein by reference.
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
     7
32
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
     8
import sys
18
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
     9
import re
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    10
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    11
allowedchars = "A-Za-z0-9_-"
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    12
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    13
goodpathre = re.compile("([%s]+/)*[%s]+$" % (allowedchars, allowedchars))
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    14
def goodpath(path):
19
62ee928ac9b3 fixes following actual testing
Paul Crowley <paul@lshift.net>
parents: 18
diff changeset
    15
    return goodpathre.match(path) is not None
18
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    16
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    17
goodglobre = re.compile("[*/%s]+$" % allowedchars)
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    18
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    19
def goodglob(pattern):
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    20
    return goodglobre.match(pattern) is not None
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    21
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    22
# Don't put anything except *A-Za-z0-9_- in rule globs or   
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    23
# it will match nothing.  No regexp metachars, not even .
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    24
# We may fix this later.
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    25
def globmatcher(pattern):
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    26
    if not goodglob(pattern):
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    27
        #fail("Bad glob pattern in auth config: %s" % pattern)
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    28
        # FIXME: report it somehow
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    29
        return lambda x: False
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    30
    # Substitution cunning so ** can be different from *
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    31
    pattern = pattern.replace("*", "[]")
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    32
    pattern = pattern.replace("[][]", "[/%s]*" % allowedchars)
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    33
    pattern = pattern.replace("[]", "[%s]*" % allowedchars)
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    34
    rex = re.compile(pattern + "$")
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    35
    # None matches everything
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    36
    return lambda x: x is None or rex.match(x) is not None
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    37
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    38
def rule(pairs):
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    39
    matchers = [(k, globmatcher(v)) for k, v in pairs]
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    40
    def c(**kw):
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    41
        for k, m in matchers:
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    42
            if k not in kw or not m(kw[k]):
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    43
                return False
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    44
        return True
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    45
    return c
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    46
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    47
class Ruleset(object):
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    48
    '''Class representing the rules in a rule file'''
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    49
    
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    50
    levels = ["init", "write", "read", "deny"]
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    51
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    52
    def __init__(self):
32
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    53
        # The user called "root" automatically has the highest
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    54
        # privilege
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    55
        self.rules = [(self.levels[0], rule([('user', 'root')]))]
21
59540181a4bb simplify by allowing some params to be preset in rules
Paul Crowley <paul@ciphergoth.org>
parents: 18
diff changeset
    56
        self.preset = {}
18
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    57
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    58
    def add(self, action, conditions):
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    59
        self.rules.append((action, conditions))
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    60
21
59540181a4bb simplify by allowing some params to be preset in rules
Paul Crowley <paul@ciphergoth.org>
parents: 18
diff changeset
    61
59540181a4bb simplify by allowing some params to be preset in rules
Paul Crowley <paul@ciphergoth.org>
parents: 18
diff changeset
    62
    def set(self, **kw):
59540181a4bb simplify by allowing some params to be preset in rules
Paul Crowley <paul@ciphergoth.org>
parents: 18
diff changeset
    63
        self.preset.update(kw)
59540181a4bb simplify by allowing some params to be preset in rules
Paul Crowley <paul@ciphergoth.org>
parents: 18
diff changeset
    64
        
18
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    65
    def matchrule(self, **kw):
21
59540181a4bb simplify by allowing some params to be preset in rules
Paul Crowley <paul@ciphergoth.org>
parents: 18
diff changeset
    66
        d = self.preset.copy()
59540181a4bb simplify by allowing some params to be preset in rules
Paul Crowley <paul@ciphergoth.org>
parents: 18
diff changeset
    67
        d.update(**kw)
18
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    68
        for a, c in self.rules:
21
59540181a4bb simplify by allowing some params to be preset in rules
Paul Crowley <paul@ciphergoth.org>
parents: 18
diff changeset
    69
            if c(**d):
18
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    70
                return a
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    71
        return None
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    72
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    73
    def allow(self, level, **kw):
19
62ee928ac9b3 fixes following actual testing
Paul Crowley <paul@lshift.net>
parents: 18
diff changeset
    74
        a = self.matchrule(**kw)
18
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    75
        return a in self.levels and self.levels.index(a) <= self.levels.index(level)
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    76
    
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    77
    @classmethod
19
62ee928ac9b3 fixes following actual testing
Paul Crowley <paul@lshift.net>
parents: 18
diff changeset
    78
    def readfile(cls, fn):
18
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    79
        res = cls()
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    80
        try:
32
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    81
            f = open(fn)
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    82
            try:
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    83
                for l in f:
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    84
                    l = l.strip()
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    85
                    if len(l) == 0 or l.startswith("#"):
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    86
                        continue
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    87
                    l = l.split()
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    88
                    res.add(l[0], rule([c.split("=", 1) for c in l[1:]]))
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    89
            finally:
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    90
                f.close()
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    91
        except Exception, e:
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    92
            print >> sys.stderr, "Failure reading rules file:", e
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    93
            return cls()
18
538d6b198f4a Big change to support file conditions; format of hg-ssh-access.conf
Paul Crowley <paul@lshift.net>
parents:
diff changeset
    94
        return res
32
4059dbe9f26a new break-in system
Paul Crowley <paul@lshift.net>
parents: 23
diff changeset
    95