# 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()
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]):
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]
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])
# 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)"),
'networks':None,
'peer':None,
'pubkey':(lambda n,v:"key %s;\n"%v),
- 'address':(lambda n,v:"address %s;\n"%v),
'mobile':sp,
})
require_properties={
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)
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))