Tizen 2.0 Release
[external/libgnutls26.git] / lib / x509 / output.c
1 /*
2  * Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3  *
4  * Author: Simon Josefsson
5  *
6  * This file is part of GnuTLS.
7  *
8  * The GnuTLS is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301, USA
22  *
23  */
24
25 /* Functions for printing X.509 Certificate structures
26  */
27
28 #include <gnutls_int.h>
29 #include <common.h>
30 #include <gnutls_x509.h>
31 #include <x509_int.h>
32 #include <gnutls_num.h>
33 #include <gnutls_errors.h>
34 #include <c-ctype.h>
35
36 /* I18n of error codes. */
37 #include "gettext.h"
38 #define _(String) dgettext (PACKAGE, String)
39
40 #define addf _gnutls_buffer_append_printf
41 #define adds _gnutls_buffer_append_str
42
43 #define ERROR_STR (char*) "(error)"
44
45 static void
46 hexdump (gnutls_buffer_st * str, const char *data, size_t len,
47          const char *spc)
48 {
49   size_t j;
50
51   if (spc)
52     adds (str, spc);
53   for (j = 0; j < len; j++)
54     {
55       if (((j + 1) % 16) == 0)
56         {
57           addf (str, "%.2x\n", (unsigned char) data[j]);
58           if (spc && j != (len - 1))
59             adds (str, spc);
60         }
61       else if (j == (len - 1))
62         addf (str, "%.2x", (unsigned char) data[j]);
63       else
64         addf (str, "%.2x:", (unsigned char) data[j]);
65     }
66   if ((j % 16) != 0)
67     adds (str, "\n");
68 }
69
70 static void
71 hexprint (gnutls_buffer_st * str, const char *data, size_t len)
72 {
73   size_t j;
74
75   if (len == 0)
76     adds (str, "00");
77   else
78     {
79       for (j = 0; j < len; j++)
80         addf (str, "%.2x", (unsigned char) data[j]);
81     }
82 }
83
84
85 static void
86 asciiprint (gnutls_buffer_st * str, const char *data, size_t len)
87 {
88   size_t j;
89
90   for (j = 0; j < len; j++)
91     if (c_isprint (data[j]))
92       addf (str, "%c", (unsigned char) data[j]);
93     else
94       addf (str, ".");
95 }
96
97 static char *
98 ip_to_string (void *_ip, int ip_size, char *string, int string_size)
99 {
100   uint8_t *ip;
101
102   if (ip_size != 4 && ip_size != 16)
103     {
104       gnutls_assert ();
105       return NULL;
106     }
107
108   if (ip_size == 4 && string_size < 16)
109     {
110       gnutls_assert ();
111       return NULL;
112     }
113
114   if (ip_size == 16 && string_size < 48)
115     {
116       gnutls_assert ();
117       return NULL;
118     }
119
120   ip = _ip;
121   switch (ip_size)
122     {
123     case 4:
124       snprintf (string, string_size, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
125       break;
126     case 16:
127       snprintf (string, string_size, "%x:%x:%x:%x:%x:%x:%x:%x",
128                (ip[0] << 8) | ip[1], (ip[2] << 8) | ip[3],
129                (ip[4] << 8) | ip[5], (ip[6] << 8) | ip[7],
130                (ip[8] << 8) | ip[9], (ip[10] << 8) | ip[11],
131                (ip[12] << 8) | ip[13], (ip[14] << 8) | ip[15]);
132       break;
133     }
134
135   return string;
136 }
137
138 static void
139 print_proxy (gnutls_buffer_st * str, gnutls_x509_crt_t cert)
140 {
141   int pathlen;
142   char *policyLanguage;
143   char *policy;
144   size_t npolicy;
145   int err;
146
147   err = gnutls_x509_crt_get_proxy (cert, NULL,
148                                    &pathlen, &policyLanguage,
149                                    &policy, &npolicy);
150   if (err < 0)
151     {
152       addf (str, "error: get_proxy: %s\n", gnutls_strerror (err));
153       return;
154     }
155
156   if (pathlen >= 0)
157     addf (str, _("\t\t\tPath Length Constraint: %d\n"), pathlen);
158   addf (str, _("\t\t\tPolicy Language: %s"), policyLanguage);
159   if (strcmp (policyLanguage, "1.3.6.1.5.5.7.21.1") == 0)
160     adds (str, " (id-ppl-inheritALL)\n");
161   else if (strcmp (policyLanguage, "1.3.6.1.5.5.7.21.2") == 0)
162     adds (str, " (id-ppl-independent)\n");
163   else
164     adds (str, "\n");
165   if (npolicy)
166     {
167       adds (str, _("\t\t\tPolicy:\n\t\t\t\tASCII: "));
168       asciiprint (str, policy, npolicy);
169       adds (str, _("\n\t\t\t\tHexdump: "));
170       hexprint (str, policy, npolicy);
171       adds (str, "\n");
172     }
173 }
174
175 static void
176 print_ski (gnutls_buffer_st * str, gnutls_x509_crt_t cert)
177 {
178   char *buffer = NULL;
179   size_t size = 0;
180   int err;
181
182   err = gnutls_x509_crt_get_subject_key_id (cert, buffer, &size, NULL);
183   if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
184     {
185       addf (str, "error: get_subject_key_id: %s\n", gnutls_strerror (err));
186       return;
187     }
188
189   buffer = gnutls_malloc (size);
190   if (!buffer)
191     {
192       addf (str, "error: malloc: %s\n",
193             gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
194       return;
195     }
196
197   err = gnutls_x509_crt_get_subject_key_id (cert, buffer, &size, NULL);
198   if (err < 0)
199     {
200       gnutls_free (buffer);
201       addf (str, "error: get_subject_key_id2: %s\n", gnutls_strerror (err));
202       return;
203     }
204
205   adds (str, "\t\t\t");
206   hexprint (str, buffer, size);
207   adds (str, "\n");
208
209   gnutls_free (buffer);
210 }
211
212 #define TYPE_CRL 1
213 #define TYPE_CRT 2
214 #define TYPE_CRQ 3
215
216 #define TYPE_CRT_SAN TYPE_CRT
217 #define TYPE_CRQ_SAN TYPE_CRQ
218 #define TYPE_CRT_IAN 4
219
220 typedef union
221 {
222   gnutls_x509_crt_t crt;
223   gnutls_x509_crq_t crq;
224   gnutls_x509_crl_t crl;
225 } cert_type_t;
226
227 static void
228 print_aki (gnutls_buffer_st * str, int type, cert_type_t cert)
229 {
230   char *buffer = NULL;
231   size_t size = 0;
232   int err;
233
234   if (type == TYPE_CRT)
235     err =
236       gnutls_x509_crt_get_authority_key_id (cert.crt, buffer, &size, NULL);
237   else if (type == TYPE_CRL)
238     err =
239       gnutls_x509_crl_get_authority_key_id (cert.crl, buffer, &size, NULL);
240   else
241     {
242       gnutls_assert ();
243       return;
244     }
245
246   if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
247     {
248       addf (str, "error: get_authority_key_id: %s\n", gnutls_strerror (err));
249       return;
250     }
251
252   buffer = gnutls_malloc (size);
253   if (!buffer)
254     {
255       addf (str, "error: malloc: %s\n",
256             gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
257       return;
258     }
259
260   if (type == TYPE_CRT)
261     err =
262       gnutls_x509_crt_get_authority_key_id (cert.crt, buffer, &size, NULL);
263   else
264     err =
265       gnutls_x509_crl_get_authority_key_id (cert.crl, buffer, &size, NULL);
266
267   if (err < 0)
268     {
269       gnutls_free (buffer);
270       addf (str, "error: get_authority_key_id2: %s\n", gnutls_strerror (err));
271       return;
272     }
273
274   adds (str, "\t\t\t");
275   hexprint (str, buffer, size);
276   adds (str, "\n");
277
278   gnutls_free (buffer);
279 }
280
281 static void
282 print_key_usage (gnutls_buffer_st * str, const char *prefix, int type,
283                  cert_type_t cert)
284 {
285   unsigned int key_usage;
286   int err;
287
288   if (type == TYPE_CRT)
289     err = gnutls_x509_crt_get_key_usage (cert.crt, &key_usage, NULL);
290   else if (type == TYPE_CRQ)
291     err = gnutls_x509_crq_get_key_usage (cert.crq, &key_usage, NULL);
292   else
293     return;
294
295   if (err < 0)
296     {
297       addf (str, "error: get_key_usage: %s\n", gnutls_strerror (err));
298       return;
299     }
300
301   if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)
302     addf (str, _("%s\t\t\tDigital signature.\n"), prefix);
303   if (key_usage & GNUTLS_KEY_NON_REPUDIATION)
304     addf (str, _("%s\t\t\tNon repudiation.\n"), prefix);
305   if (key_usage & GNUTLS_KEY_KEY_ENCIPHERMENT)
306     addf (str, _("%s\t\t\tKey encipherment.\n"), prefix);
307   if (key_usage & GNUTLS_KEY_DATA_ENCIPHERMENT)
308     addf (str, _("%s\t\t\tData encipherment.\n"), prefix);
309   if (key_usage & GNUTLS_KEY_KEY_AGREEMENT)
310     addf (str, _("%s\t\t\tKey agreement.\n"), prefix);
311   if (key_usage & GNUTLS_KEY_KEY_CERT_SIGN)
312     addf (str, _("%s\t\t\tCertificate signing.\n"), prefix);
313   if (key_usage & GNUTLS_KEY_CRL_SIGN)
314     addf (str, _("%s\t\t\tCRL signing.\n"), prefix);
315   if (key_usage & GNUTLS_KEY_ENCIPHER_ONLY)
316     addf (str, _("%s\t\t\tKey encipher only.\n"), prefix);
317   if (key_usage & GNUTLS_KEY_DECIPHER_ONLY)
318     addf (str, _("%s\t\t\tKey decipher only.\n"), prefix);
319 }
320
321 #ifdef ENABLE_PKI
322
323 static void
324 print_crldist (gnutls_buffer_st * str, gnutls_x509_crt_t cert)
325 {
326   char *buffer = NULL;
327   size_t size;
328   char str_ip[64];
329   char *p;
330   int err;
331   int indx;
332
333   for (indx = 0;; indx++)
334     {
335       size = 0;
336       err = gnutls_x509_crt_get_crl_dist_points (cert, indx, buffer, &size,
337                                                  NULL, NULL);
338       if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
339         return;
340       if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
341         {
342           addf (str, "error: get_crl_dist_points: %s\n",
343                 gnutls_strerror (err));
344           return;
345         }
346
347       buffer = gnutls_malloc (size);
348       if (!buffer)
349         {
350           addf (str, "error: malloc: %s\n",
351                 gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
352           return;
353         }
354
355       err = gnutls_x509_crt_get_crl_dist_points (cert, indx, buffer, &size,
356                                                  NULL, NULL);
357       if (err < 0)
358         {
359           gnutls_free (buffer);
360           addf (str, "error: get_crl_dist_points2: %s\n",
361                 gnutls_strerror (err));
362           return;
363         }
364
365       if ((err == GNUTLS_SAN_DNSNAME
366            || err == GNUTLS_SAN_RFC822NAME
367            || err == GNUTLS_SAN_URI) && strlen (buffer) != size)
368         {
369           adds (str, _("warning: distributionPoint contains an embedded NUL, "
370                        "replacing with '!'\n"));
371           while (strlen (buffer) < size)
372             buffer[strlen (buffer)] = '!';
373         }
374
375       switch (err)
376         {
377         case GNUTLS_SAN_DNSNAME:
378           addf (str, "\t\t\tDNSname: %.*s\n", (int) size, buffer);
379           break;
380
381         case GNUTLS_SAN_RFC822NAME:
382           addf (str, "\t\t\tRFC822name: %.*s\n", (int) size, buffer);
383           break;
384
385         case GNUTLS_SAN_URI:
386           addf (str, "\t\t\tURI: %.*s\n", (int) size, buffer);
387           break;
388
389         case GNUTLS_SAN_IPADDRESS:
390           p = ip_to_string (buffer, size, str_ip, sizeof (str_ip));
391           if (p == NULL)
392             p = ERROR_STR;
393           addf (str, "\t\t\tIPAddress: %s\n", p);
394           break;
395
396         case GNUTLS_SAN_DN:
397           addf (str, "\t\t\tdirectoryName: %.*s\n", (int) size, buffer);
398           break;
399
400         default:
401           addf (str, "error: unknown SAN\n");
402           break;
403         }
404       gnutls_free (buffer);
405     }
406 }
407
408 static void
409 print_key_purpose (gnutls_buffer_st * str, const char *prefix, int type,
410                    cert_type_t cert)
411 {
412   int indx;
413   char *buffer = NULL;
414   size_t size;
415   int err;
416
417   for (indx = 0;; indx++)
418     {
419       size = 0;
420       if (type == TYPE_CRT)
421         err = gnutls_x509_crt_get_key_purpose_oid (cert.crt, indx, buffer,
422                                                    &size, NULL);
423       else if (type == TYPE_CRQ)
424         err = gnutls_x509_crq_get_key_purpose_oid (cert.crq, indx, buffer,
425                                                    &size, NULL);
426       else
427         return;
428
429       if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
430         return;
431       if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
432         {
433           addf (str, "error: get_key_purpose_oid: %s\n",
434                 gnutls_strerror (err));
435           return;
436         }
437
438       buffer = gnutls_malloc (size);
439       if (!buffer)
440         {
441           addf (str, "error: malloc: %s\n",
442                 gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
443           return;
444         }
445
446       if (type == TYPE_CRT)
447         err = gnutls_x509_crt_get_key_purpose_oid (cert.crt, indx, buffer,
448                                                    &size, NULL);
449       else
450         err = gnutls_x509_crq_get_key_purpose_oid (cert.crq, indx, buffer,
451                                                    &size, NULL);
452
453       if (err < 0)
454         {
455           gnutls_free (buffer);
456           addf (str, "error: get_key_purpose_oid2: %s\n",
457                 gnutls_strerror (err));
458           return;
459         }
460
461       if (strcmp (buffer, GNUTLS_KP_TLS_WWW_SERVER) == 0)
462         addf (str, _("%s\t\t\tTLS WWW Server.\n"), prefix);
463       else if (strcmp (buffer, GNUTLS_KP_TLS_WWW_CLIENT) == 0)
464         addf (str, _("%s\t\t\tTLS WWW Client.\n"), prefix);
465       else if (strcmp (buffer, GNUTLS_KP_CODE_SIGNING) == 0)
466         addf (str, _("%s\t\t\tCode signing.\n"), prefix);
467       else if (strcmp (buffer, GNUTLS_KP_EMAIL_PROTECTION) == 0)
468         addf (str, _("%s\t\t\tEmail protection.\n"), prefix);
469       else if (strcmp (buffer, GNUTLS_KP_TIME_STAMPING) == 0)
470         addf (str, _("%s\t\t\tTime stamping.\n"), prefix);
471       else if (strcmp (buffer, GNUTLS_KP_OCSP_SIGNING) == 0)
472         addf (str, _("%s\t\t\tOCSP signing.\n"), prefix);
473       else if (strcmp (buffer, GNUTLS_KP_IPSEC_IKE) == 0)
474         addf (str, _("%s\t\t\tIpsec IKE.\n"), prefix);
475       else if (strcmp (buffer, GNUTLS_KP_ANY) == 0)
476         addf (str, _("%s\t\t\tAny purpose.\n"), prefix);
477       else
478         addf (str, "%s\t\t\t%s\n", prefix, buffer);
479
480       gnutls_free (buffer);
481     }
482 }
483
484 #endif
485
486 static void
487 print_basic (gnutls_buffer_st * str, const char *prefix, int type,
488              cert_type_t cert)
489 {
490   int pathlen;
491   int err;
492
493   if (type == TYPE_CRT)
494     err =
495       gnutls_x509_crt_get_basic_constraints (cert.crt, NULL, NULL, &pathlen);
496   else if (type == TYPE_CRQ)
497     err =
498       gnutls_x509_crq_get_basic_constraints (cert.crq, NULL, NULL, &pathlen);
499   else
500     return;
501
502   if (err < 0)
503     {
504       addf (str, "error: get_basic_constraints: %s\n", gnutls_strerror (err));
505       return;
506     }
507
508   if (err == 0)
509     addf (str, _("%s\t\t\tCertificate Authority (CA): FALSE\n"), prefix);
510   else
511     addf (str, _("%s\t\t\tCertificate Authority (CA): TRUE\n"), prefix);
512
513   if (pathlen >= 0)
514     addf (str, _("%s\t\t\tPath Length Constraint: %d\n"), prefix, pathlen);
515 }
516
517
518 static void
519 print_altname (gnutls_buffer_st * str, const char *prefix, int altname_type,
520                cert_type_t cert)
521 {
522   unsigned int altname_idx;
523   char str_ip[64];
524   char *p;
525
526   for (altname_idx = 0;; altname_idx++)
527     {
528       char *buffer = NULL;
529       size_t size = 0;
530       int err;
531
532       if (altname_type == TYPE_CRT_SAN)
533         err =
534           gnutls_x509_crt_get_subject_alt_name (cert.crt, altname_idx, buffer,
535                                                 &size, NULL);
536       else if (altname_type == TYPE_CRQ_SAN)
537         err =
538           gnutls_x509_crq_get_subject_alt_name (cert.crq, altname_idx, buffer,
539                                                 &size, NULL, NULL);
540       else if (altname_type == TYPE_CRT_IAN)
541         err =
542           gnutls_x509_crt_get_issuer_alt_name (cert.crt, altname_idx, buffer,
543                                                &size, NULL);
544       else
545         return;
546
547       if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
548         break;
549       if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
550         {
551           addf (str, "error: get_subject/issuer_alt_name: %s\n",
552                 gnutls_strerror (err));
553           return;
554         }
555
556       buffer = gnutls_malloc (size);
557       if (!buffer)
558         {
559           addf (str, "error: malloc: %s\n",
560                 gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
561           return;
562         }
563
564       if (altname_type == TYPE_CRT_SAN)
565         err =
566           gnutls_x509_crt_get_subject_alt_name (cert.crt, altname_idx, buffer,
567                                                 &size, NULL);
568       else if (altname_type == TYPE_CRQ_SAN)
569         err =
570           gnutls_x509_crq_get_subject_alt_name (cert.crq, altname_idx, buffer,
571                                                 &size, NULL, NULL);
572       else if (altname_type == TYPE_CRT_IAN)
573         err = gnutls_x509_crt_get_issuer_alt_name (cert.crt, altname_idx,
574                                                    buffer, &size, NULL);
575
576       if (err < 0)
577         {
578           gnutls_free (buffer);
579           addf (str, "error: get_subject/issuer_alt_name2: %s\n",
580                 gnutls_strerror (err));
581           return;
582         }
583
584       if ((err == GNUTLS_SAN_DNSNAME
585            || err == GNUTLS_SAN_RFC822NAME
586            || err == GNUTLS_SAN_URI) && strlen (buffer) != size)
587         {
588           adds (str, _("warning: altname contains an embedded NUL, "
589                        "replacing with '!'\n"));
590           while (strlen (buffer) < size)
591             buffer[strlen (buffer)] = '!';
592         }
593
594       switch (err)
595         {
596         case GNUTLS_SAN_DNSNAME:
597           addf (str, "%s\t\t\tDNSname: %.*s\n", prefix, (int) size, buffer);
598           break;
599
600         case GNUTLS_SAN_RFC822NAME:
601           addf (str, "%s\t\t\tRFC822name: %.*s\n", prefix, (int) size,
602                 buffer);
603           break;
604
605         case GNUTLS_SAN_URI:
606           addf (str, "%s\t\t\tURI: %.*s\n", prefix, (int) size, buffer);
607           break;
608
609         case GNUTLS_SAN_IPADDRESS:
610           p = ip_to_string (buffer, size, str_ip, sizeof (str_ip));
611           if (p == NULL)
612             p = ERROR_STR;
613           addf (str, "%s\t\t\tIPAddress: %s\n", prefix, p);
614           break;
615
616         case GNUTLS_SAN_DN:
617           addf (str, "%s\t\t\tdirectoryName: %.*s\n", prefix,
618                 (int) size, buffer);
619           break;
620
621         case GNUTLS_SAN_OTHERNAME:
622           {
623             char *oid = NULL;
624             size_t oidsize;
625
626             oidsize = 0;
627             if (altname_type == TYPE_CRT_SAN)
628               err = gnutls_x509_crt_get_subject_alt_othername_oid
629                 (cert.crt, altname_idx, oid, &oidsize);
630             else if (altname_type == TYPE_CRQ_SAN)
631               err = gnutls_x509_crq_get_subject_alt_othername_oid
632                 (cert.crq, altname_idx, oid, &oidsize);
633             else if (altname_type == TYPE_CRT_IAN)
634               err = gnutls_x509_crt_get_issuer_alt_othername_oid
635                 (cert.crt, altname_idx, oid, &oidsize);
636
637             if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
638               {
639                 gnutls_free (buffer);
640                 addf (str,
641                       "error: get_subject/issuer_alt_othername_oid: %s\n",
642                       gnutls_strerror (err));
643                 return;
644               }
645
646             oid = gnutls_malloc (oidsize);
647             if (!oid)
648               {
649                 gnutls_free (buffer);
650                 addf (str, "error: malloc: %s\n",
651                       gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
652                 return;
653               }
654
655             if (altname_type == TYPE_CRT_SAN)
656               err = gnutls_x509_crt_get_subject_alt_othername_oid
657                 (cert.crt, altname_idx, oid, &oidsize);
658             else if (altname_type == TYPE_CRQ_SAN)
659               err = gnutls_x509_crq_get_subject_alt_othername_oid
660                 (cert.crq, altname_idx, oid, &oidsize);
661             else if (altname_type == TYPE_CRT_IAN)
662               err = gnutls_x509_crt_get_issuer_alt_othername_oid
663                 (cert.crt, altname_idx, oid, &oidsize);
664
665             if (err < 0)
666               {
667                 gnutls_free (buffer);
668                 gnutls_free (oid);
669                 addf (str, "error: get_subject_alt_othername_oid2: %s\n",
670                       gnutls_strerror (err));
671                 return;
672               }
673
674             if (err == GNUTLS_SAN_OTHERNAME_XMPP)
675               {
676                 if (strlen (buffer) != size)
677                   {
678                     adds (str, _("warning: altname contains an embedded NUL, "
679                                  "replacing with '!'\n"));
680                     while (strlen (buffer) < size)
681                       buffer[strlen (buffer)] = '!';
682                   }
683
684                 addf (str, _("%s\t\t\tXMPP Address: %.*s\n"), prefix,
685                       (int) size, buffer);
686               }
687             else
688               {
689                 addf (str, _("%s\t\t\totherName OID: %.*s\n"), prefix,
690                       (int) oidsize, oid);
691                 addf (str, _("%s\t\t\totherName DER: "), prefix);
692                 hexprint (str, buffer, size);
693                 addf (str, _("\n%s\t\t\totherName ASCII: "), prefix);
694                 asciiprint (str, buffer, size);
695                 addf (str, "\n");
696               }
697             gnutls_free (oid);
698           }
699           break;
700
701         default:
702           addf (str, "error: unknown altname\n");
703           break;
704         }
705
706       gnutls_free (buffer);
707     }
708 }
709
710 static void
711 guiddump (gnutls_buffer_st * str, const char *data, size_t len,
712           const char *spc)
713 {
714   size_t j;
715
716   if (spc)
717     adds (str, spc);
718   addf (str, "{");
719   addf (str, "%.2X", (unsigned char) data[3]);
720   addf (str, "%.2X", (unsigned char) data[2]);
721   addf (str, "%.2X", (unsigned char) data[1]);
722   addf (str, "%.2X", (unsigned char) data[0]);
723   addf (str, "-");
724   addf (str, "%.2X", (unsigned char) data[5]);
725   addf (str, "%.2X", (unsigned char) data[4]);
726   addf (str, "-");
727   addf (str, "%.2X", (unsigned char) data[7]);
728   addf (str, "%.2X", (unsigned char) data[6]);
729   addf (str, "-");
730   addf (str, "%.2X", (unsigned char) data[8]);
731   addf (str, "%.2X", (unsigned char) data[9]);
732   addf (str, "-");
733   for (j = 10; j < 16; j++)
734     {
735       addf (str, "%.2X", (unsigned char) data[j]);
736     }
737   addf (str, "}\n");
738 }
739
740 static void
741 print_unique_ids (gnutls_buffer_st * str, const gnutls_x509_crt_t cert)
742 {
743   int result;
744   char buf[256];                /* if its longer, we won't bother to print it */
745   size_t buf_size = 256;
746
747   result = gnutls_x509_crt_get_issuer_unique_id (cert, buf, &buf_size);
748   if (result >= 0)
749     {
750       addf (str, ("\t\tIssuer Unique ID:\n"));
751       hexdump (str, buf, buf_size, "\t\t\t");
752       if (buf_size == 16)
753         {                       /* this could be a GUID */
754           guiddump (str, buf, buf_size, "\t\t\t");
755         }
756     }
757
758   buf_size = 256;
759   result = gnutls_x509_crt_get_subject_unique_id (cert, buf, &buf_size);
760   if (result >= 0)
761     {
762       addf (str, ("\t\tSubject Unique ID:\n"));
763       hexdump (str, buf, buf_size, "\t\t\t");
764       if (buf_size == 16)
765         {                       /* this could be a GUID */
766           guiddump (str, buf, buf_size, "\t\t\t");
767         }
768     }
769 }
770
771 static void
772 print_extensions (gnutls_buffer_st * str, const char *prefix, int type,
773                   cert_type_t cert)
774 {
775   int i, err;
776   int san_idx = 0;
777   int ian_idx = 0;
778   int proxy_idx = 0;
779   int basic_idx = 0;
780   int keyusage_idx = 0;
781   int keypurpose_idx = 0;
782   int ski_idx = 0;
783   int aki_idx = 0;
784   int crldist_idx = 0;
785
786   for (i = 0;; i++)
787     {
788       char oid[MAX_OID_SIZE] = "";
789       size_t sizeof_oid = sizeof (oid);
790       int critical;
791
792       if (type == TYPE_CRT)
793         err = gnutls_x509_crt_get_extension_info (cert.crt, i,
794                                                   oid, &sizeof_oid,
795                                                   &critical);
796
797       else if (type == TYPE_CRQ)
798         err = gnutls_x509_crq_get_extension_info (cert.crq, i,
799                                                   oid, &sizeof_oid,
800                                                   &critical);
801       else
802         {
803           gnutls_assert ();
804           return;
805         }
806
807       if (err < 0)
808         {
809           if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
810             break;
811           addf (str, "error: get_extension_info: %s\n",
812                 gnutls_strerror (err));
813           continue;
814         }
815
816       if (i == 0)
817         addf (str, _("%s\tExtensions:\n"), prefix);
818
819       if (strcmp (oid, "2.5.29.19") == 0)
820         {
821           if (basic_idx)
822             {
823               addf (str, "error: more than one basic constraint\n");
824               continue;
825             }
826
827           addf (str, _("%s\t\tBasic Constraints (%s):\n"), prefix,
828                 critical ? _("critical") : _("not critical"));
829
830           print_basic (str, prefix, type, cert);
831
832           basic_idx++;
833         }
834       else if (strcmp (oid, "2.5.29.14") == 0)
835         {
836           if (ski_idx)
837             {
838               addf (str, "error: more than one SKI extension\n");
839               continue;
840             }
841
842           addf (str, _("%s\t\tSubject Key Identifier (%s):\n"), prefix,
843                 critical ? _("critical") : _("not critical"));
844
845           if (type == TYPE_CRT)
846             print_ski (str, cert.crt);
847
848           ski_idx++;
849         }
850       else if (strcmp (oid, "2.5.29.35") == 0)
851         {
852
853           if (aki_idx)
854             {
855               addf (str, "error: more than one AKI extension\n");
856               continue;
857             }
858
859           addf (str, _("%s\t\tAuthority Key Identifier (%s):\n"), prefix,
860                 critical ? _("critical") : _("not critical"));
861
862           if (type == TYPE_CRT)
863             print_aki (str, TYPE_CRT, cert);
864
865           aki_idx++;
866         }
867       else if (strcmp (oid, "2.5.29.15") == 0)
868         {
869           if (keyusage_idx)
870             {
871               addf (str, "error: more than one key usage extension\n");
872               continue;
873             }
874
875           addf (str, _("%s\t\tKey Usage (%s):\n"), prefix,
876                 critical ? _("critical") : _("not critical"));
877
878           print_key_usage (str, prefix, type, cert);
879
880           keyusage_idx++;
881         }
882       else if (strcmp (oid, "2.5.29.37") == 0)
883         {
884           if (keypurpose_idx)
885             {
886               addf (str, "error: more than one key purpose extension\n");
887               continue;
888             }
889
890           addf (str, _("%s\t\tKey Purpose (%s):\n"), prefix,
891                 critical ? _("critical") : _("not critical"));
892
893 #ifdef ENABLE_PKI
894           print_key_purpose (str, prefix, type, cert);
895 #endif
896
897           keypurpose_idx++;
898         }
899       else if (strcmp (oid, "2.5.29.17") == 0)
900         {
901           if (san_idx)
902             {
903               addf (str, "error: more than one SKI extension\n");
904               continue;
905             }
906
907           addf (str, _("%s\t\tSubject Alternative Name (%s):\n"), prefix,
908                 critical ? _("critical") : _("not critical"));
909
910           print_altname (str, prefix, type, cert);
911
912           san_idx++;
913         }
914       else if (strcmp (oid, "2.5.29.18") == 0)
915         {
916           if (ian_idx)
917             {
918               addf (str, "error: more than one Issuer AltName extension\n");
919               continue;
920             }
921
922           addf (str, _("%s\t\tIssuer Alternative Name (%s):\n"), prefix,
923                 critical ? _("critical") : _("not critical"));
924
925           print_altname (str, prefix, TYPE_CRT_IAN, cert);
926
927           ian_idx++;
928         }
929       else if (strcmp (oid, "2.5.29.31") == 0)
930         {
931           if (crldist_idx)
932             {
933               addf (str, "error: more than one CRL distribution point\n");
934               continue;
935             }
936
937           addf (str, _("%s\t\tCRL Distribution points (%s):\n"), prefix,
938                 critical ? _("critical") : _("not critical"));
939
940 #ifdef ENABLE_PKI
941           if (type == TYPE_CRT)
942             print_crldist (str, cert.crt);
943 #endif
944
945           crldist_idx++;
946         }
947       else if (strcmp (oid, "1.3.6.1.5.5.7.1.14") == 0)
948         {
949           if (proxy_idx)
950             {
951               addf (str, "error: more than one proxy extension\n");
952               continue;
953             }
954
955           addf (str, _("%s\t\tProxy Certificate Information (%s):\n"), prefix,
956                 critical ? _("critical") : _("not critical"));
957
958           if (type == TYPE_CRT)
959             print_proxy (str, cert.crt);
960
961           proxy_idx++;
962         }
963       else
964         {
965           char *buffer;
966           size_t extlen = 0;
967
968           addf (str, _("%s\t\tUnknown extension %s (%s):\n"), prefix, oid,
969                 critical ? _("critical") : _("not critical"));
970
971           if (type == TYPE_CRT)
972             err =
973               gnutls_x509_crt_get_extension_data (cert.crt, i, NULL, &extlen);
974           else if (type == TYPE_CRQ)
975             err =
976               gnutls_x509_crq_get_extension_data (cert.crq, i, NULL, &extlen);
977           else
978             {
979               gnutls_assert ();
980               return;
981             }
982
983           if (err < 0)
984             {
985               addf (str, "error: get_extension_data: %s\n",
986                     gnutls_strerror (err));
987               continue;
988             }
989
990           buffer = gnutls_malloc (extlen);
991           if (!buffer)
992             {
993               addf (str, "error: malloc: %s\n",
994                     gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
995               continue;
996             }
997
998           if (type == TYPE_CRT)
999             err =
1000               gnutls_x509_crt_get_extension_data (cert.crt, i, buffer,
1001                                                   &extlen);
1002           else if (type == TYPE_CRQ)
1003             err =
1004               gnutls_x509_crq_get_extension_data (cert.crq, i, buffer,
1005                                                   &extlen);
1006
1007           if (err < 0)
1008             {
1009               gnutls_free (buffer);
1010               addf (str, "error: get_extension_data2: %s\n",
1011                     gnutls_strerror (err));
1012               continue;
1013             }
1014
1015           addf (str, _("%s\t\t\tASCII: "), prefix);
1016           asciiprint (str, buffer, extlen);
1017           addf (str, "\n");
1018
1019           addf (str, _("%s\t\t\tHexdump: "), prefix);
1020           hexprint (str, buffer, extlen);
1021           adds (str, "\n");
1022
1023           gnutls_free (buffer);
1024         }
1025     }
1026 }
1027
1028 static void
1029 print_cert (gnutls_buffer_st * str, gnutls_x509_crt_t cert, int notsigned)
1030 {
1031   /* Version. */
1032   {
1033     int version = gnutls_x509_crt_get_version (cert);
1034     if (version < 0)
1035       addf (str, "error: get_version: %s\n", gnutls_strerror (version));
1036     else
1037       addf (str, _("\tVersion: %d\n"), version);
1038   }
1039
1040   /* Serial. */
1041   {
1042     char serial[128];
1043     size_t serial_size = sizeof (serial);
1044     int err;
1045
1046     err = gnutls_x509_crt_get_serial (cert, serial, &serial_size);
1047     if (err < 0)
1048       addf (str, "error: get_serial: %s\n", gnutls_strerror (err));
1049     else
1050       {
1051         adds (str, _("\tSerial Number (hex): "));
1052         hexprint (str, serial, serial_size);
1053         adds (str, "\n");
1054       }
1055   }
1056
1057   /* Issuer. */
1058   if (!notsigned)
1059     {
1060       char *dn;
1061       size_t dn_size = 0;
1062       int err;
1063
1064       err = gnutls_x509_crt_get_issuer_dn (cert, NULL, &dn_size);
1065       if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
1066         addf (str, "error: get_issuer_dn: %s\n", gnutls_strerror (err));
1067       else
1068         {
1069           dn = gnutls_malloc (dn_size);
1070           if (!dn)
1071             addf (str, "error: malloc (%d): %s\n", (int) dn_size,
1072                   gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
1073           else
1074             {
1075               err = gnutls_x509_crt_get_issuer_dn (cert, dn, &dn_size);
1076               if (err < 0)
1077                 addf (str, "error: get_issuer_dn: %s\n",
1078                       gnutls_strerror (err));
1079               else
1080                 addf (str, _("\tIssuer: %s\n"), dn);
1081               gnutls_free (dn);
1082             }
1083         }
1084     }
1085
1086   /* Validity. */
1087   {
1088     time_t tim;
1089
1090     adds (str, _("\tValidity:\n"));
1091
1092     tim = gnutls_x509_crt_get_activation_time (cert);
1093     {
1094       char s[42];
1095       size_t max = sizeof (s);
1096       struct tm t;
1097
1098       if (gmtime_r (&tim, &t) == NULL)
1099         addf (str, "error: gmtime_r (%ld)\n", (unsigned long) tim);
1100       else if (strftime (s, max, "%a %b %d %H:%M:%S UTC %Y", &t) == 0)
1101         addf (str, "error: strftime (%ld)\n", (unsigned long) tim);
1102       else
1103         addf (str, _("\t\tNot Before: %s\n"), s);
1104     }
1105
1106     tim = gnutls_x509_crt_get_expiration_time (cert);
1107     {
1108       char s[42];
1109       size_t max = sizeof (s);
1110       struct tm t;
1111
1112       if (gmtime_r (&tim, &t) == NULL)
1113         addf (str, "error: gmtime_r (%ld)\n", (unsigned long) tim);
1114       else if (strftime (s, max, "%a %b %d %H:%M:%S UTC %Y", &t) == 0)
1115         addf (str, "error: strftime (%ld)\n", (unsigned long) tim);
1116       else
1117         addf (str, _("\t\tNot After: %s\n"), s);
1118     }
1119   }
1120
1121   /* Subject. */
1122   {
1123     char *dn;
1124     size_t dn_size = 0;
1125     int err;
1126
1127     err = gnutls_x509_crt_get_dn (cert, NULL, &dn_size);
1128     if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
1129       addf (str, "error: get_dn: %s\n", gnutls_strerror (err));
1130     else
1131       {
1132         dn = gnutls_malloc (dn_size);
1133         if (!dn)
1134           addf (str, "error: malloc (%d): %s\n", (int) dn_size,
1135                 gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
1136         else
1137           {
1138             err = gnutls_x509_crt_get_dn (cert, dn, &dn_size);
1139             if (err < 0)
1140               addf (str, "error: get_dn: %s\n", gnutls_strerror (err));
1141             else
1142               addf (str, _("\tSubject: %s\n"), dn);
1143             gnutls_free (dn);
1144           }
1145       }
1146   }
1147
1148   /* SubjectPublicKeyInfo. */
1149   {
1150     int err;
1151     unsigned int bits;
1152
1153     err = gnutls_x509_crt_get_pk_algorithm (cert, &bits);
1154     if (err < 0)
1155       addf (str, "error: get_pk_algorithm: %s\n", gnutls_strerror (err));
1156     else
1157       {
1158         const char *name = gnutls_pk_algorithm_get_name (err);
1159         if (name == NULL)
1160           name = _("unknown");
1161
1162         addf (str, _("\tSubject Public Key Algorithm: %s\n"), name);
1163         addf (str, _("\tCertificate Security Level: %s\n"),
1164               gnutls_sec_param_get_name (gnutls_pk_bits_to_sec_param
1165                                          (err, bits)));
1166
1167 #ifdef ENABLE_PKI
1168         switch (err)
1169           {
1170           case GNUTLS_PK_RSA:
1171             {
1172               gnutls_datum_t m, e;
1173
1174               err = gnutls_x509_crt_get_pk_rsa_raw (cert, &m, &e);
1175               if (err < 0)
1176                 addf (str, "error: get_pk_rsa_raw: %s\n",
1177                       gnutls_strerror (err));
1178               else
1179                 {
1180                   addf (str, _("\t\tModulus (bits %d):\n"), bits);
1181                   hexdump (str, m.data, m.size, "\t\t\t");
1182                   addf (str, _("\t\tExponent (bits %d):\n"), e.size * 8);
1183                   hexdump (str, e.data, e.size, "\t\t\t");
1184
1185                   gnutls_free (m.data);
1186                   gnutls_free (e.data);
1187                 }
1188
1189             }
1190             break;
1191
1192           case GNUTLS_PK_DSA:
1193             {
1194               gnutls_datum_t p, q, g, y;
1195
1196               err = gnutls_x509_crt_get_pk_dsa_raw (cert, &p, &q, &g, &y);
1197               if (err < 0)
1198                 addf (str, "error: get_pk_dsa_raw: %s\n",
1199                       gnutls_strerror (err));
1200               else
1201                 {
1202                   addf (str, _("\t\tPublic key (bits %d):\n"), bits);
1203                   hexdump (str, y.data, y.size, "\t\t\t");
1204                   adds (str, _("\t\tP:\n"));
1205                   hexdump (str, p.data, p.size, "\t\t\t");
1206                   adds (str, _("\t\tQ:\n"));
1207                   hexdump (str, q.data, q.size, "\t\t\t");
1208                   adds (str, _("\t\tG:\n"));
1209                   hexdump (str, g.data, g.size, "\t\t\t");
1210
1211                   gnutls_free (p.data);
1212                   gnutls_free (q.data);
1213                   gnutls_free (g.data);
1214                   gnutls_free (y.data);
1215
1216                 }
1217             }
1218             break;
1219
1220           default:
1221             break;
1222           }
1223 #endif
1224       }
1225   }
1226
1227   print_unique_ids (str, cert);
1228
1229   /* Extensions. */
1230   if (gnutls_x509_crt_get_version (cert) >= 3)
1231     {
1232       cert_type_t ccert;
1233
1234       ccert.crt = cert;
1235       print_extensions (str, "", TYPE_CRT, ccert);
1236     }
1237
1238   /* Signature. */
1239   if (!notsigned)
1240     {
1241       int err;
1242       size_t size = 0;
1243       char *buffer = NULL;
1244
1245       err = gnutls_x509_crt_get_signature_algorithm (cert);
1246       if (err < 0)
1247         addf (str, "error: get_signature_algorithm: %s\n",
1248               gnutls_strerror (err));
1249       else
1250         {
1251           const char *name = gnutls_sign_algorithm_get_name (err);
1252           if (name == NULL)
1253             name = _("unknown");
1254           addf (str, _("\tSignature Algorithm: %s\n"), name);
1255         }
1256       if (err == GNUTLS_SIGN_RSA_MD5 || err == GNUTLS_SIGN_RSA_MD2)
1257         {
1258           adds (str, _("warning: signed using a broken signature "
1259                        "algorithm that can be forged.\n"));
1260         }
1261
1262       err = gnutls_x509_crt_get_signature (cert, buffer, &size);
1263       if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
1264         {
1265           addf (str, "error: get_signature: %s\n", gnutls_strerror (err));
1266           return;
1267         }
1268
1269       buffer = gnutls_malloc (size);
1270       if (!buffer)
1271         {
1272           addf (str, "error: malloc: %s\n",
1273                 gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
1274           return;
1275         }
1276
1277       err = gnutls_x509_crt_get_signature (cert, buffer, &size);
1278       if (err < 0)
1279         {
1280           gnutls_free (buffer);
1281           addf (str, "error: get_signature2: %s\n", gnutls_strerror (err));
1282           return;
1283         }
1284
1285       adds (str, _("\tSignature:\n"));
1286       hexdump (str, buffer, size, "\t\t");
1287
1288       gnutls_free (buffer);
1289     }
1290 }
1291
1292 static void
1293 print_fingerprint (gnutls_buffer_st * str, gnutls_x509_crt_t cert,
1294                    gnutls_digest_algorithm_t algo)
1295 {
1296   int err;
1297   char buffer[MAX_HASH_SIZE];
1298   size_t size = sizeof (buffer);
1299
1300   err = gnutls_x509_crt_get_fingerprint (cert, algo, buffer, &size);
1301   if (err < 0)
1302     {
1303       addf (str, "error: get_fingerprint: %s\n", gnutls_strerror (err));
1304       return;
1305     }
1306
1307   if (algo == GNUTLS_DIG_MD5)
1308     adds (str, _("\tMD5 fingerprint:\n\t\t"));
1309   else
1310     adds (str, _("\tSHA-1 fingerprint:\n\t\t"));
1311   hexprint (str, buffer, size);
1312   adds (str, "\n");
1313 }
1314
1315 static void
1316 print_keyid (gnutls_buffer_st * str, gnutls_x509_crt_t cert)
1317 {
1318   int err;
1319   char buffer[20];
1320   size_t size = 20;
1321
1322   err = gnutls_x509_crt_get_key_id (cert, 0, buffer, &size);
1323   if (err < 0)
1324     {
1325       addf (str, "error: get_key_id: %s\n", gnutls_strerror (err));
1326       return;
1327     }
1328
1329   adds (str, _("\tPublic Key Id:\n\t\t"));
1330   hexprint (str, buffer, size);
1331   adds (str, "\n");
1332 }
1333
1334 static void
1335 print_other (gnutls_buffer_st * str, gnutls_x509_crt_t cert, int notsigned)
1336 {
1337   if (!notsigned)
1338     {
1339       print_fingerprint (str, cert, GNUTLS_DIG_MD5);
1340       print_fingerprint (str, cert, GNUTLS_DIG_SHA1);
1341     }
1342   print_keyid (str, cert);
1343 }
1344
1345 static void
1346 print_oneline (gnutls_buffer_st * str, gnutls_x509_crt_t cert)
1347 {
1348   /* Subject. */
1349   {
1350     char *dn;
1351     size_t dn_size = 0;
1352     int err;
1353
1354     err = gnutls_x509_crt_get_dn (cert, NULL, &dn_size);
1355     if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
1356       addf (str, "unknown subject (%s), ", gnutls_strerror (err));
1357     else
1358       {
1359         dn = gnutls_malloc (dn_size);
1360         if (!dn)
1361           addf (str, "unknown subject (%s), ",
1362                 gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
1363         else
1364           {
1365             err = gnutls_x509_crt_get_dn (cert, dn, &dn_size);
1366             if (err < 0)
1367               addf (str, "unknown subject (%s), ", gnutls_strerror (err));
1368             else
1369               addf (str, "subject `%s', ", dn);
1370             gnutls_free (dn);
1371           }
1372       }
1373   }
1374
1375   /* Issuer. */
1376   {
1377     char *dn;
1378     size_t dn_size = 0;
1379     int err;
1380
1381     err = gnutls_x509_crt_get_issuer_dn (cert, NULL, &dn_size);
1382     if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
1383       addf (str, "unknown issuer (%s), ", gnutls_strerror (err));
1384     else
1385       {
1386         dn = gnutls_malloc (dn_size);
1387         if (!dn)
1388           addf (str, "unknown issuer (%s), ",
1389                 gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
1390         else
1391           {
1392             err = gnutls_x509_crt_get_issuer_dn (cert, dn, &dn_size);
1393             if (err < 0)
1394               addf (str, "unknown issuer (%s), ", gnutls_strerror (err));
1395             else
1396               addf (str, "issuer `%s', ", dn);
1397             gnutls_free (dn);
1398           }
1399       }
1400   }
1401
1402   /* Key algorithm and size. */
1403   {
1404     int bits;
1405     const char *name = gnutls_pk_algorithm_get_name
1406       (gnutls_x509_crt_get_pk_algorithm (cert, &bits));
1407     if (name == NULL)
1408       name = "Unknown";
1409     addf (str, "%s key %d bits, ", name, bits);
1410   }
1411
1412   /* Signature Algorithm. */
1413   {
1414     int err;
1415
1416     err = gnutls_x509_crt_get_signature_algorithm (cert);
1417     if (err < 0)
1418       addf (str, "unknown signature algorithm (%s), ", gnutls_strerror (err));
1419     else
1420       {
1421         const char *name = gnutls_sign_algorithm_get_name (err);
1422         if (name == NULL)
1423           name = _("unknown");
1424         if (err == GNUTLS_SIGN_RSA_MD5 || err == GNUTLS_SIGN_RSA_MD2)
1425           addf (str, _("signed using %s (broken!), "), name);
1426         else
1427           addf (str, _("signed using %s, "), name);
1428       }
1429   }
1430
1431   /* Validity. */
1432   {
1433     time_t tim;
1434
1435     tim = gnutls_x509_crt_get_activation_time (cert);
1436     {
1437       char s[42];
1438       size_t max = sizeof (s);
1439       struct tm t;
1440
1441       if (gmtime_r (&tim, &t) == NULL)
1442         addf (str, "unknown activation (%ld), ", (unsigned long) tim);
1443       else if (strftime (s, max, "%Y-%m-%d %H:%M:%S UTC", &t) == 0)
1444         addf (str, "failed activation (%ld), ", (unsigned long) tim);
1445       else
1446         addf (str, "activated `%s', ", s);
1447     }
1448
1449     tim = gnutls_x509_crt_get_expiration_time (cert);
1450     {
1451       char s[42];
1452       size_t max = sizeof (s);
1453       struct tm t;
1454
1455       if (gmtime_r (&tim, &t) == NULL)
1456         addf (str, "unknown expiry (%ld), ", (unsigned long) tim);
1457       else if (strftime (s, max, "%Y-%m-%d %H:%M:%S UTC", &t) == 0)
1458         addf (str, "failed expiry (%ld), ", (unsigned long) tim);
1459       else
1460         addf (str, "expires `%s', ", s);
1461     }
1462   }
1463
1464   {
1465     int pathlen;
1466     char *policyLanguage;
1467     int err;
1468
1469     err = gnutls_x509_crt_get_proxy (cert, NULL,
1470                                      &pathlen, &policyLanguage, NULL, NULL);
1471     if (err == 0)
1472       {
1473         addf (str, "proxy certificate (policy=");
1474         if (strcmp (policyLanguage, "1.3.6.1.5.5.7.21.1") == 0)
1475           addf (str, "id-ppl-inheritALL");
1476         else if (strcmp (policyLanguage, "1.3.6.1.5.5.7.21.2") == 0)
1477           addf (str, "id-ppl-independent");
1478         else
1479           addf (str, "%s", policyLanguage);
1480         if (pathlen >= 0)
1481           addf (str, ", pathlen=%d), ", pathlen);
1482         else
1483           addf (str, "), ");
1484         gnutls_free (policyLanguage);
1485       }
1486   }
1487
1488   {
1489     char buffer[20];
1490     size_t size = sizeof (buffer);
1491     int err;
1492
1493     err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1,
1494                                            buffer, &size);
1495     if (err < 0)
1496       {
1497         addf (str, "unknown fingerprint (%s)", gnutls_strerror (err));
1498       }
1499     else
1500       {
1501         addf (str, "SHA-1 fingerprint `");
1502         hexprint (str, buffer, size);
1503         adds (str, "'");
1504       }
1505   }
1506
1507 }
1508
1509 /**
1510  * gnutls_x509_crt_print:
1511  * @cert: The structure to be printed
1512  * @format: Indicate the format to use
1513  * @out: Newly allocated datum with zero terminated string.
1514  *
1515  * This function will pretty print a X.509 certificate, suitable for
1516  * display to a human.
1517  *
1518  * If the format is %GNUTLS_CRT_PRINT_FULL then all fields of the
1519  * certificate will be output, on multiple lines.  The
1520  * %GNUTLS_CRT_PRINT_ONELINE format will generate one line with some
1521  * selected fields, which is useful for logging purposes.
1522  *
1523  * The output @out needs to be deallocate using gnutls_free().
1524  *
1525  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1526  *   negative error value.
1527  **/
1528 int
1529 gnutls_x509_crt_print (gnutls_x509_crt_t cert,
1530                        gnutls_certificate_print_formats_t format,
1531                        gnutls_datum_t * out)
1532 {
1533   gnutls_buffer_st str;
1534
1535   if (format == GNUTLS_CRT_PRINT_FULL
1536       || format == GNUTLS_CRT_PRINT_UNSIGNED_FULL)
1537     {
1538       _gnutls_buffer_init (&str);
1539
1540       _gnutls_buffer_append_str (&str, _("X.509 Certificate Information:\n"));
1541
1542       print_cert (&str, cert, format == GNUTLS_CRT_PRINT_UNSIGNED_FULL);
1543
1544       _gnutls_buffer_append_str (&str, _("Other Information:\n"));
1545
1546       print_other (&str, cert, format == GNUTLS_CRT_PRINT_UNSIGNED_FULL);
1547
1548       _gnutls_buffer_append_data (&str, "\0", 1);
1549       out->data = str.data;
1550       out->size = strlen (str.data);
1551     }
1552   else if (format == GNUTLS_CRT_PRINT_ONELINE)
1553     {
1554       _gnutls_buffer_init (&str);
1555
1556       print_oneline (&str, cert);
1557
1558       _gnutls_buffer_append_data (&str, "\0", 1);
1559       out->data = str.data;
1560       out->size = strlen (str.data);
1561     }
1562   else
1563     {
1564       gnutls_assert ();
1565       return GNUTLS_E_INVALID_REQUEST;
1566     }
1567
1568   return 0;
1569 }
1570
1571 #ifdef ENABLE_PKI
1572
1573 static void
1574 print_crl (gnutls_buffer_st * str, gnutls_x509_crl_t crl, int notsigned)
1575 {
1576   /* Version. */
1577   {
1578     int version = gnutls_x509_crl_get_version (crl);
1579     if (version == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1580       adds (str, _("\tVersion: 1 (default)\n"));
1581     else if (version < 0)
1582       addf (str, "error: get_version: %s\n", gnutls_strerror (version));
1583     else
1584       addf (str, _("\tVersion: %d\n"), version);
1585   }
1586
1587   /* Issuer. */
1588   if (!notsigned)
1589     {
1590       char *dn;
1591       size_t dn_size = 0;
1592       int err;
1593
1594       err = gnutls_x509_crl_get_issuer_dn (crl, NULL, &dn_size);
1595       if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
1596         addf (str, "error: get_issuer_dn: %s\n", gnutls_strerror (err));
1597       else
1598         {
1599           dn = gnutls_malloc (dn_size);
1600           if (!dn)
1601             addf (str, "error: malloc (%d): %s\n", (int) dn_size,
1602                   gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
1603           else
1604             {
1605               err = gnutls_x509_crl_get_issuer_dn (crl, dn, &dn_size);
1606               if (err < 0)
1607                 addf (str, "error: get_issuer_dn: %s\n",
1608                       gnutls_strerror (err));
1609               else
1610                 addf (str, _("\tIssuer: %s\n"), dn);
1611             }
1612           gnutls_free (dn);
1613         }
1614     }
1615
1616   /* Validity. */
1617   {
1618     time_t tim;
1619
1620     adds (str, _("\tUpdate dates:\n"));
1621
1622     tim = gnutls_x509_crl_get_this_update (crl);
1623     {
1624       char s[42];
1625       size_t max = sizeof (s);
1626       struct tm t;
1627
1628       if (gmtime_r (&tim, &t) == NULL)
1629         addf (str, "error: gmtime_r (%ld)\n", (unsigned long) tim);
1630       else if (strftime (s, max, "%a %b %d %H:%M:%S UTC %Y", &t) == 0)
1631         addf (str, "error: strftime (%ld)\n", (unsigned long) tim);
1632       else
1633         addf (str, _("\t\tIssued: %s\n"), s);
1634     }
1635
1636     tim = gnutls_x509_crl_get_next_update (crl);
1637     {
1638       char s[42];
1639       size_t max = sizeof (s);
1640       struct tm t;
1641
1642       if (tim == -1)
1643         addf (str, "\t\tNo next update time.\n");
1644       else if (gmtime_r (&tim, &t) == NULL)
1645         addf (str, "error: gmtime_r (%ld)\n", (unsigned long) tim);
1646       else if (strftime (s, max, "%a %b %d %H:%M:%S UTC %Y", &t) == 0)
1647         addf (str, "error: strftime (%ld)\n", (unsigned long) tim);
1648       else
1649         addf (str, _("\t\tNext at: %s\n"), s);
1650     }
1651   }
1652
1653   /* Extensions. */
1654   if (gnutls_x509_crl_get_version (crl) >= 2)
1655     {
1656       size_t i;
1657       int err = 0;
1658       int aki_idx = 0;
1659       int crl_nr = 0;
1660
1661       for (i = 0;; i++)
1662         {
1663           char oid[MAX_OID_SIZE] = "";
1664           size_t sizeof_oid = sizeof (oid);
1665           int critical;
1666
1667           err = gnutls_x509_crl_get_extension_info (crl, i,
1668                                                     oid, &sizeof_oid,
1669                                                     &critical);
1670           if (err < 0)
1671             {
1672               if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1673                 break;
1674               addf (str, "error: get_extension_info: %s\n",
1675                     gnutls_strerror (err));
1676               continue;
1677             }
1678
1679           if (i == 0)
1680             adds (str, _("\tExtensions:\n"));
1681
1682           if (strcmp (oid, "2.5.29.20") == 0)
1683             {
1684               char nr[128];
1685               size_t nr_size = sizeof (nr);
1686
1687               if (crl_nr)
1688                 {
1689                   addf (str, "error: more than one CRL number\n");
1690                   continue;
1691                 }
1692
1693               err = gnutls_x509_crl_get_number (crl, nr, &nr_size, &critical);
1694
1695               addf (str, _("\t\tCRL Number (%s): "),
1696                     critical ? _("critical") : _("not critical"));
1697
1698               if (err < 0)
1699                 addf (str, "error: get_number: %s\n", gnutls_strerror (err));
1700               else
1701                 {
1702                   hexprint (str, nr, nr_size);
1703                   addf (str, "\n");
1704                 }
1705
1706               crl_nr++;
1707             }
1708           else if (strcmp (oid, "2.5.29.35") == 0)
1709             {
1710               cert_type_t ccert;
1711
1712               if (aki_idx)
1713                 {
1714                   addf (str, "error: more than one AKI extension\n");
1715                   continue;
1716                 }
1717
1718               addf (str, _("\t\tAuthority Key Identifier (%s):\n"),
1719                     critical ? _("critical") : _("not critical"));
1720
1721               ccert.crl = crl;
1722               print_aki (str, TYPE_CRL, ccert);
1723
1724               aki_idx++;
1725             }
1726           else
1727             {
1728               char *buffer;
1729               size_t extlen = 0;
1730
1731               addf (str, _("\t\tUnknown extension %s (%s):\n"), oid,
1732                     critical ? _("critical") : _("not critical"));
1733
1734               err = gnutls_x509_crl_get_extension_data (crl, i,
1735                                                         NULL, &extlen);
1736               if (err < 0)
1737                 {
1738                   addf (str, "error: get_extension_data: %s\n",
1739                         gnutls_strerror (err));
1740                   continue;
1741                 }
1742
1743               buffer = gnutls_malloc (extlen);
1744               if (!buffer)
1745                 {
1746                   addf (str, "error: malloc: %s\n",
1747                         gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
1748                   continue;
1749                 }
1750
1751               err = gnutls_x509_crl_get_extension_data (crl, i,
1752                                                         buffer, &extlen);
1753               if (err < 0)
1754                 {
1755                   gnutls_free (buffer);
1756                   addf (str, "error: get_extension_data2: %s\n",
1757                         gnutls_strerror (err));
1758                   continue;
1759                 }
1760
1761               adds (str, _("\t\t\tASCII: "));
1762               asciiprint (str, buffer, extlen);
1763               adds (str, "\n");
1764
1765               adds (str, _("\t\t\tHexdump: "));
1766               hexprint (str, buffer, extlen);
1767               adds (str, "\n");
1768
1769               gnutls_free (buffer);
1770             }
1771         }
1772     }
1773
1774
1775   /* Revoked certificates. */
1776   {
1777     int num = gnutls_x509_crl_get_crt_count (crl);
1778     int j;
1779
1780     if (num)
1781       addf (str, _("\tRevoked certificates (%d):\n"), num);
1782     else
1783       adds (str, _("\tNo revoked certificates.\n"));
1784
1785     for (j = 0; j < num; j++)
1786       {
1787         char serial[128];
1788         size_t serial_size = sizeof (serial);
1789         int err;
1790         time_t tim;
1791
1792         err = gnutls_x509_crl_get_crt_serial (crl, j, serial,
1793                                               &serial_size, &tim);
1794         if (err < 0)
1795           addf (str, "error: get_crt_serial: %s\n", gnutls_strerror (err));
1796         else
1797           {
1798             char s[42];
1799             size_t max = sizeof (s);
1800             struct tm t;
1801
1802             adds (str, _("\t\tSerial Number (hex): "));
1803             hexprint (str, serial, serial_size);
1804             adds (str, "\n");
1805
1806             if (gmtime_r (&tim, &t) == NULL)
1807               addf (str, "error: gmtime_r (%ld)\n", (unsigned long) tim);
1808             else if (strftime (s, max, "%a %b %d %H:%M:%S UTC %Y", &t) == 0)
1809               addf (str, "error: strftime (%ld)\n", (unsigned long) tim);
1810             else
1811               addf (str, _("\t\tRevoked at: %s\n"), s);
1812           }
1813       }
1814   }
1815
1816   /* Signature. */
1817   if (!notsigned)
1818     {
1819       int err;
1820       size_t size = 0;
1821       char *buffer = NULL;
1822
1823       err = gnutls_x509_crl_get_signature_algorithm (crl);
1824       if (err < 0)
1825         addf (str, "error: get_signature_algorithm: %s\n",
1826               gnutls_strerror (err));
1827       else
1828         {
1829           const char *name = gnutls_sign_algorithm_get_name (err);
1830           if (name == NULL)
1831             name = _("unknown");
1832           addf (str, _("\tSignature Algorithm: %s\n"), name);
1833         }
1834       if (err == GNUTLS_SIGN_RSA_MD5 || err == GNUTLS_SIGN_RSA_MD2)
1835         {
1836           adds (str, _("warning: signed using a broken signature "
1837                        "algorithm that can be forged.\n"));
1838         }
1839
1840       err = gnutls_x509_crl_get_signature (crl, buffer, &size);
1841       if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
1842         {
1843           addf (str, "error: get_signature: %s\n", gnutls_strerror (err));
1844           return;
1845         }
1846
1847       buffer = gnutls_malloc (size);
1848       if (!buffer)
1849         {
1850           addf (str, "error: malloc: %s\n",
1851                 gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
1852           return;
1853         }
1854
1855       err = gnutls_x509_crl_get_signature (crl, buffer, &size);
1856       if (err < 0)
1857         {
1858           gnutls_free (buffer);
1859           addf (str, "error: get_signature2: %s\n", gnutls_strerror (err));
1860           return;
1861         }
1862
1863       adds (str, _("\tSignature:\n"));
1864       hexdump (str, buffer, size, "\t\t");
1865
1866       gnutls_free (buffer);
1867     }
1868 }
1869
1870 /**
1871  * gnutls_x509_crl_print:
1872  * @crl: The structure to be printed
1873  * @format: Indicate the format to use
1874  * @out: Newly allocated datum with zero terminated string.
1875  *
1876  * This function will pretty print a X.509 certificate revocation
1877  * list, suitable for display to a human.
1878  *
1879  * The output @out needs to be deallocate using gnutls_free().
1880  *
1881  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1882  *   negative error value.
1883  **/
1884 int
1885 gnutls_x509_crl_print (gnutls_x509_crl_t crl,
1886                        gnutls_certificate_print_formats_t format,
1887                        gnutls_datum_t * out)
1888 {
1889   gnutls_buffer_st str;
1890
1891   _gnutls_buffer_init (&str);
1892
1893   _gnutls_buffer_append_str
1894     (&str, _("X.509 Certificate Revocation List Information:\n"));
1895
1896   print_crl (&str, crl, format == GNUTLS_CRT_PRINT_UNSIGNED_FULL);
1897
1898   _gnutls_buffer_append_data (&str, "\0", 1);
1899   out->data = str.data;
1900   out->size = strlen (str.data);
1901
1902   return 0;
1903 }
1904
1905 static void
1906 print_crq (gnutls_buffer_st * str, gnutls_x509_crq_t cert)
1907 {
1908   /* Version. */
1909   {
1910     int version = gnutls_x509_crq_get_version (cert);
1911     if (version < 0)
1912       addf (str, "error: get_version: %s\n", gnutls_strerror (version));
1913     else
1914       addf (str, _("\tVersion: %d\n"), version);
1915   }
1916
1917   /* Subject */
1918   {
1919     char *dn;
1920     size_t dn_size = 0;
1921     int err;
1922
1923     err = gnutls_x509_crq_get_dn (cert, NULL, &dn_size);
1924     if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
1925       addf (str, "error: get_dn: %s\n", gnutls_strerror (err));
1926     else
1927       {
1928         dn = gnutls_malloc (dn_size);
1929         if (!dn)
1930           addf (str, "error: malloc (%d): %s\n", (int) dn_size,
1931                 gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
1932         else
1933           {
1934             err = gnutls_x509_crq_get_dn (cert, dn, &dn_size);
1935             if (err < 0)
1936               addf (str, "error: get_dn: %s\n", gnutls_strerror (err));
1937             else
1938               addf (str, _("\tSubject: %s\n"), dn);
1939             gnutls_free (dn);
1940           }
1941       }
1942   }
1943
1944   /* SubjectPublicKeyInfo. */
1945   {
1946     int err;
1947     unsigned int bits;
1948
1949     err = gnutls_x509_crq_get_pk_algorithm (cert, &bits);
1950     if (err < 0)
1951       addf (str, "error: get_pk_algorithm: %s\n", gnutls_strerror (err));
1952     else
1953       {
1954         const char *name = gnutls_pk_algorithm_get_name (err);
1955         if (name == NULL)
1956           name = _("unknown");
1957
1958         addf (str, _("\tSubject Public Key Algorithm: %s\n"), name);
1959         switch (err)
1960           {
1961           case GNUTLS_PK_RSA:
1962             {
1963               gnutls_datum_t m, e;
1964
1965               err = gnutls_x509_crq_get_key_rsa_raw (cert, &m, &e);
1966               if (err < 0)
1967                 addf (str, "error: get_pk_rsa_raw: %s\n",
1968                       gnutls_strerror (err));
1969               else
1970                 {
1971                   addf (str, _("\t\tModulus (bits %d):\n"), bits);
1972                   hexdump (str, m.data, m.size, "\t\t\t");
1973                   adds (str, _("\t\tExponent:\n"));
1974                   hexdump (str, e.data, e.size, "\t\t\t");
1975
1976                   gnutls_free (m.data);
1977                   gnutls_free (e.data);
1978                 }
1979
1980             }
1981             break;
1982 #if 0                           /* not implemented yet */
1983           case GNUTLS_PK_DSA:
1984             {
1985               gnutls_datum_t p, q, g, y;
1986
1987               err = gnutls_x509_crq_get_key_dsa_raw (cert, &p, &q, &g, &y);
1988               if (err < 0)
1989                 addf (str, "error: get_pk_dsa_raw: %s\n",
1990                       gnutls_strerror (err));
1991               else
1992                 {
1993                   addf (str, _("\t\tPublic key (bits %d):\n"), bits);
1994                   hexdump (str, y.data, y.size, "\t\t\t");
1995                   addf (str, _("\t\tP:\n"));
1996                   hexdump (str, p.data, p.size, "\t\t\t");
1997                   addf (str, _("\t\tQ:\n"));
1998                   hexdump (str, q.data, q.size, "\t\t\t");
1999                   addf (str, _("\t\tG:\n"));
2000                   hexdump (str, g.data, g.size, "\t\t\t");
2001
2002                   gnutls_free (p.data);
2003                   gnutls_free (q.data);
2004                   gnutls_free (g.data);
2005                   gnutls_free (y.data);
2006
2007                 }
2008             }
2009             break;
2010 #endif
2011           default:
2012             break;
2013           }
2014       }
2015   }
2016
2017   /* parse attributes */
2018   {
2019     size_t i;
2020     int err = 0;
2021     int extensions = 0;
2022     int challenge = 0;
2023
2024     for (i = 0;; i++)
2025       {
2026         char oid[MAX_OID_SIZE] = "";
2027         size_t sizeof_oid = sizeof (oid);
2028
2029         err = gnutls_x509_crq_get_attribute_info (cert, i, oid, &sizeof_oid);
2030         if (err < 0)
2031           {
2032             if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
2033               break;
2034             addf (str, "error: get_extension_info: %s\n",
2035                   gnutls_strerror (err));
2036             continue;
2037           }
2038
2039         if (i == 0)
2040           adds (str, _("\tAttributes:\n"));
2041
2042         if (strcmp (oid, "1.2.840.113549.1.9.14") == 0)
2043           {
2044             cert_type_t ccert;
2045
2046             if (extensions)
2047               {
2048                 addf (str, "error: more than one extensionsRequest\n");
2049                 continue;
2050               }
2051
2052             ccert.crq = cert;
2053             print_extensions (str, "\t", TYPE_CRQ, ccert);
2054
2055             extensions++;
2056           }
2057         else if (strcmp (oid, "1.2.840.113549.1.9.7") == 0)
2058           {
2059             char *pass;
2060             size_t size;
2061
2062             if (challenge)
2063               {
2064                 adds (str,
2065                       "error: more than one Challenge password attribute\n");
2066                 continue;
2067               }
2068
2069             err = gnutls_x509_crq_get_challenge_password (cert, NULL, &size);
2070             if (err < 0)
2071               {
2072                 addf (str, "error: get_challenge_password: %s\n",
2073                       gnutls_strerror (err));
2074                 continue;
2075               }
2076
2077             size++;
2078
2079             pass = gnutls_malloc (size);
2080             if (!pass)
2081               {
2082                 addf (str, "error: malloc: %s\n",
2083                       gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
2084                 continue;
2085               }
2086
2087             err = gnutls_x509_crq_get_challenge_password (cert, pass, &size);
2088             if (err < 0)
2089               addf (str, "error: get_challenge_password: %s\n",
2090                     gnutls_strerror (err));
2091             else
2092               addf (str, _("\t\tChallenge password: %s\n"), pass);
2093
2094             gnutls_free (pass);
2095
2096             challenge++;
2097           }
2098         else
2099           {
2100             char *buffer;
2101             size_t extlen = 0;
2102
2103             addf (str, _("\t\tUnknown attribute %s:\n"), oid);
2104
2105             err = gnutls_x509_crq_get_attribute_data (cert, i, NULL, &extlen);
2106             if (err < 0)
2107               {
2108                 addf (str, "error: get_attribute_data: %s\n",
2109                       gnutls_strerror (err));
2110                 continue;
2111               }
2112
2113             buffer = gnutls_malloc (extlen);
2114             if (!buffer)
2115               {
2116                 addf (str, "error: malloc: %s\n",
2117                       gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
2118                 continue;
2119               }
2120
2121             err = gnutls_x509_crq_get_attribute_data (cert, i,
2122                                                       buffer, &extlen);
2123             if (err < 0)
2124               {
2125                 gnutls_free (buffer);
2126                 addf (str, "error: get_attribute_data2: %s\n",
2127                       gnutls_strerror (err));
2128                 continue;
2129               }
2130
2131             adds (str, _("\t\t\tASCII: "));
2132             asciiprint (str, buffer, extlen);
2133             adds (str, "\n");
2134
2135             adds (str, _("\t\t\tHexdump: "));
2136             hexprint (str, buffer, extlen);
2137             adds (str, "\n");
2138
2139             gnutls_free (buffer);
2140           }
2141       }
2142   }
2143 }
2144
2145 static void
2146 print_crq_other (gnutls_buffer_st * str, gnutls_x509_crq_t crq)
2147 {
2148   int err;
2149   size_t size = 0;
2150   char *buffer = NULL;
2151
2152   err = gnutls_x509_crq_get_key_id (crq, 0, buffer, &size);
2153   if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
2154     {
2155       addf (str, "error: get_key_id: %s\n", gnutls_strerror (err));
2156       return;
2157     }
2158
2159   buffer = gnutls_malloc (size);
2160   if (!buffer)
2161     {
2162       addf (str, "error: malloc: %s\n",
2163             gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
2164       return;
2165     }
2166
2167   err = gnutls_x509_crq_get_key_id (crq, 0, buffer, &size);
2168   if (err < 0)
2169     {
2170       gnutls_free (buffer);
2171       addf (str, "error: get_key_id2: %s\n", gnutls_strerror (err));
2172       return;
2173     }
2174
2175   adds (str, _("\tPublic Key Id:\n\t\t"));
2176   hexprint (str, buffer, size);
2177   adds (str, "\n");
2178
2179   gnutls_free (buffer);
2180 }
2181
2182 /**
2183  * gnutls_x509_crq_print:
2184  * @crq: The structure to be printed
2185  * @format: Indicate the format to use
2186  * @out: Newly allocated datum with zero terminated string.
2187  *
2188  * This function will pretty print a certificate request, suitable for
2189  * display to a human.
2190  *
2191  * The output @out needs to be deallocate using gnutls_free().
2192  *
2193  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
2194  *   negative error value.
2195  *
2196  * Since: 2.8.0
2197  **/
2198 int
2199 gnutls_x509_crq_print (gnutls_x509_crq_t crq,
2200                        gnutls_certificate_print_formats_t format,
2201                        gnutls_datum_t * out)
2202 {
2203   gnutls_buffer_st str;
2204
2205   _gnutls_buffer_init (&str);
2206
2207   _gnutls_buffer_append_str
2208     (&str, _("PKCS #10 Certificate Request Information:\n"));
2209
2210   print_crq (&str, crq);
2211
2212   _gnutls_buffer_append_str (&str, _("Other Information:\n"));
2213
2214   print_crq_other (&str, crq);
2215
2216   _gnutls_buffer_append_data (&str, "\0", 1);
2217   out->data = str.data;
2218   out->size = strlen (str.data);
2219
2220   return 0;
2221 }
2222
2223 #endif /* ENABLE_PKI */