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