From b13332c991ce2695626eaca367dd8208b174c9ca Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 14 Apr 2016 17:59:24 +0300 Subject: Add support for repository authentication --- bpkg/auth | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 bpkg/auth (limited to 'bpkg/auth') diff --git a/bpkg/auth b/bpkg/auth new file mode 100644 index 0000000..54071b7 --- /dev/null +++ b/bpkg/auth @@ -0,0 +1,96 @@ +// file : bpkg/auth -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BPKG_AUTH +#define BPKG_AUTH + +#include + +#include +#include + +#include +#include + +namespace bpkg +{ + // Authenticate a repository certificate. If the configuration directory is + // NULL, then perform without a certificate database. If it is empty, then + // check if the current working directory is a configuration. If it is, then + // use its certificate database. Otherwise, continue as if it was NULL. All + // other values (including '.') are assumed to be valid configuration paths + // and will be diagnosed if that's not the case. + // + // If the configuration is used, then check if we are already in transaction. + // If so, then assume the configuration database is already opened and use + // that. Otherwise, open the database and start a new transaction. + // + // Note that one drawback of doing this as part of an existing transaction + // is that if things go south and the transaction gets aborted, then all the + // user's confirmations will be lost. For example, cfg-fetch could fail + // because it was unable to fetch some prerequisite repositories. + // + shared_ptr + authenticate_certificate (const common_options&, + const dir_path* configuration, + const optional& cert_pem, + const repository_location&); + + // Authenticate a repository. First check that the certificate can be used + // to authenticate this repository by making sure their names match. Then + // recover the packages manifest file SHA256 checksum from the signature + // and compare the calculated checksum to the recovered one. + // + // If the configuration directory is NULL, then create a temporary + // certificate PEM file (cert_pem must be present). If the directory is + // empty, then check if the current working directory is a configuration. + // If it's not, then continue as if it was NULL (cert_pem must be present). + // If it is, then continue as if a valid configuration directory was + // specified. All other values (including '.') are assumed to be valid + // configuration paths and will be diagnosed if that's not the case. In the + // case of a valid configuration use the certificate PEM file from the + // configuration (the file is supposed to have been created by the preceding + // authenticate_certificate() call). + // + void + authenticate_repository (const common_options&, + const dir_path* configuration, + const optional& cert_pem, + const certificate&, + const signature_manifest&, + const repository_location&); + + // Sign a repository by calculating its packages manifest file signature. + // This is done by encrypting the file's SHA256 checksum with the repository + // certificate's private key and then base64-encoding the result. Issue + // diagnstics and fail if the certificate has expired, and issue a warning + // if it expires in less than 2 months. The repository argument is used for + // diagnostics only. + // + // Note that currently we don't check if the key matches the certificate. A + // relatively easy way to accomplish this would be to execute the following + // commands and match the results: + // + // openssl x509 -noout -modulus -in cert.pem + // openssl rsa -noout -modulus -in key.pem + // + // But taking into account that we need to be able to use custom engines to + // access keys, it seems to be impossible to provide the same additional + // openssl options to fit both the rsa and pkeyutl commands. The first would + // require "-engine pkcs11 -inform engine", while the second -- "-engine + // pkcs11 -keyform engine". Also it would require to enter the key password + // again, which is a showstopper. Maybe the easiest would be to recover the + // sum back from the signature using the certificate, and compare it with + // the original sum (like we do in authenticate_repository()). But that + // would require to temporarily save the certificate to file. + // + std::vector + sign_repository (const common_options&, + const string& sha256sum, + const string& key_name, // --key option value + const string& cert_pem, + const dir_path& repository); +} + +#endif // BPKG_AUTH -- cgit v1.1