1 /* GLib testing framework examples and tests
2 *
3 * Copyright (C) 2011 Collabora Ltd.
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.1 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, see <http://www.gnu.org/licenses/>.
17 *
18 * Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
19 */
20
21 #include "config.h"
22
23 #include <gio/gio.h>
24
25 #include "gtesttlsbackend.h"
26
27 typedef struct
28 {
29 gchar *cert_pems[3];
30 gchar *cert_crlf_pem;
31 gchar *key_pem;
32 gchar *key_crlf_pem;
33 gchar *key8_pem;
34 } Reference;
35
36 static void
pem_parser(const Reference * ref)37 pem_parser (const Reference *ref)
38 {
39 GTlsCertificate *cert;
40 gchar *pem;
41 gsize pem_len = 0;
42 gchar *parsed_cert_pem = NULL;
43 const gchar *parsed_key_pem = NULL;
44 GError *error = NULL;
45
46 /* Check PEM parsing in certificate, private key order. */
47 g_file_get_contents (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert-key.pem", NULL), &pem, &pem_len, &error);
48 g_assert_no_error (error);
49 g_assert_nonnull (pem);
50 g_assert_cmpuint (pem_len, >=, 10);
51
52 cert = g_tls_certificate_new_from_pem (pem, -1, &error);
53 g_assert_no_error (error);
54 g_assert_nonnull (cert);
55
56 g_object_get (cert,
57 "certificate-pem", &parsed_cert_pem,
58 NULL);
59 parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
60 g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
61 g_free (parsed_cert_pem);
62 parsed_cert_pem = NULL;
63 g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem);
64 parsed_key_pem = NULL;
65
66 g_object_unref (cert);
67
68 /* Make sure length is respected and parser detect invalid PEM
69 * when cert is truncated. */
70 cert = g_tls_certificate_new_from_pem (pem, 10, &error);
71 g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE);
72 g_clear_error (&error);
73
74 /* Make sure length is respected and parser detect invalid PEM
75 * when cert exists but key is truncated. */
76 cert = g_tls_certificate_new_from_pem (pem, pem_len - 10, &error);
77 g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE);
78 g_clear_error (&error);
79 g_free (pem);
80
81 /* Check PEM parsing in private key, certificate order */
82 g_file_get_contents (g_test_get_filename (G_TEST_DIST, "cert-tests", "key-cert.pem", NULL), &pem, NULL, &error);
83 g_assert_no_error (error);
84 g_assert_nonnull (pem);
85
86 cert = g_tls_certificate_new_from_pem (pem, -1, &error);
87 g_assert_no_error (error);
88 g_assert_nonnull (cert);
89
90 g_object_get (cert,
91 "certificate-pem", &parsed_cert_pem,
92 NULL);
93 parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
94 g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
95 g_free (parsed_cert_pem);
96 parsed_cert_pem = NULL;
97 g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem);
98 parsed_key_pem = NULL;
99
100 g_free (pem);
101 g_object_unref (cert);
102
103 /* Check certificate only PEM */
104 g_file_get_contents (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL), &pem, NULL, &error);
105 g_assert_no_error (error);
106 g_assert_nonnull (pem);
107
108 cert = g_tls_certificate_new_from_pem (pem, -1, &error);
109 g_assert_no_error (error);
110 g_assert_nonnull (cert);
111
112 g_object_get (cert,
113 "certificate-pem", &parsed_cert_pem,
114 NULL);
115 parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
116 g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
117 g_free (parsed_cert_pem);
118 parsed_cert_pem = NULL;
119 g_assert_null (parsed_key_pem);
120
121 g_free (pem);
122 g_object_unref (cert);
123
124 /* Check error with private key only PEM */
125 g_file_get_contents (g_test_get_filename (G_TEST_DIST, "cert-tests", "key.pem", NULL), &pem, NULL, &error);
126 g_assert_no_error (error);
127 g_assert_nonnull (pem);
128
129 cert = g_tls_certificate_new_from_pem (pem, -1, &error);
130 g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE);
131 g_clear_error (&error);
132 g_assert_null (cert);
133 g_free (pem);
134 }
135
136 static void
pem_parser_handles_chain(const Reference * ref)137 pem_parser_handles_chain (const Reference *ref)
138 {
139 GTlsCertificate *cert;
140 GTlsCertificate *issuer;
141 GTlsCertificate *original_cert;
142 gchar *pem;
143 gchar *parsed_cert_pem = NULL;
144 const gchar *parsed_key_pem = NULL;
145 GError *error = NULL;
146
147 /* Check that a chain with exactly three certificates is returned */
148 g_file_get_contents (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert-list.pem", NULL), &pem, NULL, &error);
149 g_assert_no_error (error);
150 g_assert_nonnull (pem);
151
152 cert = original_cert = g_tls_certificate_new_from_pem (pem, -1, &error);
153 g_free (pem);
154 g_assert_no_error (error);
155 g_assert_nonnull (cert);
156
157 g_object_get (cert,
158 "certificate-pem", &parsed_cert_pem,
159 NULL);
160 g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
161 g_clear_pointer (&parsed_cert_pem, g_free);
162
163 /* Make sure the private key was parsed */
164 parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
165 g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem);
166 parsed_key_pem = NULL;
167
168 /* Now test the second cert */
169 issuer = g_tls_certificate_get_issuer (cert);
170 g_assert_nonnull (issuer);
171
172 cert = issuer;
173 issuer = g_tls_certificate_get_issuer (cert);
174 g_assert_nonnull (issuer);
175
176 g_object_get (cert,
177 "certificate-pem", &parsed_cert_pem,
178 NULL);
179 g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[1]);
180 g_clear_pointer (&parsed_cert_pem, g_free);
181
182 /* Only the first cert should have a private key */
183 parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
184 g_assert_null (parsed_key_pem);
185
186 /* Now test the final cert */
187 cert = issuer;
188 issuer = g_tls_certificate_get_issuer (cert);
189 g_assert_null (issuer);
190
191 g_object_get (cert,
192 "certificate-pem", &parsed_cert_pem,
193 NULL);
194 g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[2]);
195 g_clear_pointer (&parsed_cert_pem, g_free);
196
197 parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
198 g_assert_null (parsed_key_pem);
199
200 g_object_unref (original_cert);
201 }
202
203 static void
from_file(const Reference * ref)204 from_file (const Reference *ref)
205 {
206 GTlsCertificate *cert;
207 gchar *parsed_cert_pem = NULL;
208 const gchar *parsed_key_pem = NULL;
209 GError *error = NULL;
210
211 cert = g_tls_certificate_new_from_file (g_test_get_filename (G_TEST_DIST, "cert-tests", "key-cert.pem", NULL),
212 &error);
213 g_assert_no_error (error);
214 g_assert_nonnull (cert);
215
216 g_object_get (cert,
217 "certificate-pem", &parsed_cert_pem,
218 NULL);
219 parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
220 g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
221 g_free (parsed_cert_pem);
222 parsed_cert_pem = NULL;
223 g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem);
224 parsed_key_pem = NULL;
225
226 g_object_unref (cert);
227 }
228
229 static void
from_files(const Reference * ref)230 from_files (const Reference *ref)
231 {
232 GTlsCertificate *cert;
233 gchar *parsed_cert_pem = NULL;
234 const gchar *parsed_key_pem = NULL;
235 GError *error = NULL;
236
237 cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL),
238 g_test_get_filename (G_TEST_DIST, "cert-tests", "key.pem", NULL),
239 &error);
240 g_assert_no_error (error);
241 g_assert_nonnull (cert);
242
243 g_object_get (cert,
244 "certificate-pem", &parsed_cert_pem,
245 NULL);
246 parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
247 g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
248 g_free (parsed_cert_pem);
249 parsed_cert_pem = NULL;
250 g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem);
251 parsed_key_pem = NULL;
252
253 g_object_unref (cert);
254
255 /* Missing private key */
256 cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL),
257 g_test_get_filename (G_TEST_DIST, "cert-tests", "cert2.pem", NULL),
258 &error);
259 g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE);
260 g_clear_error (&error);
261 g_assert_null (cert);
262
263 /* Missing header private key */
264 cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL),
265 g_test_get_filename (G_TEST_DIST, "cert-tests", "key_missing-header.pem", NULL),
266 &error);
267 g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE);
268 g_clear_error (&error);
269 g_assert_null (cert);
270
271 /* Missing footer private key */
272 cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL),
273 g_test_get_filename (G_TEST_DIST, "cert-tests", "key_missing-footer.pem", NULL),
274 &error);
275 g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE);
276 g_clear_error (&error);
277 g_assert_null (cert);
278
279 /* Missing certificate */
280 cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "key.pem", NULL),
281 g_test_get_filename (G_TEST_DIST, "cert-tests", "key.pem", NULL),
282 &error);
283 g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE);
284 g_clear_error (&error);
285 g_assert_null (cert);
286
287 /* Using this method twice with a file containing both private key and
288 * certificate as a way to enforce private key presence is a fair use
289 */
290 cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "key-cert.pem", NULL),
291 g_test_get_filename (G_TEST_DIST, "cert-tests", "key-cert.pem", NULL),
292 &error);
293 g_assert_no_error (error);
294 g_assert_nonnull (cert);
295 g_object_unref (cert);
296 }
297
298 static void
from_files_crlf(const Reference * ref)299 from_files_crlf (const Reference *ref)
300 {
301 GTlsCertificate *cert;
302 gchar *parsed_cert_pem = NULL;
303 const gchar *parsed_key_pem = NULL;
304 GError *error = NULL;
305
306 cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert-crlf.pem", NULL),
307 g_test_get_filename (G_TEST_DIST, "cert-tests", "key-crlf.pem", NULL),
308 &error);
309 g_assert_no_error (error);
310 g_assert_nonnull (cert);
311
312 g_object_get (cert,
313 "certificate-pem", &parsed_cert_pem,
314 NULL);
315 parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
316 g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_crlf_pem);
317 g_free (parsed_cert_pem);
318 parsed_cert_pem = NULL;
319 g_assert_cmpstr (parsed_key_pem, ==, ref->key_crlf_pem);
320 parsed_key_pem = NULL;
321
322 g_object_unref (cert);
323 }
324
325 static void
from_files_pkcs8(const Reference * ref)326 from_files_pkcs8 (const Reference *ref)
327 {
328 GTlsCertificate *cert;
329 gchar *parsed_cert_pem = NULL;
330 const gchar *parsed_key_pem = NULL;
331 GError *error = NULL;
332
333 cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL),
334 g_test_get_filename (G_TEST_DIST, "cert-tests", "key8.pem", NULL),
335 &error);
336 g_assert_no_error (error);
337 g_assert_nonnull (cert);
338
339 g_object_get (cert,
340 "certificate-pem", &parsed_cert_pem,
341 NULL);
342 parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
343 g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
344 g_free (parsed_cert_pem);
345 parsed_cert_pem = NULL;
346 g_assert_cmpstr (parsed_key_pem, ==, ref->key8_pem);
347 parsed_key_pem = NULL;
348
349 g_object_unref (cert);
350 }
351
352 static void
from_files_pkcs8enc(const Reference * ref)353 from_files_pkcs8enc (const Reference *ref)
354 {
355 GTlsCertificate *cert;
356 GError *error = NULL;
357
358 /* Mare sure an error is returned for encrypted key */
359 cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL),
360 g_test_get_filename (G_TEST_DIST, "cert-tests", "key8enc.pem", NULL),
361 &error);
362 g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE);
363 g_clear_error (&error);
364 g_assert_null (cert);
365 }
366
367 static void
list_from_file(const Reference * ref)368 list_from_file (const Reference *ref)
369 {
370 GList *list, *l;
371 GError *error = NULL;
372 int i;
373
374 list = g_tls_certificate_list_new_from_file (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert-list.pem", NULL),
375 &error);
376 g_assert_no_error (error);
377 g_assert_cmpint (g_list_length (list), ==, 3);
378
379 l = list;
380 for (i = 0; i < 3; i++)
381 {
382 GTlsCertificate *cert = l->data;
383 gchar *parsed_cert_pem = NULL;
384 g_object_get (cert,
385 "certificate-pem", &parsed_cert_pem,
386 NULL);
387 g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[i]);
388 g_free (parsed_cert_pem);
389 l = g_list_next (l);
390 }
391
392 g_list_free_full (list, g_object_unref);
393
394 /* Empty list is not an error */
395 list = g_tls_certificate_list_new_from_file (g_test_get_filename (G_TEST_DIST, "cert-tests", "nothing.pem", NULL),
396 &error);
397 g_assert_no_error (error);
398 g_assert_cmpint (g_list_length (list), ==, 0);
399 }
400
401 static void
from_pkcs11_uri(void)402 from_pkcs11_uri (void)
403 {
404 GError *error = NULL;
405 GTlsCertificate *cert;
406 gchar *pkcs11_uri = NULL;
407
408 cert = g_tls_certificate_new_from_pkcs11_uris ("pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=ca-bundle.crt", NULL, &error);
409 g_assert_no_error (error);
410 g_assert_nonnull (cert);
411
412 g_object_get (cert, "pkcs11-uri", &pkcs11_uri, NULL);
413 g_assert_cmpstr ("pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=ca-bundle.crt", ==, pkcs11_uri);
414 g_free (pkcs11_uri);
415
416 g_object_unref (cert);
417 }
418
419 static void
from_unsupported_pkcs11_uri(void)420 from_unsupported_pkcs11_uri (void)
421 {
422 GError *error = NULL;
423 GTlsCertificate *cert;
424
425 /* This is a magic value in gtesttlsbackend.c simulating an unsupported backend */
426 cert = g_tls_certificate_new_from_pkcs11_uris ("unsupported", NULL, &error);
427 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
428 g_assert_null (cert);
429
430 g_clear_error (&error);
431 }
432
433 int
main(int argc,char * argv[])434 main (int argc,
435 char *argv[])
436 {
437 int rtv;
438 Reference ref;
439 GError *error = NULL;
440 gchar *path;
441
442 g_test_init (&argc, &argv, NULL);
443
444 _g_test_tls_backend_get_type ();
445
446 /* Load reference PEM */
447 path = g_test_build_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL);
448 g_file_get_contents (path, &ref.cert_pems[0], NULL, &error);
449 g_assert_no_error (error);
450 g_assert_nonnull (ref.cert_pems[0]);
451 g_free (path);
452 path = g_test_build_filename (G_TEST_DIST, "cert-tests", "cert2.pem", NULL);
453 g_file_get_contents (path, &ref.cert_pems[1], NULL, &error);
454 g_assert_no_error (error);
455 g_assert_nonnull (ref.cert_pems[1]);
456 g_free (path);
457 path = g_test_build_filename (G_TEST_DIST, "cert-tests", "cert3.pem", NULL);
458 g_file_get_contents (path, &ref.cert_pems[2], NULL, &error);
459 g_assert_no_error (error);
460 g_assert_nonnull (ref.cert_pems[2]);
461 g_free (path);
462 path = g_test_build_filename (G_TEST_DIST, "cert-tests", "cert-crlf.pem", NULL);
463 g_file_get_contents (path, &ref.cert_crlf_pem, NULL, &error);
464 g_assert_no_error (error);
465 g_assert_nonnull (ref.cert_crlf_pem);
466 g_free (path);
467 path = g_test_build_filename (G_TEST_DIST, "cert-tests", "key.pem", NULL);
468 g_file_get_contents (path, &ref.key_pem, NULL, &error);
469 g_assert_no_error (error);
470 g_assert_nonnull (ref.key_pem);
471 g_free (path);
472 path = g_test_build_filename (G_TEST_DIST, "cert-tests", "key-crlf.pem", NULL);
473 g_file_get_contents (path, &ref.key_crlf_pem, NULL, &error);
474 g_assert_no_error (error);
475 g_assert_nonnull (ref.key_crlf_pem);
476 g_free (path);
477 path = g_test_build_filename (G_TEST_DIST, "cert-tests", "key8.pem", NULL);
478 g_file_get_contents (path, &ref.key8_pem, NULL, &error);
479 g_assert_no_error (error);
480 g_assert_nonnull (ref.key8_pem);
481 g_free (path);
482
483 g_test_add_data_func ("/tls-certificate/pem-parser",
484 &ref, (GTestDataFunc)pem_parser);
485 g_test_add_data_func ("/tls-certificate/pem-parser-handles-chain",
486 &ref, (GTestDataFunc)pem_parser_handles_chain);
487 g_test_add_data_func ("/tls-certificate/from_file",
488 &ref, (GTestDataFunc)from_file);
489 g_test_add_data_func ("/tls-certificate/from_files",
490 &ref, (GTestDataFunc)from_files);
491 g_test_add_data_func ("/tls-certificate/from_files_crlf",
492 &ref, (GTestDataFunc)from_files_crlf);
493 g_test_add_data_func ("/tls-certificate/from_files_pkcs8",
494 &ref, (GTestDataFunc)from_files_pkcs8);
495 g_test_add_data_func ("/tls-certificate/from_files_pkcs8enc",
496 &ref, (GTestDataFunc)from_files_pkcs8enc);
497 g_test_add_data_func ("/tls-certificate/list_from_file",
498 &ref, (GTestDataFunc)list_from_file);
499 g_test_add_func ("/tls-certificate/pkcs11-uri",
500 from_pkcs11_uri);
501 g_test_add_func ("/tls-certificate/pkcs11-uri-unsupported",
502 from_unsupported_pkcs11_uri);
503
504 rtv = g_test_run();
505
506 g_free (ref.cert_pems[0]);
507 g_free (ref.cert_pems[1]);
508 g_free (ref.cert_pems[2]);
509 g_free (ref.cert_crlf_pem);
510 g_free (ref.key_pem);
511 g_free (ref.key_crlf_pem);
512 g_free (ref.key8_pem);
513
514 return rtv;
515 }
516