1# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
2#
3# SPDX-License-Identifier: MPL-2.0
4#
5# This Source Code Form is subject to the terms of the Mozilla Public
6# License, v. 2.0.  If a copy of the MPL was not distributed with this
7# file, you can obtain one at https://mozilla.org/MPL/2.0/.
8#
9# See the COPYRIGHT file distributed with this work for additional
10# information regarding copyright ownership.
11
12from collections import defaultdict
13from . import dnskey
14import os
15import glob
16
17
18########################################################################
19# Class keydict
20########################################################################
21class keydict:
22    """ A dictionary of keys, indexed by name, algorithm, and key id """
23
24    _keydict = defaultdict(lambda: defaultdict(dict))
25    _defttl = None
26    _missing = []
27
28    def __init__(self, dp=None, **kwargs):
29        self._defttl = kwargs.get('keyttl', None)
30        zones = kwargs.get('zones', None)
31
32        if not zones:
33            path = kwargs.get('path',None) or '.'
34            self.readall(path)
35        else:
36            for zone in zones:
37                if 'path' in kwargs and kwargs['path'] is not None:
38                    path = kwargs['path']
39                else:
40                    path = dp and dp.policy(zone).directory or '.'
41                if not self.readone(path, zone):
42                    self._missing.append(zone)
43
44    def readall(self, path):
45        files = glob.glob(os.path.join(path, '*.private'))
46
47        for infile in files:
48            key = dnskey(infile, path, self._defttl)
49            self._keydict[key.name][key.alg][key.keyid] = key
50
51    def readone(self, path, zone):
52        if not zone.endswith('.'):
53            zone += '.'
54        match='K' + zone + '+*.private'
55        files = glob.glob(os.path.join(path, match))
56
57        found = False
58        for infile in files:
59            key = dnskey(infile, path, self._defttl)
60            if key.fullname != zone: # shouldn't ever happen
61                continue
62            keyname=key.name if zone != '.' else '.'
63            self._keydict[keyname][key.alg][key.keyid] = key
64            found = True
65
66        return found
67
68    def __iter__(self):
69        for zone, algorithms in self._keydict.items():
70            for alg, keys in algorithms.items():
71                for key in keys.values():
72                    yield key
73
74    def __getitem__(self, name):
75        return self._keydict[name]
76
77    def zones(self):
78        return (self._keydict.keys())
79
80    def algorithms(self, zone):
81        return (self._keydict[zone].keys())
82
83    def keys(self, zone, alg):
84        return (self._keydict[zone][alg].keys())
85
86    def missing(self):
87        return (self._missing)
88