From 1aca7112d2a72bb36be50859d2e21bb3b726e741 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Sun, 9 Jan 2022 02:04:12 +0100 Subject: [PATCH] SOP commands: Throw UnsupportedSubcommand error when sop.command() returns null --- .../sop/cli/picocli/commands/ArmorCmd.java | 4 + .../sop/cli/picocli/commands/DearmorCmd.java | 6 ++ .../sop/cli/picocli/commands/DecryptCmd.java | 2 +- .../DetachInbandSignatureAndMessageCmd.java | 6 +- .../sop/cli/picocli/commands/EncryptCmd.java | 4 + .../cli/picocli/commands/ExtractCertCmd.java | 4 + .../cli/picocli/commands/GenerateKeyCmd.java | 4 + .../sop/cli/picocli/commands/SignCmd.java | 3 + .../sop/cli/picocli/commands/VerifyCmd.java | 4 + .../sop/cli/picocli/commands/VersionCmd.java | 4 + .../test/java/sop/cli/picocli/SOPTest.java | 88 +++++++++++++++++++ .../java/sop/exception/SOPGPException.java | 8 -- 12 files changed, 127 insertions(+), 10 deletions(-) diff --git a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/ArmorCmd.java b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/ArmorCmd.java index 139cfcdb..a015a688 100644 --- a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/ArmorCmd.java +++ b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/ArmorCmd.java @@ -25,6 +25,10 @@ public class ArmorCmd implements Runnable { @Override public void run() { Armor armor = SopCLI.getSop().armor(); + if (armor == null) { + throw new SOPGPException.UnsupportedSubcommand("Command 'armor' not implemented."); + } + if (label != null) { try { armor.label(label); diff --git a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/DearmorCmd.java b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/DearmorCmd.java index f3c62908..343b1135 100644 --- a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/DearmorCmd.java +++ b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/DearmorCmd.java @@ -10,6 +10,7 @@ import picocli.CommandLine; import sop.cli.picocli.Print; import sop.cli.picocli.SopCLI; import sop.exception.SOPGPException; +import sop.operation.Dearmor; @CommandLine.Command(name = "dearmor", description = "Remove ASCII Armor from standard input", @@ -18,6 +19,11 @@ public class DearmorCmd implements Runnable { @Override public void run() { + Dearmor dearmor = SopCLI.getSop().dearmor(); + if (dearmor == null) { + throw new SOPGPException.UnsupportedSubcommand("Command 'dearmor' not implemented."); + } + try { SopCLI.getSop() .dearmor() diff --git a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/DecryptCmd.java b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/DecryptCmd.java index 58f49db9..8fc4650b 100644 --- a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/DecryptCmd.java +++ b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/DecryptCmd.java @@ -94,7 +94,7 @@ public class DecryptCmd implements Runnable { Decrypt decrypt = SopCLI.getSop().decrypt(); if (decrypt == null) { - throw new SOPGPException.UnsupportedSubcommand("Subcommand 'decrypt' not implemented."); + throw new SOPGPException.UnsupportedSubcommand("Command 'decrypt' not implemented."); } setNotAfter(notAfter, decrypt); diff --git a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/DetachInbandSignatureAndMessageCmd.java b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/DetachInbandSignatureAndMessageCmd.java index 77471681..f5c71a2a 100644 --- a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/DetachInbandSignatureAndMessageCmd.java +++ b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/DetachInbandSignatureAndMessageCmd.java @@ -32,11 +32,15 @@ public class DetachInbandSignatureAndMessageCmd implements Runnable { @Override public void run() { + DetachInbandSignatureAndMessage detach = SopCLI.getSop().detachInbandSignatureAndMessage(); + if (detach == null) { + throw new SOPGPException.UnsupportedSubcommand("Command 'detach-inband-signature-and-message' not implemented."); + } + if (signaturesOut == null) { throw new SOPGPException.MissingArg("--signatures-out is required."); } - DetachInbandSignatureAndMessage detach = SopCLI.getSop().detachInbandSignatureAndMessage(); if (!armor) { detach.noArmor(); } diff --git a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/EncryptCmd.java b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/EncryptCmd.java index 2ccf0477..0634240b 100644 --- a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/EncryptCmd.java +++ b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/EncryptCmd.java @@ -51,6 +51,10 @@ public class EncryptCmd implements Runnable { @Override public void run() { Encrypt encrypt = SopCLI.getSop().encrypt(); + if (encrypt == null) { + throw new SOPGPException.UnsupportedSubcommand("Command 'encrypt' not implemented."); + } + if (type != null) { try { encrypt.mode(type); diff --git a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/ExtractCertCmd.java b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/ExtractCertCmd.java index 59656e65..f4559339 100644 --- a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/ExtractCertCmd.java +++ b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/ExtractCertCmd.java @@ -25,6 +25,10 @@ public class ExtractCertCmd implements Runnable { @Override public void run() { ExtractCert extractCert = SopCLI.getSop().extractCert(); + if (extractCert == null) { + throw new SOPGPException.UnsupportedSubcommand("Command 'extract-cert' not implemented."); + } + if (!armor) { extractCert.noArmor(); } diff --git a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/GenerateKeyCmd.java b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/GenerateKeyCmd.java index f97fcfa0..28bde279 100644 --- a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/GenerateKeyCmd.java +++ b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/GenerateKeyCmd.java @@ -31,6 +31,10 @@ public class GenerateKeyCmd implements Runnable { @Override public void run() { GenerateKey generateKey = SopCLI.getSop().generateKey(); + if (generateKey == null) { + throw new SOPGPException.UnsupportedSubcommand("Command 'generate-key' not implemented."); + } + for (String userId : userId) { generateKey.userId(userId); } diff --git a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/SignCmd.java b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/SignCmd.java index 250679fd..7574923e 100644 --- a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/SignCmd.java +++ b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/SignCmd.java @@ -47,6 +47,9 @@ public class SignCmd implements Runnable { @Override public void run() { Sign sign = SopCLI.getSop().sign(); + if (sign == null) { + throw new SOPGPException.UnsupportedSubcommand("Command 'sign' not implemented."); + } if (type != null) { try { diff --git a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/VerifyCmd.java b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/VerifyCmd.java index d731b25a..2702b4b9 100644 --- a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/VerifyCmd.java +++ b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/VerifyCmd.java @@ -53,6 +53,10 @@ public class VerifyCmd implements Runnable { @Override public void run() { Verify verify = SopCLI.getSop().verify(); + if (verify == null) { + throw new SOPGPException.UnsupportedSubcommand("Command 'verify' not implemented."); + } + if (notAfter != null) { try { verify.notAfter(DateParser.parseNotAfter(notAfter)); diff --git a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/VersionCmd.java b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/VersionCmd.java index 0d5da1a6..6926c5c9 100644 --- a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/VersionCmd.java +++ b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/VersionCmd.java @@ -7,6 +7,7 @@ package sop.cli.picocli.commands; import picocli.CommandLine; import sop.cli.picocli.Print; import sop.cli.picocli.SopCLI; +import sop.exception.SOPGPException; import sop.operation.Version; @CommandLine.Command(name = "version", description = "Display version information about the tool", @@ -16,6 +17,9 @@ public class VersionCmd implements Runnable { @Override public void run() { Version version = SopCLI.getSop().version(); + if (version == null) { + throw new SOPGPException.UnsupportedSubcommand("Command 'version' not implemented."); + } Print.outln(version.getName() + " " + version.getVersion()); } diff --git a/sop-java-picocli/src/test/java/sop/cli/picocli/SOPTest.java b/sop-java-picocli/src/test/java/sop/cli/picocli/SOPTest.java index fbf4cfa7..6360a779 100644 --- a/sop-java-picocli/src/test/java/sop/cli/picocli/SOPTest.java +++ b/sop-java-picocli/src/test/java/sop/cli/picocli/SOPTest.java @@ -4,11 +4,26 @@ package sop.cli.picocli; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + import com.ginsberg.junit.exit.ExpectSystemExitWithStatus; import org.junit.jupiter.api.Test; import sop.SOP; +import sop.operation.Armor; +import sop.operation.Dearmor; +import sop.operation.Decrypt; +import sop.operation.DetachInbandSignatureAndMessage; +import sop.operation.Encrypt; +import sop.operation.ExtractCert; +import sop.operation.GenerateKey; +import sop.operation.Sign; +import sop.operation.Verify; +import sop.operation.Version; public class SOPTest { @@ -28,4 +43,77 @@ public class SOPTest { // At this point, no SOP backend is set, so an InvalidStateException triggers exit(1) SopCLI.main(new String[] {"armor"}); } + + @Test + public void UnsupportedSubcommandsTest() { + SOP nullCommandSOP = new SOP() { + @Override + public Version version() { + return null; + } + + @Override + public GenerateKey generateKey() { + return null; + } + + @Override + public ExtractCert extractCert() { + return null; + } + + @Override + public Sign sign() { + return null; + } + + @Override + public Verify verify() { + return null; + } + + @Override + public Encrypt encrypt() { + return null; + } + + @Override + public Decrypt decrypt() { + return null; + } + + @Override + public Armor armor() { + return null; + } + + @Override + public Dearmor dearmor() { + return null; + } + + @Override + public DetachInbandSignatureAndMessage detachInbandSignatureAndMessage() { + return null; + } + }; + SopCLI.setSopInstance(nullCommandSOP); + + List commands = new ArrayList<>(); + commands.add(new String[] {"armor"}); + commands.add(new String[] {"dearmor"}); + commands.add(new String[] {"decrypt"}); + commands.add(new String[] {"detach-inband-signature-and-message"}); + commands.add(new String[] {"encrypt"}); + commands.add(new String[] {"extract-cert"}); + commands.add(new String[] {"generate-key"}); + commands.add(new String[] {"sign"}); + commands.add(new String[] {"verify", "signature.asc", "cert.asc"}); + commands.add(new String[] {"version"}); + + for (String[] command : commands) { + int exit = SopCLI.execute(command); + assertEquals(69, exit, "Unexpected exit code for non-implemented command " + Arrays.toString(command) + ": " + exit); + } + } } diff --git a/sop-java/src/main/java/sop/exception/SOPGPException.java b/sop-java/src/main/java/sop/exception/SOPGPException.java index dfd09540..6b844f59 100644 --- a/sop-java/src/main/java/sop/exception/SOPGPException.java +++ b/sop-java/src/main/java/sop/exception/SOPGPException.java @@ -52,10 +52,6 @@ public abstract class SOPGPException extends RuntimeException { super(message, e); } - public UnsupportedAsymmetricAlgo(Throwable e) { - super(e); - } - @Override public int getExitCode() { return EXIT_CODE; @@ -308,10 +304,6 @@ public abstract class SOPGPException extends RuntimeException { super(); } - public KeyCannotSign(String message) { - super(message); - } - public KeyCannotSign(String s, KeyCannotSign keyCannotSign) { super(s, keyCannotSign); }