| /* |
| * Copyright (C) 2019 Igalia S.L. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| #include "ArgumentCodersGLib.h" |
| |
| #include "DaemonDecoder.h" |
| #include "DaemonEncoder.h" |
| #include "DataReference.h" |
| #include <gio/gio.h> |
| #include <wtf/glib/GUniquePtr.h> |
| #include <wtf/text/CString.h> |
| |
| namespace IPC { |
| |
| void ArgumentCoder<GRefPtr<GVariant>>::encode(Encoder& encoder, GRefPtr<GVariant> variant) |
| { |
| if (!variant) { |
| encoder << CString(); |
| return; |
| } |
| |
| encoder << CString(g_variant_get_type_string(variant.get())); |
| encoder << DataReference(static_cast<const uint8_t*>(g_variant_get_data(variant.get())), g_variant_get_size(variant.get())); |
| } |
| |
| std::optional<GRefPtr<GVariant>> ArgumentCoder<GRefPtr<GVariant>>::decode(Decoder& decoder) |
| { |
| CString variantTypeString; |
| if (!decoder.decode(variantTypeString)) |
| return std::nullopt; |
| |
| if (variantTypeString.isNull()) |
| return GRefPtr<GVariant>(); |
| |
| if (!g_variant_type_string_is_valid(variantTypeString.data())) |
| return std::nullopt; |
| |
| DataReference data; |
| if (!decoder.decode(data)) |
| return std::nullopt; |
| |
| GUniquePtr<GVariantType> variantType(g_variant_type_new(variantTypeString.data())); |
| GRefPtr<GBytes> bytes = adoptGRef(g_bytes_new(data.data(), data.size())); |
| return std::optional<GRefPtr<GVariant> >(g_variant_new_from_bytes(variantType.get(), bytes.get(), FALSE)); |
| } |
| |
| template<typename Encoder> |
| void ArgumentCoder<GRefPtr<GTlsCertificate>>::encode(Encoder& encoder, GRefPtr<GTlsCertificate> certificate) |
| { |
| if (!certificate) { |
| encoder << 0; |
| return; |
| } |
| |
| Vector<GRefPtr<GByteArray>> certificatesDataList; |
| for (auto* nextCertificate = certificate.get(); nextCertificate; nextCertificate = g_tls_certificate_get_issuer(nextCertificate)) { |
| GRefPtr<GByteArray> certificateData; |
| g_object_get(nextCertificate, "certificate", &certificateData.outPtr(), nullptr); |
| |
| if (!certificateData) { |
| certificatesDataList.clear(); |
| break; |
| } |
| |
| certificatesDataList.append(WTFMove(certificateData)); |
| } |
| |
| encoder << static_cast<uint32_t>(certificatesDataList.size()); |
| if (certificatesDataList.isEmpty()) |
| return; |
| |
| #if GLIB_CHECK_VERSION(2, 69, 0) |
| GRefPtr<GByteArray> privateKey; |
| GUniqueOutPtr<char> privateKeyPKCS11Uri; |
| g_object_get(certificate.get(), "private-key", &privateKey.outPtr(), "private-key-pkcs11-uri", &privateKeyPKCS11Uri.outPtr(), nullptr); |
| encoder << IPC::DataReference(privateKey ? privateKey->data : nullptr, privateKey ? privateKey->len : 0); |
| encoder << CString(privateKeyPKCS11Uri.get()); |
| #endif |
| |
| // Encode starting from the root certificate. |
| while (!certificatesDataList.isEmpty()) { |
| auto certificateData = certificatesDataList.takeLast(); |
| encoder << IPC::DataReference(certificateData->data, certificateData->len); |
| } |
| } |
| template void ArgumentCoder<GRefPtr<GTlsCertificate>>::encode<Encoder>(Encoder&, GRefPtr<GTlsCertificate>); |
| template void ArgumentCoder<GRefPtr<GTlsCertificate>>::encode<WebKit::Daemon::Encoder>(WebKit::Daemon::Encoder&, GRefPtr<GTlsCertificate>); |
| |
| template<typename Decoder> |
| std::optional<GRefPtr<GTlsCertificate>> ArgumentCoder<GRefPtr<GTlsCertificate>>::decode(Decoder& decoder) |
| { |
| std::optional<uint32_t> chainLength; |
| decoder >> chainLength; |
| if (!chainLength) |
| return std::nullopt; |
| |
| if (!*chainLength) |
| return GRefPtr<GTlsCertificate>(); |
| |
| #if GLIB_CHECK_VERSION(2, 69, 0) |
| std::optional<IPC::DataReference> privateKeyData; |
| decoder >> privateKeyData; |
| if (!privateKeyData) |
| return std::nullopt; |
| GRefPtr<GByteArray> privateKey; |
| if (privateKeyData->size()) { |
| privateKey = adoptGRef(g_byte_array_sized_new(privateKeyData->size())); |
| g_byte_array_append(privateKey.get(), privateKeyData->data(), privateKeyData->size()); |
| } |
| |
| std::optional<CString> privateKeyPKCS11Uri; |
| decoder >> privateKeyPKCS11Uri; |
| if (!privateKeyPKCS11Uri) |
| return std::nullopt; |
| #endif |
| |
| GType certificateType = g_tls_backend_get_certificate_type(g_tls_backend_get_default()); |
| GRefPtr<GTlsCertificate> certificate; |
| GTlsCertificate* issuer = nullptr; |
| for (uint32_t i = 0; i < *chainLength; i++) { |
| std::optional<IPC::DataReference> certificateDataReference; |
| decoder >> certificateDataReference; |
| if (!certificateDataReference) |
| return std::nullopt; |
| |
| GRefPtr<GByteArray> certificateData = adoptGRef(g_byte_array_sized_new(certificateDataReference->size())); |
| g_byte_array_append(certificateData.get(), certificateDataReference->data(), certificateDataReference->size()); |
| |
| certificate = adoptGRef(G_TLS_CERTIFICATE(g_initable_new( |
| certificateType, nullptr, nullptr, |
| "certificate", certificateData.get(), |
| "issuer", issuer, |
| #if GLIB_CHECK_VERSION(2, 69, 0) |
| "private-key", i == *chainLength - 1 ? privateKey.get() : nullptr, |
| "private-key-pkcs11-uri", i == *chainLength - 1 ? privateKeyPKCS11Uri->data() : nullptr, |
| #endif |
| nullptr))); |
| issuer = certificate.get(); |
| } |
| |
| return certificate; |
| } |
| template std::optional<GRefPtr<GTlsCertificate>> ArgumentCoder<GRefPtr<GTlsCertificate>>::decode<Decoder>(Decoder&); |
| template std::optional<GRefPtr<GTlsCertificate>> ArgumentCoder<GRefPtr<GTlsCertificate>>::decode<WebKit::Daemon::Decoder>(WebKit::Daemon::Decoder&); |
| |
| } // namespace IPC |