chiark / gitweb /
make-secnet-sites: Support `pkg' and `pkgf'
[secnet.git] / make-secnet-sites
index f90d150dd1b53dc5b9c41d6a4f1fc976c6f8e5ff..4899dcf1820cf0813d3d57e75b34679d478b8392 100755 (executable)
@@ -479,13 +479,30 @@ class rsakey_newfmt(rsakey):
                        complain('rsa1 key in new format has bad base91')
                #print(repr(w_inner), file=sys.stderr)
                rsakey.__init__(self,w_inner)
+
+class pubkey_group(basetype):
+       "Public key group introducer"
+       # appears in the site's list of keys mixed in with the keys
+       def __init__(self,w,fallback):
+               self.i=w[1].hexid(4,'pkg-id')
+               self.fallback=fallback
+       def forsites(self,version,xcopy,fs):
+               fs.pkg=self.i
+               if version < 2: return []
+               return ['pkgf' if self.fallback else 'pkg', self.i]
+       
 def somepubkey(w):
+       #print(repr(w), file=sys.stderr)
        if w[0]=='pubkey':
                return rsakey(w)
        elif w[0]=='pub' and w[1]=='rsa1':
                return rsakey_newfmt(w)
        elif w[0]=='pub':
                return pubkey(w)
+       elif w[0]=='pkg':
+               return pubkey_group(w,False)
+       elif w[0]=='pkgf':
+               return pubkey_group(w,True)
        else:
                assert(False)
 
@@ -501,6 +518,9 @@ keywords={
  'renegotiate-time':(num,"Time after key setup to begin renegotiation (ms)"),
  'restrict-nets':(networks,"Allowable networks"),
  'networks':(networks,"Claimed networks"),
+ 'serial':(serial,"public key set serial"),
+ 'pkg':(listof(somepubkey),"start of public key group",'pub'),
+ 'pkgf':(listof(somepubkey),"start of fallback public key group",'pub'),
  'pub':(listof(somepubkey),"new style public site key"),
  'pubkey':(listof(somepubkey),"RSA public site key",'pub'),
  'peer':(single_ipaddr,"Tunnel peer IP address"),
@@ -622,6 +642,9 @@ class sitelevel(level):
         'address':sp,
         'networks':None,
         'peer':None,
+         'serial':None,
+        'pkg':None,
+        'pkgf':None,
         'pub':None,
         'pubkey':None,
         'mobile':sp,
@@ -650,6 +673,9 @@ class sitelevel(level):
                if pubkeys_install:
                        pa=self.pubkeys_path()
                        pw=open(pa+'~tmp','w')
+                       if 'serial' in self.properties:
+                               pw.write('serial %s\n' %
+                                        self.properties['serial'])
                        fs=FilterState()
                        for k in self.properties["pub"].list:
                                debugrepr('pubkeys install', k)
@@ -660,7 +686,21 @@ class sitelevel(level):
                        os.rename(pa+'~tmp',pa+'~update')
                        w.write("peer-keys \"%s\";\n"%pa);
                else:
-                       w.write("key %s;\n"%str(self.properties["pub"].list[0]))
+                       use = None
+                       indefault = True
+                       for k in self.properties["pub"].list:
+                               debugrepr('pub write', (use,indefault,k))
+                               if isinstance(k,pubkey):
+                                       if indefault:
+                                               use = k
+                                               break
+                                       if use is None:
+                                               use = k
+                               else:
+                                       raise RuntimeError('bad '+repr(k))
+                       if use is None:
+                               complain("site with no public key");
+                       w.write("key %s;\n"%str(use))
                self.output_props(w,ind+2)
                self.indent(w,ind+2)
                w.write("link netlink {\n");
@@ -715,7 +755,7 @@ class FilterState:
        def reset(self):
                # called when we enter a new node,
                # in particular, at the start of each site
-               pass
+               self.pkg = '00000000'
 
 def pline(il,filterstate,allow_include=False):
        "Process a configuration file line"