openssl: remove manual check for certificate expiration
[platform/upstream/glib-networking.git] / tls / tests / certificate.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3  * GIO TLS tests
4  *
5  * Copyright 2011 Collabora, Ltd.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General
18  * Public License along with this library; if not, see
19  * <http://www.gnu.org/licenses/>.
20  *
21  * In addition, when the library is used with OpenSSL, a special
22  * exception applies. Refer to the LICENSE_EXCEPTION file for details.
23  *
24  * Author: Stef Walter <stefw@collabora.co.uk>
25  */
26
27 #include <gio/gio.h>
28
29 #include <sys/types.h>
30 #include <string.h>
31
32 static const gchar *
33 tls_test_file_path (const char *name)
34 {
35   const gchar *const_path;
36   gchar *path;
37
38   path = g_test_build_filename (G_TEST_DIST, "files", name, NULL);
39   if (!g_path_is_absolute (path))
40     {
41       gchar *cwd, *abs;
42
43       cwd = g_get_current_dir ();
44       abs = g_build_filename (cwd, path, NULL);
45       g_free (cwd);
46       g_free (path);
47       path = abs;
48     }
49
50   const_path = g_intern_string (path);
51   g_free (path);
52   return const_path;
53 }
54
55 typedef struct {
56   GTlsBackend *backend;
57   GType cert_gtype;
58   gchar *cert_pem;
59   gsize cert_pem_length;
60   GByteArray *cert_der;
61   gchar *key_pem;
62   gsize key_pem_length;
63   GByteArray *key_der;
64 } TestCertificate;
65
66 static void
67 setup_certificate (TestCertificate *test, gconstpointer data)
68 {
69   GError *error = NULL;
70   gchar *contents;
71   gsize length;
72
73   test->backend = g_tls_backend_get_default ();
74   test->cert_gtype = g_tls_backend_get_certificate_type (test->backend);
75
76   g_file_get_contents (tls_test_file_path ("server.pem"), &test->cert_pem,
77                        &test->cert_pem_length, &error);
78   g_assert_no_error (error);
79
80   g_file_get_contents (tls_test_file_path ("server.der"),
81                        &contents, &length, &error);
82   g_assert_no_error (error);
83
84   test->cert_der = g_byte_array_new ();
85   g_byte_array_append (test->cert_der, (guint8 *)contents, length);
86   g_free (contents);
87
88   g_file_get_contents (tls_test_file_path ("server-key.pem"), &test->key_pem,
89                        &test->key_pem_length, &error);
90   g_assert_no_error (error);
91
92   g_file_get_contents (tls_test_file_path ("server-key.der"),
93                        &contents, &length, &error);
94   g_assert_no_error (error);
95
96   test->key_der = g_byte_array_new ();
97   g_byte_array_append (test->key_der, (guint8 *)contents, length);
98   g_free (contents);
99 }
100
101 static void
102 teardown_certificate (TestCertificate *test,
103                       gconstpointer data)
104 {
105   g_free (test->cert_pem);
106   g_byte_array_free (test->cert_der, TRUE);
107
108   g_free (test->key_pem);
109   g_byte_array_free (test->key_der, TRUE);
110 }
111
112 static void
113 test_create_pem (TestCertificate *test,
114                  gconstpointer data)
115 {
116   GTlsCertificate *cert;
117   gchar *pem = NULL;
118   GError *error = NULL;
119
120   cert = g_tls_certificate_new_from_pem (test->cert_pem, test->cert_pem_length, &error);
121   g_assert_no_error (error);
122   g_assert_true (G_IS_TLS_CERTIFICATE (cert));
123
124   g_object_get (cert, "certificate-pem", &pem, NULL);
125   g_assert_cmpstr (pem, ==, test->cert_pem);
126   g_free (pem);
127
128   g_object_add_weak_pointer (G_OBJECT (cert), (gpointer *)&cert);
129   g_object_unref (cert);
130   g_assert_null (cert);
131 }
132
133 static void
134 test_create_with_key_pem (TestCertificate *test,
135                           gconstpointer data)
136 {
137   GTlsCertificate *cert;
138   GError *error = NULL;
139
140   cert = g_initable_new (test->cert_gtype, NULL, &error,
141                          "certificate-pem", test->cert_pem,
142                          "private-key-pem", test->key_pem,
143                          NULL);
144   g_assert_no_error (error);
145   g_assert_true (G_IS_TLS_CERTIFICATE (cert));
146
147   g_object_add_weak_pointer (G_OBJECT (cert), (gpointer *)&cert);
148   g_object_unref (cert);
149   g_assert_null (cert);
150 }
151
152 static void
153 test_create_der (TestCertificate *test,
154                  gconstpointer data)
155 {
156   GTlsCertificate *cert;
157   GByteArray *der = NULL;
158   GError *error = NULL;
159
160   cert = g_initable_new (test->cert_gtype, NULL, &error,
161                          "certificate", test->cert_der,
162                          NULL);
163   g_assert_no_error (error);
164   g_assert_true (G_IS_TLS_CERTIFICATE (cert));
165
166   g_object_get (cert, "certificate", &der, NULL);
167   g_assert_nonnull (der);
168   g_assert_cmpuint (der->len, ==, test->cert_der->len);
169   g_assert_cmpint (memcmp (der->data, test->cert_der->data, der->len), ==, 0);
170
171   g_byte_array_unref (der);
172
173   g_object_add_weak_pointer (G_OBJECT (cert), (gpointer *)&cert);
174   g_object_unref (cert);
175   g_assert_null (cert);
176 }
177
178 static void
179 test_create_with_key_der (TestCertificate *test,
180                           gconstpointer data)
181 {
182   GTlsCertificate *cert;
183   GError *error = NULL;
184
185   cert = g_initable_new (test->cert_gtype, NULL, &error,
186                          "certificate", test->cert_der,
187                          "private-key", test->key_der,
188                          NULL);
189   g_assert_no_error (error);
190   g_assert_true (G_IS_TLS_CERTIFICATE (cert));
191
192   g_object_add_weak_pointer (G_OBJECT (cert), (gpointer *)&cert);
193   g_object_unref (cert);
194   g_assert_null (cert);
195 }
196
197 static void
198 test_create_certificate_with_issuer (TestCertificate   *test,
199                                      gconstpointer      data)
200 {
201   GTlsCertificate *cert, *issuer, *check;
202   GError *error = NULL;
203
204   issuer = g_tls_certificate_new_from_file (tls_test_file_path ("ca.pem"), &error);
205   g_assert_no_error (error);
206   g_assert_true (G_IS_TLS_CERTIFICATE (issuer));
207
208   cert = g_initable_new (test->cert_gtype, NULL, &error,
209                          "certificate-pem", test->cert_pem,
210                          "issuer", issuer,
211                          NULL);
212   g_assert_no_error (error);
213   g_assert_true (G_IS_TLS_CERTIFICATE (cert));
214
215   g_object_add_weak_pointer (G_OBJECT (issuer), (gpointer *)&issuer);
216   g_object_unref (issuer);
217   g_assert_nonnull (issuer);
218
219   check = g_tls_certificate_get_issuer (cert);
220   g_assert_true (check == issuer);
221
222   g_object_add_weak_pointer (G_OBJECT (cert), (gpointer *)&cert);
223   g_object_unref (cert);
224   g_assert_null (cert);
225   g_assert_null (issuer);
226 }
227
228 static void
229 test_create_certificate_with_garbage_input (TestCertificate *test,
230                                             gconstpointer data)
231 {
232   GTlsCertificate *cert;
233   GError *error = NULL;
234
235   cert = g_tls_certificate_new_from_file (tls_test_file_path ("garbage.pem"), &error);
236   g_assert_null (cert);
237   g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE);
238   g_clear_error (&error);
239
240   cert = g_tls_certificate_new_from_pem ("I am not a very good certificate.", -1, &error);
241   g_assert_null (cert);
242   g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE);
243   g_clear_error (&error);
244 }
245
246 static void
247 test_create_certificate_chain (void)
248 {
249   GTlsCertificate *cert, *intermediate, *root;
250   GError *error = NULL;
251
252   cert = g_tls_certificate_new_from_file (tls_test_file_path ("chain.pem"), &error);
253   g_assert_no_error (error);
254   g_assert_true (G_IS_TLS_CERTIFICATE (cert));
255
256   intermediate = g_tls_certificate_get_issuer (cert);
257   g_assert_true (G_IS_TLS_CERTIFICATE (intermediate));
258
259   root = g_tls_certificate_get_issuer (intermediate);
260   g_assert_true (G_IS_TLS_CERTIFICATE (root));
261
262   g_assert_null (g_tls_certificate_get_issuer (root));
263
264   g_object_unref (cert);
265 }
266
267 static void
268 test_create_certificate_no_chain (void)
269 {
270   GTlsCertificate *cert, *issuer;
271   GError *error = NULL;
272   gchar *cert_pem;
273   gsize cert_pem_length;
274
275   cert = g_tls_certificate_new_from_file (tls_test_file_path ("non-ca.pem"), &error);
276   g_assert_no_error (error);
277   g_assert_true (G_IS_TLS_CERTIFICATE (cert));
278
279   issuer = g_tls_certificate_get_issuer (cert);
280   g_assert_null (issuer);
281   g_object_unref (cert);
282
283   /* Truncate a valid chain certificate file. We should only get the
284    * first certificate.
285    */
286   g_file_get_contents (tls_test_file_path ("chain.pem"), &cert_pem,
287                        &cert_pem_length, &error);
288   g_assert_no_error (error);
289
290   cert = g_tls_certificate_new_from_pem (cert_pem, cert_pem_length - 100, &error);
291   g_free (cert_pem);
292   g_assert_no_error (error);
293   g_assert_true (G_IS_TLS_CERTIFICATE (cert));
294
295   issuer = g_tls_certificate_get_issuer (cert);
296   g_assert_null (issuer);
297   g_object_unref (cert);
298 }
299
300 static void
301 test_create_list (void)
302 {
303   GList *list;
304   GError *error = NULL;
305
306   list = g_tls_certificate_list_new_from_file (tls_test_file_path ("ca-roots.pem"), &error);
307   g_assert_no_error (error);
308   g_assert_cmpint (g_list_length (list), ==, 8);
309
310   g_list_free_full (list, g_object_unref);
311 }
312
313 static void
314 test_create_list_bad (void)
315 {
316   GList *list;
317   GError *error = NULL;
318
319   list = g_tls_certificate_list_new_from_file (tls_test_file_path ("ca-roots-bad.pem"), &error);
320   g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE);
321   g_assert_null (list);
322   g_error_free (error);
323 }
324
325 /* -----------------------------------------------------------------------------
326  * CERTIFICATE VERIFY
327  */
328
329 typedef struct {
330   GTlsCertificate *cert;
331   GTlsCertificate *anchor;
332   GSocketConnectable *identity;
333   GTlsDatabase *database;
334 } TestVerify;
335
336 static void
337 setup_verify (TestVerify     *test,
338               gconstpointer   data)
339 {
340   GError *error = NULL;
341
342   test->cert = g_tls_certificate_new_from_file (tls_test_file_path ("server.pem"), &error);
343   g_assert_no_error (error);
344   g_assert_true (G_IS_TLS_CERTIFICATE (test->cert));
345
346   test->identity = g_network_address_new ("server.example.com", 80);
347
348   test->anchor = g_tls_certificate_new_from_file (tls_test_file_path ("ca.pem"), &error);
349   g_assert_no_error (error);
350   g_assert_true (G_IS_TLS_CERTIFICATE (test->anchor));
351   test->database = g_tls_file_database_new (tls_test_file_path ("ca.pem"), &error);
352   g_assert_no_error (error);
353   g_assert_true (G_IS_TLS_DATABASE (test->database));
354 }
355
356 static void
357 teardown_verify (TestVerify      *test,
358                  gconstpointer    data)
359 {
360   g_assert_true (G_IS_TLS_CERTIFICATE (test->cert));
361   g_object_add_weak_pointer (G_OBJECT (test->cert),
362                              (gpointer *)&test->cert);
363   g_object_unref (test->cert);
364   g_assert_null (test->cert);
365
366   g_assert_true (G_IS_TLS_CERTIFICATE (test->anchor));
367   g_object_add_weak_pointer (G_OBJECT (test->anchor),
368                              (gpointer *)&test->anchor);
369   g_object_unref (test->anchor);
370   g_assert_null (test->anchor);
371
372   g_assert_true (G_IS_TLS_DATABASE (test->database));
373   g_object_add_weak_pointer (G_OBJECT (test->database),
374                              (gpointer *)&test->database);
375   g_object_unref (test->database);
376   g_assert_null (test->database);
377
378   g_object_add_weak_pointer (G_OBJECT (test->identity),
379                              (gpointer *)&test->identity);
380   g_object_unref (test->identity);
381   g_assert_null (test->identity);
382 }
383
384 static void
385 test_verify_certificate_good (TestVerify      *test,
386                               gconstpointer    data)
387 {
388   GSocketConnectable *identity;
389   GSocketAddress *addr;
390   GTlsCertificateFlags errors;
391
392   errors = g_tls_certificate_verify (test->cert, test->identity, test->anchor);
393   g_assert_cmpuint (errors, ==, 0);
394
395   errors = g_tls_certificate_verify (test->cert, NULL, test->anchor);
396   g_assert_cmpuint (errors, ==, 0);
397
398   identity = g_network_address_new ("192.168.1.10", 80);
399   errors = g_tls_certificate_verify (test->cert, identity, test->anchor);
400   g_assert_cmpuint (errors, ==, 0);
401   g_object_unref (identity);
402
403   addr = g_inet_socket_address_new_from_string ("192.168.1.10", 80);
404   errors = g_tls_certificate_verify (test->cert, G_SOCKET_CONNECTABLE (addr), test->anchor);
405   g_assert_cmpuint (errors, ==, 0);
406   g_object_unref (addr);
407 }
408
409 static void
410 test_verify_certificate_bad_identity (TestVerify      *test,
411                                       gconstpointer    data)
412 {
413   GSocketConnectable *identity;
414   GTlsCertificateFlags errors;
415   GSocketAddress *addr;
416
417   identity = g_network_address_new ("other.example.com", 80);
418   errors = g_tls_certificate_verify (test->cert, identity, test->anchor);
419   g_assert_cmpuint (errors, ==, G_TLS_CERTIFICATE_BAD_IDENTITY);
420   g_object_unref (identity);
421
422   identity = g_network_address_new ("127.0.0.1", 80);
423   errors = g_tls_certificate_verify (test->cert, identity, test->anchor);
424   g_assert_cmpuint (errors, ==, G_TLS_CERTIFICATE_BAD_IDENTITY);
425   g_object_unref (identity);
426
427   addr = g_inet_socket_address_new_from_string ("127.0.0.1", 80);
428   errors = g_tls_certificate_verify (test->cert, G_SOCKET_CONNECTABLE (addr), test->anchor);
429   g_assert_cmpuint (errors, ==, G_TLS_CERTIFICATE_BAD_IDENTITY);
430   g_object_unref (addr);
431 }
432
433 static void
434 test_verify_certificate_bad_ca (TestVerify      *test,
435                                 gconstpointer    data)
436 {
437   GTlsCertificateFlags errors;
438   GTlsCertificate *cert;
439   GError *error = NULL;
440
441   /* Use a client certificate as the CA, which is wrong */
442   cert = g_tls_certificate_new_from_file (tls_test_file_path ("client.pem"), &error);
443   g_assert_no_error (error);
444   g_assert_true (G_IS_TLS_CERTIFICATE (cert));
445
446   errors = g_tls_certificate_verify (test->cert, test->identity, cert);
447   g_assert_cmpuint (errors, ==, G_TLS_CERTIFICATE_UNKNOWN_CA);
448
449   g_object_unref (cert);
450 }
451
452 static void
453 test_verify_certificate_bad_before (TestVerify      *test,
454                                     gconstpointer    data)
455 {
456   GTlsCertificateFlags errors;
457   GTlsCertificate *cert;
458   GError *error = NULL;
459
460   /* This is a certificate in the future */
461   cert = g_tls_certificate_new_from_file (tls_test_file_path ("client-future.pem"), &error);
462   g_assert_no_error (error);
463   g_assert_true (G_IS_TLS_CERTIFICATE (cert));
464
465   errors = g_tls_certificate_verify (cert, NULL, test->anchor);
466   g_assert_cmpuint (errors, ==, G_TLS_CERTIFICATE_NOT_ACTIVATED);
467
468   g_object_unref (cert);
469 }
470
471 static void
472 test_verify_certificate_bad_expired (TestVerify      *test,
473                                      gconstpointer    data)
474 {
475   GTlsCertificateFlags errors;
476   GTlsCertificate *cert;
477   GError *error = NULL;
478
479   /* This is a certificate in the future */
480   cert = g_tls_certificate_new_from_file (tls_test_file_path ("client-past.pem"), &error);
481   g_assert_no_error (error);
482   g_assert_true (G_IS_TLS_CERTIFICATE (cert));
483
484   errors = g_tls_certificate_verify (cert, NULL, test->anchor);
485   g_assert_cmpuint (errors, ==, G_TLS_CERTIFICATE_EXPIRED);
486
487   g_object_unref (cert);
488 }
489
490 static void
491 test_verify_certificate_bad_combo (TestVerify      *test,
492                                    gconstpointer    data)
493 {
494   GTlsCertificate *cert;
495   GTlsCertificate *cacert;
496   GSocketConnectable *identity;
497   GTlsCertificateFlags errors;
498   GError *error = NULL;
499
500   cert = g_tls_certificate_new_from_file (tls_test_file_path ("client-past.pem"), &error);
501   g_assert_no_error (error);
502   g_assert_true (G_IS_TLS_CERTIFICATE (cert));
503
504   /* Unrelated cert used as certificate authority */
505   cacert = g_tls_certificate_new_from_file (tls_test_file_path ("server-self.pem"), &error);
506   g_assert_no_error (error);
507   g_assert_true (G_IS_TLS_CERTIFICATE (cacert));
508
509   /*
510    * - Use unrelated cert as CA
511    * - Use wrong identity.
512    * - Use expired certificate.
513    *
514    * Once upon a time, we might have asserted to see that all of these errors
515    * are set. But this is impossible to do correctly, so nowadays we only
516    * guarantee that at least one error will be set. See glib-networking#179 and
517    * glib!2214 for rationale.
518    */
519
520   identity = g_network_address_new ("other.example.com", 80);
521
522   errors = g_tls_certificate_verify (cert, identity, cacert);
523   g_assert_cmpuint (errors, !=, 0);
524
525   g_object_unref (cert);
526   g_object_unref (cacert);
527   g_object_unref (identity);
528 }
529
530 static void
531 test_certificate_is_same (void)
532 {
533   GTlsCertificate *one;
534   GTlsCertificate *two;
535   GTlsCertificate *three;
536   GError *error = NULL;
537
538   one = g_tls_certificate_new_from_file (tls_test_file_path ("client.pem"), &error);
539   g_assert_no_error (error);
540
541   two = g_tls_certificate_new_from_file (tls_test_file_path ("client-and-key.pem"), &error);
542   g_assert_no_error (error);
543
544   three = g_tls_certificate_new_from_file (tls_test_file_path ("server.pem"), &error);
545   g_assert_no_error (error);
546
547   g_assert_true (g_tls_certificate_is_same (one, two));
548   g_assert_true (g_tls_certificate_is_same (two, one));
549   g_assert_false (g_tls_certificate_is_same (three, one));
550   g_assert_false (g_tls_certificate_is_same (one, three));
551   g_assert_false (g_tls_certificate_is_same (two, three));
552   g_assert_false (g_tls_certificate_is_same (three, two));
553
554   g_object_unref (one);
555   g_object_unref (two);
556   g_object_unref (three);
557 }
558
559 int
560 main (int   argc,
561       char *argv[])
562 {
563   g_test_init (&argc, &argv, NULL);
564
565   g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
566   g_setenv ("GIO_USE_TLS", BACKEND, TRUE);
567   g_assert (g_ascii_strcasecmp (G_OBJECT_TYPE_NAME (g_tls_backend_get_default ()), "GTlsBackend" BACKEND) == 0);
568
569   g_test_add ("/tls/certificate/create-pem", TestCertificate, NULL,
570               setup_certificate, test_create_pem, teardown_certificate);
571   g_test_add ("/tls/certificate/create-der", TestCertificate, NULL,
572               setup_certificate, test_create_der, teardown_certificate);
573   g_test_add ("/tls/certificate/create-with-key-pem", TestCertificate, NULL,
574               setup_certificate, test_create_with_key_pem, teardown_certificate);
575   g_test_add ("/tls/certificate/create-with-key-der", TestCertificate, NULL,
576               setup_certificate, test_create_with_key_der, teardown_certificate);
577   g_test_add ("/tls/certificate/create-with-issuer", TestCertificate, NULL,
578               setup_certificate, test_create_certificate_with_issuer, teardown_certificate);
579   g_test_add ("/tls/certificate/create-with-garbage-input", TestCertificate, NULL,
580               setup_certificate, test_create_certificate_with_garbage_input, teardown_certificate);
581
582   g_test_add_func ("/tls/certificate/create-chain", test_create_certificate_chain);
583   g_test_add_func ("/tls/certificate/create-no-chain", test_create_certificate_no_chain);
584   g_test_add_func ("/tls/certificate/create-list", test_create_list);
585   g_test_add_func ("/tls/certificate/create-list-bad", test_create_list_bad);
586
587   g_test_add ("/tls/certificate/verify-good", TestVerify, NULL,
588               setup_verify, test_verify_certificate_good, teardown_verify);
589   g_test_add ("/tls/certificate/verify-bad-identity", TestVerify, NULL,
590               setup_verify, test_verify_certificate_bad_identity, teardown_verify);
591   g_test_add ("/tls/certificate/verify-bad-ca", TestVerify, NULL,
592               setup_verify, test_verify_certificate_bad_ca, teardown_verify);
593   g_test_add ("/tls/certificate/verify-bad-before", TestVerify, NULL,
594               setup_verify, test_verify_certificate_bad_before, teardown_verify);
595   g_test_add ("/tls/certificate/verify-bad-expired", TestVerify, NULL,
596               setup_verify, test_verify_certificate_bad_expired, teardown_verify);
597   g_test_add ("/tls/certificate/verify-bad-combo", TestVerify, NULL,
598               setup_verify, test_verify_certificate_bad_combo, teardown_verify);
599
600   g_test_add_func ("/tls/certificate/is-same", test_certificate_is_same);
601
602   return g_test_run();
603 }