Initial commit

This commit is contained in:
Paul Schaub 2022-03-01 15:53:24 +01:00
commit d18dfb1ca5
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
21 changed files with 1303 additions and 0 deletions

View file

@ -0,0 +1,73 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.cert_d.cli;
import org.pgpainless.certificate_store.CertificateReader;
import org.pgpainless.certificate_store.SharedPGPCertificateDirectoryAdapter;
import pgp.cert_d.BaseDirectoryProvider;
import pgp.cert_d.SharedPGPCertificateDirectoryImpl;
import pgp.cert_d.cli.commands.Get;
import pgp.cert_d.cli.commands.Import;
import pgp.cert_d.cli.commands.MultiImport;
import pgp.cert_d.jdbc.sqlite.DatabaseSubkeyLookup;
import pgp.cert_d.jdbc.sqlite.SqliteSubkeyLookupDaoImpl;
import pgp.certificate_store.SubkeyLookup;
import pgp.certificate_store.exception.NotAStoreException;
import pgp.certificate_store.CertificateDirectory;
import picocli.CommandLine;
import java.io.File;
import java.sql.SQLException;
@CommandLine.Command(
subcommands = {
Import.class,
MultiImport.class,
Get.class,
}
)
public class PGPCertDCli {
@CommandLine.Option(names = "--base-directory", paramLabel = "DIRECTORY", description = "Overwrite the default certificate directory")
File baseDirectory;
private static CertificateDirectory certificateDirectory;
private int executionStrategy(CommandLine.ParseResult parseResult) {
try {
initStore();
} catch (NotAStoreException | SQLException e) {
return -1;
}
return new CommandLine.RunLast().execute(parseResult);
}
private void initStore() throws NotAStoreException, SQLException {
SharedPGPCertificateDirectoryImpl certificateDirectory;
SubkeyLookup subkeyLookup;
if (baseDirectory == null) {
baseDirectory = BaseDirectoryProvider.getDefaultBaseDir();
}
certificateDirectory = new SharedPGPCertificateDirectoryImpl(
baseDirectory,
new CertificateReader());
subkeyLookup = new DatabaseSubkeyLookup(
SqliteSubkeyLookupDaoImpl.forDatabaseFile(new File(baseDirectory, "_pgpainless_subkey_map.db")));
PGPCertDCli.certificateDirectory = new SharedPGPCertificateDirectoryAdapter(certificateDirectory, subkeyLookup);
}
public static void main(String[] args) {
PGPCertDCli cli = new PGPCertDCli();
new CommandLine(cli)
.setExecutionStrategy(parserResult -> cli.executionStrategy(parserResult))
.execute(args);
}
public static CertificateDirectory getCertificateDirectory() {
return certificateDirectory;
}
}

View file

@ -0,0 +1,51 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.cert_d.cli.commands;
import java.io.IOException;
import org.bouncycastle.util.io.Streams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pgp.cert_d.cli.PGPCertDCli;
import pgp.certificate_store.Certificate;
import pgp.certificate_store.exception.BadDataException;
import pgp.certificate_store.exception.BadNameException;
import picocli.CommandLine;
@CommandLine.Command(name = "get",
description = "Retrieve certificates from the store")
public class Get implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(Get.class);
@CommandLine.Parameters(
paramLabel = "IDENTIFIER",
arity = "1",
description = "Certificate identifier (fingerprint or special name)"
)
String identifer;
@Override
public void run() {
try {
Certificate certificate = PGPCertDCli.getCertificateDirectory()
.getCertificate(identifer);
if (certificate == null) {
return;
}
Streams.pipeAll(certificate.getInputStream(), System.out);
} catch (IOException e) {
LOGGER.error("IO Error", e);
System.exit(-1);
} catch (BadDataException e) {
LOGGER.error("Certificate file contains bad data.", e);
System.exit(-1);
} catch (BadNameException e) {
LOGGER.error("Certificate fingerprint mismatch.", e);
System.exit(-1);
}
}
}

View file

@ -0,0 +1,49 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.cert_d.cli.commands;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pgp.cert_d.cli.PGPCertDCli;
import pgp.certificate_store.Certificate;
import pgp.certificate_store.MergeCallback;
import pgp.certificate_store.exception.BadDataException;
import picocli.CommandLine;
@CommandLine.Command(name = "import",
description = "Import or update a certificate")
public class Import implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(Import.class);
// TODO: Replace with proper merge callback
private final MergeCallback dummyMerge = new MergeCallback() {
@Override
public Certificate merge(Certificate data, Certificate existing) throws IOException {
return data;
}
};
@Override
public void run() {
try {
Certificate certificate = PGPCertDCli.getCertificateDirectory().insertCertificate(System.in, dummyMerge);
// CHECKSTYLE:OFF
System.out.println(certificate.getFingerprint());
// CHECKSTYLE:ON
} catch (IOException e) {
LOGGER.error("IO-Error.", e);
System.exit(-1);
} catch (InterruptedException e) {
LOGGER.error("Thread interrupted.", e);
System.exit(-1);
} catch (BadDataException e) {
LOGGER.error("Certificate contains bad data.", e);
System.exit(-1);
}
}
}

View file

@ -0,0 +1,62 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.cert_d.cli.commands;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.pgpainless.PGPainless;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pgp.cert_d.cli.PGPCertDCli;
import pgp.certificate_store.Certificate;
import pgp.certificate_store.MergeCallback;
import pgp.certificate_store.exception.BadDataException;
import picocli.CommandLine;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@CommandLine.Command(name = "multi-import",
description = "Import or update multiple certificates")
public class MultiImport implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(MultiImport.class);
// TODO: Replace with proper merge callback
private final MergeCallback dummyMerge = new MergeCallback() {
@Override
public Certificate merge(Certificate data, Certificate existing) throws IOException {
return data;
}
};
@Override
public void run() {
try {
PGPPublicKeyRingCollection certificates = PGPainless.readKeyRing().publicKeyRingCollection(System.in);
for (PGPPublicKeyRing cert : certificates) {
ByteArrayInputStream certIn = new ByteArrayInputStream(cert.getEncoded());
Certificate certificate = PGPCertDCli.getCertificateDirectory()
.insertCertificate(certIn, dummyMerge);
// CHECKSTYLE:OFF
System.out.println(certificate.getFingerprint());
// CHECKSTYLE:ON
}
} catch (IOException e) {
LOGGER.error("IO-Error.", e);
System.exit(-1);
} catch (InterruptedException e) {
LOGGER.error("Thread interrupted.", e);
System.exit(-1);
} catch (BadDataException e) {
LOGGER.error("Certificate contains bad data.", e);
System.exit(-1);
} catch (PGPException e) {
LOGGER.error("PGP Exception.", e);
System.exit(-1);
}
}
}

View file

@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: 2018 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
/**
* Subcommands.
*/
package pgp.cert_d.cli.commands;

View file

@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: 2018 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
/**
* Command Line Interface for the Shared PGP Certificate Directory.
*/
package pgp.cert_d.cli;