More tests

This commit is contained in:
Paul Schaub 2022-08-27 13:11:11 +02:00
parent 24f4e2d771
commit ceaa1e0c80
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
2 changed files with 161 additions and 61 deletions

View file

@ -0,0 +1,131 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.cert_d;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.Test;
import pgp.cert_d.backend.FileBasedCertificateDirectoryBackend;
import pgp.cert_d.dummy.TestKeyMaterialMerger;
import pgp.cert_d.dummy.TestKeyMaterialReaderBackend;
import pgp.cert_d.subkey_lookup.InMemorySubkeyLookup;
import pgp.cert_d.subkey_lookup.SubkeyLookup;
import pgp.certificate_store.certificate.Certificate;
import pgp.certificate_store.certificate.KeyMaterialMerger;
import pgp.certificate_store.certificate.KeyMaterialReaderBackend;
import pgp.certificate_store.exception.BadDataException;
import pgp.certificate_store.exception.BadNameException;
import pgp.certificate_store.exception.NotAStoreException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assumptions.assumeFalse;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
public class FileBasedPGPCertificateDirectoryTest {
private static final KeyMaterialMerger merger = new TestKeyMaterialMerger();
@Test
public void testFileBasedCertificateDirectoryTagChangesWhenFileChanges()
throws IOException, NotAStoreException, BadDataException, InterruptedException, BadNameException {
File tempDir = Files.createTempDirectory("file-based-changes").toFile();
tempDir.deleteOnExit();
PGPCertificateDirectory directory = PGPCertificateDirectories.fileBasedCertificateDirectory(
new TestKeyMaterialReaderBackend(),
tempDir,
new InMemorySubkeyLookup());
FileBasedCertificateDirectoryBackend.FilenameResolver resolver =
new FileBasedCertificateDirectoryBackend.FilenameResolver(tempDir);
// Insert certificate
Certificate certificate = directory.insert(TestKeys.getCedricCert(), merger);
Long tag = certificate.getTag();
assertNotNull(tag);
assertNull(directory.getByFingerprintIfChanged(certificate.getFingerprint(), tag));
Long oldTag = tag;
Thread.sleep(10);
// Change the file on disk directly, this invalidates the tag due to changed modification date
File certFile = resolver.getCertFileByFingerprint(certificate.getFingerprint());
FileOutputStream fileOut = new FileOutputStream(certFile);
Streams.pipeAll(certificate.getInputStream(), fileOut);
fileOut.write("\n".getBytes());
fileOut.close();
// Old invalidated tag indicates a change, so the modified certificate is returned
certificate = directory.getByFingerprintIfChanged(certificate.getFingerprint(), oldTag);
assertNotNull(certificate);
// new tag is valid
tag = certificate.getTag();
assertNotEquals(oldTag, tag);
assertNull(directory.getByFingerprintIfChanged(certificate.getFingerprint(), tag));
}
@Test
public void fileBasedStoreInWriteProtectedAreaThrows() {
File root = new File("/");
assumeTrue(root.exists(), "This test only runs on unix-like systems");
File baseDirectory = new File(root, "pgp.cert.d");
assumeFalse(baseDirectory.mkdirs(), "This test assumes that we cannot create dirs in /");
KeyMaterialReaderBackend reader = new TestKeyMaterialReaderBackend();
SubkeyLookup lookup = new InMemorySubkeyLookup();
assertThrows(NotAStoreException.class, () -> PGPCertificateDirectories.fileBasedCertificateDirectory(
reader, baseDirectory, lookup));
}
@Test
public void fileBasedStoreOnFileThrows()
throws IOException {
File tempDir = Files.createTempDirectory("containsAFile").toFile();
tempDir.deleteOnExit();
File baseDir = new File(tempDir, "pgp.cert.d");
baseDir.createNewFile(); // this is a file, not a dir
KeyMaterialReaderBackend reader = new TestKeyMaterialReaderBackend();
SubkeyLookup lookup = new InMemorySubkeyLookup();
assertThrows(NotAStoreException.class, () -> PGPCertificateDirectories.fileBasedCertificateDirectory(
reader, baseDir, lookup));
}
@Test
public void testCertificateStoredUnderWrongFingerprintThrowsBadData()
throws IOException, NotAStoreException, BadDataException, InterruptedException, BadNameException {
File tempDir = Files.createTempDirectory("wrong-fingerprint").toFile();
tempDir.deleteOnExit();
PGPCertificateDirectory directory = PGPCertificateDirectories.fileBasedCertificateDirectory(
new TestKeyMaterialReaderBackend(),
tempDir,
new InMemorySubkeyLookup());
FileBasedCertificateDirectoryBackend.FilenameResolver resolver =
new FileBasedCertificateDirectoryBackend.FilenameResolver(tempDir);
// Insert Rons certificate
directory.insert(TestKeys.getRonCert(), merger);
// Copy Rons cert to Cedrics cert file
File ronCert = resolver.getCertFileByFingerprint(TestKeys.RON_FP);
FileInputStream inputStream = new FileInputStream(ronCert);
File cedricCert = resolver.getCertFileByFingerprint(TestKeys.CEDRIC_FP);
cedricCert.getParentFile().mkdirs();
cedricCert.createNewFile();
FileOutputStream outputStream = new FileOutputStream(cedricCert);
Streams.pipeAll(inputStream, outputStream);
inputStream.close();
outputStream.close();
// Reading cedrics cert will fail, as it has Rons fingerprint
assertThrows(BadDataException.class, () -> directory.getByFingerprint(TestKeys.CEDRIC_FP));
}
}

View file

@ -6,27 +6,22 @@ package pgp.cert_d;
import org.bouncycastle.util.io.Streams; import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.Named; import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import pgp.cert_d.backend.FileBasedCertificateDirectoryBackend;
import pgp.cert_d.dummy.TestKeyMaterialMerger; import pgp.cert_d.dummy.TestKeyMaterialMerger;
import pgp.cert_d.dummy.TestKeyMaterialReaderBackend; import pgp.cert_d.dummy.TestKeyMaterialReaderBackend;
import pgp.cert_d.subkey_lookup.InMemorySubkeyLookup; import pgp.cert_d.subkey_lookup.InMemorySubkeyLookup;
import pgp.cert_d.subkey_lookup.SubkeyLookup;
import pgp.certificate_store.certificate.Certificate; import pgp.certificate_store.certificate.Certificate;
import pgp.certificate_store.certificate.Key; import pgp.certificate_store.certificate.Key;
import pgp.certificate_store.certificate.KeyMaterial; import pgp.certificate_store.certificate.KeyMaterial;
import pgp.certificate_store.certificate.KeyMaterialMerger; import pgp.certificate_store.certificate.KeyMaterialMerger;
import pgp.certificate_store.certificate.KeyMaterialReaderBackend;
import pgp.certificate_store.exception.BadDataException; import pgp.certificate_store.exception.BadDataException;
import pgp.certificate_store.exception.BadNameException; import pgp.certificate_store.exception.BadNameException;
import pgp.certificate_store.exception.NotAStoreException; import pgp.certificate_store.exception.NotAStoreException;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.file.Files; import java.nio.file.Files;
@ -45,8 +40,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assumptions.assumeFalse;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import static pgp.cert_d.TestKeys.CEDRIC_FP; import static pgp.cert_d.TestKeys.CEDRIC_FP;
import static pgp.cert_d.TestKeys.HARRY_FP; import static pgp.cert_d.TestKeys.HARRY_FP;
import static pgp.cert_d.TestKeys.RON_FP; import static pgp.cert_d.TestKeys.RON_FP;
@ -277,66 +270,42 @@ public class PGPCertificateDirectoryTest {
assertNotNull(directory.getByFingerprintIfChanged(certificate.getFingerprint(), tag + 1)); assertNotNull(directory.getByFingerprintIfChanged(certificate.getFingerprint(), tag + 1));
} }
@Test @ParameterizedTest
public void testFileBasedCertificateDirectoryTagChangesWhenFileChanges() throws IOException, NotAStoreException, BadDataException, InterruptedException, BadNameException { @MethodSource("provideTestSubjects")
File tempDir = Files.createTempDirectory("file-based-changes").toFile(); public void testOverwriteTrustRoot(PGPCertificateDirectory directory)
tempDir.deleteOnExit(); throws BadDataException, IOException, InterruptedException {
PGPCertificateDirectory directory = PGPCertificateDirectories.fileBasedCertificateDirectory( directory.insertTrustRoot(TestKeys.getHarryKey(), merger);
new TestKeyMaterialReaderBackend(), assertEquals(HARRY_FP, directory.getTrustRoot().getFingerprint());
tempDir, assertTrue(directory.getTrustRoot() instanceof Key);
new InMemorySubkeyLookup());
FileBasedCertificateDirectoryBackend.FilenameResolver resolver =
new FileBasedCertificateDirectoryBackend.FilenameResolver(tempDir);
// Insert certificate directory.insertTrustRoot(TestKeys.getCedricCert(), merger);
Certificate certificate = directory.insert(TestKeys.getCedricCert(), merger); assertEquals(CEDRIC_FP, directory.getTrustRoot().getFingerprint());
Long tag = certificate.getTag(); assertTrue(directory.getTrustRoot() instanceof Certificate);
assertNotNull(tag);
assertNull(directory.getByFingerprintIfChanged(certificate.getFingerprint(), tag));
Long oldTag = tag;
Thread.sleep(10);
// Change the file on disk directly, this invalidates the tag due to changed modification date
File certFile = resolver.getCertFileByFingerprint(certificate.getFingerprint());
FileOutputStream fileOut = new FileOutputStream(certFile);
Streams.pipeAll(certificate.getInputStream(), fileOut);
fileOut.write("\n".getBytes());
fileOut.close();
// Old invalidated tag indicates a change, so the modified certificate is returned
certificate = directory.getByFingerprintIfChanged(certificate.getFingerprint(), oldTag);
assertNotNull(certificate);
// new tag is valid
tag = certificate.getTag();
assertNotEquals(oldTag, tag);
assertNull(directory.getByFingerprintIfChanged(certificate.getFingerprint(), tag));
} }
@Test @ParameterizedTest
public void fileBasedStoreInWriteProtectedAreaThrows() { @MethodSource("provideTestSubjects")
File root = new File("/"); public void testOverwriteSpecialName(PGPCertificateDirectory directory)
assumeTrue(root.exists(), "This test only runs on unix-like systems"); throws BadDataException, IOException, InterruptedException, BadNameException {
File baseDirectory = new File(root, "pgp.cert.d"); directory.insertWithSpecialName(SpecialNames.TRUST_ROOT, TestKeys.getRonCert(), merger);
assumeFalse(baseDirectory.mkdirs(), "This test assumes that we cannot create dirs in /"); KeyMaterial bySpecialName = directory.getBySpecialName(SpecialNames.TRUST_ROOT);
assertEquals(RON_FP, bySpecialName.getFingerprint());
KeyMaterialReaderBackend reader = new TestKeyMaterialReaderBackend(); directory.insertWithSpecialName(SpecialNames.TRUST_ROOT, TestKeys.getHarryKey(), merger);
SubkeyLookup lookup = new InMemorySubkeyLookup(); assertEquals(HARRY_FP, directory.getBySpecialName(SpecialNames.TRUST_ROOT).getFingerprint());
assertThrows(NotAStoreException.class, () -> PGPCertificateDirectories.fileBasedCertificateDirectory(
reader, baseDirectory, lookup));
} }
@Test @ParameterizedTest
public void fileBasedStoreOnFileThrows() throws IOException { @MethodSource("provideTestSubjects")
File tempDir = Files.createTempDirectory("containsAFile").toFile(); public void testOverwriteByFingerprint(PGPCertificateDirectory directory)
tempDir.deleteOnExit(); throws BadDataException, IOException, InterruptedException, BadNameException {
File baseDir = new File(tempDir, "pgp.cert.d"); directory.insert(TestKeys.getRonCert(), merger);
baseDir.createNewFile(); // this is a file, not a dir Certificate extracted = directory.getByFingerprint(RON_FP);
assertEquals(RON_FP, extracted.getFingerprint());
KeyMaterialReaderBackend reader = new TestKeyMaterialReaderBackend(); directory.insert(TestKeys.getRonCert(), merger);
SubkeyLookup lookup = new InMemorySubkeyLookup(); extracted = directory.getByFingerprint(RON_FP);
assertThrows(NotAStoreException.class, () -> PGPCertificateDirectories.fileBasedCertificateDirectory( assertEquals(RON_FP, extracted.getFingerprint());
reader, baseDir, lookup));
} }
} }