Skip to content

Instantly share code, notes, and snippets.

@noamr
Created August 29, 2013 13:45
Show Gist options
  • Save noamr/6378298 to your computer and use it in GitHub Desktop.
Save noamr/6378298 to your computer and use it in GitHub Desktop.
diff --git a/Source/WebCore/platform/network/soup/ClientCertificateManager.cpp b/Source/WebCore/platform/network/soup/ClientCertificateManager.cpp
new file mode 100644
index 0000000..23d9e50
--- /dev/null
+++ b/Source/WebCore/platform/network/soup/ClientCertificateManager.cpp
@@ -0,0 +1,54 @@
+#include "config.h"
+#include "ClientCertificateManager.h"
+
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/WTFString.h>
+
+static const String ClientCertificatesFolderPath(NIX_CERTIFICATES_FOLDER);
+
+using namespace WebCore;
+
+namespace WebCore {
+
+String WebClientCertificateManager::getClientCertificateForServer(const String& serverName, uint16_t port)
+{
+ if (ClientCertificatesFolderPath.isNull()) {
+ return String();
+ }
+
+ StringBuilder certificatePathBuilder;
+
+ certificatePathBuilder.append(ClientCertificatesFolderPath);
+ certificatePathBuilder.append("/");
+
+ certificatePathBuilder.append(serverName);
+ certificatePathBuilder.append(":");
+ certificatePathBuilder.append(String::number(port));
+
+ const CString certificatePath = certificatePathBuilder.toString().utf8();
+
+ FILE *fd = fopen(certificatePath.data(), "r");
+
+ if (!fd)
+ return String();
+
+ String data;
+ size_t r;
+
+ do {
+ unsigned char buf[4096];
+ r = fread(buf, sizeof(char), sizeof(buf), fd);
+ data.append(buf, r);
+ } while (r != 0);
+
+ if (ferror(fd)) {
+ data = String();
+ }
+
+ fclose(fd);
+
+ return data;
+}
+
+} // namespace WebKit
diff --git a/Source/WebCore/platform/network/soup/ClientCertificateManager.h b/Source/WebCore/platform/network/soup/ClientCertificateManager.h
new file mode 100644
index 0000000..d3e77f1
--- /dev/null
+++ b/Source/WebCore/platform/network/soup/ClientCertificateManager.h
@@ -0,0 +1,15 @@
+#ifndef WebClientCertificateManager_h
+#define WebClientCertificateManager_h
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class WebClientCertificateManager {
+public:
+ static String getClientCertificateForServer(const String&, uint16_t);
+};
+
+} // namespace WebKit
+
+#endif // WebClientCertificateManager_h
diff --git a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
index 5d27e12..7f16227 100644
--- a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
+++ b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
@@ -31,6 +31,7 @@
#include "CachedResourceLoader.h"
#include "ChromeClient.h"
+#include "ClientCertificateManager.h"
#include "CookieJarSoup.h"
#include "CredentialStorage.h"
#include "FileSystem.h"
@@ -862,6 +863,29 @@ static void requestStartedCallback(SoupSession*, SoupMessage* soupMessage, SoupS
}
}
+static void networkEventClientCertificateCallback(SoupMessage* msg, GSocketClientEvent event, GIOStream* connection, gpointer data)
+{
+ if (event != G_SOCKET_CLIENT_TLS_HANDSHAKING)
+ return;
+
+ GRefPtr<SoupAddress> msgAddress(soup_message_get_address(msg));
+
+ String serverName(soup_address_get_name(msgAddress.get()));
+ uint16_t serverPort(soup_address_get_port(msgAddress.get()));
+
+ const CString certData = WebClientCertificateManager::getClientCertificateForServer(serverName, serverPort).latin1();
+
+ // getClientCertificateForServer returns a null String if no certificate is
+ // found, but apparently calling latin1() on it makes it an empty CString
+ if (certData.length() > 0) {
+ GOwnPtr<GError> error;
+ GRefPtr<GTlsCertificate> clientCert(g_tls_certificate_new_from_pem(certData.data(), certData.length(), &error.outPtr()));
+
+ if (!error)
+ g_tls_connection_set_certificate(G_TLS_CONNECTION(connection), clientCert.get());
+ }
+}
+
static void networkEventCallback(SoupMessage*, GSocketClientEvent event, GIOStream*, gpointer data)
{
ResourceHandle* handle = static_cast<ResourceHandle*>(data);
@@ -974,6 +998,8 @@ static bool createSoupMessageForHandleAndRequest(ResourceHandle* handle, const R
soup_message_set_flags(d->m_soupMessage.get(), static_cast<SoupMessageFlags>(soup_message_get_flags(d->m_soupMessage.get()) | SOUP_MESSAGE_NO_REDIRECT));
+ g_signal_connect(d->m_soupMessage.get(), "network-event", G_CALLBACK(networkEventClientCertificateCallback), handle);
+
#if ENABLE(WEB_TIMING)
d->m_response.setResourceLoadTiming(ResourceLoadTiming::create());
g_signal_connect(d->m_soupMessage.get(), "network-event", G_CALLBACK(networkEventCallback), handle);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment