6ab18d99f4d9f41ec6df79dd2c993758e78d216c
[platform/upstream/glib-networking.git] / tls / gnutls / gtlsfiledatabase-gnutls.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3  * GIO - GLib Input, Output and Streaming Library
4  *
5  * Copyright 2010 Collabora, Ltd
6  * Copyright 2018 Igalia S.L.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General
19  * Public License along with this library; if not, see
20  * <http://www.gnu.org/licenses/>.
21  *
22  * In addition, when the library is used with OpenSSL, a special
23  * exception applies. Refer to the LICENSE_EXCEPTION file for details.
24  *
25  * Author: Stef Walter <stefw@collabora.co.uk>
26  */
27
28 #include "config.h"
29
30 #include "gtlsfiledatabase-gnutls.h"
31
32 #include <gio/gio.h>
33
34 #include "gtlscertificate-gnutls.h"
35
36 enum
37 {
38   PROP_0,
39   PROP_ANCHORS,
40 };
41
42 struct _GTlsFileDatabaseGnutls
43 {
44   GTlsDatabaseGnutls parent_instance;
45
46   /* read-only after construct */
47   gchar *anchor_filename;
48 };
49
50 static void g_tls_file_database_gnutls_file_database_interface_init (GTlsFileDatabaseInterface *iface);
51
52 G_DEFINE_TYPE_WITH_CODE (GTlsFileDatabaseGnutls, g_tls_file_database_gnutls, G_TYPE_TLS_DATABASE_GNUTLS,
53                          G_IMPLEMENT_INTERFACE (G_TYPE_TLS_FILE_DATABASE,
54                                                 g_tls_file_database_gnutls_file_database_interface_init);
55                          );
56
57 static void
58 g_tls_file_database_gnutls_finalize (GObject *object)
59 {
60   GTlsFileDatabaseGnutls *self = G_TLS_FILE_DATABASE_GNUTLS (object);
61
62   g_clear_pointer (&self->anchor_filename, g_free);
63
64   G_OBJECT_CLASS (g_tls_file_database_gnutls_parent_class)->finalize (object);
65 }
66
67 static void
68 g_tls_file_database_gnutls_get_property (GObject    *object,
69                                          guint       prop_id,
70                                          GValue     *value,
71                                          GParamSpec *pspec)
72 {
73   GTlsFileDatabaseGnutls *self = G_TLS_FILE_DATABASE_GNUTLS (object);
74
75   switch (prop_id)
76     {
77     case PROP_ANCHORS:
78       g_value_set_string (value, self->anchor_filename);
79       break;
80     default:
81       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
82     }
83 }
84
85 static void
86 g_tls_file_database_gnutls_set_property (GObject      *object,
87                                          guint         prop_id,
88                                          const GValue *value,
89                                          GParamSpec   *pspec)
90 {
91   GTlsFileDatabaseGnutls *self = G_TLS_FILE_DATABASE_GNUTLS (object);
92   const char *anchor_path;
93
94   switch (prop_id)
95     {
96     case PROP_ANCHORS:
97       anchor_path = g_value_get_string (value);
98       if (anchor_path && !g_path_is_absolute (anchor_path))
99         {
100           g_warning ("The anchor file name used with a GTlsFileDatabase "
101                      "must be an absolute path, and not relative: %s", anchor_path);
102           return;
103         }
104
105       g_free (self->anchor_filename);
106       self->anchor_filename = g_strdup (anchor_path);
107       break;
108     default:
109       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
110     }
111 }
112
113 static gchar *
114 g_tls_file_database_gnutls_create_handle_for_certificate (GTlsDatabaseGnutls *self,
115                                                           GBytes             *der)
116 {
117   gchar *bookmark;
118   gchar *uri_part;
119   gchar *uri;
120
121   /*
122    * Here we create a URI that looks like
123    * file:///etc/ssl/certs/ca-certificates.crt#11b2641821252596420e468c275771f5e51022c121a17bd7a89a2f37b6336c8f
124    */
125
126   uri_part = g_filename_to_uri (G_TLS_FILE_DATABASE_GNUTLS (self)->anchor_filename,
127                                 NULL, NULL);
128   if (!uri_part)
129     return NULL;
130
131   bookmark = g_compute_checksum_for_bytes (G_CHECKSUM_SHA256, der);
132   uri = g_strconcat (uri_part, "#", bookmark, NULL);
133
134   g_free (bookmark);
135   g_free (uri_part);
136
137   return uri;
138 }
139
140 static gboolean
141 g_tls_file_database_gnutls_populate_trust_list (GTlsDatabaseGnutls        *self,
142                                                 gnutls_x509_trust_list_t   trust_list,
143                                                 GError                   **error)
144 {
145   gnutls_x509_trust_list_add_trust_file (trust_list,
146                                          G_TLS_FILE_DATABASE_GNUTLS (self)->anchor_filename,
147                                          NULL, GNUTLS_X509_FMT_PEM, 0, 0);
148   return TRUE;
149 }
150
151 static void
152 g_tls_file_database_gnutls_init (GTlsFileDatabaseGnutls *self)
153 {
154 }
155
156 static void
157 g_tls_file_database_gnutls_class_init (GTlsFileDatabaseGnutlsClass *klass)
158 {
159   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
160   GTlsDatabaseGnutlsClass *gnutls_database_class = G_TLS_DATABASE_GNUTLS_CLASS (klass);
161
162   gobject_class->get_property = g_tls_file_database_gnutls_get_property;
163   gobject_class->set_property = g_tls_file_database_gnutls_set_property;
164   gobject_class->finalize     = g_tls_file_database_gnutls_finalize;
165
166   gnutls_database_class->create_handle_for_certificate = g_tls_file_database_gnutls_create_handle_for_certificate;
167   gnutls_database_class->populate_trust_list           = g_tls_file_database_gnutls_populate_trust_list;
168
169   g_object_class_override_property (gobject_class, PROP_ANCHORS, "anchors");
170 }
171
172 static void
173 g_tls_file_database_gnutls_file_database_interface_init (GTlsFileDatabaseInterface *iface)
174 {
175 }