Add initial TLS (SSL) support to gio
[platform/upstream/glib.git] / gio / gtlscertificate.c
1 /* GIO - GLib Input, Output and Certificateing Library
2  *
3  * Copyright (C) 2010 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22
23 #include "gtlscertificate.h"
24
25 #include <string.h>
26 #include "ginitable.h"
27 #include "gtlsbackend.h"
28 #include "gtlsconnection.h"
29 #include "glibintl.h"
30
31 /**
32  * SECTION: gtlscertificate
33  * @title: GTlsCertificate
34  * @short_description: a TLS certificate
35  * @see_also: #GTlsConnection
36  *
37  * A certificate used for TLS authentication and encryption.
38  * This can represent either a public key only (eg, the certificate
39  * received by a client from a server), or the combination of
40  * a public key and a private key (which is needed when acting as a
41  * #GTlsServerConnection).
42  *
43  * Since: 2.28
44  */
45
46 /**
47  * GTlsCertificate:
48  *
49  * Abstract base class for TLS certificate types.
50  *
51  * Since: 2.28
52  */
53
54 G_DEFINE_ABSTRACT_TYPE (GTlsCertificate, g_tls_certificate, G_TYPE_OBJECT);
55
56 struct _GTlsCertificatePrivate
57 {
58   GTlsCertificate *issuer;
59 };
60
61 enum
62 {
63   PROP_0,
64
65   PROP_CERTIFICATE,
66   PROP_CERTIFICATE_PEM,
67   PROP_PRIVATE_KEY,
68   PROP_PRIVATE_KEY_PEM,
69   PROP_ISSUER
70 };
71
72 static void
73 g_tls_certificate_init (GTlsCertificate *cert)
74 {
75   cert->priv = G_TYPE_INSTANCE_GET_PRIVATE (cert,
76                                             G_TYPE_TLS_CERTIFICATE,
77                                             GTlsCertificatePrivate);
78 }
79
80 static void
81 g_tls_certificate_get_property (GObject    *object,
82                                 guint       prop_id,
83                                 GValue     *value,
84                                 GParamSpec *pspec)
85 {
86   GTlsCertificate *cert = G_TLS_CERTIFICATE (object);
87
88   switch (prop_id)
89     {
90     case PROP_ISSUER:
91       g_value_set_object (value, cert->priv->issuer);
92       break;
93
94     default:
95       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
96     }
97 }
98
99 static void
100 g_tls_certificate_set_property (GObject      *object,
101                                 guint         prop_id,
102                                 const GValue *value,
103                                 GParamSpec   *pspec)
104 {
105   GTlsCertificate *cert = G_TLS_CERTIFICATE (object);
106
107   switch (prop_id)
108     {
109     case PROP_ISSUER:
110       cert->priv->issuer = g_value_dup_object (value);
111       break;
112
113     default:
114       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
115     }
116 }
117
118 static void
119 g_tls_certificate_finalize (GObject *object)
120 {
121   GTlsCertificate *cert = G_TLS_CERTIFICATE (object);
122
123   if (cert->priv->issuer)
124     g_object_unref (cert->priv->issuer);
125
126   G_OBJECT_CLASS (g_tls_certificate_parent_class)->finalize (object);
127 }
128
129 static void
130 g_tls_certificate_class_init (GTlsCertificateClass *class)
131 {
132   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
133
134   g_type_class_add_private (class, sizeof (GTlsCertificatePrivate));
135
136   gobject_class->set_property = g_tls_certificate_set_property;
137   gobject_class->get_property = g_tls_certificate_get_property;
138   gobject_class->finalize = g_tls_certificate_finalize;
139
140   /**
141    * GTlsCertificate:certificate:
142    *
143    * The DER (binary) encoded representation of the certificate's
144    * public key. This property and the
145    * #GTlsCertificate:certificate-pem property represent the same
146    * data, just in different forms.
147    *
148    * Since: 2.28
149    */
150   g_object_class_install_property (gobject_class, PROP_CERTIFICATE,
151                                    g_param_spec_boxed ("certificate",
152                                                        P_("Certificate"),
153                                                        P_("The DER representation of the certificate"),
154                                                        G_TYPE_BYTE_ARRAY,
155                                                        G_PARAM_READWRITE |
156                                                        G_PARAM_CONSTRUCT_ONLY |
157                                                        G_PARAM_STATIC_STRINGS));
158   /**
159    * GTlsCertificate:certificate-pem:
160    *
161    * The PEM (ASCII) encoded representation of the certificate's
162    * public key. This property and the #GTlsCertificate:certificate
163    * property represent the same data, just in different forms.
164    *
165    * Since: 2.28
166    */
167   g_object_class_install_property (gobject_class, PROP_CERTIFICATE_PEM,
168                                    g_param_spec_string ("certificate-pem",
169                                                         P_("Certificate (PEM)"),
170                                                         P_("The PEM representation of the certificate"),
171                                                         NULL,
172                                                         G_PARAM_READWRITE |
173                                                         G_PARAM_CONSTRUCT_ONLY |
174                                                         G_PARAM_STATIC_STRINGS));
175   /**
176    * GTlsCertificate:private-key:
177    *
178    * The DER (binary) encoded representation of the certificate's
179    * private key. This property (or the
180    * #GTlsCertificate:private-key-pem property) can be set when
181    * constructing a key (eg, from a file), but cannot be read.
182    *
183    * Since: 2.28
184    */
185   g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY,
186                                    g_param_spec_boxed ("private-key",
187                                                        P_("Private key"),
188                                                        P_("The DER representation of the certificate's private key"),
189                                                        G_TYPE_BYTE_ARRAY,
190                                                        G_PARAM_WRITABLE |
191                                                        G_PARAM_CONSTRUCT_ONLY |
192                                                        G_PARAM_STATIC_STRINGS));
193   /**
194    * GTlsCertificate:private-key-pem:
195    *
196    * The PEM (ASCII) encoded representation of the certificate's
197    * private key. This property (or the #GTlsCertificate:private-key
198    * property) can be set when constructing a key (eg, from a file),
199    * but cannot be read.
200    *
201    * Since: 2.28
202    */
203   g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY_PEM,
204                                    g_param_spec_string ("private-key-pem",
205                                                         P_("Private key (PEM)"),
206                                                         P_("The PEM representation of the certificate's private key"),
207                                                         NULL,
208                                                         G_PARAM_WRITABLE |
209                                                         G_PARAM_CONSTRUCT_ONLY |
210                                                         G_PARAM_STATIC_STRINGS));
211   /**
212    * GTlsCertificate:issuer:
213    *
214    * A #GTlsCertificate representing the entity that issued this
215    * certificate. If %NULL, this means that the certificate is either
216    * self-signed, or else the certificate of the issuer is not
217    * available.
218    *
219    * Since: 2.28
220    */
221   g_object_class_install_property (gobject_class, PROP_ISSUER,
222                                    g_param_spec_object ("issuer",
223                                                         P_("Issuer"),
224                                                         P_("The certificate for the issuing entity"),
225                                                         G_TYPE_TLS_CERTIFICATE,
226                                                         G_PARAM_READWRITE |
227                                                         G_PARAM_CONSTRUCT_ONLY |
228                                                         G_PARAM_STATIC_STRINGS));
229 }
230
231 static GTlsCertificate *
232 g_tls_certificate_new_internal (const gchar  *certificate_pem,
233                                 const gchar  *private_key_pem,
234                                 GError      **error)
235 {
236   GObject *cert;
237   GTlsBackend *backend;
238
239   backend = g_tls_backend_get_default ();
240
241   cert = g_initable_new (g_tls_backend_get_certificate_type (backend),
242                          NULL, error,
243                          "certificate-pem", certificate_pem,
244                          "private-key-pem", private_key_pem,
245                          NULL);
246   return G_TLS_CERTIFICATE (cert);
247 }
248
249 #define PEM_CERTIFICATE_HEADER "-----BEGIN CERTIFICATE-----"
250 #define PEM_CERTIFICATE_FOOTER "-----END CERTIFICATE-----"
251 #define PEM_PRIVKEY_HEADER     "-----BEGIN RSA PRIVATE KEY-----"
252 #define PEM_PRIVKEY_FOOTER     "-----END RSA PRIVATE KEY-----"
253
254 static GTlsCertificate *
255 parse_next_pem_certificate (const gchar **data,
256                             const gchar  *data_end,
257                             gboolean      required,
258                             GError      **error)
259 {
260   const gchar *start, *end, *next;
261   gchar *cert_pem, *privkey_pem = NULL;
262   GTlsCertificate *cert;
263
264   start = g_strstr_len (*data, data_end - *data, PEM_CERTIFICATE_HEADER);
265   if (!start)
266     {
267       if (required)
268         {
269           g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
270                                _("No PEM-encoded certificate found"));
271         }
272       return NULL;
273     }
274
275   end = g_strstr_len (start, data_end - start, PEM_CERTIFICATE_FOOTER);
276   if (!end)
277     {
278       g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
279                            _("Could not parse PEM-encoded certificate"));
280       return NULL;
281     }
282   end += strlen (PEM_CERTIFICATE_FOOTER);
283   while (*end == '\r' || *end == '\n')
284     end++;
285
286   cert_pem = g_strndup (start, end - start);
287
288   *data = end;
289
290   next = g_strstr_len (*data, data_end - *data, PEM_CERTIFICATE_HEADER);
291   start = g_strstr_len (*data, data_end - *data, PEM_PRIVKEY_HEADER);
292   if (start)
293     end = g_strstr_len (start, data_end - start, PEM_PRIVKEY_FOOTER);
294
295   if (start && (!next || start < next))
296     {
297       if (!end || (next && end > next))
298         {
299           g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
300                                _("Could not parse PEM-encoded private key"));
301           return NULL;
302         }
303
304       end += strlen (PEM_PRIVKEY_FOOTER);
305       while (*end == '\r' || *end == '\n')
306         end++;
307
308       privkey_pem = g_strndup (start, end - start);
309
310       *data = end + strlen (PEM_PRIVKEY_FOOTER);
311     }
312
313   cert = g_tls_certificate_new_internal (cert_pem, privkey_pem, error);
314   g_free (cert_pem);
315   g_free (privkey_pem);
316
317   return cert;
318 }
319
320 /**
321  * g_tls_certificate_new_from_pem:
322  * @data: PEM-encoded certificate data
323  * @length: the length of @data, or -1 if it's 0-terminated.
324  * @error: #GError for error reporting, or %NULL to ignore.
325  *
326  * Creates a new #GTlsCertificate from the PEM-encoded data in @data.
327  * If @data includes both a certificate and a private key, then the
328  * returned certificate will include the private key data as well.
329  *
330  * If @data includes multiple certificates, only the first one will be
331  * parsed.
332  *
333  * Return value: the new certificate, or %NULL if @data is invalid
334  *
335  * Since: 2.28
336  */
337 GTlsCertificate *
338 g_tls_certificate_new_from_pem  (const gchar  *data,
339                                  gssize        length,
340                                  GError      **error)
341 {
342   const gchar *data_end;
343
344   g_return_val_if_fail (data != NULL, NULL);
345
346   if (length == -1)
347     data_end = data + strlen (data);
348   else
349     data_end = data + length;
350   return parse_next_pem_certificate (&data, data_end, TRUE, error);
351 }
352
353 /**
354  * g_tls_certificate_new_from_file:
355  * @file: file containing a PEM-encoded certificate to import
356  * @error: #GError for error reporting, or %NULL to ignore.
357  *
358  * Creates a #GTlsCertificate from the PEM-encoded data in @file. If
359  * @file cannot be read or parsed, the function will return %NULL and
360  * set @error. Otherwise, this behaves like g_tls_certificate_new().
361  *
362  * Return value: the new certificate, or %NULL on error
363  *
364  * Since: 2.28
365  */
366 GTlsCertificate *
367 g_tls_certificate_new_from_file (const gchar  *file,
368                                  GError      **error)
369 {
370   GTlsCertificate *cert;
371   gchar *contents;
372   gsize length;
373
374   if (!g_file_get_contents (file, &contents, &length, error))
375     return NULL;
376
377   cert = g_tls_certificate_new_from_pem (contents, length, error);
378   g_free (contents);
379   return cert;
380 }
381
382 /**
383  * g_tls_certificate_new_from_files:
384  * @cert_file: file containing a PEM-encoded certificate to import
385  * @key_file: file containing a PEM-encoded private key to import
386  * @error: #GError for error reporting, or %NULL to ignore.
387  *
388  * Creates a #GTlsCertificate from the PEM-encoded data in @cert_file
389  * and @key_file. If either file cannot be read or parsed, the
390  * function will return %NULL and set @error. Otherwise, this behaves
391  * like g_tls_certificate_new().
392  *
393  * Return value: the new certificate, or %NULL on error
394  *
395  * Since: 2.28
396  */
397 GTlsCertificate *
398 g_tls_certificate_new_from_files (const gchar  *cert_file,
399                                   const gchar  *key_file,
400                                   GError      **error)
401 {
402   GTlsCertificate *cert;
403   gchar *cert_data, *key_data;
404
405   if (!g_file_get_contents (cert_file, &cert_data, NULL, error))
406     return NULL;
407   if (!g_file_get_contents (key_file, &key_data, NULL, error))
408     {
409       g_free (cert_data);
410       return NULL;
411     }
412
413   cert = g_tls_certificate_new_internal (cert_data, key_data, error);
414   g_free (cert_data);
415   g_free (key_data);
416   return cert;
417 }
418
419 /**
420  * g_tls_certificate_list_new_from_file:
421  * @file: file containing PEM-encoded certificates to import
422  * @error: #GError for error reporting, or %NULL to ignore.
423  *
424  * Creates one or more #GTlsCertificate<!-- -->s from the PEM-encoded
425  * data in @file. If @file cannot be read or parsed, the function will
426  * return %NULL and set @error. If @file does not contain any
427  * PEM-encoded certificates, this will return an empty list and not
428  * set @error.
429  *
430  * Return value: (element-type Gio.TlsCertificate) (transfer full): a
431  * #GList containing #GTlsCertificate objects. You must free the list
432  * and its contents when you are done with it.
433  *
434  * Since: 2.28
435  */
436 GList *
437 g_tls_certificate_list_new_from_file (const gchar  *file,
438                                       GError      **error)
439 {
440   GTlsCertificate *cert;
441   GList *list, *l;
442   gchar *contents, *end;
443   const gchar *p;
444   gsize length;
445
446   if (!g_file_get_contents (file, &contents, &length, error))
447     return NULL;
448
449   list = NULL;
450   end = contents + length;
451   p = contents;
452   while (p && *p)
453     {
454       cert = parse_next_pem_certificate (&p, end, FALSE, error);
455       if (!cert)
456         {
457           for (l = list; l; l = l->next)
458             g_object_unref (l->data);
459           g_list_free (list);
460           list = NULL;
461           break;
462         }
463       list = g_list_prepend (list, cert);
464     }
465
466   return g_list_reverse (list);
467 }
468
469
470 /**
471  * g_tls_certificate_get_issuer:
472  * @cert: a #GTlsCertificate
473  *
474  * Gets the #GTlsCertificate representing @cert's issuer, if known
475  *
476  * Return value: (transfer none): The certificate of @cert's issuer,
477  * or %NULL if @cert is self-signed or signed with an unknown
478  * certificate.
479  *
480  * Since: 2.28
481  */
482 GTlsCertificate *
483 g_tls_certificate_get_issuer (GTlsCertificate  *cert)
484 {
485   return cert->priv->issuer;
486 }