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
|
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="http://docbook.org/xml/5.1/rng/docbook.rng" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="http://docbook.org/xml/5.1/sch/docbook.sch" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<sect1 xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink" version="5.1">
<title>Everything TLS Related</title>
<para>libsoup comes with TLS support provided by glib-networking. This has multiple backends
including gnutls (default on all platforms), SChannel on Windows, or OpenSSL.</para>
<sect2>
<title>Accepting Invalid or Pinned Certificates</title>
<para>This makes use of the <literal>SoupMessage::accept-certificate</literal> signal.</para>
<informalexample><programlisting><![CDATA[
static gboolean
accept_certificate_callback (SoupMessage *msg, GTlsCertificate *certificate,
GTlsCertificateFlags tls_errors, gpointer user_data)
{
// Here you can inspect @certificate or compare it against a trusted one
// and you can see what is considered invalid by @tls_errors.
// Returning TRUE trusts it anyway.
return TRUE;
}
int main (int argc, char **argv)
{
SoupSession *session = soup_session_new ();
SoupMessage *msg = soup_message_new (SOUP_METHOD_GET, "https://example.org");
g_signal_connect (msg, "accept-certificate", G_CALLBACK (accept_certificate_callback), NULL);
GInputStream *in_stream = soup_session_send (session, msg, NULL, NULL);
if (in_stream) {
g_object_unref (in_stream);
}
return 0;
}]]>
</programlisting></informalexample>
</sect2>
<sect2>
<title>Setting a Custom CA</title>
<informalexample><programlisting><![CDATA[
{
GError *error = NULL;
// NOTE: This is blocking IO
GTlsDatabase *tls_db = g_tls_file_database_new ("/foo/ca.pem", &error);
if (error) {
g_printerr ("Failed to load certificates: %s\n", error->message);
g_error_free (error);
return;
}
SoupSession *session = soup_session_new_with_options ("tls-database", tls_db, NULL);
g_object_unref (tls_db);
}]]>
</programlisting></informalexample>
</sect2>
<sect2>
<title>Using Client Certificates</title>
<informalexample><programlisting><![CDATA[
static gboolean
on_request_certificate (SoupMessage *msg, GTlsClientConnection *conn, gpointer user_data)
{
GTlsCertificate *client_cert = user_data;
/* We immediately set this however you can set this later in an async function. */
soup_message_set_tls_client_certificate (msg, client_cert);
return TRUE; /* We handled the request */
}
int main (int argc, char **argv)
{
GError *error = NULL;
GTlsCertificate *client_cert = g_tls_certificate_new_from_file ("/foo/cert.pem", &error);
if (error) {
g_printerr ("Failed to load certificate: %s\n", error->message);
g_error_free (error);
return 1;
}
SoupSession *session = soup_session_new ();
SoupMessage *msg = soup_message_new ("GET", "https://example.org");
/* We can set the certificate ahead of time if we already have one */
// soup_message_set_tls_client_certificate (msg, client_cert)
/* However we can also dynamically request one which is useful in
* applications that show a graphical prompt for example. */
g_signal_connect (msg, "request-certificate",
G_CALLBACK (on_request_certificate), client_cert);
// Send the message...
g_object_unref (msg);
g_object_unref (session);
g_object_unref (client_cert);
return 0;
}]]>
</programlisting></informalexample>
</sect2>
</sect1>
|