"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/bin/python/isc/keyseries.py.in" (7 Sep 2020, 8721 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 ############################################################################
    2 # Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3 #
    4 # This Source Code Form is subject to the terms of the Mozilla Public
    5 # License, v. 2.0. If a copy of the MPL was not distributed with this
    6 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7 #
    8 # See the COPYRIGHT file distributed with this work for additional
    9 # information regarding copyright ownership.
   10 ############################################################################
   11 
   12 from collections import defaultdict
   13 from .dnskey import *
   14 from .keydict import *
   15 from .keyevent import *
   16 from .policy import *
   17 import time
   18 
   19 
   20 class keyseries:
   21     _K = defaultdict(lambda: defaultdict(list))
   22     _Z = defaultdict(lambda: defaultdict(list))
   23     _zones = set()
   24     _kdict = None
   25     _context = None
   26 
   27     def __init__(self, kdict, now=time.time(), context=None):
   28         self._kdict = kdict
   29         self._context = context
   30         self._zones = set(kdict.missing())
   31 
   32         for zone in kdict.zones():
   33             self._zones.add(zone)
   34             for alg, keys in kdict[zone].items():
   35                 for k in keys.values():
   36                     if k.sep:
   37                         if not (k.delete() and k.delete() < now):
   38                           self._K[zone][alg].append(k)
   39                     else:
   40                         if not (k.delete() and k.delete() < now):
   41                           self._Z[zone][alg].append(k)
   42 
   43                 self._K[zone][alg].sort()
   44                 self._Z[zone][alg].sort()
   45 
   46     def __iter__(self):
   47         for zone in self._zones:
   48             for collection in [self._K, self._Z]:
   49                 if zone not in collection:
   50                     continue
   51                 for alg, keys in collection[zone].items():
   52                     for key in keys:
   53                         yield key
   54 
   55     def dump(self):
   56         for k in self:
   57             print("%s" % repr(k))
   58 
   59     def fixseries(self, keys, policy, now, **kwargs):
   60         force = kwargs.get('force', False)
   61         if not keys:
   62             return
   63 
   64         # handle the first key
   65         key = keys[0]
   66         if key.sep:
   67             rp = policy.ksk_rollperiod
   68             prepub = policy.ksk_prepublish or (30 * 86400)
   69             postpub = policy.ksk_postpublish or (30 * 86400)
   70         else:
   71             rp = policy.zsk_rollperiod
   72             prepub = policy.zsk_prepublish or (30 * 86400)
   73             postpub = policy.zsk_postpublish or (30 * 86400)
   74 
   75         # the first key should be published and active
   76         p = key.publish()
   77         a = key.activate()
   78         if not p or p > now:
   79             key.setpublish(now)
   80             p = now
   81         if not a or a > now:
   82             key.setactivate(now)
   83             a = now
   84 
   85         i = key.inactive()
   86         fudge = 300
   87         if not rp:
   88             key.setinactive(None, **kwargs)
   89             key.setdelete(None, **kwargs)
   90         elif not i or a + rp != i:
   91             if not i and a + rp > now + prepub + fudge:
   92                 key.setinactive(a + rp, **kwargs)
   93                 key.setdelete(a + rp + postpub, **kwargs)
   94             elif not i:
   95                 key.setinactive(now + prepub + fudge, **kwargs)
   96                 key.setdelete(now + prepub + postpub + fudge, **kwargs)
   97             elif i < now:
   98                 pass
   99             elif a + rp > i:
  100                 key.setinactive(a + rp, **kwargs)
  101                 key.setdelete(a + rp + postpub, **kwargs)
  102             elif a + rp > now + prepub + fudge:
  103                 key.setinactive(a + rp, **kwargs)
  104                 key.setdelete(a + rp + postpub, **kwargs)
  105             else:
  106                 key.setinactive(now + prepub + fudge, **kwargs)
  107                 key.setdelete(now + prepub + postpub + fudge, **kwargs)
  108         else:
  109             d = key.delete()
  110             if not d or i + postpub > now + fudge:
  111                 key.setdelete(i + postpub, **kwargs)
  112             elif not d:
  113                 key.setdelete(now + postpub + fudge, **kwargs)
  114             elif d < now + fudge:
  115                 pass
  116             elif d < i + postpub:
  117                 key.setdelete(i + postpub, **kwargs)
  118 
  119         if policy.keyttl != key.ttl:
  120             key.setttl(policy.keyttl)
  121 
  122         # handle all the subsequent keys
  123         prev = key
  124         for key in keys[1:]:
  125             # if no rollperiod, then all keys after the first in
  126             # the series kept inactive.
  127             # (XXX: we need to change this to allow standby keys)
  128             if not rp:
  129                 key.setpublish(None, **kwargs)
  130                 key.setactivate(None, **kwargs)
  131                 key.setinactive(None, **kwargs)
  132                 key.setdelete(None, **kwargs)
  133                 if policy.keyttl != key.ttl:
  134                     key.setttl(policy.keyttl)
  135                 continue
  136 
  137             # otherwise, ensure all dates are set correctly based on
  138             # the initial key
  139             a = prev.inactive()
  140             p = a - prepub
  141             key.setactivate(a, **kwargs)
  142             key.setpublish(p, **kwargs)
  143             key.setinactive(a + rp, **kwargs)
  144             key.setdelete(a + rp + postpub, **kwargs)
  145             prev.setdelete(a + postpub, **kwargs)
  146             if policy.keyttl != key.ttl:
  147                 key.setttl(policy.keyttl)
  148             prev = key
  149 
  150         # if we haven't got sufficient coverage, create successor key(s)
  151         while rp and prev.inactive() and \
  152               prev.inactive() < now + policy.coverage:
  153             # commit changes to predecessor: a successor can only be
  154             # generated if Inactive has been set in the predecessor key
  155             prev.commit(self._context['settime_path'], **kwargs)
  156             key = prev.generate_successor(self._context['keygen_path'],
  157                                           self._context['randomdev'],
  158                                           prepub, **kwargs)
  159 
  160             key.setinactive(key.activate() + rp, **kwargs)
  161             key.setdelete(key.inactive() + postpub, **kwargs)
  162             keys.append(key)
  163             prev = key
  164 
  165         # last key? we already know we have sufficient coverage now, so
  166         # disable the inactivation of the final key (if it was set),
  167         # ensuring that if dnssec-keymgr isn't run again, the last key
  168         # in the series will at least remain usable.
  169         prev.setinactive(None, **kwargs)
  170         prev.setdelete(None, **kwargs)
  171 
  172         # commit changes
  173         for key in keys:
  174             key.commit(self._context['settime_path'], **kwargs)
  175 
  176 
  177     def enforce_policy(self, policies, now=time.time(), **kwargs):
  178         # If zones is provided as a parameter, use that list.
  179         # If not, use what we have in this object
  180         zones = kwargs.get('zones', self._zones)
  181         keys_dir = kwargs.get('dir', self._context.get('keys_path', None))
  182         force = kwargs.get('force', False)
  183 
  184         for zone in zones:
  185             collections = []
  186             policy = policies.policy(zone)
  187             keys_dir = keys_dir or policy.directory or '.'
  188             alg = policy.algorithm
  189             algnum = dnskey.algnum(alg)
  190             if 'ksk' not in kwargs or not kwargs['ksk']:
  191                 if len(self._Z[zone][algnum]) == 0:
  192                     k = dnskey.generate(self._context['keygen_path'],
  193                                         self._context['randomdev'],
  194                                         keys_dir, zone, alg,
  195                                         policy.zsk_keysize, False,
  196                                         policy.keyttl or 3600,
  197                                         **kwargs)
  198                     self._Z[zone][algnum].append(k)
  199                 collections.append(self._Z[zone])
  200 
  201             if 'zsk' not in kwargs or not kwargs['zsk']:
  202                 if len(self._K[zone][algnum]) == 0:
  203                     k = dnskey.generate(self._context['keygen_path'],
  204                                         self._context['randomdev'],
  205                                         keys_dir, zone, alg,
  206                                         policy.ksk_keysize, True,
  207                                         policy.keyttl or 3600,
  208                                         **kwargs)
  209                     self._K[zone][algnum].append(k)
  210                 collections.append(self._K[zone])
  211 
  212             for collection in collections:
  213                 for algorithm, keys in collection.items():
  214                     if algorithm != algnum:
  215                         continue
  216                     try:
  217                         self.fixseries(keys, policy, now, **kwargs)
  218                     except Exception as e:
  219                         raise Exception('%s/%s: %s' %
  220                                         (zone, dnskey.algstr(algnum), str(e)))