Coverage Report

Created: 2024-07-23 07:36

/src/gnutls/lib/x509/output.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2007-2016 Free Software Foundation, Inc.
3
 * Copyright (C) 2015-2017 Red Hat, Inc.
4
 *
5
 * Author: Simon Josefsson, Nikos Mavrogiannopoulos
6
 *
7
 * This file is part of GnuTLS.
8
 *
9
 * The GnuTLS is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public License
11
 * as published by the Free Software Foundation; either version 2.1 of
12
 * the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
21
 *
22
 */
23
24
/* Functions for printing X.509 Certificate structures
25
 */
26
27
#include "gnutls_int.h"
28
#include "common.h"
29
#include "x509.h"
30
#include "x509_int.h"
31
#include "num.h"
32
#include "errors.h"
33
#include "hello_ext.h"
34
#include "ip.h"
35
36
0
#define addf _gnutls_buffer_append_printf
37
0
#define adds _gnutls_buffer_append_str
38
39
0
#define NON_NULL(x) (((x) != NULL) ? ((char *)(x)) : "")
40
0
#define ERROR_STR (char *)"(error)"
41
42
static void print_idn_name(gnutls_buffer_st *str, const char *prefix,
43
         const char *type, gnutls_datum_t *name)
44
0
{
45
0
  unsigned printable = 1;
46
0
  unsigned is_printed = 0;
47
0
  gnutls_datum_t out = { NULL, 0 };
48
0
  int ret;
49
50
0
  if (!_gnutls_str_is_print((char *)name->data, name->size))
51
0
    printable = 0;
52
53
0
  is_printed = 0;
54
0
  if (!printable) {
55
0
    addf(str, _("%s%s: %.*s (contains illegal chars)\n"), prefix,
56
0
         type, name->size, NON_NULL(name->data));
57
0
    is_printed = 1;
58
0
  } else if (name->data != NULL) {
59
0
    if (strstr((char *)name->data, "xn--") != NULL) {
60
0
      ret = gnutls_idna_reverse_map((char *)name->data,
61
0
                  name->size, &out, 0);
62
0
      if (ret >= 0) {
63
0
        addf(str, _("%s%s: %.*s (%s)\n"), prefix, type,
64
0
             name->size, NON_NULL(name->data),
65
0
             out.data);
66
0
        is_printed = 1;
67
0
        gnutls_free(out.data);
68
0
      }
69
0
    }
70
0
  }
71
72
0
  if (is_printed == 0) {
73
0
    addf(str, _("%s%s: %.*s\n"), prefix, type, name->size,
74
0
         NON_NULL(name->data));
75
0
  }
76
0
}
77
78
static void print_idn_email(gnutls_buffer_st *str, const char *prefix,
79
          const char *type, gnutls_datum_t *name)
80
0
{
81
0
  unsigned printable = 1;
82
0
  unsigned is_printed = 0;
83
0
  gnutls_datum_t out = { NULL, 0 };
84
0
  int ret;
85
86
0
  if (!_gnutls_str_is_print((char *)name->data, name->size))
87
0
    printable = 0;
88
89
0
  is_printed = 0;
90
0
  if (!printable) {
91
0
    addf(str, _("%s%s: %.*s (contains illegal chars)\n"), prefix,
92
0
         type, name->size, NON_NULL(name->data));
93
0
    is_printed = 1;
94
0
  } else if (name->data != NULL) {
95
0
    if (strstr((char *)name->data, "xn--") != NULL) {
96
0
      ret = _gnutls_idna_email_reverse_map((char *)name->data,
97
0
                   name->size, &out);
98
0
      if (ret >= 0) {
99
0
        addf(str, _("%s%s: %.*s (%s)\n"), prefix, type,
100
0
             name->size, NON_NULL(name->data),
101
0
             out.data);
102
0
        is_printed = 1;
103
0
        gnutls_free(out.data);
104
0
      }
105
0
    }
106
0
  }
107
108
0
  if (is_printed == 0) {
109
0
    addf(str, _("%s%s: %.*s\n"), prefix, type, name->size,
110
0
         NON_NULL(name->data));
111
0
  }
112
0
}
113
114
static void print_name(gnutls_buffer_st *str, const char *prefix, unsigned type,
115
           gnutls_datum_t *name, unsigned ip_is_cidr)
116
0
{
117
0
  char *sname = (char *)name->data;
118
0
  char str_ip[64];
119
0
  const char *p;
120
121
0
  if ((type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_OTHERNAME_XMPP ||
122
0
       type == GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL ||
123
0
       type == GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL ||
124
0
       type == GNUTLS_SAN_RFC822NAME || type == GNUTLS_SAN_URI) &&
125
0
      sname != NULL && strlen(sname) != name->size) {
126
0
    adds(str, _("warning: SAN contains an embedded NUL, "
127
0
          "replacing with '!'\n"));
128
0
    while (strlen(sname) < name->size)
129
0
      name->data[strlen(sname)] = '!';
130
0
  }
131
132
0
  switch (type) {
133
0
  case GNUTLS_SAN_DNSNAME:
134
0
    print_idn_name(str, prefix, "DNSname", name);
135
0
    break;
136
137
0
  case GNUTLS_SAN_RFC822NAME:
138
0
    print_idn_email(str, prefix, "RFC822Name", name);
139
0
    break;
140
141
0
  case GNUTLS_SAN_URI:
142
0
    addf(str, _("%sURI: %.*s\n"), prefix, name->size,
143
0
         NON_NULL(name->data));
144
0
    break;
145
146
0
  case GNUTLS_SAN_IPADDRESS:
147
0
    if (!ip_is_cidr)
148
0
      p = _gnutls_ip_to_string(name->data, name->size, str_ip,
149
0
             sizeof(str_ip));
150
0
    else
151
0
      p = _gnutls_cidr_to_string(name->data, name->size,
152
0
               str_ip, sizeof(str_ip));
153
0
    if (p == NULL)
154
0
      p = ERROR_STR;
155
0
    addf(str, "%sIPAddress: %s\n", prefix, p);
156
0
    break;
157
158
0
  case GNUTLS_SAN_DN:
159
0
    addf(str, _("%sdirectoryName: %.*s\n"), prefix, name->size,
160
0
         NON_NULL(name->data));
161
0
    break;
162
163
0
  case GNUTLS_SAN_REGISTERED_ID:
164
0
    addf(str, _("%sRegistered ID: %.*s\n"), prefix, name->size,
165
0
         NON_NULL(name->data));
166
0
    break;
167
168
0
  case GNUTLS_SAN_OTHERNAME_XMPP:
169
0
    addf(str, _("%sXMPP Address: %.*s\n"), prefix, name->size,
170
0
         NON_NULL(name->data));
171
0
    break;
172
173
0
  case GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL:
174
0
    addf(str, _("%sKRB5Principal: %.*s\n"), prefix, name->size,
175
0
         NON_NULL(name->data));
176
0
    break;
177
178
0
  case GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL:
179
0
    addf(str, _("%sUser Principal Name: %.*s\n"), prefix,
180
0
         name->size, NON_NULL(name->data));
181
0
    break;
182
183
0
  default:
184
0
    addf(str, _("%sUnknown name: "), prefix);
185
0
    _gnutls_buffer_hexprint(str, name->data, name->size);
186
0
    adds(str, "\n");
187
0
    break;
188
0
  }
189
0
}
190
191
static char *get_pk_name(gnutls_x509_crt_t cert, unsigned *bits)
192
0
{
193
0
  char oid[MAX_OID_SIZE];
194
0
  size_t oid_size;
195
0
  oid_size = sizeof(oid);
196
0
  int ret;
197
198
0
  ret = gnutls_x509_crt_get_pk_algorithm(cert, bits);
199
0
  if (ret > 0) {
200
0
    const char *name = gnutls_pk_algorithm_get_name(ret);
201
202
0
    if (name != NULL)
203
0
      return gnutls_strdup(name);
204
0
  }
205
206
0
  ret = gnutls_x509_crt_get_pk_oid(cert, oid, &oid_size);
207
0
  if (ret < 0)
208
0
    return NULL;
209
210
0
  return gnutls_strdup(oid);
211
0
}
212
213
static char *crq_get_pk_name(gnutls_x509_crq_t crq)
214
0
{
215
0
  char oid[MAX_OID_SIZE];
216
0
  size_t oid_size;
217
0
  oid_size = sizeof(oid);
218
0
  int ret;
219
220
0
  ret = gnutls_x509_crq_get_pk_algorithm(crq, NULL);
221
0
  if (ret > 0) {
222
0
    const char *name = gnutls_pk_algorithm_get_name(ret);
223
224
0
    if (name != NULL)
225
0
      return gnutls_strdup(name);
226
0
  }
227
228
0
  ret = gnutls_x509_crq_get_pk_oid(crq, oid, &oid_size);
229
0
  if (ret < 0)
230
0
    return NULL;
231
232
0
  return gnutls_strdup(oid);
233
0
}
234
235
static char *get_sign_name(gnutls_x509_crt_t cert, int *algo)
236
0
{
237
0
  char oid[MAX_OID_SIZE];
238
0
  size_t oid_size;
239
0
  oid_size = sizeof(oid);
240
0
  int ret;
241
242
0
  *algo = 0;
243
244
0
  ret = gnutls_x509_crt_get_signature_algorithm(cert);
245
0
  if (ret > 0) {
246
0
    const char *name = gnutls_sign_get_name(ret);
247
248
0
    *algo = ret;
249
250
0
    if (name != NULL)
251
0
      return gnutls_strdup(name);
252
0
  }
253
254
0
  ret = gnutls_x509_crt_get_signature_oid(cert, oid, &oid_size);
255
0
  if (ret < 0)
256
0
    return NULL;
257
258
0
  return gnutls_strdup(oid);
259
0
}
260
261
static char *crq_get_sign_name(gnutls_x509_crq_t crq)
262
0
{
263
0
  char oid[MAX_OID_SIZE];
264
0
  size_t oid_size;
265
0
  oid_size = sizeof(oid);
266
0
  int ret;
267
268
0
  ret = gnutls_x509_crq_get_signature_algorithm(crq);
269
0
  if (ret > 0) {
270
0
    const char *name = gnutls_sign_get_name(ret);
271
272
0
    if (name != NULL)
273
0
      return gnutls_strdup(name);
274
0
  }
275
276
0
  ret = gnutls_x509_crq_get_signature_oid(crq, oid, &oid_size);
277
0
  if (ret < 0)
278
0
    return NULL;
279
280
0
  return gnutls_strdup(oid);
281
0
}
282
283
static char *crl_get_sign_name(gnutls_x509_crl_t crl, int *algo)
284
0
{
285
0
  char oid[MAX_OID_SIZE];
286
0
  size_t oid_size;
287
0
  oid_size = sizeof(oid);
288
0
  int ret;
289
290
0
  *algo = 0;
291
292
0
  ret = gnutls_x509_crl_get_signature_algorithm(crl);
293
0
  if (ret > 0) {
294
0
    const char *name = gnutls_sign_get_name(ret);
295
296
0
    *algo = ret;
297
298
0
    if (name != NULL)
299
0
      return gnutls_strdup(name);
300
0
  }
301
302
0
  ret = gnutls_x509_crl_get_signature_oid(crl, oid, &oid_size);
303
0
  if (ret < 0)
304
0
    return NULL;
305
306
0
  return gnutls_strdup(oid);
307
0
}
308
309
static void print_proxy(gnutls_buffer_st *str, gnutls_datum_t *der)
310
0
{
311
0
  int pathlen;
312
0
  char *policyLanguage;
313
0
  char *policy;
314
0
  size_t npolicy;
315
0
  int err;
316
317
0
  err = gnutls_x509_ext_import_proxy(der, &pathlen, &policyLanguage,
318
0
             &policy, &npolicy);
319
0
  if (err < 0) {
320
0
    addf(str, "error: get_proxy: %s\n", gnutls_strerror(err));
321
0
    return;
322
0
  }
323
324
0
  if (pathlen >= 0)
325
0
    addf(str, _("\t\t\tPath Length Constraint: %d\n"), pathlen);
326
0
  addf(str, _("\t\t\tPolicy Language: %s"), policyLanguage);
327
0
  if (strcmp(policyLanguage, "1.3.6.1.5.5.7.21.1") == 0)
328
0
    adds(str, " (id-ppl-inheritALL)\n");
329
0
  else if (strcmp(policyLanguage, "1.3.6.1.5.5.7.21.2") == 0)
330
0
    adds(str, " (id-ppl-independent)\n");
331
0
  else
332
0
    adds(str, "\n");
333
0
  if (npolicy) {
334
0
    adds(str, _("\t\t\tPolicy:\n\t\t\t\tASCII: "));
335
0
    _gnutls_buffer_asciiprint(str, policy, npolicy);
336
0
    adds(str, _("\n\t\t\t\tHexdump: "));
337
0
    _gnutls_buffer_hexprint(str, policy, npolicy);
338
0
    adds(str, "\n");
339
0
  }
340
0
  gnutls_free(policy);
341
0
  gnutls_free(policyLanguage);
342
0
}
343
344
static void print_nc(gnutls_buffer_st *str, const char *prefix,
345
         gnutls_datum_t *der)
346
0
{
347
0
  gnutls_x509_name_constraints_t nc;
348
0
  int ret;
349
0
  unsigned idx = 0;
350
0
  gnutls_datum_t name;
351
0
  unsigned type;
352
0
  char new_prefix[16];
353
354
0
  ret = gnutls_x509_name_constraints_init(&nc);
355
0
  if (ret < 0)
356
0
    return;
357
358
0
  ret = gnutls_x509_ext_import_name_constraints(der, nc, 0);
359
0
  if (ret < 0)
360
0
    goto cleanup;
361
362
0
  snprintf(new_prefix, sizeof(new_prefix), "%s\t\t\t\t", prefix);
363
364
0
  do {
365
0
    ret = gnutls_x509_name_constraints_get_permitted(nc, idx++,
366
0
                 &type, &name);
367
368
0
    if (ret >= 0) {
369
0
      if (idx == 1)
370
0
        addf(str, _("%s\t\t\tPermitted:\n"), prefix);
371
372
0
      print_name(str, new_prefix, type, &name, 1);
373
0
    }
374
0
  } while (ret == 0);
375
376
0
  idx = 0;
377
0
  do {
378
0
    ret = gnutls_x509_name_constraints_get_excluded(nc, idx++,
379
0
                &type, &name);
380
381
0
    if (ret >= 0) {
382
0
      if (idx == 1)
383
0
        addf(str, _("%s\t\t\tExcluded:\n"), prefix);
384
385
0
      print_name(str, new_prefix, type, &name, 1);
386
0
    }
387
0
  } while (ret == 0);
388
389
0
cleanup:
390
0
  gnutls_x509_name_constraints_deinit(nc);
391
0
}
392
393
static void print_aia(gnutls_buffer_st *str, const gnutls_datum_t *der)
394
0
{
395
0
  int err;
396
0
  int seq;
397
0
  gnutls_datum_t san = { NULL, 0 }, oid = { NULL, 0 };
398
0
  gnutls_x509_aia_t aia;
399
0
  unsigned int san_type;
400
401
0
  err = gnutls_x509_aia_init(&aia);
402
0
  if (err < 0)
403
0
    return;
404
405
0
  err = gnutls_x509_ext_import_aia(der, aia, 0);
406
0
  if (err < 0) {
407
0
    addf(str, "error: get_aia: %s\n", gnutls_strerror(err));
408
0
    goto cleanup;
409
0
  }
410
411
0
  for (seq = 0;; seq++) {
412
0
    err = gnutls_x509_aia_get(aia, seq, &oid, &san_type, &san);
413
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
414
0
      goto cleanup;
415
0
    if (err < 0) {
416
0
      addf(str, "error: aia_get: %s\n", gnutls_strerror(err));
417
0
      goto cleanup;
418
0
    }
419
420
0
    if (strcmp((char *)oid.data, GNUTLS_OID_AD_OCSP) == 0)
421
0
      addf(str, _("\t\t\tAccess Method: %s (%s)\n"),
422
0
           GNUTLS_OID_AD_OCSP, "id-ad-ocsp");
423
0
    else if (strcmp((char *)oid.data, GNUTLS_OID_AD_CAISSUERS) == 0)
424
0
      addf(str, _("\t\t\tAccess Method: %s (%s)\n"),
425
0
           GNUTLS_OID_AD_CAISSUERS, "id-ad-caIssuers");
426
0
    else {
427
0
      addf(str, _("\t\t\tAccess Method: %s (%s)\n"),
428
0
           (char *)oid.data, "UNKNOWN");
429
0
    }
430
431
0
    adds(str, "\t\t\tAccess Location ");
432
0
    print_name(str, "", san_type, &san, 0);
433
0
  }
434
435
0
cleanup:
436
0
  gnutls_x509_aia_deinit(aia);
437
0
}
438
439
static void print_ski(gnutls_buffer_st *str, gnutls_datum_t *der)
440
0
{
441
0
  gnutls_datum_t id = { NULL, 0 };
442
0
  int err;
443
444
0
  err = gnutls_x509_ext_import_subject_key_id(der, &id);
445
0
  if (err < 0) {
446
0
    addf(str, "error: get_subject_key_id: %s\n",
447
0
         gnutls_strerror(err));
448
0
    return;
449
0
  }
450
451
0
  adds(str, "\t\t\t");
452
0
  _gnutls_buffer_hexprint(str, id.data, id.size);
453
0
  adds(str, "\n");
454
455
0
  gnutls_free(id.data);
456
0
}
457
458
static void print_time(gnutls_buffer_st *str, time_t timestamp)
459
0
{
460
0
  char s[42];
461
0
  size_t max = sizeof(s);
462
0
  struct tm t;
463
464
0
  if (gmtime_r(&timestamp, &t) == NULL) {
465
0
    addf(str, "error: gmtime_r (%lu)\n", timestamp);
466
0
    return;
467
0
  }
468
469
0
  if (strftime(s, max, "%a, %b %d %H:%M:%S UTC %Y", &t) == 0)
470
0
    addf(str, "error: strftime (%lu)\n", timestamp);
471
0
  else
472
0
    addf(str, "%s\n", s);
473
0
}
474
475
static void print_scts(gnutls_buffer_st *str, const gnutls_datum_t *der,
476
           const char *prefix)
477
0
{
478
0
  int retval;
479
0
  unsigned int version;
480
0
  time_t timestamp;
481
0
  gnutls_datum_t logid = { NULL, 0 }, sig = { NULL, 0 };
482
0
  gnutls_sign_algorithm_t sigalg;
483
0
  gnutls_x509_ct_scts_t scts;
484
485
0
  retval = gnutls_x509_ext_ct_scts_init(&scts);
486
0
  if (retval < 0) {
487
0
    addf(str, "error: gnutls_x509_ext_ct_scts_init(): %s\n",
488
0
         gnutls_strerror(retval));
489
0
    return;
490
0
  }
491
492
0
  retval = gnutls_x509_ext_ct_import_scts(der, scts, 0);
493
0
  if (retval < 0) {
494
0
    addf(str, "error: gnutls_x509_ext_ct_import_scts(): %s\n",
495
0
         gnutls_strerror(retval));
496
0
    goto cleanup;
497
0
  }
498
499
0
  for (int i = 0;; i++) {
500
0
    retval = gnutls_x509_ct_sct_get_version(scts, i, &version);
501
0
    if (retval == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
502
0
      break;
503
504
0
    addf(str, _("%s\t\t\tSigned Certificate Timestamp %d:\n"),
505
0
         prefix, (i + 1));
506
507
0
    if (version != 1) {
508
0
      addf(str,
509
0
           _("%s\t\t\t\tVersion: %d (unknown SCT version)\n"),
510
0
           prefix, version);
511
0
      continue;
512
0
    }
513
514
0
    retval = gnutls_x509_ct_sct_get(scts, i, &timestamp, &logid,
515
0
            &sigalg, &sig);
516
0
    if (retval < 0) {
517
0
      addf(str, "error: could not get SCT info: %s\n",
518
0
           gnutls_strerror(retval));
519
0
      break;
520
0
    }
521
522
0
    addf(str, _("%s\t\t\t\tVersion: %d\n"), prefix, version);
523
0
    addf(str, _("%s\t\t\t\tLog ID: "), prefix);
524
0
    _gnutls_buffer_hexprint(str, logid.data, logid.size);
525
0
    addf(str, "\n");
526
0
    addf(str, _("%s\t\t\t\tTime: "), prefix);
527
0
    print_time(str, timestamp);
528
0
    addf(str,
529
0
         _("%s\t\t\t\tExtensions: none\n"), /* there are no extensions defined for v1 */
530
0
         prefix);
531
0
    addf(str, _("%s\t\t\t\tSignature algorithm: %s\n"), prefix,
532
0
         gnutls_sign_get_name(sigalg));
533
0
    addf(str, _("%s\t\t\t\tSignature: "), prefix);
534
0
    _gnutls_buffer_hexprint(str, sig.data, sig.size);
535
0
    addf(str, "\n");
536
537
0
    _gnutls_free_datum(&sig);
538
0
    _gnutls_free_datum(&logid);
539
0
    sig.data = NULL;
540
0
    logid.data = NULL;
541
0
  }
542
543
0
cleanup:
544
0
  _gnutls_free_datum(&sig);
545
0
  _gnutls_free_datum(&logid);
546
0
  gnutls_x509_ext_ct_scts_deinit(scts);
547
0
}
548
549
0
#define TYPE_CRT 2
550
0
#define TYPE_CRQ 3
551
552
typedef union {
553
  gnutls_x509_crt_t crt;
554
  gnutls_x509_crq_t crq;
555
} cert_type_t;
556
557
static void print_aki_gn_serial(gnutls_buffer_st *str, gnutls_x509_aki_t aki)
558
0
{
559
0
  gnutls_datum_t san, other_oid, serial;
560
0
  unsigned int alt_type;
561
0
  int err;
562
563
0
  err = gnutls_x509_aki_get_cert_issuer(aki, 0, &alt_type, &san,
564
0
                &other_oid, &serial);
565
0
  if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
566
0
    return;
567
0
  } else if (err < 0) {
568
0
    addf(str, "error: gnutls_x509_aki_get_cert_issuer: %s\n",
569
0
         gnutls_strerror(err));
570
0
    return;
571
0
  }
572
573
0
  print_name(str, "\t\t\t", alt_type, &san, 0);
574
575
0
  adds(str, "\t\t\tserial: ");
576
0
  _gnutls_buffer_hexprint(str, serial.data, serial.size);
577
0
  adds(str, "\n");
578
0
}
579
580
static void print_aki(gnutls_buffer_st *str, gnutls_datum_t *der)
581
0
{
582
0
  int err;
583
0
  gnutls_x509_aki_t aki;
584
0
  gnutls_datum_t id;
585
586
0
  err = gnutls_x509_aki_init(&aki);
587
0
  if (err < 0) {
588
0
    addf(str, "error: gnutls_x509_aki_init: %s\n",
589
0
         gnutls_strerror(err));
590
0
    return;
591
0
  }
592
593
0
  err = gnutls_x509_ext_import_authority_key_id(der, aki, 0);
594
0
  if (err < 0) {
595
0
    addf(str,
596
0
         "error: gnutls_x509_ext_import_authority_key_id: %s\n",
597
0
         gnutls_strerror(err));
598
0
    goto cleanup;
599
0
  }
600
601
  /* Check if an alternative name is there */
602
0
  print_aki_gn_serial(str, aki);
603
604
0
  err = gnutls_x509_aki_get_id(aki, &id);
605
0
  if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
606
0
    goto cleanup;
607
0
  } else if (err < 0) {
608
0
    addf(str, "error: gnutls_x509_aki_get_id: %s\n",
609
0
         gnutls_strerror(err));
610
0
    goto cleanup;
611
0
  }
612
613
0
  adds(str, "\t\t\t");
614
0
  _gnutls_buffer_hexprint(str, id.data, id.size);
615
0
  adds(str, "\n");
616
617
0
cleanup:
618
0
  gnutls_x509_aki_deinit(aki);
619
0
}
620
621
static void print_key_usage2(gnutls_buffer_st *str, const char *prefix,
622
           unsigned int key_usage)
623
0
{
624
0
  if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)
625
0
    addf(str, _("%sDigital signature.\n"), prefix);
626
0
  if (key_usage & GNUTLS_KEY_NON_REPUDIATION)
627
0
    addf(str, _("%sNon repudiation.\n"), prefix);
628
0
  if (key_usage & GNUTLS_KEY_KEY_ENCIPHERMENT)
629
0
    addf(str, _("%sKey encipherment.\n"), prefix);
630
0
  if (key_usage & GNUTLS_KEY_DATA_ENCIPHERMENT)
631
0
    addf(str, _("%sData encipherment.\n"), prefix);
632
0
  if (key_usage & GNUTLS_KEY_KEY_AGREEMENT)
633
0
    addf(str, _("%sKey agreement.\n"), prefix);
634
0
  if (key_usage & GNUTLS_KEY_KEY_CERT_SIGN)
635
0
    addf(str, _("%sCertificate signing.\n"), prefix);
636
0
  if (key_usage & GNUTLS_KEY_CRL_SIGN)
637
0
    addf(str, _("%sCRL signing.\n"), prefix);
638
0
  if (key_usage & GNUTLS_KEY_ENCIPHER_ONLY)
639
0
    addf(str, _("%sKey encipher only.\n"), prefix);
640
0
  if (key_usage & GNUTLS_KEY_DECIPHER_ONLY)
641
0
    addf(str, _("%sKey decipher only.\n"), prefix);
642
0
}
643
644
static void print_key_usage(gnutls_buffer_st *str, const char *prefix,
645
          gnutls_datum_t *der)
646
0
{
647
0
  unsigned int key_usage;
648
0
  int err;
649
650
0
  err = gnutls_x509_ext_import_key_usage(der, &key_usage);
651
0
  if (err < 0) {
652
0
    addf(str, "error: get_key_usage: %s\n", gnutls_strerror(err));
653
0
    return;
654
0
  }
655
656
0
  print_key_usage2(str, prefix, key_usage);
657
0
}
658
659
static void print_private_key_usage_period(gnutls_buffer_st *str,
660
             const char *prefix,
661
             gnutls_datum_t *der)
662
0
{
663
0
  time_t activation, expiration;
664
0
  int err;
665
0
  char s[42];
666
0
  struct tm t;
667
0
  size_t max;
668
669
0
  err = gnutls_x509_ext_import_private_key_usage_period(der, &activation,
670
0
                    &expiration);
671
0
  if (err < 0) {
672
0
    addf(str, "error: get_private_key_usage_period: %s\n",
673
0
         gnutls_strerror(err));
674
0
    return;
675
0
  }
676
677
0
  max = sizeof(s);
678
679
0
  if (gmtime_r(&activation, &t) == NULL)
680
0
    addf(str, "error: gmtime_r (%ld)\n", (unsigned long)activation);
681
0
  else if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y", &t) == 0)
682
0
    addf(str, "error: strftime (%ld)\n", (unsigned long)activation);
683
0
  else
684
0
    addf(str, _("\t\t\tNot Before: %s\n"), s);
685
686
0
  if (gmtime_r(&expiration, &t) == NULL)
687
0
    addf(str, "error: gmtime_r (%ld)\n", (unsigned long)expiration);
688
0
  else if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y", &t) == 0)
689
0
    addf(str, "error: strftime (%ld)\n", (unsigned long)expiration);
690
0
  else
691
0
    addf(str, _("\t\t\tNot After: %s\n"), s);
692
0
}
693
694
static void print_crldist(gnutls_buffer_st *str, gnutls_datum_t *der)
695
0
{
696
0
  int err;
697
0
  int indx;
698
0
  gnutls_x509_crl_dist_points_t dp;
699
0
  unsigned int flags, type;
700
0
  gnutls_datum_t dist;
701
702
0
  err = gnutls_x509_crl_dist_points_init(&dp);
703
0
  if (err < 0) {
704
0
    addf(str, "error: gnutls_x509_crl_dist_points_init: %s\n",
705
0
         gnutls_strerror(err));
706
0
    return;
707
0
  }
708
709
0
  err = gnutls_x509_ext_import_crl_dist_points(der, dp, 0);
710
0
  if (err < 0) {
711
0
    addf(str, "error: gnutls_x509_ext_import_crl_dist_points: %s\n",
712
0
         gnutls_strerror(err));
713
0
    goto cleanup;
714
0
  }
715
716
0
  for (indx = 0;; indx++) {
717
0
    err = gnutls_x509_crl_dist_points_get(dp, indx, &type, &dist,
718
0
                  &flags);
719
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
720
0
      goto cleanup;
721
0
    else if (err < 0) {
722
0
      addf(str, "error: get_crl_dist_points: %s\n",
723
0
           gnutls_strerror(err));
724
0
      return;
725
0
    }
726
727
0
    print_name(str, "\t\t\t", type, &dist, 0);
728
0
  }
729
0
cleanup:
730
0
  gnutls_x509_crl_dist_points_deinit(dp);
731
0
}
732
733
static void print_key_purpose(gnutls_buffer_st *str, const char *prefix,
734
            gnutls_datum_t *der)
735
0
{
736
0
  int indx;
737
0
  gnutls_datum_t oid;
738
0
  char *p;
739
0
  int err;
740
0
  gnutls_x509_key_purposes_t purposes;
741
742
0
  err = gnutls_x509_key_purpose_init(&purposes);
743
0
  if (err < 0) {
744
0
    addf(str, "error: gnutls_x509_key_purpose_init: %s\n",
745
0
         gnutls_strerror(err));
746
0
    return;
747
0
  }
748
749
0
  err = gnutls_x509_ext_import_key_purposes(der, purposes, 0);
750
0
  if (err < 0) {
751
0
    addf(str, "error: gnutls_x509_ext_import_key_purposes: %s\n",
752
0
         gnutls_strerror(err));
753
0
    goto cleanup;
754
0
  }
755
756
0
  for (indx = 0;; indx++) {
757
0
    err = gnutls_x509_key_purpose_get(purposes, indx, &oid);
758
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
759
0
      goto cleanup;
760
0
    else if (err < 0) {
761
0
      addf(str, "error: gnutls_x509_key_purpose_get: %s\n",
762
0
           gnutls_strerror(err));
763
0
      goto cleanup;
764
0
    }
765
766
0
    p = (void *)oid.data;
767
0
    if (strcmp(p, GNUTLS_KP_TLS_WWW_SERVER) == 0)
768
0
      addf(str, _("%s\t\t\tTLS WWW Server.\n"), prefix);
769
0
    else if (strcmp(p, GNUTLS_KP_TLS_WWW_CLIENT) == 0)
770
0
      addf(str, _("%s\t\t\tTLS WWW Client.\n"), prefix);
771
0
    else if (strcmp(p, GNUTLS_KP_CODE_SIGNING) == 0)
772
0
      addf(str, _("%s\t\t\tCode signing.\n"), prefix);
773
0
    else if (strcmp(p, GNUTLS_KP_EMAIL_PROTECTION) == 0)
774
0
      addf(str, _("%s\t\t\tEmail protection.\n"), prefix);
775
0
    else if (strcmp(p, GNUTLS_KP_TIME_STAMPING) == 0)
776
0
      addf(str, _("%s\t\t\tTime stamping.\n"), prefix);
777
0
    else if (strcmp(p, GNUTLS_KP_OCSP_SIGNING) == 0)
778
0
      addf(str, _("%s\t\t\tOCSP signing.\n"), prefix);
779
0
    else if (strcmp(p, GNUTLS_KP_IPSEC_IKE) == 0)
780
0
      addf(str, _("%s\t\t\tIpsec IKE.\n"), prefix);
781
0
    else if (strcmp(p, GNUTLS_KP_MS_SMART_CARD_LOGON) == 0)
782
0
      addf(str, _("%s\t\t\tSmart Card Logon.\n"), prefix);
783
0
    else if (strcmp(p, GNUTLS_KP_ANY) == 0)
784
0
      addf(str, _("%s\t\t\tAny purpose.\n"), prefix);
785
0
    else
786
0
      addf(str, "%s\t\t\t%s\n", prefix, p);
787
0
  }
788
0
cleanup:
789
0
  gnutls_x509_key_purpose_deinit(purposes);
790
0
}
791
792
static void print_basic(gnutls_buffer_st *str, const char *prefix,
793
      gnutls_datum_t *der)
794
0
{
795
0
  int pathlen;
796
0
  unsigned ca;
797
0
  int err;
798
799
0
  err = gnutls_x509_ext_import_basic_constraints(der, &ca, &pathlen);
800
0
  if (err < 0) {
801
0
    addf(str, "error: get_basic_constraints: %s\n",
802
0
         gnutls_strerror(err));
803
0
    return;
804
0
  }
805
806
0
  if (ca == 0)
807
0
    addf(str, _("%s\t\t\tCertificate Authority (CA): FALSE\n"),
808
0
         prefix);
809
0
  else
810
0
    addf(str, _("%s\t\t\tCertificate Authority (CA): TRUE\n"),
811
0
         prefix);
812
813
0
  if (pathlen >= 0)
814
0
    addf(str, _("%s\t\t\tPath Length Constraint: %d\n"), prefix,
815
0
         pathlen);
816
0
}
817
818
static void print_altname(gnutls_buffer_st *str, const char *prefix,
819
        gnutls_datum_t *der)
820
0
{
821
0
  unsigned int altname_idx;
822
0
  gnutls_subject_alt_names_t names;
823
0
  unsigned int type;
824
0
  gnutls_datum_t san;
825
0
  gnutls_datum_t othername;
826
0
  char pfx[16];
827
0
  int err;
828
829
0
  err = gnutls_subject_alt_names_init(&names);
830
0
  if (err < 0) {
831
0
    addf(str, "error: gnutls_subject_alt_names_init: %s\n",
832
0
         gnutls_strerror(err));
833
0
    return;
834
0
  }
835
836
0
  err = gnutls_x509_ext_import_subject_alt_names(der, names, 0);
837
0
  if (err < 0) {
838
0
    addf(str,
839
0
         "error: gnutls_x509_ext_import_subject_alt_names: %s\n",
840
0
         gnutls_strerror(err));
841
0
    goto cleanup;
842
0
  }
843
844
0
  for (altname_idx = 0;; altname_idx++) {
845
0
    err = gnutls_subject_alt_names_get(names, altname_idx, &type,
846
0
               &san, &othername);
847
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
848
0
      break;
849
0
    else if (err < 0) {
850
0
      addf(str, "error: gnutls_subject_alt_names_get: %s\n",
851
0
           gnutls_strerror(err));
852
0
      break;
853
0
    }
854
855
0
    if (type == GNUTLS_SAN_OTHERNAME) {
856
0
      unsigned vtype;
857
0
      gnutls_datum_t virt;
858
859
0
      err = gnutls_x509_othername_to_virtual(
860
0
        (char *)othername.data, &san, &vtype, &virt);
861
0
      if (err >= 0) {
862
0
        snprintf(pfx, sizeof(pfx), "%s\t\t\t", prefix);
863
0
        print_name(str, pfx, vtype, &virt, 0);
864
0
        gnutls_free(virt.data);
865
0
        continue;
866
0
      }
867
868
0
      addf(str, _("%s\t\t\totherName OID: %.*s\n"), prefix,
869
0
           (int)othername.size, (char *)othername.data);
870
0
      addf(str, _("%s\t\t\totherName DER: "), prefix);
871
0
      _gnutls_buffer_hexprint(str, san.data, san.size);
872
0
      addf(str, _("\n%s\t\t\totherName ASCII: "), prefix);
873
0
      _gnutls_buffer_asciiprint(str, (char *)san.data,
874
0
              san.size);
875
0
      addf(str, "\n");
876
0
    } else {
877
0
      snprintf(pfx, sizeof(pfx), "%s\t\t\t", prefix);
878
0
      print_name(str, pfx, type, &san, 0);
879
0
    }
880
0
  }
881
882
0
cleanup:
883
0
  gnutls_subject_alt_names_deinit(names);
884
0
}
885
886
static void guiddump(gnutls_buffer_st *str, const char *data, size_t len,
887
         const char *spc)
888
0
{
889
0
  size_t j;
890
891
0
  if (spc)
892
0
    adds(str, spc);
893
0
  addf(str, "{");
894
0
  addf(str, "%.2X", (unsigned char)data[3]);
895
0
  addf(str, "%.2X", (unsigned char)data[2]);
896
0
  addf(str, "%.2X", (unsigned char)data[1]);
897
0
  addf(str, "%.2X", (unsigned char)data[0]);
898
0
  addf(str, "-");
899
0
  addf(str, "%.2X", (unsigned char)data[5]);
900
0
  addf(str, "%.2X", (unsigned char)data[4]);
901
0
  addf(str, "-");
902
0
  addf(str, "%.2X", (unsigned char)data[7]);
903
0
  addf(str, "%.2X", (unsigned char)data[6]);
904
0
  addf(str, "-");
905
0
  addf(str, "%.2X", (unsigned char)data[8]);
906
0
  addf(str, "%.2X", (unsigned char)data[9]);
907
0
  addf(str, "-");
908
0
  for (j = 10; j < 16; j++) {
909
0
    addf(str, "%.2X", (unsigned char)data[j]);
910
0
  }
911
0
  addf(str, "}\n");
912
0
}
913
914
static void print_unique_ids(gnutls_buffer_st *str,
915
           const gnutls_x509_crt_t cert)
916
0
{
917
0
  int result;
918
0
  char buf[256]; /* if its longer, we won't bother to print it */
919
0
  size_t buf_size = 256;
920
921
0
  result = gnutls_x509_crt_get_issuer_unique_id(cert, buf, &buf_size);
922
0
  if (result >= 0) {
923
0
    addf(str, ("\tIssuer Unique ID:\n"));
924
0
    _gnutls_buffer_hexdump(str, buf, buf_size, "\t\t\t");
925
0
    if (buf_size == 16) { /* this could be a GUID */
926
0
      guiddump(str, buf, buf_size, "\t\t\t");
927
0
    }
928
0
  }
929
930
0
  buf_size = 256;
931
0
  result = gnutls_x509_crt_get_subject_unique_id(cert, buf, &buf_size);
932
0
  if (result >= 0) {
933
0
    addf(str, ("\tSubject Unique ID:\n"));
934
0
    _gnutls_buffer_hexdump(str, buf, buf_size, "\t\t\t");
935
0
    if (buf_size == 16) { /* this could be a GUID */
936
0
      guiddump(str, buf, buf_size, "\t\t\t");
937
0
    }
938
0
  }
939
0
}
940
941
static void print_tlsfeatures(gnutls_buffer_st *str, const char *prefix,
942
            const gnutls_datum_t *der)
943
0
{
944
0
  int err;
945
0
  int seq;
946
0
  gnutls_x509_tlsfeatures_t features;
947
0
  const char *name;
948
0
  unsigned int feature;
949
950
0
  err = gnutls_x509_tlsfeatures_init(&features);
951
0
  if (err < 0)
952
0
    return;
953
954
0
  err = gnutls_x509_ext_import_tlsfeatures(der, features, 0);
955
0
  if (err < 0) {
956
0
    addf(str, "error: get_tlsfeatures: %s\n", gnutls_strerror(err));
957
0
    goto cleanup;
958
0
  }
959
960
0
  for (seq = 0;; seq++) {
961
0
    err = gnutls_x509_tlsfeatures_get(features, seq, &feature);
962
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
963
0
      goto cleanup;
964
0
    if (err < 0) {
965
0
      addf(str, "error: get_tlsfeatures: %s\n",
966
0
           gnutls_strerror(err));
967
0
      goto cleanup;
968
0
    }
969
970
0
    name = gnutls_ext_get_name(feature);
971
0
    if (name == NULL)
972
0
      addf(str, "%s\t\t\t%u\n", prefix, feature);
973
0
    else
974
0
      addf(str, "%s\t\t\t%s(%u)\n", prefix, name, feature);
975
0
  }
976
977
0
cleanup:
978
0
  gnutls_x509_tlsfeatures_deinit(features);
979
0
}
980
981
static void print_subject_sign_tool(gnutls_buffer_st *str, const char *prefix,
982
            const gnutls_datum_t *der)
983
0
{
984
0
  int ret;
985
0
  gnutls_datum_t tmp = { NULL, 0 };
986
987
0
  ret = _gnutls_x509_decode_string(ASN1_ETYPE_UTF8_STRING, der->data,
988
0
           der->size, &tmp, 0);
989
0
  if (ret < 0) {
990
0
    addf(str, _("%s\t\t\tASCII: "), prefix);
991
0
    _gnutls_buffer_asciiprint(str, (char *)der->data, der->size);
992
993
0
    addf(str, "\n");
994
0
    addf(str, _("%s\t\t\tHexdump: "), prefix);
995
0
    _gnutls_buffer_hexprint(str, (char *)der->data, der->size);
996
0
    adds(str, "\n");
997
998
0
    return;
999
0
  }
1000
1001
0
  addf(str, _("%s\t\t\t%.*s\n"), prefix, tmp.size, NON_NULL(tmp.data));
1002
0
  _gnutls_free_datum(&tmp);
1003
0
}
1004
1005
static void print_issuer_sign_tool(gnutls_buffer_st *str, const char *prefix,
1006
           const gnutls_datum_t *der)
1007
0
{
1008
0
  int ret;
1009
0
  asn1_node tmpasn = NULL;
1010
0
  char asn1_err[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = "";
1011
0
  gnutls_datum_t tmp;
1012
1013
0
  if (asn1_create_element(_gnutls_get_gnutls_asn(),
1014
0
        "GNUTLS.IssuerSignTool",
1015
0
        &tmpasn) != ASN1_SUCCESS) {
1016
0
    gnutls_assert();
1017
0
    goto hexdump;
1018
0
  }
1019
1020
0
  if (_asn1_strict_der_decode(&tmpasn, der->data, der->size, asn1_err) !=
1021
0
      ASN1_SUCCESS) {
1022
0
    gnutls_assert();
1023
0
    _gnutls_debug_log("_asn1_strict_der_decode: %s\n", asn1_err);
1024
0
    goto hexdump;
1025
0
  }
1026
1027
0
  ret = _gnutls_x509_read_value(tmpasn, "signTool", &tmp);
1028
0
  if (ret < 0) {
1029
0
    gnutls_assert();
1030
0
    goto hexdump;
1031
0
  }
1032
0
  addf(str, _("%s\t\t\tSignTool: %.*s\n"), prefix, tmp.size,
1033
0
       NON_NULL(tmp.data));
1034
0
  _gnutls_free_datum(&tmp);
1035
1036
0
  ret = _gnutls_x509_read_value(tmpasn, "cATool", &tmp);
1037
0
  if (ret < 0) {
1038
0
    gnutls_assert();
1039
0
    goto hexdump;
1040
0
  }
1041
0
  addf(str, _("%s\t\t\tCATool: %.*s\n"), prefix, tmp.size,
1042
0
       NON_NULL(tmp.data));
1043
0
  _gnutls_free_datum(&tmp);
1044
1045
0
  ret = _gnutls_x509_read_value(tmpasn, "signToolCert", &tmp);
1046
0
  if (ret < 0) {
1047
0
    gnutls_assert();
1048
0
    goto hexdump;
1049
0
  }
1050
0
  addf(str, _("%s\t\t\tSignToolCert: %.*s\n"), prefix, tmp.size,
1051
0
       NON_NULL(tmp.data));
1052
0
  _gnutls_free_datum(&tmp);
1053
1054
0
  ret = _gnutls_x509_read_value(tmpasn, "cAToolCert", &tmp);
1055
0
  if (ret < 0) {
1056
0
    gnutls_assert();
1057
0
    goto hexdump;
1058
0
  }
1059
0
  addf(str, _("%s\t\t\tCAToolCert: %.*s\n"), prefix, tmp.size,
1060
0
       NON_NULL(tmp.data));
1061
0
  _gnutls_free_datum(&tmp);
1062
1063
0
  asn1_delete_structure(&tmpasn);
1064
1065
0
  return;
1066
1067
0
hexdump:
1068
0
  asn1_delete_structure(&tmpasn);
1069
1070
0
  addf(str, _("%s\t\t\tASCII: "), prefix);
1071
0
  _gnutls_buffer_asciiprint(str, (char *)der->data, der->size);
1072
1073
0
  addf(str, "\n");
1074
0
  addf(str, _("%s\t\t\tHexdump: "), prefix);
1075
0
  _gnutls_buffer_hexprint(str, (char *)der->data, der->size);
1076
0
  adds(str, "\n");
1077
0
}
1078
1079
#define ENTRY(oid, name) \
1080
  { oid, sizeof(oid) - 1, name, sizeof(name) - 1, NULL, 0 }
1081
1082
static const struct oid_to_string cp_oid2str[] = {
1083
  ENTRY("2.5.29.32.0", "anyPolicy"),
1084
1085
  ENTRY("2.23.140.1.2.1", "CA/B Domain Validated"),
1086
  ENTRY("2.23.140.1.2.2", "CA/B Organization Validated"),
1087
  ENTRY("2.23.140.1.2.3", "CA/B Individual Validated"),
1088
  ENTRY("2.23.140.1.1", "CA/B Extended Validation"),
1089
1090
  /* draft-deremin-rfc4491-bis */
1091
  ENTRY("1.2.643.100.113.1", "Russian security class KC1"),
1092
  ENTRY("1.2.643.100.113.2", "Russian security class KC2"),
1093
  ENTRY("1.2.643.100.113.3", "Russian security class KC3"),
1094
  ENTRY("1.2.643.100.113.4", "Russian security class KB1"),
1095
  ENTRY("1.2.643.100.113.5", "Russian security class KB2"),
1096
  ENTRY("1.2.643.100.113.6", "Russian security class KA1"),
1097
1098
  { NULL, 0, NULL, 0 },
1099
};
1100
1101
struct ext_indexes_st {
1102
  int san;
1103
  int ian;
1104
  int proxy;
1105
  int basic;
1106
  int keyusage;
1107
  int keypurpose;
1108
  int ski;
1109
  int aki, nc;
1110
  int crldist, pkey_usage_period;
1111
  int tlsfeatures;
1112
};
1113
1114
static void print_extension(gnutls_buffer_st *str, const char *prefix,
1115
          struct ext_indexes_st *idx, const char *oid,
1116
          unsigned critical, gnutls_datum_t *der)
1117
0
{
1118
0
  int err;
1119
0
  unsigned j;
1120
0
  char pfx[16];
1121
1122
0
  if (strcmp(oid, "2.5.29.19") == 0) {
1123
0
    if (idx->basic) {
1124
0
      addf(str, "warning: more than one basic constraint\n");
1125
0
    }
1126
1127
0
    addf(str, _("%s\t\tBasic Constraints (%s):\n"), prefix,
1128
0
         critical ? _("critical") : _("not critical"));
1129
1130
0
    print_basic(str, prefix, der);
1131
0
    idx->basic++;
1132
1133
0
  } else if (strcmp(oid, "2.5.29.14") == 0) {
1134
0
    if (idx->ski) {
1135
0
      addf(str, "warning: more than one SKI extension\n");
1136
0
    }
1137
1138
0
    addf(str, _("%s\t\tSubject Key Identifier (%s):\n"), prefix,
1139
0
         critical ? _("critical") : _("not critical"));
1140
1141
0
    print_ski(str, der);
1142
1143
0
    idx->ski++;
1144
0
  } else if (strcmp(oid, "2.5.29.32") == 0) {
1145
0
    struct gnutls_x509_policy_st policy;
1146
0
    gnutls_x509_policies_t policies;
1147
0
    const char *name;
1148
0
    const struct oid_to_string *entry;
1149
0
    int x;
1150
1151
0
    err = gnutls_x509_policies_init(&policies);
1152
0
    if (err < 0) {
1153
0
      addf(str, "error: certificate policies: %s\n",
1154
0
           gnutls_strerror(err));
1155
0
      return;
1156
0
    }
1157
1158
0
    err = gnutls_x509_ext_import_policies(der, policies, 0);
1159
0
    if (err < 0) {
1160
0
      addf(str, "error: certificate policies import: %s\n",
1161
0
           gnutls_strerror(err));
1162
0
      gnutls_x509_policies_deinit(policies);
1163
0
      return;
1164
0
    }
1165
1166
0
    for (x = 0;; x++) {
1167
0
      err = gnutls_x509_policies_get(policies, x, &policy);
1168
0
      if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1169
0
        break;
1170
1171
0
      if (err < 0) {
1172
0
        addf(str, "error: certificate policy: %s\n",
1173
0
             gnutls_strerror(err));
1174
0
        break;
1175
0
      }
1176
1177
0
      if (x == 0)
1178
0
        addf(str, "%s\t\tCertificate Policies (%s):\n",
1179
0
             prefix,
1180
0
             critical ? _("critical") :
1181
0
            _("not critical"));
1182
1183
0
      entry = _gnutls_oid_get_entry(cp_oid2str, policy.oid);
1184
0
      if (entry != NULL && entry->name_desc != NULL)
1185
0
        addf(str, "%s\t\t\t%s (%s)\n", prefix,
1186
0
             policy.oid, entry->name_desc);
1187
0
      else
1188
0
        addf(str, "%s\t\t\t%s\n", prefix, policy.oid);
1189
0
      for (j = 0; j < policy.qualifiers; j++) {
1190
0
        if (policy.qualifier[j].type ==
1191
0
            GNUTLS_X509_QUALIFIER_URI)
1192
0
          name = "URI";
1193
0
        else if (policy.qualifier[j].type ==
1194
0
           GNUTLS_X509_QUALIFIER_NOTICE)
1195
0
          name = "Note";
1196
0
        else
1197
0
          name = "Unknown qualifier";
1198
0
        addf(str, "%s\t\t\t\t%s: %s\n", prefix, name,
1199
0
             policy.qualifier[j].data);
1200
0
      }
1201
0
    }
1202
0
    gnutls_x509_policies_deinit(policies);
1203
0
  } else if (strcmp(oid, "2.5.29.54") == 0) {
1204
0
    unsigned int skipcerts;
1205
1206
0
    err = gnutls_x509_ext_import_inhibit_anypolicy(der, &skipcerts);
1207
0
    if (err < 0) {
1208
0
      addf(str,
1209
0
           "error: certificate inhibit any policy import: %s\n",
1210
0
           gnutls_strerror(err));
1211
0
      return;
1212
0
    }
1213
1214
0
    addf(str, "%s\t\tInhibit anyPolicy skip certs: %u (%s)\n",
1215
0
         prefix, skipcerts,
1216
0
         critical ? _("critical") : _("not critical"));
1217
1218
0
  } else if (strcmp(oid, "2.5.29.35") == 0) {
1219
0
    if (idx->aki) {
1220
0
      addf(str, "warning: more than one AKI extension\n");
1221
0
    }
1222
1223
0
    addf(str, _("%s\t\tAuthority Key Identifier (%s):\n"), prefix,
1224
0
         critical ? _("critical") : _("not critical"));
1225
1226
0
    print_aki(str, der);
1227
1228
0
    idx->aki++;
1229
0
  } else if (strcmp(oid, "2.5.29.15") == 0) {
1230
0
    if (idx->keyusage) {
1231
0
      addf(str,
1232
0
           "warning: more than one key usage extension\n");
1233
0
    }
1234
1235
0
    addf(str, _("%s\t\tKey Usage (%s):\n"), prefix,
1236
0
         critical ? _("critical") : _("not critical"));
1237
1238
0
    snprintf(pfx, sizeof(pfx), "%s\t\t\t", prefix);
1239
0
    print_key_usage(str, pfx, der);
1240
1241
0
    idx->keyusage++;
1242
0
  } else if (strcmp(oid, "2.5.29.16") == 0) {
1243
0
    if (idx->pkey_usage_period) {
1244
0
      addf(str,
1245
0
           "warning: more than one private key usage period extension\n");
1246
0
    }
1247
1248
0
    addf(str, _("%s\t\tPrivate Key Usage Period (%s):\n"), prefix,
1249
0
         critical ? _("critical") : _("not critical"));
1250
1251
0
    print_private_key_usage_period(str, prefix, der);
1252
1253
0
    idx->pkey_usage_period++;
1254
0
  } else if (strcmp(oid, "2.5.29.37") == 0) {
1255
0
    if (idx->keypurpose) {
1256
0
      addf(str,
1257
0
           "warning: more than one key purpose extension\n");
1258
0
    }
1259
1260
0
    addf(str, _("%s\t\tKey Purpose (%s):\n"), prefix,
1261
0
         critical ? _("critical") : _("not critical"));
1262
1263
0
    print_key_purpose(str, prefix, der);
1264
0
    idx->keypurpose++;
1265
0
  } else if (strcmp(oid, "2.5.29.17") == 0) {
1266
0
    if (idx->san) {
1267
0
      addf(str, "warning: more than one SKI extension\n");
1268
0
    }
1269
1270
0
    addf(str, _("%s\t\tSubject Alternative Name (%s):\n"), prefix,
1271
0
         critical ? _("critical") : _("not critical"));
1272
0
    print_altname(str, prefix, der);
1273
0
    idx->san++;
1274
0
  } else if (strcmp(oid, "2.5.29.18") == 0) {
1275
0
    if (idx->ian) {
1276
0
      addf(str,
1277
0
           "warning: more than one Issuer AltName extension\n");
1278
0
    }
1279
1280
0
    addf(str, _("%s\t\tIssuer Alternative Name (%s):\n"), prefix,
1281
0
         critical ? _("critical") : _("not critical"));
1282
1283
0
    print_altname(str, prefix, der);
1284
1285
0
    idx->ian++;
1286
0
  } else if (strcmp(oid, "2.5.29.31") == 0) {
1287
0
    if (idx->crldist) {
1288
0
      addf(str,
1289
0
           "warning: more than one CRL distribution point\n");
1290
0
    }
1291
1292
0
    addf(str, _("%s\t\tCRL Distribution points (%s):\n"), prefix,
1293
0
         critical ? _("critical") : _("not critical"));
1294
1295
0
    print_crldist(str, der);
1296
0
    idx->crldist++;
1297
0
  } else if (strcmp(oid, "1.3.6.1.5.5.7.1.14") == 0) {
1298
0
    if (idx->proxy) {
1299
0
      addf(str, "warning: more than one proxy extension\n");
1300
0
    }
1301
1302
0
    addf(str, _("%s\t\tProxy Certificate Information (%s):\n"),
1303
0
         prefix, critical ? _("critical") : _("not critical"));
1304
1305
0
    print_proxy(str, der);
1306
1307
0
    idx->proxy++;
1308
0
  } else if (strcmp(oid, "1.3.6.1.5.5.7.1.1") == 0) {
1309
0
    addf(str,
1310
0
         _("%s\t\tAuthority Information "
1311
0
           "Access (%s):\n"),
1312
0
         prefix, critical ? _("critical") : _("not critical"));
1313
1314
0
    print_aia(str, der);
1315
0
  } else if (strcmp(oid, GNUTLS_X509EXT_OID_CT_SCT_V1) == 0) {
1316
0
    addf(str, _("%s\t\tCT Precertificate SCTs (%s):\n"), prefix,
1317
0
         critical ? _("critical") : _("not critical"));
1318
1319
0
    print_scts(str, der, prefix);
1320
0
  } else if (strcmp(oid, "2.5.29.30") == 0) {
1321
0
    if (idx->nc) {
1322
0
      addf(str,
1323
0
           "warning: more than one name constraints extension\n");
1324
0
    }
1325
0
    idx->nc++;
1326
1327
0
    addf(str, _("%s\t\tName Constraints (%s):\n"), prefix,
1328
0
         critical ? _("critical") : _("not critical"));
1329
1330
0
    print_nc(str, prefix, der);
1331
0
  } else if (strcmp(oid, GNUTLS_X509EXT_OID_TLSFEATURES) == 0) {
1332
0
    if (idx->tlsfeatures) {
1333
0
      addf(str,
1334
0
           "warning: more than one tlsfeatures extension\n");
1335
0
    }
1336
1337
0
    addf(str, _("%s\t\tTLS Features (%s):\n"), prefix,
1338
0
         critical ? _("critical") : _("not critical"));
1339
1340
0
    print_tlsfeatures(str, prefix, der);
1341
1342
0
    idx->tlsfeatures++;
1343
0
  } else if (strcmp(oid, "1.2.643.100.111") == 0) {
1344
0
    addf(str, _("%s\t\tSubject Signing Tool(%s):\n"), prefix,
1345
0
         critical ? _("critical") : _("not critical"));
1346
1347
0
    print_subject_sign_tool(str, prefix, der);
1348
0
  } else if (strcmp(oid, "1.2.643.100.112") == 0) {
1349
0
    addf(str, _("%s\t\tIssuer Signing Tool(%s):\n"), prefix,
1350
0
         critical ? _("critical") : _("not critical"));
1351
1352
0
    print_issuer_sign_tool(str, prefix, der);
1353
0
  } else if (strcmp(oid, "2.5.4.3") == 0) {
1354
0
    int ret;
1355
0
    gnutls_datum_t tmp = { NULL, 0 };
1356
1357
0
    addf(str, _("%s\t\tCommon Name (%s):\n"), prefix,
1358
0
         critical ? _("critical") : _("not critical"));
1359
1360
0
    ret = _gnutls_x509_decode_string(ASN1_ETYPE_PRINTABLE_STRING,
1361
0
             der->data, der->size, &tmp, 0);
1362
0
    if (ret < 0) {
1363
0
      addf(str, "error: x509_decode_string: %s\n",
1364
0
           gnutls_strerror(ret));
1365
0
    } else {
1366
0
      addf(str, "%s\t\t\t%s\n", prefix, tmp.data);
1367
0
      gnutls_free(tmp.data);
1368
0
    }
1369
0
  } else {
1370
0
    addf(str, _("%s\t\tUnknown extension %s (%s):\n"), prefix, oid,
1371
0
         critical ? _("critical") : _("not critical"));
1372
1373
0
    addf(str, _("%s\t\t\tASCII: "), prefix);
1374
0
    _gnutls_buffer_asciiprint(str, (char *)der->data, der->size);
1375
1376
0
    addf(str, "\n");
1377
0
    addf(str, _("%s\t\t\tHexdump: "), prefix);
1378
0
    _gnutls_buffer_hexprint(str, (char *)der->data, der->size);
1379
0
    adds(str, "\n");
1380
0
  }
1381
0
}
1382
1383
static void print_extensions(gnutls_buffer_st *str, const char *prefix,
1384
           int type, cert_type_t cert)
1385
0
{
1386
0
  unsigned i;
1387
0
  int err;
1388
0
  gnutls_datum_t der = { NULL, 0 };
1389
0
  struct ext_indexes_st idx;
1390
1391
0
  memset(&idx, 0, sizeof(idx));
1392
1393
0
  for (i = 0;; i++) {
1394
0
    char oid[MAX_OID_SIZE] = "";
1395
0
    size_t sizeof_oid = sizeof(oid);
1396
0
    unsigned int critical;
1397
1398
0
    if (type == TYPE_CRT)
1399
0
      err = gnutls_x509_crt_get_extension_info(
1400
0
        cert.crt, i, oid, &sizeof_oid, &critical);
1401
1402
0
    else if (type == TYPE_CRQ)
1403
0
      err = gnutls_x509_crq_get_extension_info(
1404
0
        cert.crq, i, oid, &sizeof_oid, &critical);
1405
0
    else {
1406
0
      gnutls_assert();
1407
0
      return;
1408
0
    }
1409
1410
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1411
0
      break;
1412
0
    if (err < 0) {
1413
0
      addf(str, "error: get_extension_info: %s\n",
1414
0
           gnutls_strerror(err));
1415
0
      break;
1416
0
    }
1417
1418
0
    if (i == 0)
1419
0
      addf(str, _("%s\tExtensions:\n"), prefix);
1420
1421
0
    if (type == TYPE_CRT)
1422
0
      err = gnutls_x509_crt_get_extension_data2(cert.crt, i,
1423
0
                  &der);
1424
0
    else
1425
0
      err = gnutls_x509_crq_get_extension_data2(cert.crq, i,
1426
0
                  &der);
1427
1428
0
    if (err < 0) {
1429
0
      der.data = NULL;
1430
0
      der.size = 0;
1431
0
    }
1432
1433
0
    print_extension(str, prefix, &idx, oid, critical, &der);
1434
0
    gnutls_free(der.data);
1435
0
  }
1436
0
}
1437
1438
static void reverse_datum(gnutls_datum_t *d)
1439
0
{
1440
0
  unsigned int i;
1441
0
  unsigned char c;
1442
1443
0
  for (i = 0; i < d->size / 2; i++) {
1444
0
    c = d->data[i];
1445
0
    d->data[i] = d->data[d->size - i - 1];
1446
0
    d->data[d->size - i - 1] = c;
1447
0
  }
1448
0
}
1449
1450
static void print_pubkey(gnutls_buffer_st *str, const char *key_name,
1451
       gnutls_pubkey_t pubkey, gnutls_x509_spki_st *spki,
1452
       gnutls_certificate_print_formats_t format)
1453
0
{
1454
0
  int err;
1455
0
  const char *name;
1456
0
  unsigned bits;
1457
0
  unsigned pk;
1458
1459
0
  err = gnutls_pubkey_get_pk_algorithm(pubkey, &bits);
1460
0
  if (err < 0) {
1461
0
    addf(str, "error: get_pk_algorithm: %s\n",
1462
0
         gnutls_strerror(err));
1463
0
    return;
1464
0
  }
1465
1466
0
  pk = err;
1467
1468
0
  name = gnutls_pk_algorithm_get_name(pk);
1469
0
  if (name == NULL)
1470
0
    name = _("unknown");
1471
1472
0
  addf(str, _("\t%sPublic Key Algorithm: %s\n"), key_name, name);
1473
1474
0
  addf(str, _("\tAlgorithm Security Level: %s (%d bits)\n"),
1475
0
       gnutls_sec_param_get_name(gnutls_pk_bits_to_sec_param(err, bits)),
1476
0
       bits);
1477
1478
0
  if (spki && pk == GNUTLS_PK_RSA_PSS && spki->pk == pk) {
1479
0
    addf(str, _("\t\tParameters:\n"));
1480
0
    addf(str, "\t\t\tHash Algorithm: %s\n",
1481
0
         gnutls_digest_get_name(spki->rsa_pss_dig));
1482
0
    addf(str, "\t\t\tSalt Length: %d\n", spki->salt_size);
1483
0
  }
1484
1485
0
  switch (pk) {
1486
0
  case GNUTLS_PK_RSA:
1487
0
  case GNUTLS_PK_RSA_PSS:
1488
0
  case GNUTLS_PK_RSA_OAEP: {
1489
0
    gnutls_datum_t m, e;
1490
1491
0
    err = gnutls_pubkey_get_pk_rsa_raw(pubkey, &m, &e);
1492
0
    if (err < 0)
1493
0
      addf(str, "error: get_pk_rsa_raw: %s\n",
1494
0
           gnutls_strerror(err));
1495
0
    else {
1496
0
      if (format == GNUTLS_CRT_PRINT_FULL_NUMBERS) {
1497
0
        addf(str, _("\t\tModulus (bits %d): "), bits);
1498
0
        _gnutls_buffer_hexprint(str, m.data, m.size);
1499
0
        adds(str, "\n");
1500
0
        addf(str, _("\t\tExponent (bits %d): "),
1501
0
             e.size * 8);
1502
0
        _gnutls_buffer_hexprint(str, e.data, e.size);
1503
0
        adds(str, "\n");
1504
0
      } else {
1505
0
        addf(str, _("\t\tModulus (bits %d):\n"), bits);
1506
0
        _gnutls_buffer_hexdump(str, m.data, m.size,
1507
0
                   "\t\t\t");
1508
0
        addf(str, _("\t\tExponent (bits %d):\n"),
1509
0
             e.size * 8);
1510
0
        _gnutls_buffer_hexdump(str, e.data, e.size,
1511
0
                   "\t\t\t");
1512
0
      }
1513
1514
0
      gnutls_free(m.data);
1515
0
      gnutls_free(e.data);
1516
0
    }
1517
1518
0
  } break;
1519
1520
0
  case GNUTLS_PK_EDDSA_ED25519:
1521
0
  case GNUTLS_PK_EDDSA_ED448:
1522
0
  case GNUTLS_PK_ECDH_X25519:
1523
0
  case GNUTLS_PK_ECDH_X448:
1524
0
  case GNUTLS_PK_ECDSA: {
1525
0
    gnutls_datum_t x, y;
1526
0
    gnutls_ecc_curve_t curve;
1527
1528
0
    err = gnutls_pubkey_get_pk_ecc_raw(pubkey, &curve, &x, &y);
1529
0
    if (err < 0) {
1530
0
      addf(str, "error: get_pk_ecc_raw: %s\n",
1531
0
           gnutls_strerror(err));
1532
0
    } else {
1533
0
      addf(str, _("\t\tCurve:\t%s\n"),
1534
0
           gnutls_ecc_curve_get_name(curve));
1535
0
      if (format == GNUTLS_CRT_PRINT_FULL_NUMBERS) {
1536
0
        adds(str, _("\t\tX: "));
1537
0
        _gnutls_buffer_hexprint(str, x.data, x.size);
1538
0
        adds(str, "\n");
1539
0
        if (y.size > 0) {
1540
0
          adds(str, _("\t\tY: "));
1541
0
          _gnutls_buffer_hexprint(str, y.data,
1542
0
                y.size);
1543
0
          adds(str, "\n");
1544
0
        }
1545
0
      } else {
1546
0
        adds(str, _("\t\tX:\n"));
1547
0
        _gnutls_buffer_hexdump(str, x.data, x.size,
1548
0
                   "\t\t\t");
1549
0
        if (y.size > 0) {
1550
0
          adds(str, _("\t\tY:\n"));
1551
0
          _gnutls_buffer_hexdump(
1552
0
            str, y.data, y.size, "\t\t\t");
1553
0
        }
1554
0
      }
1555
1556
0
      gnutls_free(x.data);
1557
0
      gnutls_free(y.data);
1558
0
    }
1559
0
  } break;
1560
0
  case GNUTLS_PK_DSA: {
1561
0
    gnutls_datum_t p, q, g, y;
1562
1563
0
    err = gnutls_pubkey_get_pk_dsa_raw(pubkey, &p, &q, &g, &y);
1564
0
    if (err < 0)
1565
0
      addf(str, "error: get_pk_dsa_raw: %s\n",
1566
0
           gnutls_strerror(err));
1567
0
    else {
1568
0
      if (format == GNUTLS_CRT_PRINT_FULL_NUMBERS) {
1569
0
        addf(str, _("\t\tPublic key (bits %d): "),
1570
0
             bits);
1571
0
        _gnutls_buffer_hexprint(str, y.data, y.size);
1572
0
        adds(str, "\n");
1573
0
        adds(str, _("\t\tP: "));
1574
0
        _gnutls_buffer_hexprint(str, p.data, p.size);
1575
0
        adds(str, "\n");
1576
0
        adds(str, _("\t\tQ: "));
1577
0
        _gnutls_buffer_hexprint(str, q.data, q.size);
1578
0
        adds(str, "\n");
1579
0
        adds(str, _("\t\tG: "));
1580
0
        _gnutls_buffer_hexprint(str, g.data, g.size);
1581
0
        adds(str, "\n");
1582
0
      } else {
1583
0
        addf(str, _("\t\tPublic key (bits %d):\n"),
1584
0
             bits);
1585
0
        _gnutls_buffer_hexdump(str, y.data, y.size,
1586
0
                   "\t\t\t");
1587
0
        adds(str, _("\t\tP:\n"));
1588
0
        _gnutls_buffer_hexdump(str, p.data, p.size,
1589
0
                   "\t\t\t");
1590
0
        adds(str, _("\t\tQ:\n"));
1591
0
        _gnutls_buffer_hexdump(str, q.data, q.size,
1592
0
                   "\t\t\t");
1593
0
        adds(str, _("\t\tG:\n"));
1594
0
        _gnutls_buffer_hexdump(str, g.data, g.size,
1595
0
                   "\t\t\t");
1596
0
      }
1597
1598
0
      gnutls_free(p.data);
1599
0
      gnutls_free(q.data);
1600
0
      gnutls_free(g.data);
1601
0
      gnutls_free(y.data);
1602
0
    }
1603
0
  } break;
1604
1605
0
  case GNUTLS_PK_GOST_01:
1606
0
  case GNUTLS_PK_GOST_12_256:
1607
0
  case GNUTLS_PK_GOST_12_512: {
1608
0
    gnutls_datum_t x, y;
1609
0
    gnutls_ecc_curve_t curve;
1610
0
    gnutls_digest_algorithm_t digest;
1611
0
    gnutls_gost_paramset_t param;
1612
1613
0
    err = gnutls_pubkey_export_gost_raw2(pubkey, &curve, &digest,
1614
0
                 &param, &x, &y, 0);
1615
0
    if (err < 0)
1616
0
      addf(str, "error: get_pk_gost_raw: %s\n",
1617
0
           gnutls_strerror(err));
1618
0
    else {
1619
0
      addf(str, _("\t\tCurve:\t%s\n"),
1620
0
           gnutls_ecc_curve_get_name(curve));
1621
0
      addf(str, _("\t\tDigest:\t%s\n"),
1622
0
           gnutls_digest_get_name(digest));
1623
0
      addf(str, _("\t\tParamSet: %s\n"),
1624
0
           gnutls_gost_paramset_get_name(param));
1625
0
      reverse_datum(&x);
1626
0
      reverse_datum(&y);
1627
0
      if (format == GNUTLS_CRT_PRINT_FULL_NUMBERS) {
1628
0
        adds(str, _("\t\tX: "));
1629
0
        _gnutls_buffer_hexprint(str, x.data, x.size);
1630
0
        adds(str, "\n");
1631
0
        adds(str, _("\t\tY: "));
1632
0
        _gnutls_buffer_hexprint(str, y.data, y.size);
1633
0
        adds(str, "\n");
1634
0
      } else {
1635
0
        adds(str, _("\t\tX:\n"));
1636
0
        _gnutls_buffer_hexdump(str, x.data, x.size,
1637
0
                   "\t\t\t");
1638
0
        adds(str, _("\t\tY:\n"));
1639
0
        _gnutls_buffer_hexdump(str, y.data, y.size,
1640
0
                   "\t\t\t");
1641
0
      }
1642
1643
0
      gnutls_free(x.data);
1644
0
      gnutls_free(y.data);
1645
0
    }
1646
0
  } break;
1647
1648
0
  default:
1649
0
    break;
1650
0
  }
1651
0
}
1652
1653
static int print_crt_sig_params(gnutls_buffer_st *str, gnutls_x509_crt_t crt,
1654
        gnutls_certificate_print_formats_t format)
1655
0
{
1656
0
  int ret;
1657
0
  gnutls_pk_algorithm_t pk;
1658
0
  gnutls_x509_spki_st params;
1659
0
  gnutls_sign_algorithm_t sign;
1660
1661
0
  sign = gnutls_x509_crt_get_signature_algorithm(crt);
1662
0
  pk = gnutls_sign_get_pk_algorithm(sign);
1663
0
  if (pk == GNUTLS_PK_RSA_PSS) {
1664
0
    ret = _gnutls_x509_read_sign_params(
1665
0
      crt->cert, "signatureAlgorithm", &params);
1666
0
    if (ret < 0) {
1667
0
      addf(str, "error: read_pss_params: %s\n",
1668
0
           gnutls_strerror(ret));
1669
0
    } else
1670
0
      addf(str, "\t\tSalt Length: %d\n", params.salt_size);
1671
0
  }
1672
1673
0
  return 0;
1674
0
}
1675
1676
static void print_pk_name(gnutls_buffer_st *str, gnutls_x509_crt_t crt)
1677
0
{
1678
0
  const char *p;
1679
0
  char *name = get_pk_name(crt, NULL);
1680
0
  if (name == NULL)
1681
0
    p = _("unknown");
1682
0
  else
1683
0
    p = name;
1684
1685
0
  addf(str, "\tSubject Public Key Algorithm: %s\n", p);
1686
0
  gnutls_free(name);
1687
0
}
1688
1689
static int print_crt_pubkey(gnutls_buffer_st *str, gnutls_x509_crt_t crt,
1690
          gnutls_certificate_print_formats_t format)
1691
0
{
1692
0
  gnutls_pubkey_t pubkey = NULL;
1693
0
  gnutls_x509_spki_st params;
1694
0
  int ret, pk;
1695
1696
0
  ret = _gnutls_x509_crt_read_spki_params(crt, &params);
1697
0
  if (ret < 0)
1698
0
    return ret;
1699
1700
0
  pk = gnutls_x509_crt_get_pk_algorithm(crt, NULL);
1701
0
  if (pk < 0) {
1702
0
    gnutls_assert();
1703
0
    pk = GNUTLS_PK_UNKNOWN;
1704
0
  }
1705
1706
0
  if (pk == GNUTLS_PK_UNKNOWN) {
1707
0
    print_pk_name(str, crt); /* print basic info only */
1708
0
    return 0;
1709
0
  }
1710
1711
0
  ret = gnutls_pubkey_init(&pubkey);
1712
0
  if (ret < 0)
1713
0
    return ret;
1714
1715
0
  ret = gnutls_pubkey_import_x509(pubkey, crt, 0);
1716
0
  if (ret < 0) {
1717
0
    if (ret != GNUTLS_E_UNIMPLEMENTED_FEATURE)
1718
0
      addf(str, "error importing public key: %s\n",
1719
0
           gnutls_strerror(ret));
1720
0
    print_pk_name(str, crt); /* print basic info only */
1721
0
    ret = 0;
1722
0
    goto cleanup;
1723
0
  }
1724
1725
0
  print_pubkey(str, _("Subject "), pubkey, &params, format);
1726
0
  ret = 0;
1727
1728
0
cleanup:
1729
0
  gnutls_pubkey_deinit(pubkey);
1730
1731
0
  return ret;
1732
0
}
1733
1734
static void print_cert(gnutls_buffer_st *str, gnutls_x509_crt_t cert,
1735
           gnutls_certificate_print_formats_t format)
1736
0
{
1737
  /* Version. */
1738
0
  {
1739
0
    int version = gnutls_x509_crt_get_version(cert);
1740
0
    if (version < 0)
1741
0
      addf(str, "error: get_version: %s\n",
1742
0
           gnutls_strerror(version));
1743
0
    else
1744
0
      addf(str, _("\tVersion: %d\n"), version);
1745
0
  }
1746
1747
  /* Serial. */
1748
0
  {
1749
0
    char serial[128];
1750
0
    size_t serial_size = sizeof(serial);
1751
0
    int err;
1752
1753
0
    err = gnutls_x509_crt_get_serial(cert, serial, &serial_size);
1754
0
    if (err < 0)
1755
0
      addf(str, "error: get_serial: %s\n",
1756
0
           gnutls_strerror(err));
1757
0
    else {
1758
0
      adds(str, _("\tSerial Number (hex): "));
1759
0
      _gnutls_buffer_hexprint(str, serial, serial_size);
1760
0
      adds(str, "\n");
1761
0
    }
1762
0
  }
1763
1764
  /* Issuer. */
1765
0
  if (format != GNUTLS_CRT_PRINT_UNSIGNED_FULL) {
1766
0
    gnutls_datum_t dn;
1767
0
    int err;
1768
1769
0
    err = gnutls_x509_crt_get_issuer_dn3(cert, &dn, 0);
1770
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1771
0
      addf(str, _("\tIssuer:\n"));
1772
0
    } else if (err < 0) {
1773
0
      addf(str, "error: get_issuer_dn: %s\n",
1774
0
           gnutls_strerror(err));
1775
0
    } else {
1776
0
      addf(str, _("\tIssuer: %s\n"), dn.data);
1777
0
      gnutls_free(dn.data);
1778
0
    }
1779
0
  }
1780
1781
  /* Validity. */
1782
0
  {
1783
0
    time_t tim;
1784
1785
0
    adds(str, _("\tValidity:\n"));
1786
1787
0
    tim = gnutls_x509_crt_get_activation_time(cert);
1788
0
    if (tim != -1) {
1789
0
      char s[42];
1790
0
      size_t max = sizeof(s);
1791
0
      struct tm t;
1792
1793
0
      if (gmtime_r(&tim, &t) == NULL)
1794
0
        addf(str, "error: gmtime_r (%ld)\n",
1795
0
             (unsigned long)tim);
1796
0
      else if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y",
1797
0
            &t) == 0)
1798
0
        addf(str, "error: strftime (%ld)\n",
1799
0
             (unsigned long)tim);
1800
0
      else
1801
0
        addf(str, _("\t\tNot Before: %s\n"), s);
1802
0
    } else {
1803
0
      addf(str, _("\t\tNot Before: %s\n"), _("unknown"));
1804
0
    }
1805
1806
0
    tim = gnutls_x509_crt_get_expiration_time(cert);
1807
0
    if (tim != -1) {
1808
0
      char s[42];
1809
0
      size_t max = sizeof(s);
1810
0
      struct tm t;
1811
1812
0
      if (gmtime_r(&tim, &t) == NULL)
1813
0
        addf(str, "error: gmtime_r (%ld)\n",
1814
0
             (unsigned long)tim);
1815
0
      else if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y",
1816
0
            &t) == 0)
1817
0
        addf(str, "error: strftime (%ld)\n",
1818
0
             (unsigned long)tim);
1819
0
      else
1820
0
        addf(str, _("\t\tNot After: %s\n"), s);
1821
0
    } else {
1822
0
      addf(str, _("\t\tNot After: %s\n"), _("unknown"));
1823
0
    }
1824
0
  }
1825
1826
  /* Subject. */
1827
0
  {
1828
0
    gnutls_datum_t dn;
1829
0
    int err;
1830
1831
0
    err = gnutls_x509_crt_get_dn3(cert, &dn, 0);
1832
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1833
0
      addf(str, _("\tSubject:\n"));
1834
0
    } else if (err < 0) {
1835
0
      addf(str, "error: get_dn: %s\n", gnutls_strerror(err));
1836
0
    } else {
1837
0
      addf(str, _("\tSubject: %s\n"), dn.data);
1838
0
      gnutls_free(dn.data);
1839
0
    }
1840
0
  }
1841
1842
  /* SubjectPublicKeyInfo. */
1843
0
  print_crt_pubkey(str, cert, format);
1844
1845
0
  print_unique_ids(str, cert);
1846
1847
  /* Extensions. */
1848
0
  if (gnutls_x509_crt_get_version(cert) >= 3) {
1849
0
    cert_type_t ccert;
1850
1851
0
    ccert.crt = cert;
1852
0
    print_extensions(str, "", TYPE_CRT, ccert);
1853
0
  }
1854
1855
  /* Signature. */
1856
0
  if (format != GNUTLS_CRT_PRINT_UNSIGNED_FULL) {
1857
0
    int err;
1858
0
    size_t size = 0;
1859
0
    char *buffer = NULL;
1860
0
    char *name;
1861
0
    const char *p;
1862
1863
0
    name = get_sign_name(cert, &err);
1864
0
    if (name == NULL)
1865
0
      p = _("unknown");
1866
0
    else
1867
0
      p = name;
1868
1869
0
    addf(str, _("\tSignature Algorithm: %s\n"), p);
1870
0
    gnutls_free(name);
1871
1872
0
    print_crt_sig_params(str, cert, format);
1873
1874
0
    if (err != GNUTLS_SIGN_UNKNOWN &&
1875
0
        gnutls_sign_is_secure2(
1876
0
          err, GNUTLS_SIGN_FLAG_SECURE_FOR_CERTS) == 0) {
1877
0
      adds(str, _("warning: signed using a broken signature "
1878
0
            "algorithm that can be forged.\n"));
1879
0
    }
1880
1881
0
    err = gnutls_x509_crt_get_signature(cert, buffer, &size);
1882
0
    if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
1883
0
      addf(str, "error: get_signature: %s\n",
1884
0
           gnutls_strerror(err));
1885
0
      return;
1886
0
    }
1887
1888
0
    buffer = gnutls_malloc(size);
1889
0
    if (!buffer) {
1890
0
      addf(str, "error: malloc: %s\n",
1891
0
           gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
1892
0
      return;
1893
0
    }
1894
1895
0
    err = gnutls_x509_crt_get_signature(cert, buffer, &size);
1896
0
    if (err < 0) {
1897
0
      gnutls_free(buffer);
1898
0
      addf(str, "error: get_signature2: %s\n",
1899
0
           gnutls_strerror(err));
1900
0
      return;
1901
0
    }
1902
1903
0
    adds(str, _("\tSignature:\n"));
1904
0
    _gnutls_buffer_hexdump(str, buffer, size, "\t\t");
1905
1906
0
    gnutls_free(buffer);
1907
0
  }
1908
0
}
1909
1910
static void print_fingerprint(gnutls_buffer_st *str, gnutls_x509_crt_t cert)
1911
0
{
1912
0
  int err;
1913
0
  char buffer[MAX_HASH_SIZE];
1914
0
  size_t size = sizeof(buffer);
1915
1916
0
  adds(str, _("\tFingerprint:\n"));
1917
1918
0
  err = gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, buffer,
1919
0
                &size);
1920
0
  if (err < 0) {
1921
0
    addf(str, "error: get_fingerprint: %s\n", gnutls_strerror(err));
1922
0
    return;
1923
0
  }
1924
1925
0
  adds(str, _("\t\tsha1:"));
1926
0
  _gnutls_buffer_hexprint(str, buffer, size);
1927
0
  adds(str, "\n");
1928
1929
0
  size = sizeof(buffer);
1930
0
  err = gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA256, buffer,
1931
0
                &size);
1932
0
  if (err < 0) {
1933
0
    addf(str, "error: get_fingerprint: %s\n", gnutls_strerror(err));
1934
0
    return;
1935
0
  }
1936
0
  adds(str, _("\t\tsha256:"));
1937
0
  _gnutls_buffer_hexprint(str, buffer, size);
1938
0
  adds(str, "\n");
1939
0
}
1940
1941
typedef int get_id_func(void *obj, unsigned, unsigned char *, size_t *);
1942
1943
static void print_obj_id(gnutls_buffer_st *str, const char *prefix, void *obj,
1944
       get_id_func *get_id)
1945
0
{
1946
0
  unsigned char sha1_buffer[MAX_HASH_SIZE];
1947
0
  unsigned char sha2_buffer[MAX_HASH_SIZE];
1948
0
  int err;
1949
0
  size_t sha1_size, sha2_size;
1950
1951
0
  sha1_size = sizeof(sha1_buffer);
1952
0
  err = get_id(obj, GNUTLS_KEYID_USE_SHA1, sha1_buffer, &sha1_size);
1953
0
  if (err == GNUTLS_E_UNIMPLEMENTED_FEATURE) /* unsupported algo */
1954
0
    return;
1955
1956
0
  if (err < 0) {
1957
0
    addf(str, "error: get_key_id(sha1): %s\n",
1958
0
         gnutls_strerror(err));
1959
0
    return;
1960
0
  }
1961
1962
0
  sha2_size = sizeof(sha2_buffer);
1963
0
  err = get_id(obj, GNUTLS_KEYID_USE_SHA256, sha2_buffer, &sha2_size);
1964
0
  if (err == GNUTLS_E_UNIMPLEMENTED_FEATURE) /* unsupported algo */
1965
0
    return;
1966
1967
0
  if (err < 0) {
1968
0
    addf(str, "error: get_key_id(sha256): %s\n",
1969
0
         gnutls_strerror(err));
1970
0
    return;
1971
0
  }
1972
1973
0
  addf(str, _("%sPublic Key ID:\n%s\tsha1:"), prefix, prefix);
1974
0
  _gnutls_buffer_hexprint(str, sha1_buffer, sha1_size);
1975
0
  addf(str, "\n%s\tsha256:", prefix);
1976
0
  _gnutls_buffer_hexprint(str, sha2_buffer, sha2_size);
1977
0
  adds(str, "\n");
1978
1979
0
  addf(str, _("%sPublic Key PIN:\n%s\tpin-sha256:"), prefix, prefix);
1980
0
  _gnutls_buffer_base64print(str, sha2_buffer, sha2_size);
1981
0
  adds(str, "\n");
1982
1983
0
  return;
1984
0
}
1985
1986
static void print_keyid(gnutls_buffer_st *str, gnutls_x509_crt_t cert)
1987
0
{
1988
0
  int err;
1989
0
  const char *name;
1990
0
  unsigned int bits;
1991
0
  unsigned char sha1_buffer[MAX_HASH_SIZE];
1992
0
  size_t sha1_size;
1993
1994
0
  err = gnutls_x509_crt_get_pk_algorithm(cert, &bits);
1995
0
  if (err < 0)
1996
0
    return;
1997
1998
0
  print_obj_id(str, "\t", cert,
1999
0
         (get_id_func *)gnutls_x509_crt_get_key_id);
2000
2001
0
  if (IS_EC(err)) {
2002
0
    gnutls_ecc_curve_t curve;
2003
2004
0
    err = gnutls_x509_crt_get_pk_ecc_raw(cert, &curve, NULL, NULL);
2005
0
    if (err < 0)
2006
0
      return;
2007
2008
0
    name = gnutls_ecc_curve_get_name(curve);
2009
0
    bits = 0;
2010
0
  } else if (IS_GOSTEC(err)) {
2011
0
    gnutls_ecc_curve_t curve;
2012
2013
0
    err = gnutls_x509_crt_get_pk_gost_raw(cert, &curve, NULL, NULL,
2014
0
                  NULL, NULL);
2015
0
    if (err < 0)
2016
0
      return;
2017
2018
0
    name = gnutls_ecc_curve_get_name(curve);
2019
0
    bits = 0;
2020
0
  } else {
2021
0
    name = gnutls_pk_get_name(err);
2022
0
  }
2023
2024
0
  if (name == NULL)
2025
0
    return;
2026
2027
0
  sha1_size = sizeof(sha1_buffer);
2028
0
  err = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA1,
2029
0
           sha1_buffer, &sha1_size);
2030
0
  if (err == GNUTLS_E_UNIMPLEMENTED_FEATURE) /* unsupported algo */
2031
0
    return;
2032
0
}
2033
2034
static void print_other(gnutls_buffer_st *str, gnutls_x509_crt_t cert,
2035
      gnutls_certificate_print_formats_t format)
2036
0
{
2037
0
  if (format != GNUTLS_CRT_PRINT_UNSIGNED_FULL) {
2038
0
    print_fingerprint(str, cert);
2039
0
  }
2040
0
  print_keyid(str, cert);
2041
0
}
2042
2043
static void print_oneline(gnutls_buffer_st *str, gnutls_x509_crt_t cert)
2044
0
{
2045
0
  int err;
2046
2047
  /* Subject. */
2048
0
  {
2049
0
    gnutls_datum_t dn;
2050
2051
0
    err = gnutls_x509_crt_get_dn3(cert, &dn, 0);
2052
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2053
0
      addf(str, _("no subject,"));
2054
0
    } else if (err < 0) {
2055
0
      addf(str, "unknown subject (%s), ",
2056
0
           gnutls_strerror(err));
2057
0
    } else {
2058
0
      addf(str, "subject `%s', ", dn.data);
2059
0
      gnutls_free(dn.data);
2060
0
    }
2061
0
  }
2062
2063
  /* Issuer. */
2064
0
  {
2065
0
    gnutls_datum_t dn;
2066
2067
0
    err = gnutls_x509_crt_get_issuer_dn3(cert, &dn, 0);
2068
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2069
0
      addf(str, _("no issuer,"));
2070
0
    } else if (err < 0) {
2071
0
      addf(str, "unknown issuer (%s), ",
2072
0
           gnutls_strerror(err));
2073
0
    } else {
2074
0
      addf(str, "issuer `%s', ", dn.data);
2075
0
      gnutls_free(dn.data);
2076
0
    }
2077
0
  }
2078
2079
0
  {
2080
0
    char serial[128];
2081
0
    size_t serial_size = sizeof(serial);
2082
2083
0
    err = gnutls_x509_crt_get_serial(cert, serial, &serial_size);
2084
0
    if (err >= 0) {
2085
0
      adds(str, "serial 0x");
2086
0
      _gnutls_buffer_hexprint(str, serial, serial_size);
2087
0
      adds(str, ", ");
2088
0
    }
2089
0
  }
2090
2091
  /* Key algorithm and size. */
2092
0
  {
2093
0
    unsigned int bits;
2094
0
    const char *p;
2095
0
    char *name = get_pk_name(cert, &bits);
2096
0
    if (name == NULL)
2097
0
      p = _("unknown");
2098
0
    else
2099
0
      p = name;
2100
0
    addf(str, "%s key %d bits, ", p, bits);
2101
0
    gnutls_free(name);
2102
0
  }
2103
2104
  /* Signature Algorithm. */
2105
0
  {
2106
0
    char *name = get_sign_name(cert, &err);
2107
0
    const char *p;
2108
2109
0
    if (name == NULL)
2110
0
      p = _("unknown");
2111
0
    else
2112
0
      p = name;
2113
2114
0
    if (err != GNUTLS_SIGN_UNKNOWN &&
2115
0
        gnutls_sign_is_secure2(
2116
0
          err, GNUTLS_SIGN_FLAG_SECURE_FOR_CERTS) == 0)
2117
0
      addf(str, _("signed using %s (broken!), "), p);
2118
0
    else
2119
0
      addf(str, _("signed using %s, "), p);
2120
0
    gnutls_free(name);
2121
0
  }
2122
2123
  /* Validity. */
2124
0
  {
2125
0
    time_t tim;
2126
2127
0
    tim = gnutls_x509_crt_get_activation_time(cert);
2128
0
    {
2129
0
      char s[42];
2130
0
      size_t max = sizeof(s);
2131
0
      struct tm t;
2132
2133
0
      if (gmtime_r(&tim, &t) == NULL)
2134
0
        addf(str, "unknown activation (%ld), ",
2135
0
             (unsigned long)tim);
2136
0
      else if (strftime(s, max, "%Y-%m-%d %H:%M:%S UTC",
2137
0
            &t) == 0)
2138
0
        addf(str, "failed activation (%ld), ",
2139
0
             (unsigned long)tim);
2140
0
      else
2141
0
        addf(str, "activated `%s', ", s);
2142
0
    }
2143
2144
0
    tim = gnutls_x509_crt_get_expiration_time(cert);
2145
0
    {
2146
0
      char s[42];
2147
0
      size_t max = sizeof(s);
2148
0
      struct tm t;
2149
2150
0
      if (gmtime_r(&tim, &t) == NULL)
2151
0
        addf(str, "unknown expiry (%ld), ",
2152
0
             (unsigned long)tim);
2153
0
      else if (strftime(s, max, "%Y-%m-%d %H:%M:%S UTC",
2154
0
            &t) == 0)
2155
0
        addf(str, "failed expiry (%ld), ",
2156
0
             (unsigned long)tim);
2157
0
      else
2158
0
        addf(str, "expires `%s', ", s);
2159
0
    }
2160
0
  }
2161
2162
0
  {
2163
0
    int pathlen;
2164
0
    char *policyLanguage;
2165
2166
0
    err = gnutls_x509_crt_get_proxy(cert, NULL, &pathlen,
2167
0
            &policyLanguage, NULL, NULL);
2168
0
    if (err == 0) {
2169
0
      addf(str, "proxy certificate (policy=");
2170
0
      if (strcmp(policyLanguage, "1.3.6.1.5.5.7.21.1") == 0)
2171
0
        addf(str, "id-ppl-inheritALL");
2172
0
      else if (strcmp(policyLanguage, "1.3.6.1.5.5.7.21.2") ==
2173
0
         0)
2174
0
        addf(str, "id-ppl-independent");
2175
0
      else
2176
0
        addf(str, "%s", policyLanguage);
2177
0
      if (pathlen >= 0)
2178
0
        addf(str, ", pathlen=%d), ", pathlen);
2179
0
      else
2180
0
        addf(str, "), ");
2181
0
      gnutls_free(policyLanguage);
2182
0
    }
2183
0
  }
2184
2185
0
  {
2186
0
    unsigned char buffer[MAX_HASH_SIZE];
2187
0
    size_t size = sizeof(buffer);
2188
2189
0
    err = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256,
2190
0
             buffer, &size);
2191
0
    if (err >= 0) {
2192
0
      addf(str, "pin-sha256=\"");
2193
0
      _gnutls_buffer_base64print(str, buffer, size);
2194
0
      adds(str, "\"");
2195
0
    }
2196
0
  }
2197
0
}
2198
2199
/**
2200
 * gnutls_x509_crt_print:
2201
 * @cert: The data to be printed
2202
 * @format: Indicate the format to use
2203
 * @out: Newly allocated datum with null terminated string.
2204
 *
2205
 * This function will pretty print a X.509 certificate, suitable for
2206
 * display to a human.
2207
 *
2208
 * If the format is %GNUTLS_CRT_PRINT_FULL then all fields of the
2209
 * certificate will be output, on multiple lines.  The
2210
 * %GNUTLS_CRT_PRINT_ONELINE format will generate one line with some
2211
 * selected fields, which is useful for logging purposes.
2212
 *
2213
 * The output @out needs to be deallocated using gnutls_free().
2214
 *
2215
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2216
 *   negative error value.
2217
 **/
2218
int gnutls_x509_crt_print(gnutls_x509_crt_t cert,
2219
        gnutls_certificate_print_formats_t format,
2220
        gnutls_datum_t *out)
2221
0
{
2222
0
  gnutls_buffer_st str;
2223
0
  int ret;
2224
2225
0
  if (format == GNUTLS_CRT_PRINT_COMPACT) {
2226
0
    _gnutls_buffer_init(&str);
2227
2228
0
    print_oneline(&str, cert);
2229
2230
0
    ret = _gnutls_buffer_append_data(&str, "\n", 1);
2231
0
    if (ret < 0)
2232
0
      return gnutls_assert_val(ret);
2233
2234
0
    print_keyid(&str, cert);
2235
2236
0
    return _gnutls_buffer_to_datum(&str, out, 1);
2237
0
  } else if (format == GNUTLS_CRT_PRINT_ONELINE) {
2238
0
    _gnutls_buffer_init(&str);
2239
2240
0
    print_oneline(&str, cert);
2241
2242
0
    return _gnutls_buffer_to_datum(&str, out, 1);
2243
0
  } else {
2244
0
    _gnutls_buffer_init(&str);
2245
2246
0
    _gnutls_buffer_append_str(
2247
0
      &str, _("X.509 Certificate Information:\n"));
2248
2249
0
    print_cert(&str, cert, format);
2250
2251
0
    _gnutls_buffer_append_str(&str, _("Other Information:\n"));
2252
2253
0
    print_other(&str, cert, format);
2254
2255
0
    return _gnutls_buffer_to_datum(&str, out, 1);
2256
0
  }
2257
0
}
2258
2259
static void print_crl(gnutls_buffer_st *str, gnutls_x509_crl_t crl,
2260
          int notsigned)
2261
0
{
2262
  /* Version. */
2263
0
  {
2264
0
    int version = gnutls_x509_crl_get_version(crl);
2265
0
    if (version < 0)
2266
0
      addf(str, "error: get_version: %s\n",
2267
0
           gnutls_strerror(version));
2268
0
    else
2269
0
      addf(str, _("\tVersion: %d\n"), version);
2270
0
  }
2271
2272
  /* Issuer. */
2273
0
  if (!notsigned) {
2274
0
    gnutls_datum_t dn;
2275
0
    int err;
2276
2277
0
    err = gnutls_x509_crl_get_issuer_dn3(crl, &dn, 0);
2278
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2279
0
      addf(str, _("\tIssuer:\n"));
2280
0
    } else if (err < 0) {
2281
0
      addf(str, "error: get_issuer_dn: %s\n",
2282
0
           gnutls_strerror(err));
2283
0
    } else {
2284
0
      addf(str, _("\tIssuer: %s\n"), dn.data);
2285
0
      gnutls_free(dn.data);
2286
0
    }
2287
0
  }
2288
2289
  /* Validity. */
2290
0
  {
2291
0
    time_t tim;
2292
2293
0
    adds(str, _("\tUpdate dates:\n"));
2294
2295
0
    tim = gnutls_x509_crl_get_this_update(crl);
2296
0
    {
2297
0
      char s[42];
2298
0
      size_t max = sizeof(s);
2299
0
      struct tm t;
2300
2301
0
      if (gmtime_r(&tim, &t) == NULL)
2302
0
        addf(str, "error: gmtime_r (%ld)\n",
2303
0
             (unsigned long)tim);
2304
0
      else if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y",
2305
0
            &t) == 0)
2306
0
        addf(str, "error: strftime (%ld)\n",
2307
0
             (unsigned long)tim);
2308
0
      else
2309
0
        addf(str, _("\t\tIssued: %s\n"), s);
2310
0
    }
2311
2312
0
    tim = gnutls_x509_crl_get_next_update(crl);
2313
0
    {
2314
0
      char s[42];
2315
0
      size_t max = sizeof(s);
2316
0
      struct tm t;
2317
2318
0
      if (tim == -1)
2319
0
        addf(str, "\t\tNo next update time.\n");
2320
0
      else if (gmtime_r(&tim, &t) == NULL)
2321
0
        addf(str, "error: gmtime_r (%ld)\n",
2322
0
             (unsigned long)tim);
2323
0
      else if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y",
2324
0
            &t) == 0)
2325
0
        addf(str, "error: strftime (%ld)\n",
2326
0
             (unsigned long)tim);
2327
0
      else
2328
0
        addf(str, _("\t\tNext at: %s\n"), s);
2329
0
    }
2330
0
  }
2331
2332
  /* Extensions. */
2333
0
  if (gnutls_x509_crl_get_version(crl) >= 2) {
2334
0
    size_t i;
2335
0
    int err = 0;
2336
0
    int aki_idx = 0;
2337
0
    int crl_nr = 0;
2338
2339
0
    for (i = 0;; i++) {
2340
0
      char oid[MAX_OID_SIZE] = "";
2341
0
      size_t sizeof_oid = sizeof(oid);
2342
0
      unsigned int critical;
2343
2344
0
      err = gnutls_x509_crl_get_extension_info(
2345
0
        crl, i, oid, &sizeof_oid, &critical);
2346
0
      if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
2347
0
        break;
2348
0
      if (err < 0) {
2349
0
        addf(str, "error: get_extension_info: %s\n",
2350
0
             gnutls_strerror(err));
2351
0
        break;
2352
0
      }
2353
2354
0
      if (i == 0)
2355
0
        adds(str, _("\tExtensions:\n"));
2356
2357
0
      if (strcmp(oid, "2.5.29.20") == 0) {
2358
0
        char nr[128];
2359
0
        size_t nr_size = sizeof(nr);
2360
2361
0
        if (crl_nr) {
2362
0
          addf(str,
2363
0
               "warning: more than one CRL number\n");
2364
0
        }
2365
2366
0
        err = gnutls_x509_crl_get_number(
2367
0
          crl, nr, &nr_size, &critical);
2368
2369
0
        addf(str, _("\t\tCRL Number (%s): "),
2370
0
             critical ? _("critical") :
2371
0
            _("not critical"));
2372
2373
0
        if (err < 0)
2374
0
          addf(str, "error: get_number: %s\n",
2375
0
               gnutls_strerror(err));
2376
0
        else {
2377
0
          _gnutls_buffer_hexprint(str, nr,
2378
0
                nr_size);
2379
0
          addf(str, "\n");
2380
0
        }
2381
2382
0
        crl_nr++;
2383
0
      } else if (strcmp(oid, "2.5.29.35") == 0) {
2384
0
        gnutls_datum_t der;
2385
2386
0
        if (aki_idx) {
2387
0
          addf(str,
2388
0
               "warning: more than one AKI extension\n");
2389
0
        }
2390
2391
0
        addf(str,
2392
0
             _("\t\tAuthority Key Identifier (%s):\n"),
2393
0
             critical ? _("critical") :
2394
0
            _("not critical"));
2395
2396
0
        err = gnutls_x509_crl_get_extension_data2(
2397
0
          crl, i, &der);
2398
0
        if (err < 0) {
2399
0
          addf(str,
2400
0
               "error: get_extension_data2: %s\n",
2401
0
               gnutls_strerror(err));
2402
0
          continue;
2403
0
        }
2404
0
        print_aki(str, &der);
2405
0
        gnutls_free(der.data);
2406
2407
0
        aki_idx++;
2408
0
      } else {
2409
0
        gnutls_datum_t der;
2410
2411
0
        addf(str, _("\t\tUnknown extension %s (%s):\n"),
2412
0
             oid,
2413
0
             critical ? _("critical") :
2414
0
            _("not critical"));
2415
2416
0
        err = gnutls_x509_crl_get_extension_data2(
2417
0
          crl, i, &der);
2418
0
        if (err < 0) {
2419
0
          addf(str,
2420
0
               "error: get_extension_data2: %s\n",
2421
0
               gnutls_strerror(err));
2422
0
          continue;
2423
0
        }
2424
2425
0
        adds(str, _("\t\t\tASCII: "));
2426
0
        _gnutls_buffer_asciiprint(str, (char *)der.data,
2427
0
                der.size);
2428
0
        adds(str, "\n");
2429
2430
0
        adds(str, _("\t\t\tHexdump: "));
2431
0
        _gnutls_buffer_hexprint(str, der.data,
2432
0
              der.size);
2433
0
        adds(str, "\n");
2434
2435
0
        gnutls_free(der.data);
2436
0
      }
2437
0
    }
2438
0
  }
2439
2440
  /* Revoked certificates. */
2441
0
  {
2442
0
    int num = gnutls_x509_crl_get_crt_count(crl);
2443
0
    gnutls_x509_crl_iter_t iter = NULL;
2444
0
    int j;
2445
2446
0
    if (num)
2447
0
      addf(str, _("\tRevoked certificates (%d):\n"), num);
2448
0
    else
2449
0
      adds(str, _("\tNo revoked certificates.\n"));
2450
2451
0
    for (j = 0; j < num; j++) {
2452
0
      unsigned char serial[128];
2453
0
      size_t serial_size = sizeof(serial);
2454
0
      int err;
2455
0
      time_t tim;
2456
2457
0
      err = gnutls_x509_crl_iter_crt_serial(
2458
0
        crl, &iter, serial, &serial_size, &tim);
2459
0
      if (err < 0) {
2460
0
        addf(str, "error: iter_crt_serial: %s\n",
2461
0
             gnutls_strerror(err));
2462
0
        break;
2463
0
      } else {
2464
0
        char s[42];
2465
0
        size_t max = sizeof(s);
2466
0
        struct tm t;
2467
2468
0
        adds(str, _("\t\tSerial Number (hex): "));
2469
0
        _gnutls_buffer_hexprint(str, serial,
2470
0
              serial_size);
2471
0
        adds(str, "\n");
2472
2473
0
        if (gmtime_r(&tim, &t) == NULL)
2474
0
          addf(str, "error: gmtime_r (%ld)\n",
2475
0
               (unsigned long)tim);
2476
0
        else if (strftime(s, max,
2477
0
              "%a %b %d %H:%M:%S UTC %Y",
2478
0
              &t) == 0)
2479
0
          addf(str, "error: strftime (%ld)\n",
2480
0
               (unsigned long)tim);
2481
0
        else
2482
0
          addf(str, _("\t\tRevoked at: %s\n"), s);
2483
0
      }
2484
0
    }
2485
0
    gnutls_x509_crl_iter_deinit(iter);
2486
0
  }
2487
2488
  /* Signature. */
2489
0
  if (!notsigned) {
2490
0
    int err;
2491
0
    size_t size = 0;
2492
0
    char *buffer = NULL;
2493
0
    char *name;
2494
0
    const char *p;
2495
2496
0
    name = crl_get_sign_name(crl, &err);
2497
0
    if (name == NULL)
2498
0
      p = _("unknown");
2499
0
    else
2500
0
      p = name;
2501
2502
0
    addf(str, _("\tSignature Algorithm: %s\n"), p);
2503
0
    gnutls_free(name);
2504
2505
0
    if (err != GNUTLS_SIGN_UNKNOWN &&
2506
0
        gnutls_sign_is_secure2(
2507
0
          err, GNUTLS_SIGN_FLAG_SECURE_FOR_CERTS) == 0) {
2508
0
      adds(str, _("warning: signed using a broken signature "
2509
0
            "algorithm that can be forged.\n"));
2510
0
    }
2511
2512
0
    err = gnutls_x509_crl_get_signature(crl, buffer, &size);
2513
0
    if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
2514
0
      addf(str, "error: get_signature: %s\n",
2515
0
           gnutls_strerror(err));
2516
0
      return;
2517
0
    }
2518
2519
0
    buffer = gnutls_malloc(size);
2520
0
    if (!buffer) {
2521
0
      addf(str, "error: malloc: %s\n",
2522
0
           gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
2523
0
      return;
2524
0
    }
2525
2526
0
    err = gnutls_x509_crl_get_signature(crl, buffer, &size);
2527
0
    if (err < 0) {
2528
0
      gnutls_free(buffer);
2529
0
      addf(str, "error: get_signature2: %s\n",
2530
0
           gnutls_strerror(err));
2531
0
      return;
2532
0
    }
2533
2534
0
    adds(str, _("\tSignature:\n"));
2535
0
    _gnutls_buffer_hexdump(str, buffer, size, "\t\t");
2536
2537
0
    gnutls_free(buffer);
2538
0
  }
2539
0
}
2540
2541
/**
2542
 * gnutls_x509_crl_print:
2543
 * @crl: The data to be printed
2544
 * @format: Indicate the format to use
2545
 * @out: Newly allocated datum with null terminated string.
2546
 *
2547
 * This function will pretty print a X.509 certificate revocation
2548
 * list, suitable for display to a human.
2549
 *
2550
 * The output @out needs to be deallocated using gnutls_free().
2551
 *
2552
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2553
 *   negative error value.
2554
 **/
2555
int gnutls_x509_crl_print(gnutls_x509_crl_t crl,
2556
        gnutls_certificate_print_formats_t format,
2557
        gnutls_datum_t *out)
2558
0
{
2559
0
  gnutls_buffer_st str;
2560
2561
0
  _gnutls_buffer_init(&str);
2562
2563
0
  _gnutls_buffer_append_str(
2564
0
    &str, _("X.509 Certificate Revocation List Information:\n"));
2565
2566
0
  print_crl(&str, crl, format == GNUTLS_CRT_PRINT_UNSIGNED_FULL);
2567
2568
0
  return _gnutls_buffer_to_datum(&str, out, 1);
2569
0
}
2570
2571
static int print_crq_sig_params(gnutls_buffer_st *str, gnutls_x509_crq_t crt,
2572
        gnutls_certificate_print_formats_t format)
2573
0
{
2574
0
  int ret;
2575
0
  gnutls_pk_algorithm_t pk;
2576
0
  gnutls_x509_spki_st params;
2577
0
  gnutls_sign_algorithm_t sign;
2578
2579
0
  sign = gnutls_x509_crq_get_signature_algorithm(crt);
2580
0
  pk = gnutls_sign_get_pk_algorithm(sign);
2581
0
  if (pk == GNUTLS_PK_RSA_PSS) {
2582
0
    ret = _gnutls_x509_read_sign_params(
2583
0
      crt->crq, "signatureAlgorithm", &params);
2584
0
    if (ret < 0) {
2585
0
      addf(str, "error: read_pss_params: %s\n",
2586
0
           gnutls_strerror(ret));
2587
0
    } else
2588
0
      addf(str, "\t\tSalt Length: %d\n", params.salt_size);
2589
0
  }
2590
2591
0
  return 0;
2592
0
}
2593
2594
static int print_crq_pubkey(gnutls_buffer_st *str, gnutls_x509_crq_t crq,
2595
          gnutls_certificate_print_formats_t format)
2596
0
{
2597
0
  gnutls_pubkey_t pubkey;
2598
0
  gnutls_x509_spki_st params;
2599
0
  int ret;
2600
2601
0
  ret = _gnutls_x509_crq_read_spki_params(crq, &params);
2602
0
  if (ret < 0)
2603
0
    return ret;
2604
2605
0
  ret = gnutls_pubkey_init(&pubkey);
2606
0
  if (ret < 0)
2607
0
    return ret;
2608
2609
0
  ret = gnutls_pubkey_import_x509_crq(pubkey, crq, 0);
2610
0
  if (ret < 0)
2611
0
    goto cleanup;
2612
2613
0
  print_pubkey(str, _("Subject "), pubkey, &params, format);
2614
0
  ret = 0;
2615
2616
0
cleanup:
2617
0
  gnutls_pubkey_deinit(pubkey);
2618
2619
0
  if (ret < 0) { /* print only name */
2620
0
    const char *p;
2621
0
    char *name = crq_get_pk_name(crq);
2622
0
    if (name == NULL)
2623
0
      p = _("unknown");
2624
0
    else
2625
0
      p = name;
2626
2627
0
    addf(str, "\tSubject Public Key Algorithm: %s\n", p);
2628
0
    gnutls_free(name);
2629
0
    ret = 0;
2630
0
  }
2631
2632
0
  return ret;
2633
0
}
2634
2635
static void print_crq(gnutls_buffer_st *str, gnutls_x509_crq_t cert,
2636
          gnutls_certificate_print_formats_t format)
2637
0
{
2638
  /* Version. */
2639
0
  {
2640
0
    int version = gnutls_x509_crq_get_version(cert);
2641
0
    if (version < 0)
2642
0
      addf(str, "error: get_version: %s\n",
2643
0
           gnutls_strerror(version));
2644
0
    else
2645
0
      addf(str, _("\tVersion: %d\n"), version);
2646
0
  }
2647
2648
  /* Subject */
2649
0
  {
2650
0
    gnutls_datum_t dn;
2651
0
    int err;
2652
2653
0
    err = gnutls_x509_crq_get_dn3(cert, &dn, 0);
2654
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2655
0
      addf(str, _("\tSubject:\n"));
2656
0
    } else if (err < 0) {
2657
0
      addf(str, "error: get_dn: %s\n", gnutls_strerror(err));
2658
0
    } else {
2659
0
      addf(str, _("\tSubject: %s\n"), dn.data);
2660
0
      gnutls_free(dn.data);
2661
0
    }
2662
0
  }
2663
2664
0
  {
2665
0
    char *name;
2666
0
    const char *p;
2667
2668
0
    print_crq_pubkey(str, cert, format);
2669
2670
0
    name = crq_get_sign_name(cert);
2671
0
    if (name == NULL)
2672
0
      p = _("unknown");
2673
0
    else
2674
0
      p = name;
2675
2676
0
    addf(str, _("\tSignature Algorithm: %s\n"), p);
2677
2678
0
    gnutls_free(name);
2679
2680
0
    print_crq_sig_params(str, cert, format);
2681
0
  }
2682
2683
  /* parse attributes */
2684
0
  {
2685
0
    size_t i;
2686
0
    int err = 0;
2687
0
    int extensions = 0;
2688
0
    int challenge = 0;
2689
2690
0
    for (i = 0;; i++) {
2691
0
      char oid[MAX_OID_SIZE] = "";
2692
0
      size_t sizeof_oid = sizeof(oid);
2693
2694
0
      err = gnutls_x509_crq_get_attribute_info(cert, i, oid,
2695
0
                 &sizeof_oid);
2696
0
      if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
2697
0
        break;
2698
0
      if (err < 0) {
2699
0
        addf(str, "error: get_extension_info: %s\n",
2700
0
             gnutls_strerror(err));
2701
0
        break;
2702
0
      }
2703
2704
0
      if (i == 0)
2705
0
        adds(str, _("\tAttributes:\n"));
2706
2707
0
      if (strcmp(oid, "1.2.840.113549.1.9.14") == 0) {
2708
0
        cert_type_t ccert;
2709
2710
0
        if (extensions) {
2711
0
          addf(str,
2712
0
               "warning: more than one extensionsRequest\n");
2713
0
        }
2714
2715
0
        ccert.crq = cert;
2716
0
        print_extensions(str, "\t", TYPE_CRQ, ccert);
2717
2718
0
        extensions++;
2719
0
      } else if (strcmp(oid, "1.2.840.113549.1.9.7") == 0) {
2720
0
        char *pass;
2721
0
        size_t size;
2722
2723
0
        if (challenge) {
2724
0
          adds(str,
2725
0
               "warning: more than one Challenge password attribute\n");
2726
0
        }
2727
2728
0
        err = gnutls_x509_crq_get_challenge_password(
2729
0
          cert, NULL, &size);
2730
0
        if (err < 0 &&
2731
0
            err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
2732
0
          addf(str,
2733
0
               "error: get_challenge_password: %s\n",
2734
0
               gnutls_strerror(err));
2735
0
          continue;
2736
0
        }
2737
2738
0
        size++;
2739
2740
0
        pass = gnutls_malloc(size);
2741
0
        if (!pass) {
2742
0
          addf(str, "error: malloc: %s\n",
2743
0
               gnutls_strerror(
2744
0
                 GNUTLS_E_MEMORY_ERROR));
2745
0
          continue;
2746
0
        }
2747
2748
0
        err = gnutls_x509_crq_get_challenge_password(
2749
0
          cert, pass, &size);
2750
0
        if (err < 0)
2751
0
          addf(str,
2752
0
               "error: get_challenge_password: %s\n",
2753
0
               gnutls_strerror(err));
2754
0
        else
2755
0
          addf(str,
2756
0
               _("\t\tChallenge password: %s\n"),
2757
0
               pass);
2758
2759
0
        gnutls_free(pass);
2760
2761
0
        challenge++;
2762
0
      } else {
2763
0
        char *buffer;
2764
0
        size_t extlen = 0;
2765
2766
0
        addf(str, _("\t\tUnknown attribute %s:\n"),
2767
0
             oid);
2768
2769
0
        err = gnutls_x509_crq_get_attribute_data(
2770
0
          cert, i, NULL, &extlen);
2771
0
        if (err < 0) {
2772
0
          addf(str,
2773
0
               "error: get_attribute_data: %s\n",
2774
0
               gnutls_strerror(err));
2775
0
          continue;
2776
0
        }
2777
2778
0
        buffer = gnutls_malloc(extlen);
2779
0
        if (!buffer) {
2780
0
          addf(str, "error: malloc: %s\n",
2781
0
               gnutls_strerror(
2782
0
                 GNUTLS_E_MEMORY_ERROR));
2783
0
          continue;
2784
0
        }
2785
2786
0
        err = gnutls_x509_crq_get_attribute_data(
2787
0
          cert, i, buffer, &extlen);
2788
0
        if (err < 0) {
2789
0
          gnutls_free(buffer);
2790
0
          addf(str,
2791
0
               "error: get_attribute_data2: %s\n",
2792
0
               gnutls_strerror(err));
2793
0
          continue;
2794
0
        }
2795
2796
0
        adds(str, _("\t\t\tASCII: "));
2797
0
        _gnutls_buffer_asciiprint(str, buffer, extlen);
2798
0
        adds(str, "\n");
2799
2800
0
        adds(str, _("\t\t\tHexdump: "));
2801
0
        _gnutls_buffer_hexprint(str, buffer, extlen);
2802
0
        adds(str, "\n");
2803
2804
0
        gnutls_free(buffer);
2805
0
      }
2806
0
    }
2807
0
  }
2808
0
}
2809
2810
static void print_crq_other(gnutls_buffer_st *str, gnutls_x509_crq_t crq)
2811
0
{
2812
0
  int ret;
2813
2814
  /* on unknown public key algorithms don't print the key ID */
2815
0
  ret = gnutls_x509_crq_get_pk_algorithm(crq, NULL);
2816
0
  if (ret < 0)
2817
0
    return;
2818
2819
0
  print_obj_id(str, "\t", crq, (get_id_func *)gnutls_x509_crq_get_key_id);
2820
0
}
2821
2822
/**
2823
 * gnutls_x509_crq_print:
2824
 * @crq: The data to be printed
2825
 * @format: Indicate the format to use
2826
 * @out: Newly allocated datum with null terminated string.
2827
 *
2828
 * This function will pretty print a certificate request, suitable for
2829
 * display to a human.
2830
 *
2831
 * The output @out needs to be deallocated using gnutls_free().
2832
 *
2833
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2834
 *   negative error value.
2835
 *
2836
 * Since: 2.8.0
2837
 **/
2838
int gnutls_x509_crq_print(gnutls_x509_crq_t crq,
2839
        gnutls_certificate_print_formats_t format,
2840
        gnutls_datum_t *out)
2841
0
{
2842
0
  gnutls_buffer_st str;
2843
2844
0
  _gnutls_buffer_init(&str);
2845
2846
0
  _gnutls_buffer_append_str(
2847
0
    &str, _("PKCS #10 Certificate Request Information:\n"));
2848
2849
0
  print_crq(&str, crq, format);
2850
2851
0
  _gnutls_buffer_append_str(&str, _("Other Information:\n"));
2852
2853
0
  print_crq_other(&str, crq);
2854
2855
0
  return _gnutls_buffer_to_datum(&str, out, 1);
2856
0
}
2857
2858
static void print_pubkey_other(gnutls_buffer_st *str, gnutls_pubkey_t pubkey,
2859
             gnutls_certificate_print_formats_t format)
2860
0
{
2861
0
  int ret;
2862
0
  unsigned int usage;
2863
2864
0
  ret = gnutls_pubkey_get_key_usage(pubkey, &usage);
2865
0
  if (ret < 0) {
2866
0
    addf(str, "error: get_key_usage: %s\n", gnutls_strerror(ret));
2867
0
    return;
2868
0
  }
2869
2870
0
  adds(str, "\n");
2871
0
  if (pubkey->key_usage) {
2872
0
    adds(str, _("Public Key Usage:\n"));
2873
0
    print_key_usage2(str, "\t", pubkey->key_usage);
2874
0
  }
2875
2876
  /* on unknown public key algorithms don't print the key ID */
2877
0
  ret = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);
2878
0
  if (ret < 0)
2879
0
    return;
2880
2881
0
  print_obj_id(str, "", pubkey, (get_id_func *)gnutls_pubkey_get_key_id);
2882
0
}
2883
2884
/**
2885
 * gnutls_pubkey_print:
2886
 * @pubkey: The data to be printed
2887
 * @format: Indicate the format to use
2888
 * @out: Newly allocated datum with null terminated string.
2889
 *
2890
 * This function will pretty print public key information, suitable for
2891
 * display to a human.
2892
 *
2893
 * Only %GNUTLS_CRT_PRINT_FULL and %GNUTLS_CRT_PRINT_FULL_NUMBERS
2894
 * are implemented.
2895
 *
2896
 * The output @out needs to be deallocated using gnutls_free().
2897
 *
2898
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2899
 *   negative error value.
2900
 *
2901
 * Since: 3.1.5
2902
 **/
2903
int gnutls_pubkey_print(gnutls_pubkey_t pubkey,
2904
      gnutls_certificate_print_formats_t format,
2905
      gnutls_datum_t *out)
2906
0
{
2907
0
  gnutls_buffer_st str;
2908
2909
0
  _gnutls_buffer_init(&str);
2910
2911
0
  _gnutls_buffer_append_str(&str, _("Public Key Information:\n"));
2912
2913
0
  print_pubkey(&str, "", pubkey, NULL, format);
2914
0
  print_pubkey_other(&str, pubkey, format);
2915
2916
0
  return _gnutls_buffer_to_datum(&str, out, 1);
2917
0
}
2918
2919
/**
2920
 * gnutls_x509_ext_print:
2921
 * @exts: The data to be printed
2922
 * @exts_size: the number of available structures
2923
 * @format: Indicate the format to use
2924
 * @out: Newly allocated datum with null terminated string.
2925
 *
2926
 * This function will pretty print X.509 certificate extensions,
2927
 * suitable for display to a human.
2928
 *
2929
 * The output @out needs to be deallocated using gnutls_free().
2930
 *
2931
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2932
 *   negative error value.
2933
 **/
2934
int gnutls_x509_ext_print(gnutls_x509_ext_st *exts, unsigned int exts_size,
2935
        gnutls_certificate_print_formats_t format,
2936
        gnutls_datum_t *out)
2937
0
{
2938
0
  gnutls_buffer_st str;
2939
0
  struct ext_indexes_st idx;
2940
0
  unsigned i;
2941
2942
0
  memset(&idx, 0, sizeof(idx));
2943
0
  _gnutls_buffer_init(&str);
2944
2945
0
  for (i = 0; i < exts_size; i++)
2946
0
    print_extension(&str, "", &idx, (char *)exts[i].oid,
2947
0
        exts[i].critical, &exts[i].data);
2948
2949
0
  return _gnutls_buffer_to_datum(&str, out, 1);
2950
0
}