Refactor SigningTable and KeyTables based on more careful reading of the documentation

This commit is contained in:
Scott Kitterman
2019-10-29 01:50:28 -04:00
parent 403f8c8d1d
commit 5b956b9c7d
3 changed files with 43 additions and 59 deletions
+23 -35
View File
@@ -261,26 +261,10 @@ def _make_authserv_id(as_id):
as_id = socket.gethostname()
return as_id
def _dataset_multiline(dst, dataset):
"""Convert one list element per line on multi-line datasets to a list of
lists"""
result = []
for row in dataset:
rowl = row.split(',')
for element in rowl:
rowl[rowl.index(element)] = element.strip().strip(',')
if dst == 'KeyTable' and len(rowl) != 3:
raise dkim.ParameterError('Invalid {0} element (need three paramters per row): {1}'
.format(str(dst), str(rowl)))
if dst == 'SigningTable' and len(rowl) > 2:
raise dkim.ParameterError('Invalid {0} element (need one or two paramters per row): {1}'
.format(str(dst), str(rowl)))
result.append(rowl)
return result
def _dataset_to_list(dataset):
"""Convert a dataset (as defined in dkimpymilter.8) and return a python
list of values."""
list of values. For multiline datasets like KeyTable and SigningTable a
key : values dictionary is returned"""
if not isinstance(dataset, str):
# If it was a csl with more than one value, it's already a list, we
# only need to remove the name from the first value.
@@ -290,23 +274,34 @@ def _dataset_to_list(dataset):
dataset[dataset.index(item)] = item.strip().strip(',')
return dataset
elif isinstance(dataset, str):
if dataset[0] == '/' or dataset[:5] == 'file:':
# This is a flat file dataset
if dataset[0] == '/' or dataset[:5] == 'file:' or dataset[:7] == 'refile:':
# This is a flat file dataset, which are key value:value stores
ds = []
dsd = {}
if dataset[0] == '/':
dsname = dataset
if dataset[:5] == 'file:':
elif dataset[:5] == 'file:':
dsname = dataset[5:]
elif dataset[:7] == 'refile:':
dsname = dataset[7:]
dsf = open(dsname, 'r')
for line in dsf.readlines():
if line[0] != '#':
if len(line.split(':')) == 1:
ds.append(line.strip())
else:
for element in line.split(':'):
ds.append(element.strip().strip(':'))
if len(line.split()) == 1:
if len(line.split(':')) == 1:
ds.append(line.strip())
else:
for element in line.split(':'):
ds.append(element.strip().strip(':'))
elif len(line.split()) == 2: # key value:value:value
key, values = line.split()
values = values.split(':')
dsd.update({key:values})
dsf.close()
return ds
if ds:
return ds
elif dsd:
return dsd
# If it's a str and csl, it has one value and we return a list
if dataset[:4] == 'csl:':
return [dataset[4:].strip().strip(',')]
@@ -428,14 +423,7 @@ def _readConfigFile(path, configData=None, configGlobal={}):
elif conversion == 'int':
configData[name] = int(value)
elif conversion == 'dataset':
interim_value = _dataset_to_list(value)
# These are the only multi-line dataset types
if name == 'KeyTable' or name == 'KeyTableEd25519':
configData[name] = _dataset_multiline('KeyTable', interim_value)
elif name == 'SigningTable':
configData[name] = _dataset_multiline('SigningTable', interim_value)
else:
configData[name] = interim_value
configData[name] = _dataset_to_list(value)
else:
syslog.syslog(str('name: ' + name + ' value: ' + value +
' conversion: ' + conversion))
+9 -15
View File
@@ -187,25 +187,19 @@ def read_keyfile(keyfile, milterconfig):
key += line
return key
def read_keytable(tablelist, milterconfig):
def read_keytable(tabledict, milterconfig):
"""Read keytables into in memory configuration data so all keys are read
before priviledges are dropped.
tablelist contains a list of KeyTable rows (three elements, comma separated):
domain, selector, key file location
When loaded, KeyTableData is a dict:
{domain: [selector, key]}"""
When loaded, tabeldict is a dict:
{searchkey: [donamin, selector, key]}
If key is a file (startswith('/'), then the key is returned in its place."""
import dkim
import syslog
keytabledata = {}
for row in tablelist:
for element in row:
row[row.index(element)] = element.strip().strip(',')
if len(row) != 3:
raise dkim.ParameterError('Invalid KeyTable element (need three paramters per row): {0}'
.format(str(row)))
key = read_keyfile(row[2], milterconfig)
keytabledata.update({row[0]:[row[1], key]})
return keytabledata
for dictkey, values in tabledict.items():
if values[-1][:1] == '/':
key = read_keyfile(values[-1], milterconfig)
tabledict[dictkey] = [values[0], values[1], key]
return tabledict
def get_keys(milterconfig):
"""Read keys (table or file) into memory before dropping priviledges"""
+11 -9
View File
@@ -77,21 +77,23 @@ debugLevel 5
EOF
cat > "$keytype.table.verify.conf" <<EOF
Socket unix:$keytype.stable.verify.sock
PidFile $keytype.table.verify.pid
Mode v
DNSOverride $(cat testkey.$keytype.dns)
UserID $(id --name --user):$(id --name --group)
Socket unix:$keytype.stable.verify.sock
PidFile $keytype.table.verify.pid
Mode v
DNSOverride $(cat testkey.$keytype.dns)
UserID $(id --name --user):$(id --name --group)
EOF
cat > "$keytype-table" <<EOF
example.org, testnokey, testkey.$keytype.key
example.net, testkey, testkey.$keytype.key
preskey example.org:testkey:$WORKDIR/testkey.$keytype.key
orgkey example.org:testkey:$WORKDIR/testkey.$keytype.key
netkey example.net:testkey:$WORKDIR/testkey.$keytype.key
EOF
cat > "signing-table" <<EOF
example.org
%, @test.test.example.net
president@example.org @special.example.org:preskey
*@example.org orgkey
*@example.net netkey
EOF
done