diff options
| -rw-r--r-- | README.md | 10 | ||||
| -rwxr-xr-x | sigsum-witness.py | 27 | ||||
| -rw-r--r-- | sigsum-witness_test.py | 66 | 
3 files changed, 95 insertions, 8 deletions
| @@ -9,3 +9,13 @@ The full license text can be found in the file LICENSE.  This license is also known as the BSD-2-Clause and the Simplified BSD  License. + +## Hacking + +### Running tests + +Use [`pytest`](https://docs.pytest.org/) to run the automated tests: + +``` +$ pytest . +``` diff --git a/sigsum-witness.py b/sigsum-witness.py index 15bfb07..ef63c4c 100755 --- a/sigsum-witness.py +++ b/sigsum-witness.py @@ -386,14 +386,10 @@ def generate_and_store_sigkey(fn):          f.write(signing_key.encode(encoder=nacl.encoding.HexEncoder).decode('ascii'))  def read_sigkeyfile(fn): -    s = os.stat(fn, follow_symlinks=False) -    if not S_ISREG(s.st_mode): -        return None, (ERR_SIGKEYFILE, -                      "ERROR: Signing key file {} must be a regular file".format(fn)) -    if S_IMODE(s.st_mode) & 0o077 != 0: -        return None, (ERR_SIGKEYFILE, -                      "ERROR: Signing key file {} permissions too lax: {:04o}".format(fn, S_IMODE(s.st_mode))) - +    try: +        check_sigkeyfile(fn) +    except SigKeyFileError as err: +        return None, (ERR_SIGKEYFILE, str(err))      with open(fn, 'r') as f:          try:              signing_key = nacl.signing.SigningKey(f.readline().strip(), nacl.encoding.HexEncoder) @@ -405,6 +401,21 @@ def read_sigkeyfile(fn):      return signing_key, None +def check_sigkeyfile(fn): +    try: +        s = os.stat(fn, follow_symlinks=True) +    except FileNotFoundError: +        raise SigKeyFileError(f"ERROR: File not found: {fn}") +    if not S_ISREG(s.st_mode): +        raise SigKeyFileError(f"ERROR: Signing key file {fn} must be a regular file") +    if S_IMODE(s.st_mode) & 0o077 != 0: +        raise SigKeyFileError(f"ERROR: Signing key file {fn} permissions too lax: {S_IMODE(s.st_mode):04o}") + + +class SigKeyFileError(Exception): +    pass + +  # Read signature key from file, or generate one and write it to file.  def ensure_sigkey(fn):      try: diff --git a/sigsum-witness_test.py b/sigsum-witness_test.py new file mode 100644 index 0000000..3c0241b --- /dev/null +++ b/sigsum-witness_test.py @@ -0,0 +1,66 @@ +import importlib + +import pytest + +witness = importlib.import_module("sigsum-witness")  # To import a module with a '-' + + +class Test_check_sigkeyfile: +    def test_file_ok(self, tmp_path): +        path = tmp_path / "key" +        path.touch(mode=0o700) +        witness.check_sigkeyfile(path) + +    def test_file_notfound(self, tmp_path): +        path = tmp_path / "key" +        with pytest.raises( +            witness.SigKeyFileError, +            match=f"ERROR: File not found: {path}", +        ): +            witness.check_sigkeyfile(path) + +    def test_notafile(self, tmp_path): +        path = tmp_path / "key" +        path.mkdir() +        with pytest.raises( +            witness.SigKeyFileError, +            match=f"ERROR: Signing key file {path} must be a regular file", +        ): +            witness.check_sigkeyfile(path) + +    def test_file_badmode(self, tmp_path): +        path = tmp_path / "key" +        path.touch(mode=0o755) +        with pytest.raises( +            witness.SigKeyFileError, +            match=f"ERROR: Signing key file {path} permissions too lax: 0755", +        ): +            witness.check_sigkeyfile(path) + +    def test_symlink_ok(self, tmp_path): +        filepath = tmp_path / "thekey" +        filepath.touch(mode=0o700) +        linkpath = tmp_path / "key" +        linkpath.symlink_to(filepath) +        assert witness.check_sigkeyfile(linkpath) is None + +    def test_symlink_badmode(self, tmp_path): +        filepath = tmp_path / "thekey" +        filepath.touch(mode=0o755) +        linkpath = tmp_path / "key" +        linkpath.symlink_to(filepath) +        with pytest.raises( +            witness.SigKeyFileError, +            match=f"ERROR: Signing key file {linkpath} permissions too lax: 0755", +        ): +            witness.check_sigkeyfile(linkpath) + +    def test_symlink_dangling(self, tmp_path): +        filepath = tmp_path / "thekey" +        linkpath = tmp_path / "key" +        linkpath.symlink_to(filepath) +        with pytest.raises( +            witness.SigKeyFileError, +            match=f"ERROR: File not found: {linkpath}", +        ): +            witness.check_sigkeyfile(linkpath) | 
