aboutsummaryrefslogtreecommitdiff
path: root/bpkg/auth.hxx
blob: 90f60e42ea2a40814e9054a5b66e549fb517ba5b (plain)
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