Location | Tool | Test ID | Function | Issue |
---|---|---|---|---|
e-cert.c:718:3 | clang-analyzer | Function call argument is an uninitialized value | ||
e-cert.c:718:3 | clang-analyzer | Function call argument is an uninitialized value | ||
e-cert.c:725:3 | clang-analyzer | Function call argument is an uninitialized value | ||
e-cert.c:725:3 | clang-analyzer | Function call argument is an uninitialized value | ||
e-cert.c:1007:10 | clang-analyzer | Access to field 'avas' results in a dereference of a null pointer | ||
e-cert.c:1007:10 | clang-analyzer | Access to field 'avas' results in a dereference of a null pointer |
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* The following is the mozilla license blurb, as the bodies some of
3 * these functions were derived from the mozilla source. */
4 /*
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is the Netscape security libraries.
18 *
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1994-2000
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 */
36
37 /*
38 * Author: Chris Toshok (toshok@ximian.com)
39 *
40 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
41 */
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif
45
46 #include <time.h>
47
48 #include <glib/gi18n.h>
49
50 /* for e_utf8_strftime, what about e_time_format_time? */
51 #include <e-util/e-util.h>
52
53 #include "e-cert.h"
54 #include "e-cert-trust.h"
55 #include "pk11func.h"
56 #include "certdb.h"
57 #include "hasht.h"
58
59 #define E_CERT_GET_PRIVATE(obj) \
60 (G_TYPE_INSTANCE_GET_PRIVATE \
61 ((obj), E_TYPE_CERT, ECertPrivate))
62
63 struct _ECertPrivate {
64 CERTCertificate *cert;
65
66 /* pointers we cache since the nss implementation allocs the
67 * string */
68 gchar *org_name;
69 gchar *org_unit_name;
70 gchar *cn;
71
72 gchar *issuer_org_name;
73 gchar *issuer_org_unit_name;
74 gchar *issuer_cn;
75
76 PRTime issued_on;
77 PRTime expires_on;
78
79 gchar *issued_on_string;
80 gchar *expires_on_string;
81
82 gchar *serial_number;
83
84 gchar *usage_string;
85
86 gchar *sha1_fingerprint;
87 gchar *md5_fingerprint;
88
89 EASN1Object *asn1;
90
91 gboolean delete;
92 };
93
94 G_DEFINE_TYPE (ECert, e_cert, G_TYPE_OBJECT)
95
96 static void
97 e_cert_finalize (GObject *object)
98 {
99 ECertPrivate *priv;
100
101 priv = E_CERT_GET_PRIVATE (object);
102
103 if (priv->org_name)
104 PORT_Free (priv->org_name);
105 if (priv->org_unit_name)
106 PORT_Free (priv->org_unit_name);
107 if (priv->cn)
108 PORT_Free (priv->cn);
109
110 if (priv->issuer_org_name)
111 PORT_Free (priv->issuer_org_name);
112 if (priv->issuer_org_unit_name)
113 PORT_Free (priv->issuer_org_unit_name);
114 if (priv->issuer_cn)
115 PORT_Free (priv->issuer_cn);
116
117 if (priv->issued_on_string)
118 PORT_Free (priv->issued_on_string);
119 if (priv->expires_on_string)
120 PORT_Free (priv->expires_on_string);
121 if (priv->serial_number)
122 PORT_Free (priv->serial_number);
123
124 g_free (priv->usage_string);
125
126 if (priv->sha1_fingerprint)
127 PORT_Free (priv->sha1_fingerprint);
128 if (priv->md5_fingerprint)
129 PORT_Free (priv->md5_fingerprint);
130
131 if (priv->asn1)
132 g_object_unref (priv->asn1);
133
134 if (priv->delete) {
135 printf ("attempting to delete cert marked for deletion\n");
136 if (e_cert_get_cert_type (E_CERT (object)) == E_CERT_USER) {
137 PK11_DeleteTokenCertAndKey (priv->cert, NULL);
138 } else if (!PK11_IsReadOnly (priv->cert->slot)) {
139 /* If the list of built-ins does contain a non-removable
140 * copy of this certificate, our call will not remove
141 * the certificate permanently, but rather remove all trust. */
142 SEC_DeletePermCertificate (priv->cert);
143 }
144 }
145
146 if (priv->cert)
147 CERT_DestroyCertificate (priv->cert);
148
149 /* Chain up to parent's finalize() method. */
150 G_OBJECT_CLASS (e_cert_parent_class)->finalize (object);
151 }
152
153 static void
154 e_cert_class_init (ECertClass *class)
155 {
156 GObjectClass *object_class;
157
158 g_type_class_add_private (class, sizeof (ECertPrivate));
159
160 object_class = G_OBJECT_CLASS (class);
161 object_class->finalize = e_cert_finalize;
162 }
163
164 static void
165 e_cert_init (ECert *ec)
166 {
167 ec->priv = E_CERT_GET_PRIVATE (ec);
168 }
169
170 static void
171 e_cert_populate (ECert *cert)
172 {
173 CERTCertificate *c = cert->priv->cert;
174 guchar fingerprint[20];
175 SECItem fpItem;
176
177 cert->priv->org_name = CERT_GetOrgName (&c->subject);
178 cert->priv->org_unit_name = CERT_GetOrgUnitName (&c->subject);
179
180 cert->priv->issuer_org_name = CERT_GetOrgName (&c->issuer);
181 cert->priv->issuer_org_unit_name = CERT_GetOrgUnitName (&c->issuer);
182
183 cert->priv->cn = CERT_GetCommonName (&c->subject);
184 cert->priv->issuer_cn = CERT_GetCommonName (&c->issuer);
185
186 if (SECSuccess == CERT_GetCertTimes (
187 c, &cert->priv->issued_on, &cert->priv->expires_on)) {
188 PRExplodedTime explodedTime;
189 struct tm exploded_tm;
190 gchar buf[32];
191
192 PR_ExplodeTime (
193 cert->priv->issued_on,
194 PR_LocalTimeParameters, &explodedTime);
195 exploded_tm.tm_sec = explodedTime.tm_sec;
196 exploded_tm.tm_min = explodedTime.tm_min;
197 exploded_tm.tm_hour = explodedTime.tm_hour;
198 exploded_tm.tm_mday = explodedTime.tm_mday;
199 exploded_tm.tm_mon = explodedTime.tm_month;
200 exploded_tm.tm_year = explodedTime.tm_year - 1900;
201 e_utf8_strftime (buf, sizeof (buf), _("%d/%m/%Y"), &exploded_tm);
202 cert->priv->issued_on_string = g_strdup (buf);
203
204 PR_ExplodeTime (
205 cert->priv->expires_on,
206 PR_LocalTimeParameters, &explodedTime);
207 exploded_tm.tm_sec = explodedTime.tm_sec;
208 exploded_tm.tm_min = explodedTime.tm_min;
209 exploded_tm.tm_hour = explodedTime.tm_hour;
210 exploded_tm.tm_mday = explodedTime.tm_mday;
211 exploded_tm.tm_mon = explodedTime.tm_month;
212 exploded_tm.tm_year = explodedTime.tm_year - 1900;
213 e_utf8_strftime (buf, sizeof (buf), _("%d/%m/%Y"), &exploded_tm);
214 cert->priv->expires_on_string = g_strdup (buf);
215 }
216
217 cert->priv->serial_number = CERT_Hexify (&cert->priv->cert->serialNumber, TRUE);
218
219 memset (fingerprint, 0, sizeof fingerprint);
220 PK11_HashBuf (
221 SEC_OID_SHA1, fingerprint,
222 cert->priv->cert->derCert.data,
223 cert->priv->cert->derCert.len);
224 fpItem.data = fingerprint;
225 fpItem.len = SHA1_LENGTH;
226 cert->priv->sha1_fingerprint = CERT_Hexify (&fpItem, TRUE);
227
228 memset (fingerprint, 0, sizeof fingerprint);
229 PK11_HashBuf (
230 SEC_OID_MD5, fingerprint,
231 cert->priv->cert->derCert.data,
232 cert->priv->cert->derCert.len);
233 fpItem.data = fingerprint;
234 fpItem.len = MD5_LENGTH;
235 cert->priv->md5_fingerprint = CERT_Hexify (&fpItem, TRUE);
236 }
237
238 ECert *
239 e_cert_new (CERTCertificate *cert)
240 {
241 ECert *ecert = E_CERT (g_object_new (E_TYPE_CERT, NULL));
242
243 /* ECert owns a reference to the 'cert', which will be freed on ECert finalize */
244 ecert->priv->cert = cert;
245
246 e_cert_populate (ecert);
247
248 return ecert;
249 }
250
251 ECert *
252 e_cert_new_from_der (gchar *data,
253 guint32 len)
254 {
255 CERTCertificate *cert = CERT_DecodeCertFromPackage (data, len);
256
257 if (!cert)
258 return NULL;
259
260 if (cert->dbhandle == NULL)
261 cert->dbhandle = CERT_GetDefaultCertDB ();
262
263 return e_cert_new (cert);
264 }
265
266 CERTCertificate *
267 e_cert_get_internal_cert (ECert *cert)
268 {
269 /* XXX should this refcnt it? */
270 return cert->priv->cert;
271 }
272
273 gboolean
274 e_cert_get_raw_der (ECert *cert,
275 gchar **data,
276 guint32 *len)
277 {
278 /* XXX do we really need to check if cert->priv->cert is NULL
279 * here? it should always be non - null if we have the
280 * ECert.. */
281 if (cert->priv->cert) {
282 *data = (gchar *)cert->priv->cert->derCert.data;
283 *len = (guint32)cert->priv->cert->derCert.len;
284 return TRUE;
285 }
286
287 *len = 0;
288 return FALSE;
289
290 }
291
292 const gchar *
293 e_cert_get_window_title (ECert *cert)
294 {
295 if (cert->priv->cert->nickname)
296 return cert->priv->cert->nickname;
297 else if (cert->priv->cn)
298 return cert->priv->cn;
299 else
300 return cert->priv->cert->subjectName;
301 }
302
303 const gchar *
304 e_cert_get_nickname (ECert *cert)
305 {
306 return cert->priv->cert->nickname;
307 }
308
309 const gchar *
310 e_cert_get_email (ECert *cert)
311 {
312 return cert->priv->cert->emailAddr;
313 }
314
315 const gchar *
316 e_cert_get_org (ECert *cert)
317 {
318 return cert->priv->org_name;
319 }
320
321 const gchar *
322 e_cert_get_org_unit (ECert *cert)
323 {
324 return cert->priv->org_unit_name;
325 }
326
327 const gchar *
328 e_cert_get_cn (ECert *cert)
329 {
330 return cert->priv->cn;
331 }
332
333 const gchar *
334 e_cert_get_issuer_name (ECert *cert)
335 {
336 return cert->priv->cert->issuerName;
337 }
338
339 const gchar *
340 e_cert_get_issuer_cn (ECert *cert)
341 {
342 return cert->priv->issuer_cn;
343 }
344
345 const gchar *
346 e_cert_get_issuer_org (ECert *cert)
347 {
348 return cert->priv->issuer_org_name;
349 }
350
351 const gchar *
352 e_cert_get_issuer_org_unit (ECert *cert)
353 {
354 return cert->priv->issuer_org_unit_name;
355 }
356
357 const gchar *
358 e_cert_get_subject_name (ECert *cert)
359 {
360 return cert->priv->cert->subjectName;
361 }
362
363 PRTime
364 e_cert_get_issued_on_time (ECert *cert)
365 {
366 return cert->priv->issued_on;
367 }
368
369 const gchar *
370 e_cert_get_issued_on (ECert *cert)
371 {
372 return cert->priv->issued_on_string;
373 }
374
375 PRTime
376 e_cert_get_expires_on_time (ECert *cert)
377 {
378 return cert->priv->expires_on;
379 }
380
381 const gchar *
382 e_cert_get_expires_on (ECert *cert)
383 {
384 return cert->priv->expires_on_string;
385 }
386
387 static struct {
388 gint bit;
389 const gchar *text;
390 } usageinfo[] = {
391 /* x509 certificate usage types */
392 { certificateUsageEmailSigner, N_("Sign") },
393 { certificateUsageEmailRecipient, N_("Encrypt") },
394 };
395
396 const gchar *
397 e_cert_get_usage (ECert *cert)
398 {
399 if (cert->priv->usage_string == NULL) {
400 gint i;
401 GString *str = g_string_new ("");
402 CERTCertificate *icert = e_cert_get_internal_cert (cert);
403
404 for (i = 0; i < G_N_ELEMENTS (usageinfo); i++) {
405 if (icert->keyUsage & usageinfo[i].bit) {
406 if (str->len != 0)
407 g_string_append (str, ", ");
408 g_string_append (str, _(usageinfo[i].text));
409 }
410 }
411
412 cert->priv->usage_string = str->str;
413 g_string_free (str, FALSE);
414 }
415
416 return cert->priv->usage_string;
417 }
418
419 const gchar *
420 e_cert_get_serial_number (ECert *cert)
421 {
422 return cert->priv->serial_number;
423 }
424
425 const gchar *
426 e_cert_get_sha1_fingerprint (ECert *cert)
427 {
428 return cert->priv->sha1_fingerprint;
429 }
430
431 const gchar *
432 e_cert_get_md5_fingerprint (ECert *cert)
433 {
434 return cert->priv->md5_fingerprint;
435 }
436
437 GList *
438 e_cert_get_chain (ECert *ecert)
439 {
440 GList *l = NULL;
441
442 g_object_ref (ecert);
443
444 while (ecert) {
445 CERTCertificate *cert = e_cert_get_internal_cert (ecert);
446 CERTCertificate *next_cert;
447
448 l = g_list_append (l, ecert);
449
450 if (SECITEM_CompareItem (&cert->derIssuer, &cert->derSubject) == SECEqual)
451 break;
452
453 next_cert = CERT_FindCertIssuer (cert, PR_Now (), certUsageSSLClient);
454 if (!next_cert)
455 break;
456
457 /* next_cert has a reference already */
458 ecert = e_cert_new (next_cert);
459 }
460
461 return l;
462 }
463
464 ECert *
465 e_cert_get_ca_cert (ECert *ecert)
466 {
467 CERTCertificate *cert, *next = e_cert_get_internal_cert (ecert), *internal;
468
469 cert = next;
470 internal = cert;
471 do {
472 if (cert != next && cert != internal)
473 CERT_DestroyCertificate (cert);
474
475 cert = next;
476 next = CERT_FindCertIssuer (cert, PR_Now (), certUsageAnyCA);
477 } while (next && next != cert);
478
479 if (cert == internal)
480 return g_object_ref (ecert);
481 else
482 return e_cert_new (cert);
483 }
484
485 static gboolean
486 get_int_value (SECItem *versionItem,
487 gulong *version)
488 {
489 SECStatus srv;
490 srv = SEC_ASN1DecodeInteger (versionItem,version);
491 if (srv != SECSuccess) {
492 g_warning ("could not decode version of cert");
493 return FALSE;
494 }
495 return TRUE;
496 }
497
498 static gboolean
499 process_version (SECItem *versionItem,
500 EASN1Object **retItem)
501 {
502 EASN1Object *item = e_asn1_object_new ();
503 gulong version;
504
505 e_asn1_object_set_display_name (item, _("Version"));
506
507 /* Now to figure out what version this certificate is. */
508
509 if (versionItem->data) {
510 if (!get_int_value (versionItem, &version))
511 return FALSE;
512 } else {
513 /* If there is no version present in the cert, then rfc2459
514 * says we default to v1 (0) */
515 version = 0;
516 }
517
518 switch (version) {
519 case 0:
520 e_asn1_object_set_display_value (item, _("Version 1"));
521 break;
522 case 1:
523 e_asn1_object_set_display_value (item, _("Version 2"));
524 break;
525 case 2:
526 e_asn1_object_set_display_value (item, _("Version 3"));
527 break;
528 default:
529 g_warning ("Bad value for cert version");
530 return FALSE;
531 }
532
533 *retItem = item;
534 return TRUE;
535 }
536
537 static gboolean
538 process_serial_number_der (SECItem *serialItem,
539 EASN1Object **retItem)
540 {
541 gchar *serialNumber;
542 EASN1Object *item = e_asn1_object_new ();
543
544 e_asn1_object_set_display_name (item, _("Serial Number"));
545
546 serialNumber = CERT_Hexify (serialItem, 1);
547
548 e_asn1_object_set_display_value (item, serialNumber);
549 PORT_Free (serialNumber); /* XXX the right free to use? */
550
551 *retItem = item;
552 return TRUE;
553 }
554
555 static gboolean
556 get_default_oid_format (SECItem *oid,
557 gchar **text)
558 {
559 gchar buf[300];
560 guint len;
561 gint written;
562
563 gulong val = oid->data[0];
564 guint i = val % 40;
565 val /= 40;
566 written = PR_snprintf (buf, 300, "%lu %u ", val, i);
567 if (written < 0)
568 return FALSE;
569 len = written;
570
571 val = 0;
572 for (i = 1; i < oid->len; ++i) {
573 /* In this loop, we have to parse a DER formatted
574 * If the first bit is a 1, then the integer is
575 * represented by more than one byte. If the
576 * first bit is set then we continue on and add
577 * the values of the later bytes until we get
578 * a byte without the first bit set.
579 */
580 gulong j;
581
582 j = oid->data[i];
583 val = (val << 7) | (j & 0x7f);
584 if (j & 0x80)
585 continue;
586 written = PR_snprintf (&buf[len], sizeof (buf) - len, "%lu ", val);
587 if (written < 0)
588 return FALSE;
589
590 len += written;
591 if (len >= sizeof (buf))
592 g_warning ("OID data to big to display in 300 chars.");
593 val = 0;
594 }
595
596 *text = g_strdup (buf);
597 return TRUE;
598 }
599
600 static gboolean
601 get_oid_text (SECItem *oid,
602 gchar **text)
603 {
604 SECOidTag oidTag = SECOID_FindOIDTag (oid);
605 gchar *temp;
606
607 switch (oidTag) {
608 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
609 *text = g_strdup (_("PKCS #1 MD2 With RSA Encryption"));
610 break;
611 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
612 *text = g_strdup (_("PKCS #1 MD5 With RSA Encryption"));
613 break;
614 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
615 *text = g_strdup (_("PKCS #1 SHA-1 With RSA Encryption"));
616 break;
617 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
618 *text = g_strdup (_("PKCS #1 SHA-256 With RSA Encryption"));
619 break;
620 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
621 *text = g_strdup (_("PKCS #1 SHA-384 With RSA Encryption"));
622 break;
623 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
624 *text = g_strdup (_("PKCS #1 SHA-512 With RSA Encryption"));
625 break;
626 case SEC_OID_AVA_COUNTRY_NAME:
627 *text = g_strdup ("C");
628 break;
629 case SEC_OID_AVA_COMMON_NAME:
630 *text = g_strdup ("CN");
631 break;
632 case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
633 *text = g_strdup ("OU");
634 break;
635 case SEC_OID_AVA_ORGANIZATION_NAME:
636 *text = g_strdup ("O");
637 break;
638 case SEC_OID_AVA_LOCALITY:
639 *text = g_strdup ("L");
640 break;
641 case SEC_OID_AVA_DN_QUALIFIER:
642 *text = g_strdup ("DN");
643 break;
644 case SEC_OID_AVA_DC:
645 *text = g_strdup ("DC");
646 break;
647 case SEC_OID_AVA_STATE_OR_PROVINCE:
648 *text = g_strdup ("ST");
649 break;
650 case SEC_OID_PKCS1_RSA_ENCRYPTION:
651 *text = g_strdup (_("PKCS #1 RSA Encryption"));
652 break;
653 case SEC_OID_X509_KEY_USAGE:
654 *text = g_strdup (_("Certificate Key Usage"));
655 break;
656 case SEC_OID_NS_CERT_EXT_CERT_TYPE:
657 *text = g_strdup (_("Netscape Certificate Type"));
658 break;
659 case SEC_OID_X509_AUTH_KEY_ID:
660 *text = g_strdup (_("Certificate Authority Key Identifier"));
661 break;
662 case SEC_OID_RFC1274_UID:
663 *text = g_strdup ("UID");
664 break;
665 case SEC_OID_PKCS9_EMAIL_ADDRESS:
666 *text = g_strdup ("E");
667 break;
668 default:
669 if (!get_default_oid_format (oid, &temp))
670 return FALSE;
671
672 *text = g_strdup_printf (_("Object Identifier (%s)"), temp);
673 g_free (temp);
674
675 break;
676 }
677 return TRUE;
678 }
679
680 static gboolean
681 process_raw_bytes (SECItem *data,
682 gchar **text)
683 {
684 /* This function is used to display some DER bytes
685 * that we have not added support for decoding.
686 * It prints the value of the byte out into a
687 * string that can later be displayed as a byte
688 * string. We place a new line after 24 bytes
689 * to break up extermaly long sequence of bytes.
690 */
691 GString *str = g_string_new ("");
692 PRUint32 i;
693 gchar buffer[5];
694 for (i = 0; i < data->len; i++) {
695 PR_snprintf (buffer, 5, "%02x ", data->data[i]);
696 g_string_append (str, buffer);
697 if ((i + 1) % 16 == 0) {
698 g_string_append (str, "\n");
699 }
700 }
701 *text = g_string_free (str, FALSE);
702 return TRUE;
703 }
704
705 static gboolean
706 process_sec_algorithm_id (SECAlgorithmID *algID,
707 EASN1Object **retSequence)
708 {
709 EASN1Object *sequence = e_asn1_object_new ();
710 gchar *text;
711
712 *retSequence = NULL;
713
714 get_oid_text (&algID->algorithm, &text);
715
716 if (!algID->parameters.len ||
717 algID->parameters.data[0] == E_ASN1_OBJECT_TYPE_NULL) {
718 e_asn1_object_set_display_value (sequence, text);
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
719 e_asn1_object_set_valid_container (sequence, FALSE);
720 } else {
721 EASN1Object *subitem;
722
723 subitem = e_asn1_object_new ();
724 e_asn1_object_set_display_name (subitem, _("Algorithm Identifier"));
725 e_asn1_object_set_display_value (subitem, text);
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
726 e_asn1_object_append_child (sequence, subitem);
727 g_object_unref (subitem);
728
729 g_free (text);
730
731 subitem = e_asn1_object_new ();
732 e_asn1_object_set_display_name (subitem, _("Algorithm Parameters"));
733 process_raw_bytes (&algID->parameters, &text);
734 e_asn1_object_set_display_value (subitem, text);
735 e_asn1_object_append_child (sequence, subitem);
736 g_object_unref (subitem);
737 }
738
739 g_free (text);
740 *retSequence = sequence;
741 return TRUE;
742 }
743
744 static gboolean
745 process_subject_public_key_info (CERTSubjectPublicKeyInfo *spki,
746 EASN1Object *parentSequence)
747 {
748 EASN1Object *spkiSequence = e_asn1_object_new ();
749 EASN1Object *sequenceItem;
750 EASN1Object *printableItem;
751 SECItem data;
752 gchar *text;
753
754 e_asn1_object_set_display_name (spkiSequence, _("Subject Public Key Info"));
755
756 if (!process_sec_algorithm_id (&spki->algorithm, &sequenceItem))
757 return FALSE;
758
759 e_asn1_object_set_display_name (sequenceItem, _("Subject Public Key Algorithm"));
760
761 e_asn1_object_append_child (spkiSequence, sequenceItem);
762
763 /* The subjectPublicKey field is encoded as a bit string.
764 * ProcessRawBytes expects the lenght to be in bytes, so
765 * let's convert the lenght into a temporary SECItem.
766 */
767 data.data = spki->subjectPublicKey.data;
768 data.len = spki->subjectPublicKey.len / 8;
769
770 process_raw_bytes (&data, &text);
771 printableItem = e_asn1_object_new ();
772
773 e_asn1_object_set_display_value (printableItem, text);
774 e_asn1_object_set_display_name (printableItem, _("Subject's Public Key"));
775 e_asn1_object_append_child (spkiSequence, printableItem);
776 g_object_unref (printableItem);
777
778 e_asn1_object_append_child (parentSequence, spkiSequence);
779 g_object_unref (spkiSequence);
780
781 return TRUE;
782 }
783
784 static gboolean
785 process_ns_cert_type_extensions (SECItem *extData,
786 GString *text)
787 {
788 SECItem decoded;
789 guchar nsCertType;
790
791 decoded.data = NULL;
792 decoded.len = 0;
793 if (SECSuccess != SEC_ASN1DecodeItem (NULL, &decoded,
794 SEC_ASN1_GET (SEC_BitStringTemplate), extData)) {
795 g_string_append (text, _("Error: Unable to process extension"));
796 return TRUE;
797 }
798
799 nsCertType = decoded.data[0];
800
801 PORT_Free (decoded.data); /* XXX right free? */
802
803 if (nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
804 g_string_append (text, _("SSL Client Certificate"));
805 g_string_append (text, "\n");
806 }
807 if (nsCertType & NS_CERT_TYPE_SSL_SERVER) {
808 g_string_append (text, _("SSL Server Certificate"));
809 g_string_append (text, "\n");
810 }
811 if (nsCertType & NS_CERT_TYPE_EMAIL) {
812 g_string_append (text, _("Email"));
813 g_string_append (text, "\n");
814 }
815 if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING) {
816 g_string_append (text, _("Object Signer"));
817 g_string_append (text, "\n");
818 }
819 if (nsCertType & NS_CERT_TYPE_SSL_CA) {
820 g_string_append (text, _("SSL Certificate Authority"));
821 g_string_append (text, "\n");
822 }
823 if (nsCertType & NS_CERT_TYPE_EMAIL_CA) {
824 g_string_append (text, _("Email Certificate Authority"));
825 g_string_append (text, "\n");
826 }
827 if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING_CA) {
828 g_string_append (text, _("Object Signer"));
829 g_string_append (text, "\n");
830 }
831 return TRUE;
832 }
833
834 static gboolean
835 process_key_usage_extensions (SECItem *extData,
836 GString *text)
837 {
838 SECItem decoded;
839 guchar keyUsage;
840
841 decoded.data = NULL;
842 decoded.len = 0;
843 if (SECSuccess != SEC_ASN1DecodeItem (NULL, &decoded,
844 SEC_ASN1_GET (SEC_BitStringTemplate), extData)) {
845 g_string_append (text, _("Error: Unable to process extension"));
846 return TRUE;
847 }
848
849 keyUsage = decoded.data[0];
850 PORT_Free (decoded.data); /* XXX right free? */
851
852 if (keyUsage & KU_DIGITAL_SIGNATURE) {
853 g_string_append (text, _("Signing"));
854 g_string_append (text, "\n");
855 }
856 if (keyUsage & KU_NON_REPUDIATION) {
857 g_string_append (text, _("Non-repudiation"));
858 g_string_append (text, "\n");
859 }
860 if (keyUsage & KU_KEY_ENCIPHERMENT) {
861 g_string_append (text, _("Key Encipherment"));
862 g_string_append (text, "\n");
863 }
864 if (keyUsage & KU_DATA_ENCIPHERMENT) {
865 g_string_append (text, _("Data Encipherment"));
866 g_string_append (text, "\n");
867 }
868 if (keyUsage & KU_KEY_AGREEMENT) {
869 g_string_append (text, _("Key Agreement"));
870 g_string_append (text, "\n");
871 }
872 if (keyUsage & KU_KEY_CERT_SIGN) {
873 g_string_append (text, _("Certificate Signer"));
874 g_string_append (text, "\n");
875 }
876 if (keyUsage & KU_CRL_SIGN) {
877 g_string_append (text, _("CRL Signer"));
878 g_string_append (text, "\n");
879 }
880
881 return TRUE;
882 }
883
884 static gboolean
885 process_extension_data (SECOidTag oidTag,
886 SECItem *extData,
887 GString *str)
888 {
889 gboolean rv;
890 switch (oidTag) {
891 case SEC_OID_NS_CERT_EXT_CERT_TYPE:
892 rv = process_ns_cert_type_extensions (extData, str);
893 break;
894 case SEC_OID_X509_KEY_USAGE:
895 rv = process_key_usage_extensions (extData, str);
896 break;
897 default: {
898 gchar *text;
899 rv = process_raw_bytes (extData, &text);
900 g_string_append (str, text);
901 g_free (text);
902 break;
903 }
904 }
905 return rv;
906 }
907
908 static gboolean
909 process_single_extension (CERTCertExtension *extension,
910 EASN1Object **retExtension)
911 {
912 GString *str = g_string_new ("");
913 gchar *text;
914 EASN1Object *extensionItem;
915 SECOidTag oidTag = SECOID_FindOIDTag (&extension->id);
916
917 get_oid_text (&extension->id, &text);
918
919 extensionItem = e_asn1_object_new ();
920
921 e_asn1_object_set_display_name (extensionItem, text);
922 g_free (text);
923
924 if (extension->critical.data != NULL) {
925 if (extension->critical.data[0]) {
926 g_string_append (str, _("Critical"));
927 } else {
928 g_string_append (str, _("Not Critical"));
929 }
930 } else {
931 g_string_append (str, _("Not Critical"));
932 }
933 g_string_append (str, "\n");
934 if (!process_extension_data (oidTag, &extension->value, str)) {
935 g_string_free (str, TRUE);
936 return FALSE;
937 }
938
939 e_asn1_object_set_display_value (extensionItem, str->str);
940 g_string_free (str, TRUE);
941 *retExtension = extensionItem;
942 return TRUE;
943 }
944
945 static gboolean
946 process_extensions (CERTCertExtension **extensions,
947 EASN1Object *parentSequence)
948 {
949 EASN1Object *extensionSequence = e_asn1_object_new ();
950 PRInt32 i;
951
952 e_asn1_object_set_display_name (extensionSequence, _("Extensions"));
953
954 for (i = 0; extensions[i] != NULL; i++) {
955 EASN1Object *newExtension;
956
957 if (!process_single_extension (extensions[i],
958 &newExtension))
959 return FALSE;
960
961 e_asn1_object_append_child (extensionSequence, newExtension);
962 }
963 e_asn1_object_append_child (parentSequence, extensionSequence);
964 return TRUE;
965 }
966
967 static gboolean
968 process_name (CERTName *name,
969 gchar **value)
970 {
971 CERTRDN ** rdns;
972 CERTRDN ** rdn;
973 CERTAVA ** avas;
974 CERTAVA * ava;
975 SECItem *decodeItem = NULL;
976 GString *final_string = g_string_new ("");
977
978 gchar *type;
979 GString *avavalue;
980 gchar *temp;
981 CERTRDN **lastRdn;
982
983 rdns = name->rdns;
984
985 /* find last RDN */
986 lastRdn = rdns;
987 while (*lastRdn) lastRdn++;
988
989 /* The above whille loop will put us at the last member
990 * of the array which is a NULL pointer. So let's back
991 * up one spot so that we have the last non-NULL entry in
992 * the array in preparation for traversing the
993 * RDN's (Relative Distinguished Name) in reverse order.
994 */
995 lastRdn--;
996
997 /*
998 * Loop over name contents in _reverse_ RDN order appending to string
999 * When building the Ascii string, NSS loops over these entries in
1000 * reverse order, so I will as well. The difference is that NSS
1001 * will always place them in a one line string separated by commas,
1002 * where I want each entry on a single line. I can't just use a comma
1003 * as my delimitter because it is a valid character to have in the
1004 * value portion of the AVA and could cause trouble when parsing.
1005 */
1006 for (rdn = lastRdn; rdn >= rdns; rdn--) {
1007 avas = (*rdn)->avas;
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
1008 while ((ava = *avas++) != 0) {
1009 if (!get_oid_text (&ava->type, &type))
1010 return FALSE;
1011
1012 /* This function returns a string in UTF8 format. */
1013 decodeItem = CERT_DecodeAVAValue (&ava->value);
1014 if (!decodeItem) {
1015 return FALSE;
1016 }
1017
1018 avavalue = g_string_new_len (
1019 (gchar *) decodeItem->data, decodeItem->len);
1020
1021 SECITEM_FreeItem (decodeItem, PR_TRUE);
1022
1023 /* Translators: This string is used in Certificate
1024 * details for fields like Issuer or Subject, which
1025 * shows the field name on the left and its respective
1026 * value on the right, both as stored in the
1027 * certificate itself. You probably do not need to
1028 * change this string, unless changing the order of
1029 * name and value. As a result example:
1030 * "OU = VeriSign Trust Network" */
1031 temp = g_strdup_printf (_("%s = %s"), type, avavalue->str);
1032
1033 g_string_append (final_string, temp);
1034 g_string_append (final_string, "\n");
1035 g_string_free (avavalue, TRUE);
1036 g_free (temp);
1037 }
1038 }
1039 *value = g_string_free (final_string, FALSE);
1040 return TRUE;
1041 }
1042
1043 static gboolean
1044 create_tbs_certificate_asn1_struct (ECert *cert,
1045 EASN1Object **seq)
1046 {
1047 /*
1048 ** TBSCertificate ::= SEQUENCE {
1049 ** version [0] EXPLICIT Version DEFAULT v1,
1050 ** serialNumber CertificateSerialNumber,
1051 ** signature AlgorithmIdentifier,
1052 ** issuer Name,
1053 ** validity Validity,
1054 ** subject Name,
1055 ** subjectPublicKeyInfo SubjectPublicKeyInfo,
1056 ** issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
1057 ** -- If present, version shall be v2 or v3
1058 ** subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
1059 ** -- If present, version shall be v2 or v3
1060 ** extensions [3] EXPLICIT Extensions OPTIONAL
1061 ** -- If present, version shall be v3
1062 ** }
1063 **
1064 ** This is the ASN1 structure we should be dealing with at this point.
1065 ** The code in this method will assert this is the structure we're dealing
1066 ** and then add more user friendly text for that field.
1067 */
1068 EASN1Object *sequence = e_asn1_object_new ();
1069 gchar *text;
1070 EASN1Object *subitem;
1071 SECItem data;
1072
1073 e_asn1_object_set_display_name (sequence, _("Certificate"));
1074
1075 if (!process_version (&cert->priv->cert->version, &subitem))
1076 return FALSE;
1077 e_asn1_object_append_child (sequence, subitem);
1078 g_object_unref (subitem);
1079
1080 if (!process_serial_number_der (&cert->priv->cert->serialNumber, &subitem))
1081 return FALSE;
1082 e_asn1_object_append_child (sequence, subitem);
1083 g_object_unref (subitem);
1084
1085 if (!process_sec_algorithm_id (&cert->priv->cert->signature, &subitem))
1086 return FALSE;
1087 e_asn1_object_set_display_name (subitem, _("Certificate Signature Algorithm"));
1088 e_asn1_object_append_child (sequence, subitem);
1089 g_object_unref (subitem);
1090
1091 process_name (&cert->priv->cert->issuer, &text);
1092 subitem = e_asn1_object_new ();
1093 e_asn1_object_set_display_value (subitem, text);
1094 g_free (text);
1095
1096 e_asn1_object_set_display_name (subitem, _("Issuer"));
1097 e_asn1_object_append_child (sequence, subitem);
1098 g_object_unref (subitem);
1099
1100 #ifdef notyet
1101 nsCOMPtr < nsIASN1Sequence> validitySequence = new nsNSSASN1Sequence ();
1102 nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpValidity").get (),
1103 text);
1104 validitySequence->SetDisplayName (text);
1105 asn1Objects->AppendElement (validitySequence, PR_FALSE);
1106 nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpNotBefore").get (),
1107 text);
1108 nsCOMPtr < nsIX509CertValidity> validityData;
1109 GetValidity (getter_AddRefs (validityData));
1110 PRTime notBefore, notAfter;
1111
1112 validityData->GetNotBefore (¬Before);
1113 validityData->GetNotAfter (¬After);
1114 validityData = 0;
1115 rv = ProcessTime (notBefore, text.get (), validitySequence);
1116 if (NS_FAILED (rv))
1117 return rv;
1118
1119 nssComponent->GetPIPNSSBundleString (NS_LITERAL_STRING ("CertDumpNotAfter").get (),
1120 text);
1121 rv = ProcessTime (notAfter, text.get (), validitySequence);
1122 if (NS_FAILED (rv))
1123 return rv;
1124 #endif
1125
1126 subitem = e_asn1_object_new ();
1127 e_asn1_object_set_display_name (subitem, _("Subject"));
1128
1129 process_name (&cert->priv->cert->subject, &text);
1130 e_asn1_object_set_display_value (subitem, text);
1131 g_free (text);
1132 e_asn1_object_append_child (sequence, subitem);
1133 g_object_unref (subitem);
1134
1135 if (!process_subject_public_key_info (
1136 &cert->priv->cert->subjectPublicKeyInfo, sequence))
1137 return FALSE;
1138
1139 /* Is there an issuerUniqueID? */
1140 if (cert->priv->cert->issuerID.data) {
1141 /* The issuerID is encoded as a bit string.
1142 * The function ProcessRawBytes expects the
1143 * length to be in bytes, so let's convert the
1144 * length in a temporary SECItem
1145 */
1146 data.data = cert->priv->cert->issuerID.data;
1147 data.len = cert->priv->cert->issuerID.len / 8;
1148
1149 subitem = e_asn1_object_new ();
1150
1151 e_asn1_object_set_display_name (subitem, _("Issuer Unique ID"));
1152 process_raw_bytes (&data, &text);
1153 e_asn1_object_set_display_value (subitem, text);
1154 g_free (text);
1155
1156 e_asn1_object_append_child (sequence, subitem);
1157 }
1158
1159 if (cert->priv->cert->subjectID.data) {
1160 /* The subjectID is encoded as a bit string.
1161 * The function ProcessRawBytes expects the
1162 * length to be in bytes, so let's convert the
1163 * length in a temporary SECItem
1164 */
1165 data.data = cert->priv->cert->issuerID.data;
1166 data.len = cert->priv->cert->issuerID.len / 8;
1167
1168 subitem = e_asn1_object_new ();
1169
1170 e_asn1_object_set_display_name (subitem, _("Subject Unique ID"));
1171 process_raw_bytes (&data, &text);
1172 e_asn1_object_set_display_value (subitem, text);
1173 g_free (text);
1174
1175 e_asn1_object_append_child (sequence, subitem);
1176 }
1177 if (cert->priv->cert->extensions) {
1178 if (!process_extensions (cert->priv->cert->extensions, sequence))
1179 return FALSE;
1180 }
1181
1182 *seq = sequence;
1183
1184 return TRUE;
1185 }
1186
1187 static gboolean
1188 create_asn1_struct (ECert *cert)
1189 {
1190 EASN1Object *sequence;
1191 SECItem temp;
1192 gchar *text;
1193
1194 cert->priv->asn1 = e_asn1_object_new ();
1195
1196 e_asn1_object_set_display_name (cert->priv->asn1, e_cert_get_window_title (cert));
1197
1198 /* This sequence will be contain the tbsCertificate, signatureAlgorithm,
1199 * and signatureValue. */
1200
1201 if (!create_tbs_certificate_asn1_struct (cert, &sequence))
1202 return FALSE;
1203 e_asn1_object_append_child (cert->priv->asn1, sequence);
1204 g_object_unref (sequence);
1205
1206 if (!process_sec_algorithm_id (
1207 &cert->priv->cert->signatureWrap.signatureAlgorithm, &sequence))
1208 return FALSE;
1209 e_asn1_object_set_display_name (
1210 sequence, _("Certificate Signature Algorithm"));
1211 e_asn1_object_append_child (cert->priv->asn1, sequence);
1212 g_object_unref (sequence);
1213
1214 sequence = e_asn1_object_new ();
1215 e_asn1_object_set_display_name (
1216 sequence, _("Certificate Signature Value"));
1217
1218 /* The signatureWrap is encoded as a bit string.
1219 * The function ProcessRawBytes expects the
1220 * length to be in bytes, so let's convert the
1221 * length in a temporary SECItem */
1222 temp.data = cert->priv->cert->signatureWrap.signature.data;
1223 temp.len = cert->priv->cert->signatureWrap.signature.len / 8;
1224 process_raw_bytes (&temp, &text);
1225 e_asn1_object_set_display_value (sequence, text);
1226 e_asn1_object_append_child (cert->priv->asn1, sequence);
1227 g_free (text);
1228
1229 return TRUE;
1230 }
1231
1232 EASN1Object *
1233 e_cert_get_asn1_struct (ECert *cert)
1234 {
1235 if (!cert->priv->asn1)
1236 create_asn1_struct (cert);
1237
1238 return g_object_ref (cert->priv->asn1);
1239 }
1240
1241 gboolean
1242 e_cert_mark_for_deletion (ECert *cert)
1243 {
1244 /* nsNSSShutDownPreventionLock locker; */
1245
1246 #if 0
1247 /* make sure user is logged in to the token */
1248 nsCOMPtr < nsIInterfaceRequestor> ctx = new PipUIContext ();
1249 #endif
1250
1251 if (PK11_NeedLogin (cert->priv->cert->slot)
1252 && !PK11_NeedUserInit (cert->priv->cert->slot)
1253 && !PK11_IsInternal (cert->priv->cert->slot)) {
1254 if (PK11_Authenticate (
1255 cert->priv->cert->slot, PR_TRUE, NULL) != SECSuccess) {
1256 return FALSE;
1257 }
1258 }
1259
1260 cert->priv->delete = TRUE;
1261
1262 return TRUE;
1263 }
1264
1265 ECertType
1266 e_cert_get_cert_type (ECert *ecert)
1267 {
1268 const gchar *nick = e_cert_get_nickname (ecert);
1269 const gchar *email = e_cert_get_email (ecert);
1270 CERTCertificate *cert = ecert->priv->cert;
1271
1272 if (nick) {
1273 if (e_cert_trust_has_any_user (cert->trust))
1274 return E_CERT_USER;
1275 if (e_cert_trust_has_any_ca (cert->trust)
1276 || CERT_IsCACert (cert,NULL))
1277 return E_CERT_CA;
1278 if (e_cert_trust_has_peer (cert->trust, PR_TRUE, PR_FALSE, PR_FALSE))
1279 return E_CERT_SITE;
1280 }
1281 if (email && e_cert_trust_has_peer (cert->trust, PR_FALSE, PR_TRUE, PR_FALSE))
1282 return E_CERT_CONTACT;
1283
1284 return E_CERT_UNKNOWN;
1285 }