Compare commits

..

No commits in common. "b66888f695837b238e67d551fc454d846f078642" and "c2114dcd5a1308e40a05ae8fea62d562c5a31a8d" have entirely different histories.

12 changed files with 51 additions and 80 deletions

View file

@ -120,9 +120,6 @@ class ExternalSOP(
val errorMessage = readString(errIn) val errorMessage = readString(errIn)
when (exitCode) { when (exitCode) {
UnspecificFailure.EXIT_CODE ->
throw UnspecificFailure(
"External SOP backend reported an unspecific error ($exitCode):\n$errorMessage")
NoSignature.EXIT_CODE -> NoSignature.EXIT_CODE ->
throw NoSignature( throw NoSignature(
"External SOP backend reported error NoSignature ($exitCode):\n$errorMessage") "External SOP backend reported error NoSignature ($exitCode):\n$errorMessage")
@ -185,16 +182,13 @@ class ExternalSOP(
"External SOP backend reported error NoHardwareKeyFound ($exitCode):\n$errorMessage") "External SOP backend reported error NoHardwareKeyFound ($exitCode):\n$errorMessage")
HardwareKeyFailure.EXIT_CODE -> HardwareKeyFailure.EXIT_CODE ->
throw HardwareKeyFailure( throw HardwareKeyFailure(
"External SOP backend reported error HardwareKeyFailure ($exitCode):\n$errorMessage") "External SOP backend reported error HardwareKeyFalure ($exitCode):\n$errorMessage")
PrimaryKeyBad.EXIT_CODE -> PrimaryKeyBad.EXIT_CODE ->
throw PrimaryKeyBad( throw PrimaryKeyBad(
"External SOP backend reported error PrimaryKeyBad ($exitCode):\n$errorMessage") "External SOP backend reported error PrimaryKeyBad ($exitCode):\n$errorMessage")
CertUserIdNoMatch.EXIT_CODE -> CertUserIdNoMatch.EXIT_CODE ->
throw CertUserIdNoMatch( throw CertUserIdNoMatch(
"External SOP backend reported error CertUserIdNoMatch ($exitCode):\n$errorMessage") "External SOP backend reported error CertUserIdNoMatch ($exitCode):\n$errorMessage")
KeyCannotCertify.EXIT_CODE ->
throw KeyCannotCertify(
"External SOP backend reported error KeyCannotCertify ($exitCode):\n$errorMessage")
// Did you forget to add a case for a new exception type? // Did you forget to add a case for a new exception type?
else -> else ->

View file

@ -12,7 +12,7 @@ import sop.operation.CertifyUserId
class CertifyUserIdExternal(binary: String, environment: Properties) : CertifyUserId { class CertifyUserIdExternal(binary: String, environment: Properties) : CertifyUserId {
private val commandList = mutableListOf(binary, "certify-userid") private val commandList = mutableListOf(binary, "version")
private val envList = ExternalSOP.propertiesToEnv(environment).toMutableList() private val envList = ExternalSOP.propertiesToEnv(environment).toMutableList()
private var argCount = 0 private var argCount = 0
@ -44,5 +44,5 @@ class CertifyUserIdExternal(binary: String, environment: Properties) : CertifyUs
override fun certs(certs: InputStream): Ready = override fun certs(certs: InputStream): Ready =
ExternalSOP.executeTransformingOperation( ExternalSOP.executeTransformingOperation(
Runtime.getRuntime(), commandList.plus("--").plus(keys), envList, certs) Runtime.getRuntime(), commandList.plus(keys), envList, certs)
} }

View file

@ -12,7 +12,7 @@ import sop.operation.MergeCerts
class MergeCertsExternal(binary: String, environment: Properties) : MergeCerts { class MergeCertsExternal(binary: String, environment: Properties) : MergeCerts {
private val commandList = mutableListOf(binary, "merge-certs") private val commandList = mutableListOf(binary, "version")
private val envList = ExternalSOP.propertiesToEnv(environment).toMutableList() private val envList = ExternalSOP.propertiesToEnv(environment).toMutableList()
private var argCount = 0 private var argCount = 0

View file

@ -12,7 +12,7 @@ import sop.util.UTCUtil
class ValidateUserIdExternal(binary: String, environment: Properties) : ValidateUserId { class ValidateUserIdExternal(binary: String, environment: Properties) : ValidateUserId {
private val commandList = mutableListOf(binary, "validate-userid") private val commandList = mutableListOf(binary, "version")
private val envList = ExternalSOP.propertiesToEnv(environment).toMutableList() private val envList = ExternalSOP.propertiesToEnv(environment).toMutableList()
private var argCount = 0 private var argCount = 0

View file

@ -1,13 +0,0 @@
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package sop.testsuite.external.operation;
import org.junit.jupiter.api.condition.EnabledIf;
import sop.testsuite.operation.CertifyValidateUserIdTest;
@EnabledIf("sop.testsuite.operation.AbstractSOPTest#hasBackends")
public class ExternalCertifyValidateUserIdTest extends CertifyValidateUserIdTest {
}

View file

@ -1,13 +0,0 @@
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package sop.testsuite.external.operation;
import org.junit.jupiter.api.condition.EnabledIf;
import sop.testsuite.operation.ChangeKeyPasswordTest;
@EnabledIf("sop.testsuite.operation.AbstractSOPTest#hasBackends")
public class ExternalChangeKeyPasswordTest extends ChangeKeyPasswordTest {
}

View file

@ -1,13 +0,0 @@
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package sop.testsuite.external.operation;
import org.junit.jupiter.api.condition.EnabledIf;
import sop.testsuite.operation.MergeCertsTest;
@EnabledIf("sop.testsuite.operation.AbstractSOPTest#hasBackends")
public class ExternalMergeCertsTest extends MergeCertsTest {
}

View file

@ -64,7 +64,7 @@ class SopCLI {
@JvmField var EXECUTABLE_NAME = "sop" @JvmField var EXECUTABLE_NAME = "sop"
@JvmField @JvmField
@Option(names = ["--stacktrace", "--debug"], scope = ScopeType.INHERIT) @Option(names = ["--stacktrace"], scope = ScopeType.INHERIT)
var stacktrace = false var stacktrace = false
@JvmStatic @JvmStatic

View file

@ -45,7 +45,7 @@ class SopVCLI {
@JvmField var EXECUTABLE_NAME = "sopv" @JvmField var EXECUTABLE_NAME = "sopv"
@JvmField @JvmField
@CommandLine.Option(names = ["--stacktrace", "--debug"], scope = CommandLine.ScopeType.INHERIT) @CommandLine.Option(names = ["--stacktrace"], scope = CommandLine.ScopeType.INHERIT)
var stacktrace = false var stacktrace = false
@JvmStatic @JvmStatic

View file

@ -14,6 +14,7 @@ import sop.exception.SOPGPException;
import java.io.IOException; import java.io.IOException;
import java.util.stream.Stream; import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertFalse;
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;
@ -46,17 +47,16 @@ public class CertifyValidateUserIdTest {
// Alice has her own user-id self-certified // Alice has her own user-id self-certified
assertTrue(sop.validateUserId() assertTrue(sop.validateUserId()
.authorities(aliceCert) .authorities(aliceCert)
.userId("Alice <alice@pgpainless.org>") .userId("Alice <alice@pgpainless.org>")
.subjects(aliceCert), .subjects(aliceCert),
"Alice accepts her own self-certified user-id"); "Alice accepts her own self-certified user-id");
// Alice has not yet certified Bobs user-id // Alice has not yet certified Bobs user-id
assertThrows(SOPGPException.CertUserIdNoMatch.class, () -> assertFalse(sop.validateUserId()
sop.validateUserId() .authorities(aliceCert)
.authorities(aliceCert) .userId("Bob <bob@pgpainless.org>")
.userId("Bob <bob@pgpainless.org>") .subjects(bobCert),
.subjects(bobCert),
"Alice has not yet certified Bobs user-id"); "Alice has not yet certified Bobs user-id");
byte[] bobCertifiedByAlice = sop.certifyUserId() byte[] bobCertifiedByAlice = sop.certifyUserId()
@ -67,10 +67,10 @@ public class CertifyValidateUserIdTest {
.getBytes(); .getBytes();
assertTrue(sop.validateUserId() assertTrue(sop.validateUserId()
.userId("Bob <bob@pgpainless.org>") .userId("Bob <bob@pgpainless.org>")
.authorities(aliceCert) .authorities(aliceCert)
.subjects(bobCertifiedByAlice), .subjects(bobCertifiedByAlice),
"Alice accepts Bobs user-id after she certified it"); "Alice accepts Bobs user-id after she certified it");
} }
@ParameterizedTest @ParameterizedTest
@ -132,11 +132,11 @@ public class CertifyValidateUserIdTest {
.getBytes(); .getBytes();
assertThrows(SOPGPException.CertUserIdNoMatch.class, () -> assertThrows(SOPGPException.CertUserIdNoMatch.class, () ->
sop.certifyUserId() sop.certifyUserId()
.userId("Bobby") .userId("Bobby")
.keys(aliceKey) .keys(aliceKey)
.certs(bobCert) .certs(bobCert)
.getBytes(), .getBytes(),
"Alice cannot create a pet-name for Bob without the --no-require-self-sig flag"); "Alice cannot create a pet-name for Bob without the --no-require-self-sig flag");
byte[] bobWithPetName = sop.certifyUserId() byte[] bobWithPetName = sop.certifyUserId()
@ -147,16 +147,15 @@ public class CertifyValidateUserIdTest {
.getBytes(); .getBytes();
assertTrue(sop.validateUserId() assertTrue(sop.validateUserId()
.userId("Bobby") .userId("Bobby")
.authorities(aliceCert) .authorities(aliceCert)
.subjects(bobWithPetName), .subjects(bobWithPetName),
"Alice accepts the pet-name she gave to Bob"); "Alice accepts the pet-name she gave to Bob");
assertThrows(SOPGPException.CertUserIdNoMatch.class, () -> assertFalse(sop.validateUserId()
sop.validateUserId() .userId("Bobby")
.userId("Bobby") .authorities(bobWithPetName)
.authorities(bobWithPetName) .subjects(bobWithPetName),
.subjects(bobWithPetName),
"Bob does not accept the pet-name Alice gave him"); "Bob does not accept the pet-name Alice gave him");
} }

View file

@ -119,9 +119,7 @@ public class GenerateKeyTest extends AbstractSOPTest {
assertThrows(SOPGPException.CertCannotEncrypt.class, () -> assertThrows(SOPGPException.CertCannotEncrypt.class, () ->
sop.encrypt().withCert(signingOnlyCert) sop.encrypt().withCert(signingOnlyCert)
.plaintext(TestData.PLAINTEXT.getBytes(StandardCharsets.UTF_8)) .plaintext(TestData.PLAINTEXT.getBytes(StandardCharsets.UTF_8)));
.toByteArrayAndResult()
.getBytes());
} }
@ParameterizedTest @ParameterizedTest

View file

@ -25,15 +25,18 @@ public class MergeCertsTest extends AbstractSOPTest {
@MethodSource("provideInstances") @MethodSource("provideInstances")
public void testMergeWithItself(SOP sop) throws IOException { public void testMergeWithItself(SOP sop) throws IOException {
byte[] key = sop.generateKey() byte[] key = sop.generateKey()
.noArmor()
.userId("Alice <alice@pgpainless.org>") .userId("Alice <alice@pgpainless.org>")
.generate() .generate()
.getBytes(); .getBytes();
byte[] cert = sop.extractCert() byte[] cert = sop.extractCert()
.noArmor()
.key(key) .key(key)
.getBytes(); .getBytes();
byte[] merged = sop.mergeCerts() byte[] merged = sop.mergeCerts()
.noArmor()
.updates(cert) .updates(cert)
.baseCertificates(cert) .baseCertificates(cert)
.getBytes(); .getBytes();
@ -66,17 +69,20 @@ public class MergeCertsTest extends AbstractSOPTest {
@MethodSource("provideInstances") @MethodSource("provideInstances")
public void testMergeWithItselfViaBase(SOP sop) throws IOException { public void testMergeWithItselfViaBase(SOP sop) throws IOException {
byte[] key = sop.generateKey() byte[] key = sop.generateKey()
.noArmor()
.userId("Alice <alice@pgpainless.org>") .userId("Alice <alice@pgpainless.org>")
.generate() .generate()
.getBytes(); .getBytes();
byte[] cert = sop.extractCert() byte[] cert = sop.extractCert()
.noArmor()
.key(key) .key(key)
.getBytes(); .getBytes();
byte[] certs = ArraysKt.plus(cert, cert); byte[] certs = ArraysKt.plus(cert, cert);
byte[] merged = sop.mergeCerts() byte[] merged = sop.mergeCerts()
.noArmor()
.updates(cert) .updates(cert)
.baseCertificates(certs) .baseCertificates(certs)
.getBytes(); .getBytes();
@ -88,19 +94,23 @@ public class MergeCertsTest extends AbstractSOPTest {
@MethodSource("provideInstances") @MethodSource("provideInstances")
public void testApplyBaseToUpdate(SOP sop) throws IOException { public void testApplyBaseToUpdate(SOP sop) throws IOException {
byte[] key = sop.generateKey() byte[] key = sop.generateKey()
.noArmor()
.userId("Alice <alice@pgpainless.org>") .userId("Alice <alice@pgpainless.org>")
.generate() .generate()
.getBytes(); .getBytes();
byte[] cert = sop.extractCert() byte[] cert = sop.extractCert()
.noArmor()
.key(key) .key(key)
.getBytes(); .getBytes();
byte[] update = sop.revokeKey() byte[] update = sop.revokeKey()
.noArmor()
.keys(key) .keys(key)
.getBytes(); .getBytes();
byte[] merged = sop.mergeCerts() byte[] merged = sop.mergeCerts()
.noArmor()
.updates(cert) .updates(cert)
.baseCertificates(update) .baseCertificates(update)
.getBytes(); .getBytes();
@ -112,19 +122,23 @@ public class MergeCertsTest extends AbstractSOPTest {
@MethodSource("provideInstances") @MethodSource("provideInstances")
public void testApplyUpdateToBase(SOP sop) throws IOException { public void testApplyUpdateToBase(SOP sop) throws IOException {
byte[] key = sop.generateKey() byte[] key = sop.generateKey()
.noArmor()
.userId("Alice <alice@pgpainless.org>") .userId("Alice <alice@pgpainless.org>")
.generate() .generate()
.getBytes(); .getBytes();
byte[] cert = sop.extractCert() byte[] cert = sop.extractCert()
.noArmor()
.key(key) .key(key)
.getBytes(); .getBytes();
byte[] update = sop.revokeKey() byte[] update = sop.revokeKey()
.noArmor()
.keys(key) .keys(key)
.getBytes(); .getBytes();
byte[] merged = sop.mergeCerts() byte[] merged = sop.mergeCerts()
.noArmor()
.updates(update) .updates(update)
.baseCertificates(cert) .baseCertificates(cert)
.getBytes(); .getBytes();
@ -136,24 +150,29 @@ public class MergeCertsTest extends AbstractSOPTest {
@MethodSource("provideInstances") @MethodSource("provideInstances")
public void testApplyUpdateToMissingBaseDoesNothing(SOP sop) throws IOException { public void testApplyUpdateToMissingBaseDoesNothing(SOP sop) throws IOException {
byte[] aliceKey = sop.generateKey() byte[] aliceKey = sop.generateKey()
.noArmor()
.userId("Alice <alice@pgpainless.org>") .userId("Alice <alice@pgpainless.org>")
.generate() .generate()
.getBytes(); .getBytes();
byte[] aliceCert = sop.extractCert() byte[] aliceCert = sop.extractCert()
.noArmor()
.key(aliceKey) .key(aliceKey)
.getBytes(); .getBytes();
byte[] bobKey = sop.generateKey() byte[] bobKey = sop.generateKey()
.noArmor()
.userId("Bob <bob@pgpainless.org>") .userId("Bob <bob@pgpainless.org>")
.generate() .generate()
.getBytes(); .getBytes();
byte[] bobCert = sop.extractCert() byte[] bobCert = sop.extractCert()
.noArmor()
.key(bobKey) .key(bobKey)
.getBytes(); .getBytes();
byte[] merged = sop.mergeCerts() byte[] merged = sop.mergeCerts()
.noArmor()
.updates(bobCert) .updates(bobCert)
.baseCertificates(aliceCert) .baseCertificates(aliceCert)
.getBytes(); .getBytes();