@@@ simplify makefile
[secnet] / make-secnet-sites
index b66f950..e63a2c2 100755 (executable)
@@ -68,14 +68,32 @@ VERSION="0.1.18"
 
 # Classes describing possible datatypes in the configuration file
 
-class single_ipaddr:
+class basetype:
+       "Common protocol for configuration types."
+       def add(self,obj,w):
+               complain("%s %s already has property %s defined"%
+                       (obj.type,obj.name,w[0]))
+
+class conflist:
+       "A list of some kind of configuration type."
+       def __init__(self,subtype,w):
+               self.subtype=subtype
+               self.list=[subtype(w)]
+       def add(self,obj,w):
+               self.list.append(self.subtype(w))
+       def __str__(self):
+               return ', '.join(map(str, self.list))
+def listof(subtype):
+       return lambda w: conflist(subtype, w)
+
+class single_ipaddr (basetype):
        "An IP address"
        def __init__(self,w):
                self.addr=ipaddr.IPAddress(w[1])
        def __str__(self):
                return '"%s"'%self.addr
 
-class networks:
+class networks (basetype):
        "A set of IP addresses specified as a list of networks"
        def __init__(self,w):
                self.set=ipaddrset.IPAddressSet()
@@ -85,31 +103,34 @@ class networks:
        def __str__(self):
                return ",".join(map((lambda n: '"%s"'%n), self.set.networks()))
 
-class dhgroup:
+class trad_dhgroup (basetype):
        "A Diffie-Hellman group"
        def __init__(self,w):
                self.mod=w[1]
                self.gen=w[2]
        def __str__(self):
                return 'diffie-hellman("%s","%s")'%(self.mod,self.gen)
+def dhgroup(w):
+       if w[1] in ('x25519', 'x448'): return w[1]
+       else: return trad_dhgroup(w)
 
-class hash:
+class hash (basetype):
        "A choice of hash function"
        def __init__(self,w):
                self.ht=w[1]
-               if (self.ht!='md5' and self.ht!='sha1'):
+               if (self.ht not in ('md5', 'sha1', 'sha512')):
                        complain("unknown hash type %s"%(self.ht))
        def __str__(self):
                return '%s'%(self.ht)
 
-class email:
+class email (basetype):
        "An email address"
        def __init__(self,w):
                self.addr=w[1]
        def __str__(self):
                return '<%s>'%(self.addr)
 
-class boolean:
+class boolean (basetype):
        "A boolean"
        def __init__(self,w):
                if re.match('[TtYy1]',w[1]):
@@ -121,14 +142,14 @@ class boolean:
        def __str__(self):
                return ['False','True'][self.b]
 
-class num:
+class num (basetype):
        "A decimal number"
        def __init__(self,w):
                self.n=string.atol(w[1])
        def __str__(self):
                return '%d'%(self.n)
 
-class address:
+class address (basetype):
        "A DNS name and UDP port number"
        def __init__(self,w):
                self.adr=w[1]
@@ -138,7 +159,7 @@ class address:
        def __str__(self):
                return '"%s"; port %d'%(self.adr,self.port)
 
-class rsakey:
+class rsakey (basetype):
        "An RSA public key"
        def __init__(self,w):
                self.l=string.atoi(w[1])
@@ -150,7 +171,7 @@ class rsakey:
 # Possible properties of configuration nodes
 keywords={
  'contact':(email,"Contact address"),
- 'dh':(dhgroup,"Diffie-Hellman group"),
+ 'dh':(listof(dhgroup),"Diffie-Hellman group"),
  'hash':(hash,"Hash function"),
  'key-lifetime':(num,"Maximum key lifetime (ms)"),
  'setup-timeout':(num,"Key setup timeout (ms)"),
@@ -324,8 +345,7 @@ prefix=''
 def set_property(obj,w):
        "Set a property on a configuration node"
        if obj.properties.has_key(w[0]):
-               complain("%s %s already has property %s defined"%
-                       (obj.type,obj.name,w[0]))
+               obj.properties[w[0]].add(obj,w)
        else:
                obj.properties[w[0]]=keywords[w[0]][0](w)
 
@@ -380,13 +400,16 @@ def pline(i,allow_include=False):
                        current=nl
                obstack.append(current)
                return [i]
-       if current.allow_properties.has_key(keyword):
-               set_property(current,w)
-               return [i]
-       else:
+       if not current.allow_properties.has_key(keyword):
                complain("Property %s not allowed at %s level"%
                        (keyword,current.type))
                return []
+       elif current.depth == vpnlevel.depth < allow_defs:
+               complain("Not allowed to set VPN properties here")
+               return []
+       else:
+               set_property(current,w)
+               return [i]
 
        complain("unknown keyword '%s'"%(keyword))