From 19482a2958faba86b49e8eede95ba56402d0ec74 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Thu, 24 Oct 2019 15:24:42 +0100 Subject: [PATCH] make-secnet-sites: Do not write out unchecked output in sites In principle our downstreams should be able to cope with this. But maybe they haven't had the fixes, and dumping strange stuff into the output file seems unfriendly. So reimplement copyout as a function which reassembles the output line from pieces, and checks that each Tainted word it is writing out has been verified by someone to be OK. As a side effect we normalise the whitespace including indentation. We rename the input line variable in pline from `i' to `il', since it contains possibly dangerous content. This makes sure we caught all of the places it is used. With these changes, it is necessary to add a couple of explicit calls to Tainted methods for otherwise-unused parameters, notably the group name in location() definitions in user-provided site fragments, and the (optional) email address in an ssh1 rsa key. Signed-off-by: Ian Jackson --- make-secnet-sites | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/make-secnet-sites b/make-secnet-sites index 55c66cc..845cdd5 100755 --- a/make-secnet-sites +++ b/make-secnet-sites @@ -136,6 +136,14 @@ class Tainted: # caller promises to throw if syntax was dangeorus return self._rtn(True) + def output(self): + if self._ok is False: return '' + if self._ok is True: return self._s + print('%s:%d: unchecked/unknown additional data "%s"' % + (self._file,self._line,self._s), + file=sys.stderr) + sys.exit(1) + bad_name=re.compile(r'^[^a-zA-Z]|[^-_0-9a-zA-Z]') # secnet accepts _ at start of names, but we reserve that bad_name_counter=0 @@ -345,6 +353,7 @@ class rsakey (basetype): self.l=w[1].number(0,max['rsa_bits'],'rsa len') self.e=w[2].bignum_10('rsa','rsa e') self.n=w[3].bignum_10('rsa','rsa n') + if len(w) >= 5: w[4].email() def __str__(self): return 'rsa-public("%s","%s")'%(self.e,self.n) @@ -537,15 +546,18 @@ def set_property(obj,w): else: obj.properties[prop.raw()]=keywords[prop.raw_mark_ok()][0](w) -def pline(i,allow_include=False): + +def pline(il,allow_include=False): "Process a configuration file line" global allow_defs, obstack, root - w=i.rstrip('\n').split() - if len(w)==0: return [i] + w=il.rstrip('\n').split() + if len(w)==0: return [''] w=list([Tainted(x) for x in w]) keyword=w[0] current=obstack[len(obstack)-1] - copyout=lambda: [i] + copyout=lambda: [' '*len(obstack) + + ' '.join([ww.output() for ww in w]) + + '\n'] if keyword=='end-definitions': keyword.raw_mark_ok() allow_defs=sitelevel.depth @@ -580,6 +592,7 @@ def pline(i,allow_include=False): if service and group and current.depth==2: if group!=current.group: complain("Incorrect group!") + w[2].groupname() else: # New # Ignore depth check for now -- 2.30.2