chiark / gitweb /
make-secnet-sites: Check input file word syntax
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 24 Oct 2019 14:10:29 +0000 (15:10 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 24 Oct 2019 18:16:17 +0000 (19:16 +0100)
commit410f5f2601e71101cebb2fef0f7c12725d36bfd8
tree32c58eb91f81ea70f42931eb41f0a143434c5907
parente5baf0cd0e91353194df02c4c376b0c472f49ec2
make-secnet-sites: Check input file word syntax

make-secnet sites sometimes reads untrusted input.  And we copy it to
various output files, including secnet configuration files which have
a different lexical syntax and are particularly vulnerable to a
syntax stuffing/inadequate escaping attack.

In principle we could quote everything appropriately on output but a
actually we probably just want to check it since the syntax of all
these directives and their parameters is quite restricted.

In order to ensure that we catch everything, and that if we missed a
location we get a crash rather than a security vulnerability, we take
the following approach:

Each untrusted input word is wrapped up in a new Tainted object.  The
Tainted object has a number of methods for checking and returning
values which are suitable for various purposes.  But attempts to
simply print it (eg to an output file) are made to fail.

The Tainted object keeps track internally of whether it has been
checked.  This is going to be important in a moment.

Naive call sites use straightforward methods on w[N] to get checked
values for storage in their own data structures.

Knowledgeable use sites may call .raw() to get the unchecked value,
and .raw_mark_ok() if they know that the value is good (or are about
to do something which will definitely crash if not, so that a bad
value cannot escape).

Obviously storing the results of .raw() in a call site's data
structure would escape the taint checking.  So we don't do that unless
we have done the check ourselves.

Within the Tainted implication we really wanted an error monad.  Using
python exceptions for this looked like it was going to be too
abstruse.  So we open-code the monad with a conventional `ok' local
variable.  Each entrypoint returns using ._rtn() which can
double-check that no error has been lost.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
make-secnet-sites