1 //  gnoMint: a graphical interface for managing a certification authority
2 //  Copyright (C) 2006-2009 David Marín Carreño <davefx@gmail.com>
3 //
4 //  This file is part of gnoMint.
5 //
6 //  gnoMint is free software; you can redistribute it and/or modify
7 //  it under the terms of the GNU General Public License as published by
8 //  the Free Software Foundation; either version 3 of the License, or
9 //  (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 
20 #ifndef GNOMINTCLI
21 
22 #include <gtk/gtk.h>
23 #endif
24 
25 #include <glib-object.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include "import.h"
30 #include "tls.h"
31 #include "dialog.h"
32 #include "ca_file.h"
33 
34 
35 gchar * __import_ask_password (const gchar *crypted_part_description);
36 gint __import_csr (gnutls_x509_crq_t *crq, gchar ** csr_dn, guint64 *id);
37 gint __import_cert (gnutls_x509_crt_t *cert, gchar ** cert_dn, guint64 *id);
38 
__import_ask_password(const gchar * crypted_part_description)39 gchar * __import_ask_password (const gchar *crypted_part_description)
40 {
41 #ifndef GNOMINTCLI
42 	gchar *password;
43 	GObject * widget = NULL, * password_widget = NULL, *description_widget = NULL;
44 	GtkBuilder * dialog_gtkb = NULL;
45         gchar     * label = NULL;
46 	gint response = 0;
47 
48 	dialog_gtkb = gtk_builder_new();
49 	gtk_builder_add_from_file (dialog_gtkb,
50 				   g_build_filename (PACKAGE_DATA_DIR, "gnomint", "import_password_dialog.ui", NULL),
51 				   NULL);
52 	gtk_builder_connect_signals (dialog_gtkb, NULL);
53 
54 	password_widget = gtk_builder_get_object (dialog_gtkb, "import_password_entry");
55 	description_widget = gtk_builder_get_object (dialog_gtkb, "import_crypted_part_description");
56 
57         label = g_strdup_printf ("<small><i>%s</i></small>", crypted_part_description);
58         gtk_label_set_markup (GTK_LABEL(description_widget), (const gchar *) label);
59         g_free (label);
60 
61         gtk_widget_grab_focus (GTK_WIDGET(password_widget));
62         widget = gtk_builder_get_object (dialog_gtkb, "import_password_dialog");
63         response = gtk_dialog_run(GTK_DIALOG(widget));
64 
65         if (!response) {
66                 gtk_widget_destroy (GTK_WIDGET(widget));
67                 g_object_unref (G_OBJECT(dialog_gtkb));
68                 return NULL;
69         } else {
70                 password = g_strdup ((gchar *) gtk_entry_get_text (GTK_ENTRY(password_widget)));
71         }
72 
73 	widget = gtk_builder_get_object (dialog_gtkb, "import_password_dialog");
74 	gtk_widget_destroy (GTK_WIDGET(widget));
75 	g_object_unref (G_OBJECT(dialog_gtkb));
76 
77 	return password;
78 #else
79 	gchar *password = NULL;
80 	gchar *prompt = NULL;
81 
82 	printf (_("The whole selected file, or some of its elements, seems to\n"
83 		  "be cyphered using a password or passphrase. For importing\n"
84 		  "the file into gnoMint database, you must provide an \n"
85 		  "appropiate password.\n"));
86 
87 	prompt = g_strdup_printf (_("Please introduce password for `%s'"), crypted_part_description);
88 	password = dialog_ask_for_password (prompt);
89 	g_free (prompt);
90 
91 	return password;
92 #endif
93 }
94 
95 
__import_csr(gnutls_x509_crq_t * crq,gchar ** csr_dn,guint64 * id)96 gint __import_csr (gnutls_x509_crq_t *crq, gchar ** csr_dn, guint64 *id)
97 {
98 	gchar * pem_csr=NULL;
99 	size_t size;
100 	gchar * error_msg;
101         gint result = -1;
102 	gchar *aux = NULL;
103 
104 
105         if (csr_dn) {
106                 size = 0;
107                 gnutls_x509_crq_get_dn (*crq, aux, &size);
108                 if (size) {
109                         aux = g_new0(gchar, size);
110                         gnutls_x509_crq_get_dn (*crq, aux, &size);
111                         *csr_dn = g_strdup (aux);
112                         g_free (aux);
113                         aux = NULL;
114                 }
115         }
116 
117 	size = 0;
118 	gnutls_x509_crq_export (*crq, GNUTLS_X509_FMT_PEM, pem_csr, &size)  ;
119 	if (size) {
120 		pem_csr = g_new0(gchar, size);
121 		gnutls_x509_crq_export (*crq, GNUTLS_X509_FMT_PEM, pem_csr, &size);
122 
123 	}
124 
125 	error_msg = ca_file_insert_csr (NULL, pem_csr, NULL, id);
126 
127 
128 	if (error_msg) {
129 		gchar *message = g_strdup_printf (_("Couldn't import the certificate request. \n"
130 						    "The database returned this error: \n\n'%s'"),
131 						  error_msg);
132 		dialog_error (message);
133 		g_free (message);
134 	} else {
135                 result = 1;
136         }
137         return result;
138 }
139 
__import_cert(gnutls_x509_crt_t * cert,gchar ** cert_dn,guint64 * id)140 gint __import_cert (gnutls_x509_crt_t *cert, gchar **cert_dn, guint64 *id)
141 {
142 	guchar *serial_str = NULL;
143 	UInt160 serial;
144 	gchar * pem_cert=NULL;
145 	size_t size;
146 	gchar * error_msg;
147 	gboolean is_ca;
148 	guint is_critical;
149 	gchar *aux = NULL;
150         gint result = -1;
151 
152 	// For inserting the cert into the database we must get:
153 	// - if the certificate is a CA certificate
154 	// - serial
155 	// - activation time
156 	// - expiration time
157 
158 	// Is_CA?
159 	is_ca = gnutls_x509_crt_get_ca_status (*cert, &is_critical);
160 	if (is_ca == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
161 		is_ca = FALSE;
162 
163 	// Serial
164 	size = 0;
165 	gnutls_x509_crt_get_serial (*cert, aux, &size);
166 	aux = NULL;
167 	if (size) {
168 		serial_str = g_new0(guchar, size);
169 		gnutls_x509_crt_get_serial (*cert, serial_str, &size);
170 		uint160_read (&serial, serial_str, size);
171 		g_free (serial_str);
172                 aux = NULL;
173 	}
174 
175         if (cert_dn) {
176                 size = 0;
177                 gnutls_x509_crt_get_dn (*cert, aux, &size);
178                 if (size) {
179                         aux = g_new0(gchar, size);
180                         gnutls_x509_crt_get_dn (*cert, aux, &size);
181                         *cert_dn = g_strdup (aux);
182                         g_free (aux);
183                         aux = NULL;
184                 }
185         }
186 
187 
188 	// Now we re-export the PEM (as the original PEM can be a list of certs)
189 	size = 0;
190 	gnutls_x509_crt_export (*cert, GNUTLS_X509_FMT_PEM, aux, &size);
191 	if (size) {
192 		aux = g_new0(gchar, size);
193 		gnutls_x509_crt_export (*cert, GNUTLS_X509_FMT_PEM, aux, &size);
194 		pem_cert = g_strdup (aux);
195 		g_free (aux);
196 		aux = NULL;
197 	}
198 
199 	error_msg = ca_file_insert_imported_cert (is_ca, serial, pem_cert, id);
200 
201 	if (pem_cert)
202 		g_free (pem_cert);
203 
204 
205 	if (error_msg) {
206 		gchar *message = g_strdup_printf (_("Couldn't import the certificate. \n"
207 						    "The database returned this error: \n\n'%s'"),
208 						  error_msg);
209 		dialog_error (message);
210 		g_free (message);
211 	} else {
212                 result = 1;
213         }
214 
215         return result;
216 }
217 
__import_crl(gnutls_x509_crl_t * crl)218 gint __import_crl (gnutls_x509_crl_t *crl)
219 {
220         gint result = -1;
221 	gnutls_x509_crt_t issuer_crt;
222         gsize size = 0;
223         gchar *issuer_dn = NULL;
224         gchar *cert_pem = NULL;
225         guint64 issuer_id;
226 	gnutls_datum_t file_datum;
227 
228 
229         size = 0;
230         gnutls_x509_crl_get_issuer_dn (*crl, issuer_dn, &size)  ;
231         if (size) {
232                 issuer_dn = g_new0(gchar, size);
233                 gnutls_x509_crl_get_issuer_dn (*crl, issuer_dn, &size);
234         }
235 
236         // First, we search the issuer in the database, using DN
237         if (ca_file_get_id_from_dn (CA_FILE_ELEMENT_TYPE_CERT, issuer_dn, &issuer_id)) {
238 
239                 // We check if the supposed issuer is the actual issuer
240                 cert_pem = ca_file_get_public_pem_from_id (CA_FILE_ELEMENT_TYPE_CERT, issuer_id);
241 
242                 if (gnutls_x509_crt_init (&issuer_crt) < 0) {
243                         g_free (issuer_dn);
244                         g_free (cert_pem);
245                         return result;
246                 }
247 
248                 file_datum.data = (guchar *) cert_pem;
249                 file_datum.size = strlen(cert_pem);
250 
251                 if (gnutls_x509_crt_import (issuer_crt, &file_datum, GNUTLS_X509_FMT_PEM) == GNUTLS_E_SUCCESS) {
252 
253                         if (gnutls_x509_crl_check_issuer (*crl, issuer_crt)) {
254                                 int number_of_certs;
255                                 int i;
256 
257                                 // If it is, we recover all the certificates
258                                 number_of_certs = gnutls_x509_crl_get_crt_count(*crl);
259 
260                                 for (i=0; i<number_of_certs; i++) {
261                                         guchar *serialcrt = NULL;
262                                         UInt160 serial;
263                                         time_t revocation = 0;
264 
265                                         // We look up each of the certificates in the crl
266 
267                                         size = 0;
268                                         gnutls_x509_crl_get_crt_serial (*crl, i, serialcrt, &size, &revocation);
269                                         if (size) {
270                                                 guint64 cert_id;
271 
272                                                 serialcrt = g_new0 (guchar, size);
273                                                 gnutls_x509_crl_get_crt_serial (*crl, i, serialcrt, &size, &revocation);
274                                                 uint160_read (&serial, serialcrt, size);
275                                                 g_free (serialcrt);
276                                                 serialcrt = NULL;
277 
278                                                 if (ca_file_get_id_from_serial_issuer_id (&serial, issuer_id, &cert_id)) {
279                                                         // If found, we revoke it with the correct date
280                                                         ca_file_revoke_crt_with_date (cert_id, revocation);
281                                                         result = 1;
282                                                 }
283                                         }
284                                 }
285 
286                         }
287                 }
288 
289                 gnutls_x509_crt_deinit (issuer_crt);
290         }
291         return result;
292 }
293 
import_csr(guchar * file_contents,gsize file_contents_size,gchar ** csr_dn,guint64 * id)294 gint import_csr (guchar *file_contents, gsize file_contents_size, gchar **csr_dn, guint64 *id)
295 {
296 	gnutls_x509_crq_t crq;
297 	gnutls_datum_t file_datum;
298         gint result = 0;
299 
300         file_datum.data = file_contents;
301         file_datum.size = file_contents_size;
302 
303 	// Trying to import a Certificate Signing Request
304 
305 	if (gnutls_x509_crq_init (&crq) < 0)
306 		return result;
307 
308 	if (gnutls_x509_crq_import (crq, &file_datum, GNUTLS_X509_FMT_PEM) == 0 ||
309 	    gnutls_x509_crq_import (crq, &file_datum, GNUTLS_X509_FMT_DER) == 0) {
310 
311 		result = __import_csr (&crq, csr_dn, id);
312 	}
313 
314 	gnutls_x509_crq_deinit (crq);
315 
316 	return result;
317 
318 }
319 
320 
import_certlist(guchar * file_contents,gsize file_contents_size,gchar ** cert_dn,guint64 * id)321 gint import_certlist (guchar *file_contents, gsize file_contents_size, gchar **cert_dn, guint64 *id)
322 {
323 	gnutls_x509_crt_t cert;
324 	gnutls_x509_crt_t *certs = NULL;
325 	gnutls_datum_t file_datum;
326         guint num_certs = 0;
327         gint result = 0;
328 
329 	file_datum.size = file_contents_size;
330 	file_datum.data = file_contents;
331 
332 
333 	// Trying to import a list of certificates in PEM format
334         gnutls_x509_crt_list_import (NULL, &num_certs, &file_datum, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
335 
336         certs = g_new0 (gnutls_x509_crt_t, num_certs);
337 
338 	if (gnutls_x509_crt_list_import (certs, &num_certs, &file_datum, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED) > 0) {
339 
340                 int i;
341 
342                 // We go through all the certificates in inverse
343                 // order, as it's usual having a list of certificates conforming a
344                 // certification path, with the root CA certificate as the last
345                 // certificate
346                 result = -1;
347                 for (i = num_certs - 1; i>=0; i--) {
348                         if (cert_dn && *cert_dn) {
349                                 g_free (*cert_dn);
350                                 *cert_dn = NULL;
351                         }
352 			if (__import_cert (&certs[i], cert_dn, id) > 0)
353                                 result = 1;
354                 }
355 
356                 g_free (certs);
357 
358                 return result;
359 	}
360 
361 	// Trying to import a single certificate in DER format
362 
363         if (gnutls_x509_crt_init (&cert) < 0)
364                 return 0;
365 
366 	if (gnutls_x509_crt_import (cert, &file_datum, GNUTLS_X509_FMT_DER) == 0) {
367                 result = __import_cert (&cert, cert_dn, id);
368         }
369 
370 	gnutls_x509_crt_deinit (cert);
371 
372 	return result;
373 }
374 
import_pkey_wo_passwd(guchar * file_contents,gsize file_contents_size)375 gint import_pkey_wo_passwd (guchar *file_contents, gsize file_contents_size)
376 {
377         gint result = 0;
378 	gnutls_x509_privkey_t privkey;
379 	gnutls_datum_t file_datum;
380         gchar *result_import;
381 
382         file_datum.data = file_contents;
383         file_datum.size = file_contents_size;
384 
385 	// Trying to import a Private Key in PEM format
386 
387 	if (gnutls_x509_privkey_init (&privkey) < 0)
388 		return 0;
389 
390 	// Trying to import a Private Key in DER format
391 
392 	if (gnutls_x509_privkey_import (privkey, &file_datum, GNUTLS_X509_FMT_PEM) == 0 ||
393 	    gnutls_x509_privkey_import (privkey, &file_datum, GNUTLS_X509_FMT_DER) == 0) {
394 		gchar * pem_privkey=NULL;
395 		size_t size;
396                 result = -1;
397 
398 		size = 0;
399 		gnutls_x509_privkey_export (privkey, GNUTLS_X509_FMT_PEM, pem_privkey, &size)  ;
400 		if (size) {
401 			pem_privkey = g_new0(gchar, size);
402 			gnutls_x509_privkey_export (privkey, GNUTLS_X509_FMT_PEM, pem_privkey, &size);
403 
404 		}
405 
406                 result_import = ca_file_insert_imported_privkey (pem_privkey);
407 		if (result_import) {
408                         dialog_error (result_import);
409                 } else {
410                         result = 1;
411                 }
412 		g_free (pem_privkey);
413 
414 	}
415 
416 	gnutls_x509_privkey_deinit (privkey);
417 
418 	return result;
419 }
420 
import_crl(guchar * file_contents,gsize file_contents_size)421 gint import_crl (guchar *file_contents, gsize file_contents_size)
422 {
423         gint result = 0;
424 	gnutls_x509_crl_t crl;
425 	gnutls_datum_t file_datum;
426 
427         file_datum.data = file_contents;
428         file_datum.size = file_contents_size;
429 
430 	// Trying to import a Certificate Revocation List in PEM format
431 
432 	if (gnutls_x509_crl_init (&crl) < 0)
433 		return 0;
434 
435 	if (gnutls_x509_crl_import (crl, &file_datum, GNUTLS_X509_FMT_PEM) != 0 &&
436             gnutls_x509_crl_import (crl, &file_datum, GNUTLS_X509_FMT_DER) != 0) {
437                 // The given file is not a DER-coded CRL, neither a PEM-coded CRL
438 
439                 gnutls_x509_crl_deinit (crl);
440                 return 0;
441         }
442 
443         result = __import_crl (&crl);
444 
445 	gnutls_x509_crl_deinit (crl);
446 
447 	return result;
448 }
449 
450 /* PKCS#7 importing was removed in libgnutls 2.6.0 */
451 
452 /* gint import_pkcs7 (guchar *file_contents, gsize file_contents_size) */
453 /* { */
454 /* 	gboolean successful_import = FALSE; */
455 /* 	gnutls_pkcs7_t pkcs7; */
456 /* 	gnutls_datum_t file_datum; */
457 
458 /*         file_datum.data = file_contents; */
459 /*         file_datum.size = file_contents_size; */
460 
461 /* 	// Trying to import a Private Key in PEM format */
462 
463 /* 	if (gnutls_pkcs7_init (&pkcs7) < 0) */
464 /* 		return FALSE; */
465 
466 /* 	// Trying to import a Private Key in DER format */
467 
468 /* 	if (gnutls_pkcs7_import (pkcs7, &file_datum, GNUTLS_X509_FMT_PEM) == 0 || */
469 /* 	    gnutls_pkcs7_import (pkcs7, &file_datum, GNUTLS_X509_FMT_DER) == 0) { */
470 /* 		int i; */
471 /* 		int certs_no = gnutls_pkcs7_get_crt_count (pkcs7); */
472 /* 		int crl_no = gnutls_pkcs7_get_crl_count (pkcs7); */
473 
474 /* 		for (i=0; i < certs_no; i++) { */
475 /* 			guchar *raw_cert = NULL; */
476 /* 			gsize raw_cert_size = 0; */
477 
478 /* 			gnutls_pkcs7_get_crt_raw (pkcs7, i, raw_cert, &raw_cert_size); */
479 
480 /* 			raw_cert = g_new0(guchar, raw_cert_size); */
481 /* 			gnutls_pkcs7_get_crt_raw (pkcs7, i, raw_cert, &raw_cert_size); */
482 
483 /* 			import_certlist (raw_cert, raw_cert_size); */
484 
485 /* 			g_free (raw_cert); */
486 /* 		} */
487 
488 /* 		for (i=0; i < crl_no; i++) { */
489 /* 			guchar *raw_crl = NULL; */
490 /* 			gsize raw_crl_size = 0; */
491 
492 /* 			gnutls_pkcs7_get_crl_raw (pkcs7, i, raw_crl, &raw_crl_size); */
493 
494 /* 			raw_crl = g_new0(guchar, raw_crl_size); */
495 /* 			gnutls_pkcs7_get_crl_raw (pkcs7, i, raw_crl, &raw_crl_size); */
496 
497 /* 			import_crl (raw_crl, raw_crl_size); */
498 
499 /* 			g_free (raw_crl); */
500 /* 		} */
501 
502 /* 		successful_import = TRUE; */
503 /* 	} */
504 
505 /* 	gnutls_pkcs7_deinit (pkcs7); */
506 
507 /* 	return successful_import; */
508 /* } */
509 
import_pkcs8(guchar * file_contents,gsize file_contents_size)510 gint import_pkcs8 (guchar *file_contents, gsize file_contents_size)
511 {
512 	gint result = 0;
513 	gnutls_x509_privkey_t privkey;
514 	gnutls_datum_t file_datum;
515 
516         file_datum.data = file_contents;
517         file_datum.size = file_contents_size;
518 
519 	// Trying to import a Private Key in PEM format
520 
521 	if (gnutls_x509_privkey_init (&privkey) < 0)
522 		return 0;
523 
524 	// Trying to import a Private Key in DER format
525 
526 	if (gnutls_x509_privkey_import_pkcs8 (privkey, &file_datum, GNUTLS_X509_FMT_PEM, NULL, GNUTLS_PKCS_PLAIN) == 0 ||
527 	    gnutls_x509_privkey_import_pkcs8 (privkey, &file_datum, GNUTLS_X509_FMT_DER, NULL, GNUTLS_PKCS_PLAIN) == 0) {
528                 result = -1;
529 		gchar * pem_privkey=NULL;
530                 gchar * error_msg = NULL;
531 		size_t size;
532 
533 		size = 0;
534 		gnutls_x509_privkey_export (privkey, GNUTLS_X509_FMT_PEM, pem_privkey, &size)  ;
535 		if (size) {
536 			pem_privkey = g_new0(gchar, size);
537 			gnutls_x509_privkey_export (privkey, GNUTLS_X509_FMT_PEM, pem_privkey, &size);
538 
539 		}
540 
541                 error_msg = ca_file_insert_imported_privkey (pem_privkey);
542 		if (error_msg) {
543                         dialog_error (error_msg);
544                 } else {
545                         result = 1;
546                 }
547 
548 		g_free (pem_privkey);
549 
550 	} else {
551                 // Now we check if the given file is a PEM codified encrypted private key: while trying to import,
552                 // the password won't be correct.
553 
554                 gint result_decryption = gnutls_x509_privkey_import_pkcs8 (privkey, &file_datum, GNUTLS_X509_FMT_PEM, NULL, 0);
555 
556                 while (result_decryption==GNUTLS_E_DECRYPTION_FAILED) {
557 
558                         // We mark a successful import, as it is a PKCS#8 cyphered file: it must not be probed with other formats.
559                         result = -1;
560 
561                         // We launch a window for asking the password.
562                         gchar * password = __import_ask_password (_("PKCS#8 crypted private key"));
563 
564                         if (! password) {
565                                 gnutls_x509_privkey_deinit (privkey);
566                                 return result;
567                         }
568 
569                         result_decryption = gnutls_x509_privkey_import_pkcs8 (privkey, &file_datum, GNUTLS_X509_FMT_PEM, password, 0);
570                         g_free (password);
571 
572                         if (result_decryption == GNUTLS_E_DECRYPTION_FAILED) {
573                                 dialog_error (_("The given password doesn't match the one used for crypting this part"));
574                         }
575                 }
576 
577                 if (result_decryption == GNUTLS_E_SUCCESS) {
578                         gchar * pem_privkey=NULL;
579                         size_t size;
580                         gchar * error_msg = NULL;
581 
582                         result = -1;
583 
584                         size = 0;
585                         gnutls_x509_privkey_export (privkey, GNUTLS_X509_FMT_PEM, pem_privkey, &size)  ;
586                         if (size) {
587                                 pem_privkey = g_new0(gchar, size);
588                                 gnutls_x509_privkey_export (privkey, GNUTLS_X509_FMT_PEM, pem_privkey, &size);
589 
590                         }
591 
592                         error_msg = ca_file_insert_imported_privkey (pem_privkey);
593                         if (error_msg) {
594                                 dialog_error (error_msg);
595                         } else {
596                                 result = 1;
597                         }
598                         g_free (pem_privkey);
599                 }
600 
601                 // Importing DER-codified encrypted private keys is not supported, as they cannot be probed without
602                 // a password.
603         }
604 
605 	gnutls_x509_privkey_deinit (privkey);
606 
607 	return result;
608 }
609 
import_pkcs12(guchar * file_contents,gsize file_contents_size)610 gint import_pkcs12 (guchar *file_contents, gsize file_contents_size)
611 {
612         gint result = 0;
613 	gnutls_pkcs12_t pkcs12;
614 	gnutls_datum_t file_datum;
615 
616         file_datum.data = file_contents;
617         file_datum.size = file_contents_size;
618 
619 	// Trying to import a Private Key in PEM format
620 
621 	if (gnutls_pkcs12_init (&pkcs12) < 0)
622 		return result;
623 
624         // Trying to import a PKCS#12 in PEM or DER format
625 	if (gnutls_pkcs12_import (pkcs12, &file_datum, GNUTLS_X509_FMT_PEM, 0) == 0 ||
626 	    gnutls_pkcs12_import (pkcs12, &file_datum, GNUTLS_X509_FMT_DER, 0) == 0) {
627                 guint n_bags = 0;
628                 gnutls_pkcs12_bag_t *pkcs12_aux_bag = NULL;
629                 GArray *pkcs_bag_array = g_array_new (FALSE, TRUE, sizeof(gnutls_pkcs12_bag_t));
630                 gint get_bag_status;
631                 gchar *password = NULL;
632                 guint i;
633 
634                 result = -1;
635 
636                 // Now, we walk through all the bags in the PKCS12 structure
637                 // inserting them into an array for walking through them afterwards
638                 do {
639                         pkcs12_aux_bag = g_new0 (gnutls_pkcs12_bag_t, 1);
640                         gnutls_pkcs12_bag_init (pkcs12_aux_bag);
641 
642                         get_bag_status = gnutls_pkcs12_get_bag (pkcs12, n_bags, *pkcs12_aux_bag);
643 
644                         if (get_bag_status == GNUTLS_E_SUCCESS) {
645                                 g_array_append_val (pkcs_bag_array, pkcs12_aux_bag);
646                                 n_bags ++;
647                         } else {
648                                 gnutls_pkcs12_bag_deinit (*pkcs12_aux_bag);
649                                 g_free (pkcs12_aux_bag);
650                         }
651 
652                 } while (get_bag_status == GNUTLS_E_SUCCESS);
653 
654                 if (n_bags == 0) {
655                         // Couldn't get any bag.
656                         // Exiting with error
657                         gnutls_pkcs12_deinit (pkcs12);
658                         return result;
659                 }
660 
661 
662                 // Now, we first uncrypt all crypted bags
663                 for (i=0; i<n_bags; i++) {
664                         if (gnutls_pkcs12_bag_get_type (* g_array_index (pkcs_bag_array, gnutls_pkcs12_bag_t *, i), 0) == GNUTLS_BAG_ENCRYPTED) {
665                                 gboolean pkcs12_bag_decrypted = FALSE;
666                                 if (! password)
667                                         password = __import_ask_password (_("Encrypted PKCS#12 bag"));
668 
669                                 if (! password) {
670                                         // The user cancelled the operation
671                                         for (i=0; i<n_bags; i++) {
672                                                 gnutls_pkcs12_bag_deinit (* g_array_index (pkcs_bag_array, gnutls_pkcs12_bag_t *, i));
673                                                 g_free (g_array_index (pkcs_bag_array, gnutls_pkcs12_bag_t *, i));
674                                                 gnutls_pkcs12_deinit (pkcs12);
675                                                 g_array_free (pkcs_bag_array, TRUE);
676                                                 return result;
677                                         }
678                                 }
679 
680                                 pkcs12_bag_decrypted = ! (gnutls_pkcs12_bag_decrypt (* g_array_index (pkcs_bag_array, gnutls_pkcs12_bag_t *, i),
681                                                                                      password));
682                                 if (!pkcs12_bag_decrypted) {
683                                         gint j;
684                                         dialog_error (_("The given password doesn't match with the password used for encrypting this part."));
685                                         for (j=0; j<n_bags; j++) {
686                                                 gnutls_pkcs12_bag_deinit (* g_array_index (pkcs_bag_array, gnutls_pkcs12_bag_t *, j));
687                                                 g_free (g_array_index (pkcs_bag_array, gnutls_pkcs12_bag_t *, j));
688                                         }
689                                         gnutls_pkcs12_deinit (pkcs12);
690                                         g_array_free (pkcs_bag_array, TRUE);
691                                         return result;
692                                 }
693                         }
694                 }
695 
696                 // After having all the parts unencrypted, we import all certificates first.
697                 for (i=0; i<n_bags; i++) {
698                         gnutls_pkcs12_bag_t * pkcs12_bag = g_array_index (pkcs_bag_array, gnutls_pkcs12_bag_t *, i);
699                         guint num_elements_in_bag = gnutls_pkcs12_bag_get_count (*pkcs12_bag);
700 
701                         for (i=0; i < num_elements_in_bag; i++) {
702                                 gnutls_datum data;
703                                 if (gnutls_pkcs12_bag_get_type (*pkcs12_bag, i) == GNUTLS_BAG_CERTIFICATE) {
704                                         gnutls_x509_crt cert;
705 
706                                         gnutls_x509_crt_init (&cert);
707                                         if (gnutls_pkcs12_bag_get_data(*pkcs12_bag, i, &data) < 0) {
708                                                 gnutls_x509_crt_deinit (cert);
709                                                 continue;
710                                         }
711                                         if (gnutls_x509_crt_import(cert, &data, GNUTLS_X509_FMT_DER) < 0) {
712                                                 gnutls_x509_crt_deinit (cert);
713                                                 continue;
714                                         }
715                                         __import_cert (& cert, NULL, NULL);
716 
717                                         gnutls_x509_crt_deinit (cert);
718                                 }
719                         }
720                 }
721 
722 
723                 // Then, we import all PKCS8 private keys.
724                 for (i=0; i<n_bags; i++) {
725                         gnutls_pkcs12_bag_t * pkcs12_bag = g_array_index (pkcs_bag_array, gnutls_pkcs12_bag_t *, i);
726                         guint num_elements_in_bag = gnutls_pkcs12_bag_get_count (*pkcs12_bag);
727 
728                         for (i=0; i < num_elements_in_bag; i++) {
729                                 gnutls_datum data;
730                                 if (gnutls_pkcs12_bag_get_type (*pkcs12_bag, i) == GNUTLS_BAG_PKCS8_KEY ||
731                                     gnutls_pkcs12_bag_get_type (*pkcs12_bag, i) == GNUTLS_BAG_PKCS8_ENCRYPTED_KEY) {
732                                         gnutls_x509_privkey pkey;
733                                         gint result_decryption;
734 
735                                         gnutls_x509_privkey_init (&pkey);
736                                         if (gnutls_pkcs12_bag_get_data(*pkcs12_bag, i, &data) < 0) {
737                                                 gnutls_x509_privkey_deinit (pkey);
738                                                 continue;
739                                         }
740 
741                                         result_decryption = gnutls_x509_privkey_import_pkcs8(pkey, &data, GNUTLS_X509_FMT_DER, password, 0);
742                                         if (result_decryption < 0) {
743                                                 while (result_decryption==GNUTLS_E_DECRYPTION_FAILED) {
744                                                         if (password)
745                                                                 g_free (password);
746 
747                                                         // We launch a window for asking the password.
748                                                         password = __import_ask_password (_("PKCS#8 crypted private key"));
749 
750                                                         if (! password) {
751                                                                 break;
752                                                         }
753 
754                                                         result_decryption = gnutls_x509_privkey_import_pkcs8 (pkey, &data, GNUTLS_X509_FMT_DER,
755                                                                                                               password, 0);
756 
757                                                         if (result_decryption == GNUTLS_E_DECRYPTION_FAILED) {
758                                                                 dialog_error (_("The given password doesn't match the one used "
759                                                                                    "for crypting this part"));
760                                                         }
761                                                 }
762                                                 if (result_decryption < 0) {
763                                                         // The user pressed "Cancel" button, or
764                                                         // the decryption has failed
765                                                         gnutls_x509_privkey_deinit (pkey);
766                                                         continue;
767                                                 }
768                                         }
769                                         if (result_decryption == GNUTLS_E_SUCCESS) {
770                                                 gchar * pem_privkey=NULL;
771                                                 size_t size;
772                                                 gchar * error_msg = NULL;
773 
774                                                 result = -1;
775 
776                                                 size = 0;
777                                                 gnutls_x509_privkey_export (pkey, GNUTLS_X509_FMT_PEM, pem_privkey, &size)  ;
778                                                 if (size) {
779                                                         pem_privkey = g_new0(gchar, size);
780                                                         gnutls_x509_privkey_export (pkey, GNUTLS_X509_FMT_PEM, pem_privkey, &size);
781 
782                                                 }
783 
784                                                 error_msg = ca_file_insert_imported_privkey (pem_privkey);
785                                                 if (error_msg) {
786                                                         dialog_error (error_msg);
787                                                 } else {
788                                                         result = 1;
789                                                 }
790                                                 g_free (pem_privkey);
791                                                 gnutls_x509_privkey_deinit (pkey);
792                                         }
793                                 }
794                         }
795                 }
796                 // Then we import the CRLs
797 
798                 for (i=0; i<n_bags; i++) {
799                         gnutls_pkcs12_bag_t * pkcs12_bag = g_array_index (pkcs_bag_array, gnutls_pkcs12_bag_t *, i);
800                         guint num_elements_in_bag = gnutls_pkcs12_bag_get_count (*pkcs12_bag);
801 
802                         for (i=0; i < num_elements_in_bag; i++) {
803                                 gnutls_datum data;
804                                 if (gnutls_pkcs12_bag_get_type (*pkcs12_bag, i) == GNUTLS_BAG_CRL) {
805                                         gnutls_x509_crl crl;
806 
807                                         gnutls_x509_crl_init (&crl);
808                                         if (gnutls_pkcs12_bag_get_data(*pkcs12_bag, i, &data) < 0) {
809                                                 gnutls_x509_crl_deinit (crl);
810                                                 continue;
811                                         }
812                                         if (gnutls_x509_crl_import(crl, &data, GNUTLS_X509_FMT_DER) < 0) {
813                                                 gnutls_x509_crl_deinit (crl);
814                                                 continue;
815                                         }
816                                         __import_crl (& crl);
817 
818                                         gnutls_x509_crl_deinit (crl);
819                                 }
820                         }
821                 }
822 
823                 // Ok. Now we free all the bags
824                 for (i=0; i<n_bags; i++) {
825                         gnutls_pkcs12_bag_deinit (* g_array_index (pkcs_bag_array, gnutls_pkcs12_bag_t *, i));
826                         g_free (g_array_index (pkcs_bag_array, gnutls_pkcs12_bag_t *, i));
827                 }
828                 g_array_free (pkcs_bag_array, TRUE);
829 
830 	}
831 
832 	gnutls_pkcs12_deinit (pkcs12);
833 
834 	return result;
835 }
836 
import_single_file(gchar * filename,gchar ** dn,guint64 * id)837 gboolean import_single_file (gchar *filename, gchar **dn, guint64 *id)
838 {
839         gboolean successful_import = FALSE;
840 	GError *error = NULL;
841 	guchar *file_contents = NULL;
842         gsize   file_contents_size = 0;
843 
844 	GMappedFile * mapped_file = g_mapped_file_new (filename, FALSE, &error);
845 
846 	if (error) {
847 		dialog_error (_(error->message));
848 		return FALSE;
849 	}
850 
851 	file_contents_size = g_mapped_file_get_length (mapped_file);
852 	file_contents = g_new0 (guchar, file_contents_size);
853 	memcpy (file_contents, g_mapped_file_get_contents (mapped_file), file_contents_size);
854 
855 	g_mapped_file_free (mapped_file);
856 
857 
858 	// We start to check each type of file, in PEM and DER
859 	// formats, for see if some of them matches with the actual file
860 
861 
862 	// Certificate request
863         successful_import = import_csr (file_contents, file_contents_size, dn, id);
864 
865 	// Certificate list (or single certificate)
866         if (! successful_import)
867                 successful_import = import_certlist (file_contents, file_contents_size, dn, id);
868 
869 	// Private key without password
870         if (! successful_import)
871                 successful_import = import_pkey_wo_passwd (file_contents, file_contents_size);
872 
873 	// Certificate revocation list
874         if (! successful_import)
875                 successful_import = import_crl (file_contents, file_contents_size);
876 
877         /* PKCS7 importing was removed in libgnutls 2.6.0 */
878 	/* // PKCS7 structure */
879         /* if (! successful_import) */
880         /*         successful_import = import_pkcs7 (file_contents, file_contents_size); */
881 
882 	// PKCS12 structure
883         if (! successful_import)
884                 successful_import = import_pkcs12 (file_contents, file_contents_size);
885 
886         // PKCS8 privkey structure
887         if (! successful_import)
888                 successful_import = import_pkcs8 (file_contents, file_contents_size);
889 
890         g_free (file_contents);
891 
892 	if (successful_import) {
893 		dialog_refresh_list();
894 	} else {
895 		dialog_error (_("Couldn't find any supported format in the given file"));
896 	}
897 
898 	return TRUE;
899 
900 }
901 
import_openssl_private_key(const gchar * filename,gchar ** last_password,gchar * file_description)902 gint import_openssl_private_key (const gchar *filename, gchar **last_password, gchar *file_description)
903 {
904 	guint result = 0;
905 	gchar *filecontents = NULL;
906 
907 	if (! g_file_get_contents (filename, &filecontents, NULL, NULL)) {
908 		gchar *message = g_strdup_printf(_("Couldn't open %s file. Check permissions."), filename);
909 		dialog_error (message);
910 		g_free (message);
911 		return result;
912 	}
913 	if (g_strrstr (filecontents, "Proc-Type") &&
914 	    g_strrstr (filecontents, "DEK-Info")) {
915 		// The file is codified with a proprietary OpenSSL format
916 		// so we call openssl for decoding it
917 		gchar *keytype = NULL;
918 		gchar *uncyphered_cakey = NULL;
919 		gchar *error_message = NULL;
920 		gchar *temp_pwd = NULL;
921 		gint   exit_status = 0;
922 		GError *gerror = NULL;
923 		gchar *opensslargv[7];
924 		gboolean first_time = TRUE;
925 
926 		if (g_strrstr (filecontents, "BEGIN RSA")) {
927 			keytype = "rsa";
928 		}
929 
930 		if (g_strrstr (filecontents, "BEGIN DSA")) {
931 			keytype = "dsa";
932 		}
933 
934 		if (!keytype) {
935 			gchar * message = g_strdup_printf(_("Couldn't recognize the file %s as a RSA or DSA private key."), filename);
936 			dialog_error (message);
937 			g_free (message);
938 			g_free (filecontents);
939 			return result;
940 		}
941 
942 		do {
943 			gchar *description;
944 			gchar *dirname = NULL;
945 
946 			if (! first_time ||  ! *last_password) {
947 				// We ask for a password only if there is no current password
948 				// or if the current password has already failed.
949 
950                                 if (file_description)
951                                         description = g_strdup_printf (_("Private key for %s"),file_description);
952                                 else
953                                         description = g_strdup_printf (_("Private key %s"), filename);
954 				*last_password = __import_ask_password (description);
955 				g_free (description);
956 
957 				if (*last_password == NULL) {
958 					g_free (filecontents);
959 					break;
960 				}
961 			}
962 
963 			temp_pwd = g_strdup_printf ("pass:%s", *last_password);
964 			opensslargv[0] = "openssl";
965 			opensslargv[1] = keytype;
966 			opensslargv[2] = "-in";
967 			opensslargv[3] = (gchar *) filename;
968 			opensslargv[4] = "-passin";
969 			opensslargv[5] = temp_pwd;
970 			opensslargv[6] = NULL;
971 
972 			dirname = g_path_get_dirname (filename);
973 
974 			if (! g_spawn_sync (dirname,
975 					    opensslargv,
976 					    NULL,
977 					    G_SPAWN_SEARCH_PATH,
978 					    NULL,
979 					    NULL,
980 					    &uncyphered_cakey,
981 					    &error_message,
982 					    &exit_status,
983 					    &gerror)) {
984 				// Problem while launching openssl...
985 				g_free (filecontents);
986 				g_free (temp_pwd);
987 				g_free (dirname);
988 				dialog_error (_("Problem while calling to openssl for decyphering private key."));
989 				break;
990 			}
991 
992 			g_free (dirname);
993 			g_free (temp_pwd);
994 
995 			if (exit_status != 0) {
996 				gchar *error_to_show = g_strdup_printf (_("OpenSSL has returned the following error "
997 									  "while trying to decypher the private key:\n\n%s"),
998 									error_message);
999 				dialog_error (error_to_show);
1000 				g_free (error_to_show);
1001 				first_time = FALSE;
1002 			}
1003 		} while (exit_status != 0);
1004 
1005 		if (* last_password == NULL || gerror) {
1006 			return result;
1007 		}
1008 
1009 		g_free (filecontents);
1010 		if (error_message)
1011 			g_free (error_message);
1012 
1013 		filecontents = uncyphered_cakey;
1014 	}
1015 	// Now, we import the uncyphered private key:
1016 
1017 	result = import_pkey_wo_passwd ((guchar *) filecontents, strlen(filecontents));
1018 
1019 	if (result == 1)
1020 		dialog_refresh_list();
1021 
1022 	g_free (filecontents);
1023 
1024 	return result;
1025 }
1026 
import_whole_dir(gchar * dirname)1027 gchar * import_whole_dir (gchar *dirname)
1028 {
1029         gchar *result = NULL;
1030 	gchar *filename = NULL;
1031 	const gchar *int_filename = NULL;
1032 
1033         guint CA_directory_type = 0;
1034 	gboolean error = FALSE;
1035 	gchar *ca_password = NULL;
1036 
1037 	GError *gerror = NULL;
1038 
1039 	GDir * dir = NULL;
1040 	GList * problematic_files = NULL, *cursor = NULL;
1041 
1042         GHashTable *descriptions = NULL;
1043         guint64 ca_root_id;
1044 
1045         gchar *filecontents = NULL;
1046 
1047         UInt160 next_serial;
1048 
1049         // First, we try to probe if this is really a CA-containing directory
1050 
1051         // * Try to detect OpenSSL CA.pl or TinyCA
1052 	{
1053 		filename = g_build_filename (dirname, "cacert.pem", NULL);
1054 		if (! g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
1055 			error = TRUE;
1056 		}
1057 		g_free (filename);
1058 		filename = g_build_filename (dirname, "serial", NULL);
1059 		if (! g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
1060 			error = TRUE;
1061 		}
1062 		g_free (filename);
1063 		filename = g_build_filename (dirname, "certs", NULL);
1064 		if (! g_file_test(filename, G_FILE_TEST_IS_DIR)) {
1065 			error = TRUE;
1066 		}
1067 		g_free (filename);
1068 		filename = g_build_filename (dirname, "crl", NULL);
1069 		if (! g_file_test(filename, G_FILE_TEST_IS_DIR)) {
1070 			error = TRUE;
1071 		}
1072 		g_free (filename);
1073 		filename = g_build_filename (dirname, "cacert.key", NULL);
1074 		if (! g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
1075 			g_free (filename);
1076 			filename = g_build_filename (dirname, "private", "cakey.pem", NULL);
1077 			if (! g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
1078 				error = TRUE;
1079 			} else {
1080 				if (! error)
1081 					CA_directory_type = 2; // OpenSSL CA.pl
1082 			}
1083 		}
1084 		g_free (filename);
1085 
1086 		if (! error && ! CA_directory_type) {
1087 			CA_directory_type = 1; //TinyCA
1088 		}
1089 
1090 		if (error) {
1091 			CA_directory_type = 0;
1092 		}
1093 	}
1094 
1095         // * Other formats... (?)
1096 
1097         switch (CA_directory_type) {
1098 	case 1:
1099 	case 2:
1100 
1101                 descriptions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1102 
1103 		// First we import the public CA root certificate
1104 		filename = g_build_filename (dirname, "cacert.pem", NULL);
1105 		if (import_single_file (filename, NULL, &ca_root_id) == FALSE) {
1106 			g_free (filename);
1107 			result = _("There was a problem while importing the public CA root certificate");
1108 			break;
1109 		}
1110 		g_free (filename);
1111 
1112 		// Now we import the private CA root-certificate private key
1113 		// Usually, it is crypted in a OpenSSL proprietary format.
1114 		// Let's check it:
1115 		if (CA_directory_type == 1 /* TinyCA */) {
1116 			filename = g_build_filename (dirname, "cacert.key", NULL);
1117 		} else {
1118 			/* CA_directory_type == 2  (OpenSSL's CA.pl) */
1119 			filename = g_build_filename (dirname, "private", "cakey.pem", NULL);
1120 		}
1121 		if (import_openssl_private_key (filename, &ca_password, _("CA Root certificate")) == 0) {
1122 			g_free (filename);
1123 			result = _("There was a problem while importing the private key corresponding to CA root certificate");
1124 			break;
1125 		}
1126 		g_free (filename);
1127 
1128 		// Now we import all the certificates emitted by the CA
1129 		filename = g_build_filename (dirname, "certs", NULL);
1130 		dir = g_dir_open (filename, 0, &gerror);
1131 		if (! dir) {
1132 			g_free (filename);
1133 			result = _("There was a problem while opening the directory certs/.");
1134 		} else {
1135 			g_free (filename);
1136 			while ((int_filename = g_dir_read_name (dir))) {
1137 
1138 				if (g_strrstr (int_filename, ".pem")) {
1139 					gchar *description = NULL;
1140 					filename = g_build_filename (dirname, "certs", int_filename, NULL);
1141 					if (import_single_file ((gchar *) filename, &description, NULL) == 0) {
1142 						problematic_files = g_list_append (problematic_files, g_strdup(filename));
1143 					} else {
1144 						if (description && ! g_hash_table_lookup (descriptions, int_filename))
1145 							g_hash_table_insert (descriptions, g_strdup(int_filename), description);
1146 					}
1147 					g_free (filename);
1148 				}
1149 			}
1150 			g_dir_close (dir);
1151 		}
1152 		filename = g_build_filename (dirname, "newcerts", NULL);
1153 		if (g_file_test(filename, G_FILE_TEST_IS_DIR)) {
1154 			dir = g_dir_open (filename, 0, &gerror);
1155 			if (! dir) {
1156 				g_free (filename);
1157 				result = _("There was a problem while opening the directory newcerts/.");
1158 			} else {
1159 				g_free (filename);
1160 				while ((int_filename = g_dir_read_name (dir))) {
1161 
1162 					if (g_strrstr (int_filename, ".pem")) {
1163 						gchar *description = NULL;
1164 						filename = g_build_filename (dirname, "newcerts", int_filename, NULL);
1165 						if (import_single_file ((gchar *) filename, &description, NULL) == 0) {
1166 							problematic_files = g_list_append (problematic_files, g_strdup(filename));
1167 						} else {
1168 							if (description && ! g_hash_table_lookup (descriptions, int_filename))
1169 								g_hash_table_insert (descriptions, g_strdup(int_filename), description);
1170 						}
1171 						g_free (filename);
1172 					}
1173 				}
1174 				g_dir_close (dir);
1175 			}
1176 		}
1177 
1178 		// Now we import all the CSRs of the CA
1179 		filename = g_build_filename (dirname, "req", NULL);
1180 		if (g_file_test(filename, G_FILE_TEST_IS_DIR)) {
1181 			dir = g_dir_open (filename, 0, &gerror);
1182 			if (! dir) {
1183 				g_free (filename);
1184 				result = _("There was a problem while opening the directory req.");
1185 				break;
1186 			}
1187 			g_free (filename);
1188 			while ((int_filename = g_dir_read_name (dir))) {
1189 
1190 				if (g_strrstr (int_filename, ".pem")) {
1191 					gchar *description = NULL;
1192 					filename = g_build_filename (dirname, "req", int_filename, NULL);
1193 					if (import_single_file ((gchar *) filename, &description, NULL) == 0) {
1194 						problematic_files = g_list_append (problematic_files, g_strdup(filename));
1195 					} else {
1196 						if (description && ! g_hash_table_lookup (descriptions, int_filename))
1197 							g_hash_table_insert (descriptions, g_strdup(int_filename), description);
1198 					}
1199 					g_free (filename);
1200 				}
1201 			}
1202 			g_dir_close (dir);
1203 		}
1204 
1205 		// Now we import all the CRLs of the CA
1206 		filename = g_build_filename (dirname, "crl", NULL);
1207 		dir = g_dir_open (filename, 0, &gerror);
1208 		if (! dir) {
1209 			g_free (filename);
1210 			result = _("There was a problem while opening the directory crl/.");
1211 			break;
1212 		}
1213 		g_free (filename);
1214 		while ((int_filename = g_dir_read_name (dir))) {
1215 
1216 			if (g_strrstr (int_filename, ".pem")) {
1217 				filename = g_build_filename (dirname, "crl", int_filename, NULL);
1218 				if (import_single_file ((gchar *) filename, NULL, NULL) == 0) {
1219 					problematic_files = g_list_append (problematic_files, g_strdup(filename));
1220 				}
1221 				g_free (filename);
1222 			}
1223 		}
1224 		g_dir_close (dir);
1225 
1226 		// Now we import all the private keys of the CA
1227 		filename = g_build_filename (dirname, "keys", NULL);
1228 		if (g_file_test(filename, G_FILE_TEST_IS_DIR)) {
1229 			dir = g_dir_open (filename, 0, &gerror);
1230 			if (! dir) {
1231 				g_free (filename);
1232 				result = _("There was a problem while opening the directory keys/.");
1233 				break;
1234 			}
1235 			g_free (filename);
1236 			while ((int_filename = g_dir_read_name (dir))) {
1237 
1238 				if (g_strrstr (int_filename, ".pem")) {
1239 					gchar *description = NULL;
1240 
1241 					filename = g_build_filename (dirname, "keys", int_filename, NULL);
1242 
1243 					description = g_hash_table_lookup (descriptions, int_filename);
1244 					if (! description)
1245 						description = filename;
1246 
1247 					if (import_openssl_private_key (filename, &ca_password, description) == 0) {
1248 						problematic_files = g_list_append (problematic_files, g_strdup(filename));
1249 					}
1250 					g_free (filename);
1251 				}
1252 			}
1253 			g_dir_close (dir);
1254 		}
1255 
1256 		// Now we import the last serial number
1257 		filename = g_build_filename (dirname, "serial", NULL);
1258                 if (! g_file_get_contents (filename, &filecontents, NULL, NULL)) {
1259                         gchar *message = g_strdup_printf(_("Couldn't open %s file. Check permissions."), filename);
1260                         dialog_error (message);
1261                         g_free (message);
1262                         return result;
1263                 }
1264 		g_free (filename);
1265 
1266                 if (! uint160_assign_hexstr (&next_serial, filecontents))
1267                         uint160_assign (&next_serial, 1);
1268 
1269                 g_free (filecontents);
1270 
1271                 ca_file_set_next_serial (&next_serial, ca_root_id);
1272 
1273 
1274 		// We must show the problematic files.
1275 		// TO DO
1276 
1277 		cursor = g_list_first (problematic_files);
1278 		while (cursor) {
1279 			g_free (cursor->data);
1280 			cursor->data = NULL;
1281 			cursor = cursor->next;
1282 		}
1283 		g_list_free (problematic_files);
1284 
1285                 g_hash_table_destroy (descriptions);
1286 
1287 		break;
1288         case 0:
1289 	default:
1290                 result = _("Files in the directory don't belong to any supported CA format.");
1291                 break;
1292         }
1293 
1294 
1295         return result;
1296 }
1297