⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 268909 in webkit


Ignore:
Timestamp:
Oct 23, 2020, 1:25:27 AM (6 years ago)
Author:
Carlos Garcia Campos
Message:

Merge r268394 - [SOUP] webkit_web_view_get_https_status() broken with service workers
https://bugs.webkit.org/show_bug.cgi?id=216038

Patch by Michael Catanzaro <Michael Catanzaro> on 2020-10-13
Reviewed by Carlos Garcia Campos.

This implements CertificateInfo::isolatedCopy for libsoup ports. This is impossible to do
completely, because we cannot copy the private key portion of the GTlsCertificate, because
it is a write-only property, because it might be backed by a hardware token and therefore
really impossible to write software to get it. If we were to implement g_tls_certificate_copy()
in GLib -- which I will probably do eventually, because I need this outside WebKit as well --
then GTlsCertificate implementations could copy the private key or PKCS#11 handle or
whatever.

But anyway, let not perfect be the enemy of the good. We only need this for service workers
currently. (Probably that's all we'll *ever* need it for.) So we are only working with
server certificates, and the private portion of the certificate is guaranteed to not exist
(because servers don't send us their private keys), and we can just forget about it. As
long as nobody tries to copy a client certificate in the future -- where we really would
need the private key portion of the certificate -- this will be perfectly fine.

Actually copying the certificate is kind of annoying, because a chain of certificates is
represented by having the main (server) certificate keep a reference to its issuer, which is
not referenced anywhere else, so we have to reconstruct the chain in reverse order starting
from the final certificate, working back towards the server cert. Fun. Let's also be
careful to construct a completely new GByteArray rather than expecting the GTlsCertificate
implementation to copy it for us. Because GTlsCertificate is implemented by an extension
point and applications and system administrators can -- and do -- implement their own,
implementations could do anything, including keep a reference to the GByteArray that we
pass in.

It would be nice to have a test for this, but writing tests is hard. Also, I don't really
want to learn what service workers are. :)

Drive-by fix: also remove explicit from a constructor that doesn't need it.

  • platform/network/soup/CertificateInfo.h:

(WebCore::CertificateInfo::isolatedCopy const):

  • platform/network/soup/CertificateInfoSoup.cpp:

(WebCore::createCertificate):
(WebCore::CertificateInfo::isolatedCopy const):

Location:
releases/WebKitGTK/webkit-2.30/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • releases/WebKitGTK/webkit-2.30/Source/WebCore/ChangeLog

    r268908 r268909  
     12020-10-13  Michael Catanzaro  <mcatanzaro@gnome.org>
     2
     3        [SOUP] webkit_web_view_get_https_status() broken with service workers
     4        https://bugs.webkit.org/show_bug.cgi?id=216038
     5
     6        Reviewed by Carlos Garcia Campos.
     7
     8        This implements CertificateInfo::isolatedCopy for libsoup ports. This is impossible to do
     9        completely, because we cannot copy the private key portion of the GTlsCertificate, because
     10        it is a write-only property, because it might be backed by a hardware token and therefore
     11        really impossible to write software to get it. If we were to implement g_tls_certificate_copy()
     12        in GLib -- which I will probably do eventually, because I need this outside WebKit as well --
     13        then GTlsCertificate implementations could copy the private key or PKCS#11 handle or
     14        whatever.
     15
     16        But anyway, let not perfect be the enemy of the good. We only need this for service workers
     17        currently. (Probably that's all we'll *ever* need it for.) So we are only working with
     18        server certificates, and the private portion of the certificate is guaranteed to not exist
     19        (because servers don't send us their private keys), and we can just forget about it. As
     20        long as nobody tries to copy a client certificate in the future -- where we really would
     21        need the private key portion of the certificate -- this will be perfectly fine.
     22
     23        Actually copying the certificate is kind of annoying, because a chain of certificates is
     24        represented by having the main (server) certificate keep a reference to its issuer, which is
     25        not referenced anywhere else, so we have to reconstruct the chain in reverse order starting
     26        from the final certificate, working back towards the server cert. Fun. Let's also be
     27        careful to construct a completely new GByteArray rather than expecting the GTlsCertificate
     28        implementation to copy it for us. Because GTlsCertificate is implemented by an extension
     29        point and applications and system administrators can -- and do -- implement their own,
     30        implementations could do anything, including keep a reference to the GByteArray that we
     31        pass in.
     32
     33        It would be nice to have a test for this, but writing tests is hard. Also, I don't really
     34        want to learn what service workers are. :)
     35
     36        Drive-by fix: also remove explicit from a constructor that doesn't need it.
     37
     38        * platform/network/soup/CertificateInfo.h:
     39        (WebCore::CertificateInfo::isolatedCopy const):
     40        * platform/network/soup/CertificateInfoSoup.cpp:
     41        (WebCore::createCertificate):
     42        (WebCore::CertificateInfo::isolatedCopy const):
     43
    1442020-10-13  Philippe Normand  <pnormand@igalia.com>
    245
  • releases/WebKitGTK/webkit-2.30/Source/WebCore/platform/network/soup/CertificateInfo.h

    r264724 r268909  
    4646    explicit CertificateInfo(const WebCore::ResourceResponse&);
    4747    explicit CertificateInfo(const WebCore::ResourceError&);
    48     explicit CertificateInfo(GTlsCertificate*, GTlsCertificateFlags);
     48    CertificateInfo(GTlsCertificate*, GTlsCertificateFlags);
    4949    WEBCORE_EXPORT ~CertificateInfo();
    5050
    51     CertificateInfo isolatedCopy() const { notImplemented(); return { }; }
     51    CertificateInfo isolatedCopy() const;
    5252
    5353    GTlsCertificate* certificate() const { return m_certificate.get(); }
  • releases/WebKitGTK/webkit-2.30/Source/WebCore/platform/network/soup/CertificateInfoSoup.cpp

    r238122 r268909  
    3333#include <ResourceResponse.h>
    3434#include <libsoup/soup.h>
     35#include <wtf/glib/GRefPtr.h>
     36#include <wtf/glib/GUniquePtr.h>
    3537
    3638namespace WebCore {
     
    6163CertificateInfo::~CertificateInfo() = default;
    6264
     65static GRefPtr<GTlsCertificate> createCertificate(GByteArray* bytes, GTlsCertificate* issuer)
     66{
     67    gpointer cert = g_initable_new(g_tls_backend_get_certificate_type(g_tls_backend_get_default()),
     68        nullptr, nullptr,
     69        "certificate", bytes,
     70        "issuer", issuer,
     71        nullptr);
     72    RELEASE_ASSERT(cert);
     73    return adoptGRef(G_TLS_CERTIFICATE(cert));
     74}
     75
     76CertificateInfo CertificateInfo::isolatedCopy() const
     77{
     78    // We can only copy the public portions, so this can only be used for server certificates, not
     79    // for client certificates. Sadly, other ports don't have this restriction, and there is no way
     80    // to assert that we are not messing up here because we can't know how callers are using the
     81    // certificate. So be careful?
     82    //
     83    // We should add g_tls_certificate_copy() to GLib so that we can copy the private portion too.
     84
     85    Vector<GRefPtr<GByteArray>> certificateBytes;
     86    GTlsCertificate* cert = m_certificate.get();
     87    if (!cert)
     88        return CertificateInfo();
     89
     90    do {
     91        GRefPtr<GByteArray> der;
     92        g_object_get(cert, "certificate", &der.outPtr(), nullptr);
     93
     94        GRefPtr<GByteArray> copy = adoptGRef(g_byte_array_new());
     95        g_byte_array_append(copy.get(), der->data, der->len);
     96        certificateBytes.append(WTFMove(copy));
     97    } while ((cert = g_tls_certificate_get_issuer(cert)));
     98
     99    auto finalCertificateIndex = certificateBytes.size() - 1;
     100    GRefPtr<GTlsCertificate> copy = createCertificate(certificateBytes[finalCertificateIndex].get(), nullptr);
     101    for (ssize_t i = finalCertificateIndex - 1; i >= 0; i--)
     102        copy = createCertificate(certificateBytes[i].get(), copy.get());
     103    return CertificateInfo(copy.get(), m_tlsErrors);
     104}
     105
    63106} // namespace WebCore
    64107
Note: See TracChangeset for help on using the changeset viewer.