summaryrefslogtreecommitdiffstats
path: root/src/util/confvalidator/validator.py
blob: d739bc091351670a89e0172199ea957d4ca237cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
'''
Created on Jan 25, 2010

@author: tsitkova
'''
import os
import sys
import re
import yaml
from optparse import OptionParser
from confparser import ConfParser

class Rule(object):
    def __init__(self):
        pass
    
    def validate(self,node):
        (path,dirs,avs) = node        


class Validator(object):
    def __init__(self, kerberosPath, confPath=None, rulesPath=None, hfilePath=None):
        self.parser = ConfParser(kerberosPath)
        if confPath is not None:
            content = self._readConfigFile(confPath)
            rulesPath = content['RulesPath']
            hfilePath = content['HfilePath']
        if rulesPath is not None and hfilePath is not None:    
            self.rules = self._loadRules(rulesPath)
            self.validKeys = SupportedKeys(hfilePath).validKeys.union(self.rules['Attributes'])
        else:
            raise ValueError('Invalid arguments for validator: no path to rules and definition files')
        
        self._attribute_pattern = re.compile(r'^\w+$')
        self._lowercase_pattern = re.compile(r'[a-z]')

    def _readConfigFile(self,path):
        f = open(path)
        result = dict()
        for line in f:
            line = line.rstrip()
            fields = line.split('=')
            result[fields[0]] = fields[1]
        
        return result
    
    def _loadRules(self, path):
        f = open(path)
        rules = yaml.load(f)
        f.close()
        
        return rules
        
    def validate(self):
        typeInfo = self.rules['Types']
        
        for node in self.parser.walk():
            self._validateTypes(node, typeInfo)
            self._validateAttrubutes(node, self.validKeys)
            # self._validateRealm(node)


    def _validateTypes(self, node, typeInfo):
        (path, dirs, avs) = node
        for (key, value) in avs:
            valid_type_pattern = typeInfo.get(key)
            if valid_type_pattern is not None:
                for t in value:
                    if re.match(valid_type_pattern, t) is None:
                        print 'Wrong type %s for attribute %s.%s' % (t,path,key)
                        
    def _validateAttrubutes(self, node, validKeys):
        (path, dirs, avs) = node 
        attributes = list()
        for attr in dirs:
            if self._attribute_pattern.match(attr) is not None:
                attributes.append(attr)
        for (attr, value) in avs:
            if self._attribute_pattern.match(attr) is not None:
                attributes.append(attr)

        for attr in attributes:
            if attr not in validKeys:
                print 'Unrecognized attribute %s at %s' % (attr, path)

#    def _validateRealm(self, node):
#        (path, dirs, avs) = node 
#        if path == 'root.realms':
#            for attr in dirs:
#                if self._lowercase_pattern.search(attr) is not None:
#                    print 'Lower case letter in realm attribute: %s at %s' % (attr, path)

class SupportedKeys(object):
    def __init__(self, path):
        self.validKeys = self.getKeysFromHfile(path)
    
    def getKeysFromHfile(self, path):
        pattern = re.compile(r'^[#]define KRB5_CONF_\w+\s+["](\w+)["]')
        f = open(path)
        result = set()
        for l in f:
            l = l.rstrip()
            m = pattern.match(l)
            if m is not None:
                result.add(m.groups()[0])
        f.close()
        
        return result

    
class ValidatorTest(Validator):
    def __init__(self):
        self.kerberosPath = '../tests/kdc1.conf'
        self.rulesPath = '../tests/rules.yml'
        self.hfilePath = '../tests/k5-int.h'
        self.confPath = '../tests/validator.conf'

        super(ValidatorTest, self).__init__(self.kerberosPath, 
                                            rulesPath=self.rulesPath, 
                                            hfilePath=self.hfilePath)

    def run_tests(self):
        self._test_validate()
    
    def _test__loadRules(self):
        result = self._loadRules(self.rulesPath)
        print result
        
    def _test_validate(self):
        self.validate()
        
    def _test__readConfigFile(self):
        result = self._readConfigFile(self.confPath)
        print result

class SupportedKeysTest(SupportedKeys):
    def __init__(self):
        self.path = '../tests/k5-int.h'
        
    def run_tests(self):
        self._test_getKeysFromHFile()
    
    def _test_getKeysFromHFile(self):
        result = set()
        krb5keys = self.getKeysFromHfile(self.path)
        for key in krb5keys:
            print key
            result.update(key)
        print len(krb5keys)  
        
        return result
    
def _test():        
    tester = ValidatorTest()
    krb5keys = tester.run_tests()
                    
if __name__ == '__main__':
    TEST = False
    if TEST:
        _test()
        sys.exit()
    
    
    usage = "\n\t%prog path [-d defPath] [-r rulesPath] [-c validatorConfPath]"
    description = 'Description: validates kerberos configuration file'
    parser = OptionParser(usage = usage, description = description)
    parser.add_option("-c", dest="confPath",
                      help='path to validator config file')
    parser.add_option("-d", dest="hfilePath",
                      help='path to h-file with attribute definition')
    parser.add_option("-r", dest="rulesPath",
                      help='path to file with validation rules')
    (options, args) = parser.parse_args()

    if len(args) != 1 and len(sys.argv) <= 3:
        print '\n%s' % parser.get_usage()
        sys.exit()

    validator = None
    if options.confPath is not None:
        validator = Validator(args[0], confPath=options.confPath)
    elif options.hfilePath is not None and options.rulesPath is not None:
        validator = Validator(args[0], hfilePath=options.hfilePath, rulesPath=options.rulesPath)
    else:
        print '\nMust specify either configuration file or paths to rules and definitions files'
        print '%s' % parser.get_usage()
        sys.exit()
    
    validator.validate()