1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
// file : bpkg/auth.hxx -*- C++ -*-
// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
#ifndef BPKG_AUTH_HXX
#define BPKG_AUTH_HXX
#include <libbpkg/manifest.hxx>
#include <bpkg/types.hxx>
#include <bpkg/utility.hxx>
#include <bpkg/package.hxx>
#include <bpkg/common-options.hxx>
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, rep-fetch could fail
// because it was unable to fetch some prerequisite repositories.
//
shared_ptr<const certificate>
authenticate_certificate (const common_options&,
const dir_path* configuration,
const optional<string>& 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<string>& 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<char>
sign_repository (const common_options&,
const string& sha256sum,
const string& key_name, // --key option value
const string& cert_pem,
const dir_path& repository);
// Parse a repository certificate. The repository location argument is used
// for diagnostics only.
//
shared_ptr<certificate>
parse_certificate (const common_options&,
const string& cert_pem,
const repository_location&);
}
#endif // BPKG_AUTH_HXX
|