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