Compare commits

...

10 commits

12 changed files with 80 additions and 51 deletions

View file

@ -120,6 +120,9 @@ class ExternalSOP(
val errorMessage = readString(errIn)
when (exitCode) {
UnspecificFailure.EXIT_CODE ->
throw UnspecificFailure(
"External SOP backend reported an unspecific error ($exitCode):\n$errorMessage")
NoSignature.EXIT_CODE ->
throw NoSignature(
"External SOP backend reported error NoSignature ($exitCode):\n$errorMessage")
@ -182,13 +185,16 @@ class ExternalSOP(
"External SOP backend reported error NoHardwareKeyFound ($exitCode):\n$errorMessage")
HardwareKeyFailure.EXIT_CODE ->
throw HardwareKeyFailure(
"External SOP backend reported error HardwareKeyFalure ($exitCode):\n$errorMessage")
"External SOP backend reported error HardwareKeyFailure ($exitCode):\n$errorMessage")
PrimaryKeyBad.EXIT_CODE ->
throw PrimaryKeyBad(
"External SOP backend reported error PrimaryKeyBad ($exitCode):\n$errorMessage")
CertUserIdNoMatch.EXIT_CODE ->
throw CertUserIdNoMatch(
"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?
else ->

View file

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

View file

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

View file

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

View file

@ -0,0 +1,13 @@
// 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

@ -0,0 +1,13 @@
// 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

@ -0,0 +1,13 @@
// 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
@Option(names = ["--stacktrace"], scope = ScopeType.INHERIT)
@Option(names = ["--stacktrace", "--debug"], scope = ScopeType.INHERIT)
var stacktrace = false
@JvmStatic

View file

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

View file

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

View file

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

View file

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