chiark / gitweb /
make-secnet-sites: Set .type in the `level' base class
[secnet.git] / make-secnet-sites
index 04ead35dd955aae5ad33453ffadc352a67557e5a..65baa11c0b98b3d44d2e5d6f8fb9859cf8f86fda 100755 (executable)
@@ -51,6 +51,9 @@ Cendio Systems AB.
 
 """
 
+from __future__ import print_function
+from builtins import int
+
 import string
 import time
 import sys
@@ -60,12 +63,59 @@ import re
 
 import ipaddr
 
-sys.path.insert(0,"/usr/local/share/secnet")
-sys.path.insert(0,"/usr/share/secnet")
+# entry 0 is "near the executable", or maybe from PYTHONPATH=.,
+# which we don't want to preempt
+sys.path.insert(1,"/usr/local/share/secnet")
+sys.path.insert(1,"/usr/share/secnet")
 import ipaddrset
 
 VERSION="0.1.18"
 
+# Are we being invoked from userv?
+service=0
+# If we are, which group does the caller want to modify?
+group=None
+
+if len(sys.argv)<2:
+       inputfile=None
+       of=sys.stdout
+else:
+       if sys.argv[1]=='-u':
+               if len(sys.argv)!=6:
+                       print("Wrong number of arguments")
+                       sys.exit(1)
+               service=1
+               header=sys.argv[2]
+               groupfiledir=sys.argv[3]
+               sitesfile=sys.argv[4]
+               group=sys.argv[5]
+               if "USERV_USER" not in os.environ:
+                       print("Environment variable USERV_USER not found")
+                       sys.exit(1)
+               user=os.environ["USERV_USER"]
+               # Check that group is in USERV_GROUP
+               if "USERV_GROUP" not in os.environ:
+                       print("Environment variable USERV_GROUP not found")
+                       sys.exit(1)
+               ugs=os.environ["USERV_GROUP"]
+               ok=0
+               for i in ugs.split():
+                       if group==i: ok=1
+               if not ok:
+                       print("caller not in group %s"%group)
+                       sys.exit(1)
+       else:
+               if sys.argv[1]=='-P':
+                       prefix=sys.argv[2]
+                       sys.argv[1:3]=[]
+               if len(sys.argv)>3:
+                       print("Too many arguments")
+                       sys.exit(1)
+               inputfile=sys.argv[1]
+               of=sys.stdout
+               if len(sys.argv)>2:
+                       of=open(sys.argv[2],'w')
+
 # Classes describing possible datatypes in the configuration file
 
 class basetype:
@@ -142,7 +192,7 @@ class boolean (basetype):
 class num (basetype):
        "A decimal number"
        def __init__(self,w):
-               self.n=string.atol(w[1])
+               self.n=int(w[1])
        def __str__(self):
                return '%d'%(self.n)
 
@@ -150,7 +200,7 @@ class address (basetype):
        "A DNS name and UDP port number"
        def __init__(self,w):
                self.adr=w[1]
-               self.port=string.atoi(w[2])
+               self.port=int(w[2])
                if (self.port<1 or self.port>65535):
                        complain("invalid port number")
        def __str__(self):
@@ -159,7 +209,7 @@ class address (basetype):
 class rsakey (basetype):
        "An RSA public key"
        def __init__(self,w):
-               self.l=string.atoi(w[1])
+               self.l=int(w[1])
                self.e=w[2]
                self.n=w[3]
        def __str__(self):
@@ -207,6 +257,7 @@ class level:
        allow_properties={}
        require_properties={}
        def __init__(self,w):
+               self.type=w[0]
                self.name=w[1]
                self.properties={}
                self.children={}
@@ -250,7 +301,7 @@ class vpnlevel(level):
                w.write("\n")
                self.indent(w,ind+2)
                w.write("all-sites %s;\n"%
-                       string.join(self.children.keys(),','))
+                       ','.join(self.children.keys()))
                self.indent(w,ind)
                w.write("};\n")
 
@@ -270,9 +321,9 @@ class locationlevel(level):
                self.indent(w,ind)
                # The "h=h,self=self" abomination below exists because
                # Python didn't support nested_scopes until version 2.1
-               w.write("%s %s;\n"%(self.name,string.join(
+               w.write("%s %s;\n"%(self.name,','.join(
                        map(lambda x,h=h,self=self:
-                               h+"/"+x,self.children.keys()),',')))
+                               h+"/"+x,self.children.keys()))))
 
 class sitelevel(level):
        "Site level (i.e. a leafnode) in the configuration hierarchy"
@@ -326,12 +377,12 @@ reserved.update(levels)
 def complain(msg):
        "Complain about a particular input line"
        global complaints
-       print ("%s line %d: "%(file,line))+msg
+       print(("%s line %d: "%(file,line))+msg)
        complaints=complaints+1
 def moan(msg):
        "Complain about something in general"
        global complaints
-       print msg;
+       print(msg);
        complaints=complaints+1
 
 root=level(['root','root'])   # All vpns are children of this node
@@ -341,7 +392,7 @@ prefix=''
 
 def set_property(obj,w):
        "Set a property on a configuration node"
-       if obj.properties.has_key(w[0]):
+       if w[0] in obj.properties:
                obj.properties[w[0]].add(obj,w)
        else:
                obj.properties[w[0]]=keywords[w[0]][0](w)
@@ -349,7 +400,7 @@ def set_property(obj,w):
 def pline(i,allow_include=False):
        "Process a configuration file line"
        global allow_defs, obstack, root
-       w=string.split(i.rstrip('\n'))
+       w=i.rstrip('\n').split()
        if len(w)==0: return [i]
        keyword=w[0]
        current=obstack[len(obstack)-1]
@@ -366,7 +417,7 @@ def pline(i,allow_include=False):
                        return []
                newfile=os.path.join(os.path.dirname(file),w[1])
                return pfilepath(newfile,allow_include=allow_include)
-       if levels.has_key(keyword):
+       if keyword in levels:
                # We may go up any number of levels, but only down by one
                newdepth=levels[keyword].depth
                currentdepth=len(obstack) # actually +1...
@@ -378,7 +429,7 @@ def pline(i,allow_include=False):
                # See if it's a new one (and whether that's permitted)
                # or an existing one
                current=obstack[len(obstack)-1]
-               if current.children.has_key(w[1]):
+               if w[1] in current.children:
                        # Not new
                        current=current.children[w[1]]
                        if service and group and current.depth==2:
@@ -397,7 +448,7 @@ def pline(i,allow_include=False):
                        current=nl
                obstack.append(current)
                return [i]
-       if not current.allow_properties.has_key(keyword):
+       if keyword not in current.allow_properties:
                complain("Property %s not allowed at %s level"%
                        (keyword,current.type))
                return []
@@ -433,7 +484,7 @@ def outputsites(w):
        w.write("# secnet sites file autogenerated by make-secnet-sites "
                +"version %s\n"%VERSION)
        w.write("# %s\n"%time.asctime(time.localtime(time.time())))
-       w.write("# Command line: %s\n\n"%string.join(sys.argv))
+       w.write("# Command line: %s\n\n"%' '.join(sys.argv))
 
        # Raw VPN data section of file
        w.write(prefix+"vpn-data {\n")
@@ -448,59 +499,14 @@ def outputsites(w):
        w.write("};\n")
 
        # Flattened list of sites
-       w.write(prefix+"all-sites %s;\n"%string.join(
+       w.write(prefix+"all-sites %s;\n"%",".join(
                map(lambda x:"%svpn/%s/all-sites"%(prefix,x),
-                       root.children.keys()),","))
-
-# Are we being invoked from userv?
-service=0
-# If we are, which group does the caller want to modify?
-group=None
+                       root.children.keys())))
 
 line=0
 file=None
 complaints=0
 
-if len(sys.argv)<2:
-       inputfile=None
-       of=sys.stdout
-else:
-       if sys.argv[1]=='-u':
-               if len(sys.argv)!=6:
-                       print "Wrong number of arguments"
-                       sys.exit(1)
-               service=1
-               header=sys.argv[2]
-               groupfiledir=sys.argv[3]
-               sitesfile=sys.argv[4]
-               group=sys.argv[5]
-               if not os.environ.has_key("USERV_USER"):
-                       print "Environment variable USERV_USER not found"
-                       sys.exit(1)
-               user=os.environ["USERV_USER"]
-               # Check that group is in USERV_GROUP
-               if not os.environ.has_key("USERV_GROUP"):
-                       print "Environment variable USERV_GROUP not found"
-                       sys.exit(1)
-               ugs=os.environ["USERV_GROUP"]
-               ok=0
-               for i in string.split(ugs):
-                       if group==i: ok=1
-               if not ok:
-                       print "caller not in group %s"%group
-                       sys.exit(1)
-       else:
-               if sys.argv[1]=='-P':
-                       prefix=sys.argv[2]
-                       sys.argv[1:3]=[]
-               if len(sys.argv)>3:
-                       print "Too many arguments"
-                       sys.exit(1)
-               inputfile=sys.argv[1]
-               of=sys.stdout
-               if len(sys.argv)>2:
-                       of=open(sys.argv[2],'w')
-
 # Sanity check section
 # Delete nodes where leaf=0 that have no children
 
@@ -524,22 +530,22 @@ def checkconstraints(n,p,ra):
        new_p=p.copy()
        new_p.update(n.properties)
        for i in n.require_properties.keys():
-               if not new_p.has_key(i):
+               if i not in new_p:
                        moan("%s %s is missing property %s"%
                                (n.type,n.name,i))
        for i in new_p.keys():
-               if not n.allow_properties.has_key(i):
+               if i not in n.allow_properties:
                        moan("%s %s has forbidden property %s"%
                                (n.type,n.name,i))
        # Check address range restrictions
-       if n.properties.has_key("restrict-nets"):
+       if "restrict-nets" in n.properties:
                new_ra=ra.intersection(n.properties["restrict-nets"].set)
        else:
                new_ra=ra
-       if n.properties.has_key("networks"):
+       if "networks" in n.properties:
                if not n.properties["networks"].set <= new_ra:
                        moan("%s %s networks out of bounds"%(n.type,n.name))
-               if n.properties.has_key("peer"):
+               if "peer" in n.properties:
                        if not n.properties["networks"].set.contains(
                                n.properties["peer"].addr):
                                moan("%s %s peer not in networks"%(n.type,n.name))
@@ -560,8 +566,8 @@ delempty(root)
 checkconstraints(root,{},ipaddrset.complete_set())
 
 if complaints>0:
-       if complaints==1: print "There was 1 problem."
-       else: print "There were %d problems."%(complaints)
+       if complaints==1: print("There was 1 problem.")
+       else: print("There were %d problems."%(complaints))
        sys.exit(1)
 
 if service: