winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

add-server-certificate-validation.patch (9698B)


      1 From 888b4ed8f4f7d25cb05a47210e083fe29348163b Mon Sep 17 00:00:00 2001
      2 From: JohnMcPMS <johnmcp@microsoft.com>
      3 Date: Wed, 27 Jul 2022 18:03:45 -0700
      4 Subject: [PATCH] Server certificate pinning for Store source (#2347)
      5 
      6 This change adds a generic certificate chain verification infrastructure for pinning certificate chains. It is specifically used to pin the Microsoft Store source by default. More sources may be pinned later, but currently the packaged index is less in need of it because it is already signed.
      7 
      8 The pinning configuration consists of 1 or more chains, only one of which needs to successfully validate the incoming certificate. This allows for rolling to a new certificate when needed. Each chain consists of a fixed set of certificates, which can each be configured to validate any or all of the following properties:
      9 
     10 - Public Key
     11 - Subject
     12 - Issuer
     13 
     14 If the certificate is configured to validate none of the values, it will allow any certificate through.
     15 
     16 An admin setting is added to disable pinning, both as an emergency measure in the event that there is a bug or rolled certificate that was not communicated, but also because there are test scenarios where the user actively wants to disable it (HTTPS redirection via something like Fiddler).
     17 
     18 The configuration can be loaded from JSON for future dynamic configuration, but it is currently only as a test hook to enable configuration via Group Policy.
     19 
     20 In order to better secure the source by default, reconfiguring (remove then add) the Store source manually will convert it back to the built-in values. This includes the pinning configuration.
     21 
     22 It was necessary to modify the cpprestsdk subtree to add a new callback. This enables the request handle to be passed back to our code when the server certificate is first available. We can then check the server certificate against the configured pinning chain, making a decision to terminate the request before it is sent.
     23 ---
     24  .github/actions/spelling/allow.txt            |   7 +-
     25  .github/actions/spelling/expect.txt           |  10 +
     26  src/AppInstallerCLI.sln                       |   8 +
     27  src/AppInstallerCLIE2ETests/BaseCommand.cs    |   6 +-
     28  src/AppInstallerCLIE2ETests/Constants.cs      |  11 +
     29  .../GroupPolicyHelper.cs                      |  44 ++
     30  src/AppInstallerCLIE2ETests/SearchCommand.cs  |  73 ++-
     31  src/AppInstallerCLIE2ETests/SetUpFixture.cs   |   2 +-
     32  src/AppInstallerCLIE2ETests/SourceCommand.cs  |   4 +-
     33  src/AppInstallerCLIE2ETests/TestCommon.cs     |  56 +-
     34  src/AppInstallerCLIE2ETests/TestIndexSetup.cs |   6 +-
     35  .../AppInstallerCLITests.vcxproj              |   2 +
     36  .../AppInstallerCLITests.vcxproj.filters      |   3 +
     37  src/AppInstallerCLITests/Certificates.cpp     | 185 ++++++
     38  src/AppInstallerCLITests/Command.cpp          |   2 +-
     39  src/AppInstallerCLITests/Completion.cpp       |  48 +-
     40  src/AppInstallerCLITests/GroupPolicy.cpp      |  60 +-
     41  src/AppInstallerCLITests/HttpClientHelper.cpp |  23 +
     42  src/AppInstallerCLITests/Sources.cpp          |  41 ++
     43  src/AppInstallerCLITests/Strings.cpp          |   9 +
     44  src/AppInstallerCommonCore/AdminSettings.cpp  | 146 +++--
     45  .../AppInstallerCommonCore.vcxproj            |   4 +
     46  .../AppInstallerCommonCore.vcxproj.filters    |   9 +
     47  .../AppInstallerStrings.cpp                   |  39 ++
     48  src/AppInstallerCommonCore/Certificates.cpp   | 549 ++++++++++++++++++
     49  src/AppInstallerCommonCore/Errors.cpp         |   2 +
     50  src/AppInstallerCommonCore/GroupPolicy.cpp    |  13 +
     51  .../JsonSchemaValidation.cpp                  |  36 +-
     52  .../Manifest/ManifestSchemaValidation.cpp     |   3 +-
     53  .../Public/AppInstallerErrors.h               |   1 +
     54  .../Public/AppInstallerStrings.h              |   6 +
     55  .../Public/winget/AdminSettings.h             |   1 +
     56  .../Public/winget/Certificates.h              | 153 +++++
     57  .../Public/winget/GroupPolicy.h               |  11 +-
     58  .../Public/winget/JsonSchemaValidation.h      |   5 +-
     59  .../Public/winget/Resources.h                 |  68 ++-
     60  src/AppInstallerCommonCore/Resources.cpp      |  58 ++
     61  src/AppInstallerCommonCore/SHA256.cpp         |  33 +-
     62  src/AppInstallerCommonCore/pch.h              |   1 +
     63  .../AppInstallerRepositoryCore.vcxproj        |   4 +-
     64  .../Public/winget/RepositorySource.h          |   8 +-
     65  .../RepositorySource.cpp                      |  24 +-
     66  .../Rest/RestSourceFactory.cpp                |   6 +-
     67  .../Rest/Schema/HttpClientHelper.cpp          |  26 +-
     68  .../Rest/Schema/HttpClientHelper.h            |  10 +-
     69  src/AppInstallerRepositoryCore/SourceList.cpp |  54 ++
     70  src/AppInstallerRepositoryCore/SourceList.h   |   1 +
     71  src/AppInstallerRepositoryCore/pch.h          |   1 +
     72  .../CertificateResources.h                    |   9 +
     73  .../CertificateResources.rc                   |  69 +++
     74  .../CertificateResources.vcxitems             |  28 +
     75  .../CertificateResources.vcxitems.filters     |  26 +
     76  .../StoreIntermediate1.cer                    | Bin 0 -> 1527 bytes
     77  src/CertificateResources/StoreLeaf1.cer       | Bin 0 -> 2642 bytes
     78  src/CertificateResources/StoreRoot1.cer       | Bin 0 -> 914 bytes
     79  src/CertificateResources/resource.h           |  14 +
     80  src/LocalhostWebServer/Program.cs             |  14 +-
     81  .../Run-LocalhostWebServer.ps1                |   2 +-
     82  src/LocalhostWebServer/Startup.cs             |   2 +
     83  .../Properties/Resources.Designer.cs          |   2 +-
     84  .../WindowsPackageManager.vcxproj             |   1 +
     85  .../Release/include/cpprest/http_client.h     |  27 +
     86  .../src/http/client/http_client_winhttp.cpp   |  12 +
     87  63 files changed, 1852 insertions(+), 226 deletions(-)
     88  create mode 100644 src/AppInstallerCLITests/Certificates.cpp
     89  create mode 100644 src/AppInstallerCommonCore/Certificates.cpp
     90  create mode 100644 src/AppInstallerCommonCore/Public/winget/Certificates.h
     91  create mode 100644 src/AppInstallerCommonCore/Resources.cpp
     92  create mode 100644 src/CertificateResources/CertificateResources.h
     93  create mode 100644 src/CertificateResources/CertificateResources.rc
     94  create mode 100644 src/CertificateResources/CertificateResources.vcxitems
     95  create mode 100644 src/CertificateResources/CertificateResources.vcxitems.filters
     96  create mode 100644 src/CertificateResources/StoreIntermediate1.cer
     97  create mode 100644 src/CertificateResources/StoreLeaf1.cer
     98  create mode 100644 src/CertificateResources/StoreRoot1.cer
     99  create mode 100644 src/CertificateResources/resource.h
    100 
    101 diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h
    102 index fb7c6067ab..b862a5778f 100644
    103 --- a/Release/include/cpprest/http_client.h
    104 +++ b/Release/include/cpprest/http_client.h
    105 @@ -362,6 +362,32 @@ class http_client_config
    106          if (m_set_user_nativehandle_options) m_set_user_nativehandle_options(handle);
    107      }
    108  
    109 +    /// <summary>
    110 +    /// Sets a callback to enable custom handling when the server certificate is available.
    111 +    /// </summary>
    112 +    /// <remarks>
    113 +    /// The native_handle is the following type depending on the underlying platform:
    114 +    ///     Windows Desktop, WinHTTP - HINTERNET !!! Is only implemented to call in here !!!
    115 +    ///     Windows Runtime, WinRT - IXMLHTTPRequest2 *
    116 +    ///     All other platforms, Boost.Asio:
    117 +    ///         https - boost::asio::ssl::stream<boost::asio::ip::tcp::socket &> *
    118 +    ///         http - boost::asio::ip::tcp::socket *
    119 +    /// </remarks>
    120 +    /// <param name="callback">A user callback allowing for validation of the server certificate.</param>
    121 +    void set_nativehandle_servercertificate_validation(const std::function<void(native_handle)>& callback)
    122 +    {
    123 +        m_nativehandle_servercertificate_validation = callback;
    124 +    }
    125 +
    126 +    /// <summary>
    127 +    /// Invokes a user's callback to validate the server certificate.
    128 +    /// </summary>
    129 +    /// <param name="handle">A internal implementation handle.</param>
    130 +    void invoke_nativehandle_servercertificate_validation(native_handle handle) const
    131 +    {
    132 +        if (m_nativehandle_servercertificate_validation) m_nativehandle_servercertificate_validation(handle);
    133 +    }
    134 +
    135  #if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO)
    136      /// <summary>
    137      /// Sets a callback to enable custom setting of the ssl context, at construction time.
    138 @@ -418,6 +444,7 @@ class http_client_config
    139  
    140      std::function<void(native_handle)> m_set_user_nativehandle_options;
    141      std::function<void(native_handle)> m_set_user_nativesessionhandle_options;
    142 +    std::function<void(native_handle)> m_nativehandle_servercertificate_validation;
    143  
    144  #if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO)
    145      std::function<void(boost::asio::ssl::context&)> m_ssl_context_callback;
    146 diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp
    147 index d6cdb5384a..5a517ec334 100644
    148 --- a/Release/src/http/client/http_client_winhttp.cpp
    149 +++ b/Release/src/http/client/http_client_winhttp.cpp
    150 @@ -2039,6 +2039,18 @@ class winhttp_client final : public _http_client_communicator
    151              case WINHTTP_CALLBACK_STATUS_SENDING_REQUEST:
    152              {
    153                  p_request_context->on_send_request_validate_cn();
    154 +
    155 +                try
    156 +                {
    157 +                    p_request_context->m_http_client->client_config().invoke_nativehandle_servercertificate_validation(hRequestHandle);
    158 +                }
    159 +                catch (...)
    160 +                {
    161 +                    p_request_context->report_exception(std::current_exception());
    162 +                    p_request_context->cleanup();
    163 +                    return;
    164 +                }
    165 +
    166                  return;
    167              }
    168              case WINHTTP_CALLBACK_STATUS_SECURE_FAILURE:
    169