Coverage Report

Created: 2024-06-20 06:28

/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
  {                                                             \
1081
    oid, sizeof(oid) - 1, name, sizeof(name) - 1, NULL, 0 \
1082
  }
1083
1084
static const struct oid_to_string cp_oid2str[] = {
1085
  ENTRY("2.5.29.32.0", "anyPolicy"),
1086
1087
  ENTRY("2.23.140.1.2.1", "CA/B Domain Validated"),
1088
  ENTRY("2.23.140.1.2.2", "CA/B Organization Validated"),
1089
  ENTRY("2.23.140.1.2.3", "CA/B Individual Validated"),
1090
  ENTRY("2.23.140.1.1", "CA/B Extended Validation"),
1091
1092
  /* draft-deremin-rfc4491-bis */
1093
  ENTRY("1.2.643.100.113.1", "Russian security class KC1"),
1094
  ENTRY("1.2.643.100.113.2", "Russian security class KC2"),
1095
  ENTRY("1.2.643.100.113.3", "Russian security class KC3"),
1096
  ENTRY("1.2.643.100.113.4", "Russian security class KB1"),
1097
  ENTRY("1.2.643.100.113.5", "Russian security class KB2"),
1098
  ENTRY("1.2.643.100.113.6", "Russian security class KA1"),
1099
1100
  { NULL, 0, NULL, 0 },
1101
};
1102
1103
struct ext_indexes_st {
1104
  int san;
1105
  int ian;
1106
  int proxy;
1107
  int basic;
1108
  int keyusage;
1109
  int keypurpose;
1110
  int ski;
1111
  int aki, nc;
1112
  int crldist, pkey_usage_period;
1113
  int tlsfeatures;
1114
};
1115
1116
static void print_extension(gnutls_buffer_st *str, const char *prefix,
1117
          struct ext_indexes_st *idx, const char *oid,
1118
          unsigned critical, gnutls_datum_t *der)
1119
0
{
1120
0
  int err;
1121
0
  unsigned j;
1122
0
  char pfx[16];
1123
1124
0
  if (strcmp(oid, "2.5.29.19") == 0) {
1125
0
    if (idx->basic) {
1126
0
      addf(str, "warning: more than one basic constraint\n");
1127
0
    }
1128
1129
0
    addf(str, _("%s\t\tBasic Constraints (%s):\n"), prefix,
1130
0
         critical ? _("critical") : _("not critical"));
1131
1132
0
    print_basic(str, prefix, der);
1133
0
    idx->basic++;
1134
1135
0
  } else if (strcmp(oid, "2.5.29.14") == 0) {
1136
0
    if (idx->ski) {
1137
0
      addf(str, "warning: more than one SKI extension\n");
1138
0
    }
1139
1140
0
    addf(str, _("%s\t\tSubject Key Identifier (%s):\n"), prefix,
1141
0
         critical ? _("critical") : _("not critical"));
1142
1143
0
    print_ski(str, der);
1144
1145
0
    idx->ski++;
1146
0
  } else if (strcmp(oid, "2.5.29.32") == 0) {
1147
0
    struct gnutls_x509_policy_st policy;
1148
0
    gnutls_x509_policies_t policies;
1149
0
    const char *name;
1150
0
    const struct oid_to_string *entry;
1151
0
    int x;
1152
1153
0
    err = gnutls_x509_policies_init(&policies);
1154
0
    if (err < 0) {
1155
0
      addf(str, "error: certificate policies: %s\n",
1156
0
           gnutls_strerror(err));
1157
0
      return;
1158
0
    }
1159
1160
0
    err = gnutls_x509_ext_import_policies(der, policies, 0);
1161
0
    if (err < 0) {
1162
0
      addf(str, "error: certificate policies import: %s\n",
1163
0
           gnutls_strerror(err));
1164
0
      gnutls_x509_policies_deinit(policies);
1165
0
      return;
1166
0
    }
1167
1168
0
    for (x = 0;; x++) {
1169
0
      err = gnutls_x509_policies_get(policies, x, &policy);
1170
0
      if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1171
0
        break;
1172
1173
0
      if (err < 0) {
1174
0
        addf(str, "error: certificate policy: %s\n",
1175
0
             gnutls_strerror(err));
1176
0
        break;
1177
0
      }
1178
1179
0
      if (x == 0)
1180
0
        addf(str, "%s\t\tCertificate Policies (%s):\n",
1181
0
             prefix,
1182
0
             critical ? _("critical") :
1183
0
            _("not critical"));
1184
1185
0
      entry = _gnutls_oid_get_entry(cp_oid2str, policy.oid);
1186
0
      if (entry != NULL && entry->name_desc != NULL)
1187
0
        addf(str, "%s\t\t\t%s (%s)\n", prefix,
1188
0
             policy.oid, entry->name_desc);
1189
0
      else
1190
0
        addf(str, "%s\t\t\t%s\n", prefix, policy.oid);
1191
0
      for (j = 0; j < policy.qualifiers; j++) {
1192
0
        if (policy.qualifier[j].type ==
1193
0
            GNUTLS_X509_QUALIFIER_URI)
1194
0
          name = "URI";
1195
0
        else if (policy.qualifier[j].type ==
1196
0
           GNUTLS_X509_QUALIFIER_NOTICE)
1197
0
          name = "Note";
1198
0
        else
1199
0
          name = "Unknown qualifier";
1200
0
        addf(str, "%s\t\t\t\t%s: %s\n", prefix, name,
1201
0
             policy.qualifier[j].data);
1202
0
      }
1203
0
    }
1204
0
    gnutls_x509_policies_deinit(policies);
1205
0
  } else if (strcmp(oid, "2.5.29.54") == 0) {
1206
0
    unsigned int skipcerts;
1207
1208
0
    err = gnutls_x509_ext_import_inhibit_anypolicy(der, &skipcerts);
1209
0
    if (err < 0) {
1210
0
      addf(str,
1211
0
           "error: certificate inhibit any policy import: %s\n",
1212
0
           gnutls_strerror(err));
1213
0
      return;
1214
0
    }
1215
1216
0
    addf(str, "%s\t\tInhibit anyPolicy skip certs: %u (%s)\n",
1217
0
         prefix, skipcerts,
1218
0
         critical ? _("critical") : _("not critical"));
1219
1220
0
  } else if (strcmp(oid, "2.5.29.35") == 0) {
1221
0
    if (idx->aki) {
1222
0
      addf(str, "warning: more than one AKI extension\n");
1223
0
    }
1224
1225
0
    addf(str, _("%s\t\tAuthority Key Identifier (%s):\n"), prefix,
1226
0
         critical ? _("critical") : _("not critical"));
1227
1228
0
    print_aki(str, der);
1229
1230
0
    idx->aki++;
1231
0
  } else if (strcmp(oid, "2.5.29.15") == 0) {
1232
0
    if (idx->keyusage) {
1233
0
      addf(str,
1234
0
           "warning: more than one key usage extension\n");
1235
0
    }
1236
1237
0
    addf(str, _("%s\t\tKey Usage (%s):\n"), prefix,
1238
0
         critical ? _("critical") : _("not critical"));
1239
1240
0
    snprintf(pfx, sizeof(pfx), "%s\t\t\t", prefix);
1241
0
    print_key_usage(str, pfx, der);
1242
1243
0
    idx->keyusage++;
1244
0
  } else if (strcmp(oid, "2.5.29.16") == 0) {
1245
0
    if (idx->pkey_usage_period) {
1246
0
      addf(str,
1247
0
           "warning: more than one private key usage period extension\n");
1248
0
    }
1249
1250
0
    addf(str, _("%s\t\tPrivate Key Usage Period (%s):\n"), prefix,
1251
0
         critical ? _("critical") : _("not critical"));
1252
1253
0
    print_private_key_usage_period(str, prefix, der);
1254
1255
0
    idx->pkey_usage_period++;
1256
0
  } else if (strcmp(oid, "2.5.29.37") == 0) {
1257
0
    if (idx->keypurpose) {
1258
0
      addf(str,
1259
0
           "warning: more than one key purpose extension\n");
1260
0
    }
1261
1262
0
    addf(str, _("%s\t\tKey Purpose (%s):\n"), prefix,
1263
0
         critical ? _("critical") : _("not critical"));
1264
1265
0
    print_key_purpose(str, prefix, der);
1266
0
    idx->keypurpose++;
1267
0
  } else if (strcmp(oid, "2.5.29.17") == 0) {
1268
0
    if (idx->san) {
1269
0
      addf(str, "warning: more than one SKI extension\n");
1270
0
    }
1271
1272
0
    addf(str, _("%s\t\tSubject Alternative Name (%s):\n"), prefix,
1273
0
         critical ? _("critical") : _("not critical"));
1274
0
    print_altname(str, prefix, der);
1275
0
    idx->san++;
1276
0
  } else if (strcmp(oid, "2.5.29.18") == 0) {
1277
0
    if (idx->ian) {
1278
0
      addf(str,
1279
0
           "warning: more than one Issuer AltName extension\n");
1280
0
    }
1281
1282
0
    addf(str, _("%s\t\tIssuer Alternative Name (%s):\n"), prefix,
1283
0
         critical ? _("critical") : _("not critical"));
1284
1285
0
    print_altname(str, prefix, der);
1286
1287
0
    idx->ian++;
1288
0
  } else if (strcmp(oid, "2.5.29.31") == 0) {
1289
0
    if (idx->crldist) {
1290
0
      addf(str,
1291
0
           "warning: more than one CRL distribution point\n");
1292
0
    }
1293
1294
0
    addf(str, _("%s\t\tCRL Distribution points (%s):\n"), prefix,
1295
0
         critical ? _("critical") : _("not critical"));
1296
1297
0
    print_crldist(str, der);
1298
0
    idx->crldist++;
1299
0
  } else if (strcmp(oid, "1.3.6.1.5.5.7.1.14") == 0) {
1300
0
    if (idx->proxy) {
1301
0
      addf(str, "warning: more than one proxy extension\n");
1302
0
    }
1303
1304
0
    addf(str, _("%s\t\tProxy Certificate Information (%s):\n"),
1305
0
         prefix, critical ? _("critical") : _("not critical"));
1306
1307
0
    print_proxy(str, der);
1308
1309
0
    idx->proxy++;
1310
0
  } else if (strcmp(oid, "1.3.6.1.5.5.7.1.1") == 0) {
1311
0
    addf(str,
1312
0
         _("%s\t\tAuthority Information "
1313
0
           "Access (%s):\n"),
1314
0
         prefix, critical ? _("critical") : _("not critical"));
1315
1316
0
    print_aia(str, der);
1317
0
  } else if (strcmp(oid, GNUTLS_X509EXT_OID_CT_SCT_V1) == 0) {
1318
0
    addf(str, _("%s\t\tCT Precertificate SCTs (%s):\n"), prefix,
1319
0
         critical ? _("critical") : _("not critical"));
1320
1321
0
    print_scts(str, der, prefix);
1322
0
  } else if (strcmp(oid, "2.5.29.30") == 0) {
1323
0
    if (idx->nc) {
1324
0
      addf(str,
1325
0
           "warning: more than one name constraints extension\n");
1326
0
    }
1327
0
    idx->nc++;
1328
1329
0
    addf(str, _("%s\t\tName Constraints (%s):\n"), prefix,
1330
0
         critical ? _("critical") : _("not critical"));
1331
1332
0
    print_nc(str, prefix, der);
1333
0
  } else if (strcmp(oid, GNUTLS_X509EXT_OID_TLSFEATURES) == 0) {
1334
0
    if (idx->tlsfeatures) {
1335
0
      addf(str,
1336
0
           "warning: more than one tlsfeatures extension\n");
1337
0
    }
1338
1339
0
    addf(str, _("%s\t\tTLS Features (%s):\n"), prefix,
1340
0
         critical ? _("critical") : _("not critical"));
1341
1342
0
    print_tlsfeatures(str, prefix, der);
1343
1344
0
    idx->tlsfeatures++;
1345
0
  } else if (strcmp(oid, "1.2.643.100.111") == 0) {
1346
0
    addf(str, _("%s\t\tSubject Signing Tool(%s):\n"), prefix,
1347
0
         critical ? _("critical") : _("not critical"));
1348
1349
0
    print_subject_sign_tool(str, prefix, der);
1350
0
  } else if (strcmp(oid, "1.2.643.100.112") == 0) {
1351
0
    addf(str, _("%s\t\tIssuer Signing Tool(%s):\n"), prefix,
1352
0
         critical ? _("critical") : _("not critical"));
1353
1354
0
    print_issuer_sign_tool(str, prefix, der);
1355
0
  } else if (strcmp(oid, "2.5.4.3") == 0) {
1356
0
    int ret;
1357
0
    gnutls_datum_t tmp = { NULL, 0 };
1358
1359
0
    addf(str, _("%s\t\tCommon Name (%s):\n"), prefix,
1360
0
         critical ? _("critical") : _("not critical"));
1361
1362
0
    ret = _gnutls_x509_decode_string(ASN1_ETYPE_PRINTABLE_STRING,
1363
0
             der->data, der->size, &tmp, 0);
1364
0
    if (ret < 0) {
1365
0
      addf(str, "error: x509_decode_string: %s\n",
1366
0
           gnutls_strerror(ret));
1367
0
    } else {
1368
0
      addf(str, "%s\t\t\t%s\n", prefix, tmp.data);
1369
0
      gnutls_free(tmp.data);
1370
0
    }
1371
0
  } else {
1372
0
    addf(str, _("%s\t\tUnknown extension %s (%s):\n"), prefix, oid,
1373
0
         critical ? _("critical") : _("not critical"));
1374
1375
0
    addf(str, _("%s\t\t\tASCII: "), prefix);
1376
0
    _gnutls_buffer_asciiprint(str, (char *)der->data, der->size);
1377
1378
0
    addf(str, "\n");
1379
0
    addf(str, _("%s\t\t\tHexdump: "), prefix);
1380
0
    _gnutls_buffer_hexprint(str, (char *)der->data, der->size);
1381
0
    adds(str, "\n");
1382
0
  }
1383
0
}
1384
1385
static void print_extensions(gnutls_buffer_st *str, const char *prefix,
1386
           int type, cert_type_t cert)
1387
0
{
1388
0
  unsigned i;
1389
0
  int err;
1390
0
  gnutls_datum_t der = { NULL, 0 };
1391
0
  struct ext_indexes_st idx;
1392
1393
0
  memset(&idx, 0, sizeof(idx));
1394
1395
0
  for (i = 0;; i++) {
1396
0
    char oid[MAX_OID_SIZE] = "";
1397
0
    size_t sizeof_oid = sizeof(oid);
1398
0
    unsigned int critical;
1399
1400
0
    if (type == TYPE_CRT)
1401
0
      err = gnutls_x509_crt_get_extension_info(
1402
0
        cert.crt, i, oid, &sizeof_oid, &critical);
1403
1404
0
    else if (type == TYPE_CRQ)
1405
0
      err = gnutls_x509_crq_get_extension_info(
1406
0
        cert.crq, i, oid, &sizeof_oid, &critical);
1407
0
    else {
1408
0
      gnutls_assert();
1409
0
      return;
1410
0
    }
1411
1412
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1413
0
      break;
1414
0
    if (err < 0) {
1415
0
      addf(str, "error: get_extension_info: %s\n",
1416
0
           gnutls_strerror(err));
1417
0
      break;
1418
0
    }
1419
1420
0
    if (i == 0)
1421
0
      addf(str, _("%s\tExtensions:\n"), prefix);
1422
1423
0
    if (type == TYPE_CRT)
1424
0
      err = gnutls_x509_crt_get_extension_data2(cert.crt, i,
1425
0
                  &der);
1426
0
    else
1427
0
      err = gnutls_x509_crq_get_extension_data2(cert.crq, i,
1428
0
                  &der);
1429
1430
0
    if (err < 0) {
1431
0
      der.data = NULL;
1432
0
      der.size = 0;
1433
0
    }
1434
1435
0
    print_extension(str, prefix, &idx, oid, critical, &der);
1436
0
    gnutls_free(der.data);
1437
0
  }
1438
0
}
1439
1440
static void reverse_datum(gnutls_datum_t *d)
1441
0
{
1442
0
  unsigned int i;
1443
0
  unsigned char c;
1444
1445
0
  for (i = 0; i < d->size / 2; i++) {
1446
0
    c = d->data[i];
1447
0
    d->data[i] = d->data[d->size - i - 1];
1448
0
    d->data[d->size - i - 1] = c;
1449
0
  }
1450
0
}
1451
1452
static void print_pubkey(gnutls_buffer_st *str, const char *key_name,
1453
       gnutls_pubkey_t pubkey, gnutls_x509_spki_st *spki,
1454
       gnutls_certificate_print_formats_t format)
1455
0
{
1456
0
  int err;
1457
0
  const char *name;
1458
0
  unsigned bits;
1459
0
  unsigned pk;
1460
1461
0
  err = gnutls_pubkey_get_pk_algorithm(pubkey, &bits);
1462
0
  if (err < 0) {
1463
0
    addf(str, "error: get_pk_algorithm: %s\n",
1464
0
         gnutls_strerror(err));
1465
0
    return;
1466
0
  }
1467
1468
0
  pk = err;
1469
1470
0
  name = gnutls_pk_algorithm_get_name(pk);
1471
0
  if (name == NULL)
1472
0
    name = _("unknown");
1473
1474
0
  addf(str, _("\t%sPublic Key Algorithm: %s\n"), key_name, name);
1475
1476
0
  addf(str, _("\tAlgorithm Security Level: %s (%d bits)\n"),
1477
0
       gnutls_sec_param_get_name(gnutls_pk_bits_to_sec_param(err, bits)),
1478
0
       bits);
1479
1480
0
  if (spki && pk == GNUTLS_PK_RSA_PSS && spki->pk == pk) {
1481
0
    addf(str, _("\t\tParameters:\n"));
1482
0
    addf(str, "\t\t\tHash Algorithm: %s\n",
1483
0
         gnutls_digest_get_name(spki->rsa_pss_dig));
1484
0
    addf(str, "\t\t\tSalt Length: %d\n", spki->salt_size);
1485
0
  }
1486
1487
0
  switch (pk) {
1488
0
  case GNUTLS_PK_RSA:
1489
0
  case GNUTLS_PK_RSA_PSS: {
1490
0
    gnutls_datum_t m, e;
1491
1492
0
    err = gnutls_pubkey_get_pk_rsa_raw(pubkey, &m, &e);
1493
0
    if (err < 0)
1494
0
      addf(str, "error: get_pk_rsa_raw: %s\n",
1495
0
           gnutls_strerror(err));
1496
0
    else {
1497
0
      if (format == GNUTLS_CRT_PRINT_FULL_NUMBERS) {
1498
0
        addf(str, _("\t\tModulus (bits %d): "), bits);
1499
0
        _gnutls_buffer_hexprint(str, m.data, m.size);
1500
0
        adds(str, "\n");
1501
0
        addf(str, _("\t\tExponent (bits %d): "),
1502
0
             e.size * 8);
1503
0
        _gnutls_buffer_hexprint(str, e.data, e.size);
1504
0
        adds(str, "\n");
1505
0
      } else {
1506
0
        addf(str, _("\t\tModulus (bits %d):\n"), bits);
1507
0
        _gnutls_buffer_hexdump(str, m.data, m.size,
1508
0
                   "\t\t\t");
1509
0
        addf(str, _("\t\tExponent (bits %d):\n"),
1510
0
             e.size * 8);
1511
0
        _gnutls_buffer_hexdump(str, e.data, e.size,
1512
0
                   "\t\t\t");
1513
0
      }
1514
1515
0
      gnutls_free(m.data);
1516
0
      gnutls_free(e.data);
1517
0
    }
1518
1519
0
  } break;
1520
1521
0
  case GNUTLS_PK_EDDSA_ED25519:
1522
0
  case GNUTLS_PK_EDDSA_ED448:
1523
0
  case GNUTLS_PK_ECDH_X25519:
1524
0
  case GNUTLS_PK_ECDH_X448:
1525
0
  case GNUTLS_PK_ECDSA: {
1526
0
    gnutls_datum_t x, y;
1527
0
    gnutls_ecc_curve_t curve;
1528
1529
0
    err = gnutls_pubkey_get_pk_ecc_raw(pubkey, &curve, &x, &y);
1530
0
    if (err < 0) {
1531
0
      addf(str, "error: get_pk_ecc_raw: %s\n",
1532
0
           gnutls_strerror(err));
1533
0
    } else {
1534
0
      addf(str, _("\t\tCurve:\t%s\n"),
1535
0
           gnutls_ecc_curve_get_name(curve));
1536
0
      if (format == GNUTLS_CRT_PRINT_FULL_NUMBERS) {
1537
0
        adds(str, _("\t\tX: "));
1538
0
        _gnutls_buffer_hexprint(str, x.data, x.size);
1539
0
        adds(str, "\n");
1540
0
        if (y.size > 0) {
1541
0
          adds(str, _("\t\tY: "));
1542
0
          _gnutls_buffer_hexprint(str, y.data,
1543
0
                y.size);
1544
0
          adds(str, "\n");
1545
0
        }
1546
0
      } else {
1547
0
        adds(str, _("\t\tX:\n"));
1548
0
        _gnutls_buffer_hexdump(str, x.data, x.size,
1549
0
                   "\t\t\t");
1550
0
        if (y.size > 0) {
1551
0
          adds(str, _("\t\tY:\n"));
1552
0
          _gnutls_buffer_hexdump(
1553
0
            str, y.data, y.size, "\t\t\t");
1554
0
        }
1555
0
      }
1556
1557
0
      gnutls_free(x.data);
1558
0
      gnutls_free(y.data);
1559
0
    }
1560
0
  } break;
1561
0
  case GNUTLS_PK_DSA: {
1562
0
    gnutls_datum_t p, q, g, y;
1563
1564
0
    err = gnutls_pubkey_get_pk_dsa_raw(pubkey, &p, &q, &g, &y);
1565
0
    if (err < 0)
1566
0
      addf(str, "error: get_pk_dsa_raw: %s\n",
1567
0
           gnutls_strerror(err));
1568
0
    else {
1569
0
      if (format == GNUTLS_CRT_PRINT_FULL_NUMBERS) {
1570
0
        addf(str, _("\t\tPublic key (bits %d): "),
1571
0
             bits);
1572
0
        _gnutls_buffer_hexprint(str, y.data, y.size);
1573
0
        adds(str, "\n");
1574
0
        adds(str, _("\t\tP: "));
1575
0
        _gnutls_buffer_hexprint(str, p.data, p.size);
1576
0
        adds(str, "\n");
1577
0
        adds(str, _("\t\tQ: "));
1578
0
        _gnutls_buffer_hexprint(str, q.data, q.size);
1579
0
        adds(str, "\n");
1580
0
        adds(str, _("\t\tG: "));
1581
0
        _gnutls_buffer_hexprint(str, g.data, g.size);
1582
0
        adds(str, "\n");
1583
0
      } else {
1584
0
        addf(str, _("\t\tPublic key (bits %d):\n"),
1585
0
             bits);
1586
0
        _gnutls_buffer_hexdump(str, y.data, y.size,
1587
0
                   "\t\t\t");
1588
0
        adds(str, _("\t\tP:\n"));
1589
0
        _gnutls_buffer_hexdump(str, p.data, p.size,
1590
0
                   "\t\t\t");
1591
0
        adds(str, _("\t\tQ:\n"));
1592
0
        _gnutls_buffer_hexdump(str, q.data, q.size,
1593
0
                   "\t\t\t");
1594
0
        adds(str, _("\t\tG:\n"));
1595
0
        _gnutls_buffer_hexdump(str, g.data, g.size,
1596
0
                   "\t\t\t");
1597
0
      }
1598
1599
0
      gnutls_free(p.data);
1600
0
      gnutls_free(q.data);
1601
0
      gnutls_free(g.data);
1602
0
      gnutls_free(y.data);
1603
0
    }
1604
0
  } break;
1605
1606
0
  case GNUTLS_PK_GOST_01:
1607
0
  case GNUTLS_PK_GOST_12_256:
1608
0
  case GNUTLS_PK_GOST_12_512: {
1609
0
    gnutls_datum_t x, y;
1610
0
    gnutls_ecc_curve_t curve;
1611
0
    gnutls_digest_algorithm_t digest;
1612
0
    gnutls_gost_paramset_t param;
1613
1614
0
    err = gnutls_pubkey_export_gost_raw2(pubkey, &curve, &digest,
1615
0
                 &param, &x, &y, 0);
1616
0
    if (err < 0)
1617
0
      addf(str, "error: get_pk_gost_raw: %s\n",
1618
0
           gnutls_strerror(err));
1619
0
    else {
1620
0
      addf(str, _("\t\tCurve:\t%s\n"),
1621
0
           gnutls_ecc_curve_get_name(curve));
1622
0
      addf(str, _("\t\tDigest:\t%s\n"),
1623
0
           gnutls_digest_get_name(digest));
1624
0
      addf(str, _("\t\tParamSet: %s\n"),
1625
0
           gnutls_gost_paramset_get_name(param));
1626
0
      reverse_datum(&x);
1627
0
      reverse_datum(&y);
1628
0
      if (format == GNUTLS_CRT_PRINT_FULL_NUMBERS) {
1629
0
        adds(str, _("\t\tX: "));
1630
0
        _gnutls_buffer_hexprint(str, x.data, x.size);
1631
0
        adds(str, "\n");
1632
0
        adds(str, _("\t\tY: "));
1633
0
        _gnutls_buffer_hexprint(str, y.data, y.size);
1634
0
        adds(str, "\n");
1635
0
      } else {
1636
0
        adds(str, _("\t\tX:\n"));
1637
0
        _gnutls_buffer_hexdump(str, x.data, x.size,
1638
0
                   "\t\t\t");
1639
0
        adds(str, _("\t\tY:\n"));
1640
0
        _gnutls_buffer_hexdump(str, y.data, y.size,
1641
0
                   "\t\t\t");
1642
0
      }
1643
1644
0
      gnutls_free(x.data);
1645
0
      gnutls_free(y.data);
1646
0
    }
1647
0
  } break;
1648
1649
0
  default:
1650
0
    break;
1651
0
  }
1652
0
}
1653
1654
static int print_crt_sig_params(gnutls_buffer_st *str, gnutls_x509_crt_t crt,
1655
        gnutls_certificate_print_formats_t format)
1656
0
{
1657
0
  int ret;
1658
0
  gnutls_pk_algorithm_t pk;
1659
0
  gnutls_x509_spki_st params;
1660
0
  gnutls_sign_algorithm_t sign;
1661
1662
0
  sign = gnutls_x509_crt_get_signature_algorithm(crt);
1663
0
  pk = gnutls_sign_get_pk_algorithm(sign);
1664
0
  if (pk == GNUTLS_PK_RSA_PSS) {
1665
0
    ret = _gnutls_x509_read_sign_params(
1666
0
      crt->cert, "signatureAlgorithm", &params);
1667
0
    if (ret < 0) {
1668
0
      addf(str, "error: read_pss_params: %s\n",
1669
0
           gnutls_strerror(ret));
1670
0
    } else
1671
0
      addf(str, "\t\tSalt Length: %d\n", params.salt_size);
1672
0
  }
1673
1674
0
  return 0;
1675
0
}
1676
1677
static void print_pk_name(gnutls_buffer_st *str, gnutls_x509_crt_t crt)
1678
0
{
1679
0
  const char *p;
1680
0
  char *name = get_pk_name(crt, NULL);
1681
0
  if (name == NULL)
1682
0
    p = _("unknown");
1683
0
  else
1684
0
    p = name;
1685
1686
0
  addf(str, "\tSubject Public Key Algorithm: %s\n", p);
1687
0
  gnutls_free(name);
1688
0
}
1689
1690
static int print_crt_pubkey(gnutls_buffer_st *str, gnutls_x509_crt_t crt,
1691
          gnutls_certificate_print_formats_t format)
1692
0
{
1693
0
  gnutls_pubkey_t pubkey = NULL;
1694
0
  gnutls_x509_spki_st params;
1695
0
  int ret, pk;
1696
1697
0
  ret = _gnutls_x509_crt_read_spki_params(crt, &params);
1698
0
  if (ret < 0)
1699
0
    return ret;
1700
1701
0
  pk = gnutls_x509_crt_get_pk_algorithm(crt, NULL);
1702
0
  if (pk < 0) {
1703
0
    gnutls_assert();
1704
0
    pk = GNUTLS_PK_UNKNOWN;
1705
0
  }
1706
1707
0
  if (pk == GNUTLS_PK_UNKNOWN) {
1708
0
    print_pk_name(str, crt); /* print basic info only */
1709
0
    return 0;
1710
0
  }
1711
1712
0
  ret = gnutls_pubkey_init(&pubkey);
1713
0
  if (ret < 0)
1714
0
    return ret;
1715
1716
0
  ret = gnutls_pubkey_import_x509(pubkey, crt, 0);
1717
0
  if (ret < 0) {
1718
0
    if (ret != GNUTLS_E_UNIMPLEMENTED_FEATURE)
1719
0
      addf(str, "error importing public key: %s\n",
1720
0
           gnutls_strerror(ret));
1721
0
    print_pk_name(str, crt); /* print basic info only */
1722
0
    ret = 0;
1723
0
    goto cleanup;
1724
0
  }
1725
1726
0
  print_pubkey(str, _("Subject "), pubkey, &params, format);
1727
0
  ret = 0;
1728
1729
0
cleanup:
1730
0
  gnutls_pubkey_deinit(pubkey);
1731
1732
0
  return ret;
1733
0
}
1734
1735
static void print_cert(gnutls_buffer_st *str, gnutls_x509_crt_t cert,
1736
           gnutls_certificate_print_formats_t format)
1737
0
{
1738
  /* Version. */
1739
0
  {
1740
0
    int version = gnutls_x509_crt_get_version(cert);
1741
0
    if (version < 0)
1742
0
      addf(str, "error: get_version: %s\n",
1743
0
           gnutls_strerror(version));
1744
0
    else
1745
0
      addf(str, _("\tVersion: %d\n"), version);
1746
0
  }
1747
1748
  /* Serial. */
1749
0
  {
1750
0
    char serial[128];
1751
0
    size_t serial_size = sizeof(serial);
1752
0
    int err;
1753
1754
0
    err = gnutls_x509_crt_get_serial(cert, serial, &serial_size);
1755
0
    if (err < 0)
1756
0
      addf(str, "error: get_serial: %s\n",
1757
0
           gnutls_strerror(err));
1758
0
    else {
1759
0
      adds(str, _("\tSerial Number (hex): "));
1760
0
      _gnutls_buffer_hexprint(str, serial, serial_size);
1761
0
      adds(str, "\n");
1762
0
    }
1763
0
  }
1764
1765
  /* Issuer. */
1766
0
  if (format != GNUTLS_CRT_PRINT_UNSIGNED_FULL) {
1767
0
    gnutls_datum_t dn;
1768
0
    int err;
1769
1770
0
    err = gnutls_x509_crt_get_issuer_dn3(cert, &dn, 0);
1771
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1772
0
      addf(str, _("\tIssuer:\n"));
1773
0
    } else if (err < 0) {
1774
0
      addf(str, "error: get_issuer_dn: %s\n",
1775
0
           gnutls_strerror(err));
1776
0
    } else {
1777
0
      addf(str, _("\tIssuer: %s\n"), dn.data);
1778
0
      gnutls_free(dn.data);
1779
0
    }
1780
0
  }
1781
1782
  /* Validity. */
1783
0
  {
1784
0
    time_t tim;
1785
1786
0
    adds(str, _("\tValidity:\n"));
1787
1788
0
    tim = gnutls_x509_crt_get_activation_time(cert);
1789
0
    if (tim != -1) {
1790
0
      char s[42];
1791
0
      size_t max = sizeof(s);
1792
0
      struct tm t;
1793
1794
0
      if (gmtime_r(&tim, &t) == NULL)
1795
0
        addf(str, "error: gmtime_r (%ld)\n",
1796
0
             (unsigned long)tim);
1797
0
      else if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y",
1798
0
            &t) == 0)
1799
0
        addf(str, "error: strftime (%ld)\n",
1800
0
             (unsigned long)tim);
1801
0
      else
1802
0
        addf(str, _("\t\tNot Before: %s\n"), s);
1803
0
    } else {
1804
0
      addf(str, _("\t\tNot Before: %s\n"), _("unknown"));
1805
0
    }
1806
1807
0
    tim = gnutls_x509_crt_get_expiration_time(cert);
1808
0
    if (tim != -1) {
1809
0
      char s[42];
1810
0
      size_t max = sizeof(s);
1811
0
      struct tm t;
1812
1813
0
      if (gmtime_r(&tim, &t) == NULL)
1814
0
        addf(str, "error: gmtime_r (%ld)\n",
1815
0
             (unsigned long)tim);
1816
0
      else if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y",
1817
0
            &t) == 0)
1818
0
        addf(str, "error: strftime (%ld)\n",
1819
0
             (unsigned long)tim);
1820
0
      else
1821
0
        addf(str, _("\t\tNot After: %s\n"), s);
1822
0
    } else {
1823
0
      addf(str, _("\t\tNot After: %s\n"), _("unknown"));
1824
0
    }
1825
0
  }
1826
1827
  /* Subject. */
1828
0
  {
1829
0
    gnutls_datum_t dn;
1830
0
    int err;
1831
1832
0
    err = gnutls_x509_crt_get_dn3(cert, &dn, 0);
1833
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1834
0
      addf(str, _("\tSubject:\n"));
1835
0
    } else if (err < 0) {
1836
0
      addf(str, "error: get_dn: %s\n", gnutls_strerror(err));
1837
0
    } else {
1838
0
      addf(str, _("\tSubject: %s\n"), dn.data);
1839
0
      gnutls_free(dn.data);
1840
0
    }
1841
0
  }
1842
1843
  /* SubjectPublicKeyInfo. */
1844
0
  print_crt_pubkey(str, cert, format);
1845
1846
0
  print_unique_ids(str, cert);
1847
1848
  /* Extensions. */
1849
0
  if (gnutls_x509_crt_get_version(cert) >= 3) {
1850
0
    cert_type_t ccert;
1851
1852
0
    ccert.crt = cert;
1853
0
    print_extensions(str, "", TYPE_CRT, ccert);
1854
0
  }
1855
1856
  /* Signature. */
1857
0
  if (format != GNUTLS_CRT_PRINT_UNSIGNED_FULL) {
1858
0
    int err;
1859
0
    size_t size = 0;
1860
0
    char *buffer = NULL;
1861
0
    char *name;
1862
0
    const char *p;
1863
1864
0
    name = get_sign_name(cert, &err);
1865
0
    if (name == NULL)
1866
0
      p = _("unknown");
1867
0
    else
1868
0
      p = name;
1869
1870
0
    addf(str, _("\tSignature Algorithm: %s\n"), p);
1871
0
    gnutls_free(name);
1872
1873
0
    print_crt_sig_params(str, cert, format);
1874
1875
0
    if (err != GNUTLS_SIGN_UNKNOWN &&
1876
0
        gnutls_sign_is_secure2(
1877
0
          err, GNUTLS_SIGN_FLAG_SECURE_FOR_CERTS) == 0) {
1878
0
      adds(str, _("warning: signed using a broken signature "
1879
0
            "algorithm that can be forged.\n"));
1880
0
    }
1881
1882
0
    err = gnutls_x509_crt_get_signature(cert, buffer, &size);
1883
0
    if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
1884
0
      addf(str, "error: get_signature: %s\n",
1885
0
           gnutls_strerror(err));
1886
0
      return;
1887
0
    }
1888
1889
0
    buffer = gnutls_malloc(size);
1890
0
    if (!buffer) {
1891
0
      addf(str, "error: malloc: %s\n",
1892
0
           gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
1893
0
      return;
1894
0
    }
1895
1896
0
    err = gnutls_x509_crt_get_signature(cert, buffer, &size);
1897
0
    if (err < 0) {
1898
0
      gnutls_free(buffer);
1899
0
      addf(str, "error: get_signature2: %s\n",
1900
0
           gnutls_strerror(err));
1901
0
      return;
1902
0
    }
1903
1904
0
    adds(str, _("\tSignature:\n"));
1905
0
    _gnutls_buffer_hexdump(str, buffer, size, "\t\t");
1906
1907
0
    gnutls_free(buffer);
1908
0
  }
1909
0
}
1910
1911
static void print_fingerprint(gnutls_buffer_st *str, gnutls_x509_crt_t cert)
1912
0
{
1913
0
  int err;
1914
0
  char buffer[MAX_HASH_SIZE];
1915
0
  size_t size = sizeof(buffer);
1916
1917
0
  adds(str, _("\tFingerprint:\n"));
1918
1919
0
  err = gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, buffer,
1920
0
                &size);
1921
0
  if (err < 0) {
1922
0
    addf(str, "error: get_fingerprint: %s\n", gnutls_strerror(err));
1923
0
    return;
1924
0
  }
1925
1926
0
  adds(str, _("\t\tsha1:"));
1927
0
  _gnutls_buffer_hexprint(str, buffer, size);
1928
0
  adds(str, "\n");
1929
1930
0
  size = sizeof(buffer);
1931
0
  err = gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA256, buffer,
1932
0
                &size);
1933
0
  if (err < 0) {
1934
0
    addf(str, "error: get_fingerprint: %s\n", gnutls_strerror(err));
1935
0
    return;
1936
0
  }
1937
0
  adds(str, _("\t\tsha256:"));
1938
0
  _gnutls_buffer_hexprint(str, buffer, size);
1939
0
  adds(str, "\n");
1940
0
}
1941
1942
typedef int get_id_func(void *obj, unsigned, unsigned char *, size_t *);
1943
1944
static void print_obj_id(gnutls_buffer_st *str, const char *prefix, void *obj,
1945
       get_id_func *get_id)
1946
0
{
1947
0
  unsigned char sha1_buffer[MAX_HASH_SIZE];
1948
0
  unsigned char sha2_buffer[MAX_HASH_SIZE];
1949
0
  int err;
1950
0
  size_t sha1_size, sha2_size;
1951
1952
0
  sha1_size = sizeof(sha1_buffer);
1953
0
  err = get_id(obj, GNUTLS_KEYID_USE_SHA1, sha1_buffer, &sha1_size);
1954
0
  if (err == GNUTLS_E_UNIMPLEMENTED_FEATURE) /* unsupported algo */
1955
0
    return;
1956
1957
0
  if (err < 0) {
1958
0
    addf(str, "error: get_key_id(sha1): %s\n",
1959
0
         gnutls_strerror(err));
1960
0
    return;
1961
0
  }
1962
1963
0
  sha2_size = sizeof(sha2_buffer);
1964
0
  err = get_id(obj, GNUTLS_KEYID_USE_SHA256, sha2_buffer, &sha2_size);
1965
0
  if (err == GNUTLS_E_UNIMPLEMENTED_FEATURE) /* unsupported algo */
1966
0
    return;
1967
1968
0
  if (err < 0) {
1969
0
    addf(str, "error: get_key_id(sha256): %s\n",
1970
0
         gnutls_strerror(err));
1971
0
    return;
1972
0
  }
1973
1974
0
  addf(str, _("%sPublic Key ID:\n%s\tsha1:"), prefix, prefix);
1975
0
  _gnutls_buffer_hexprint(str, sha1_buffer, sha1_size);
1976
0
  addf(str, "\n%s\tsha256:", prefix);
1977
0
  _gnutls_buffer_hexprint(str, sha2_buffer, sha2_size);
1978
0
  adds(str, "\n");
1979
1980
0
  addf(str, _("%sPublic Key PIN:\n%s\tpin-sha256:"), prefix, prefix);
1981
0
  _gnutls_buffer_base64print(str, sha2_buffer, sha2_size);
1982
0
  adds(str, "\n");
1983
1984
0
  return;
1985
0
}
1986
1987
static void print_keyid(gnutls_buffer_st *str, gnutls_x509_crt_t cert)
1988
0
{
1989
0
  int err;
1990
0
  const char *name;
1991
0
  unsigned int bits;
1992
0
  unsigned char sha1_buffer[MAX_HASH_SIZE];
1993
0
  size_t sha1_size;
1994
1995
0
  err = gnutls_x509_crt_get_pk_algorithm(cert, &bits);
1996
0
  if (err < 0)
1997
0
    return;
1998
1999
0
  print_obj_id(str, "\t", cert,
2000
0
         (get_id_func *)gnutls_x509_crt_get_key_id);
2001
2002
0
  if (IS_EC(err)) {
2003
0
    gnutls_ecc_curve_t curve;
2004
2005
0
    err = gnutls_x509_crt_get_pk_ecc_raw(cert, &curve, NULL, NULL);
2006
0
    if (err < 0)
2007
0
      return;
2008
2009
0
    name = gnutls_ecc_curve_get_name(curve);
2010
0
    bits = 0;
2011
0
  } else if (IS_GOSTEC(err)) {
2012
0
    gnutls_ecc_curve_t curve;
2013
2014
0
    err = gnutls_x509_crt_get_pk_gost_raw(cert, &curve, NULL, NULL,
2015
0
                  NULL, NULL);
2016
0
    if (err < 0)
2017
0
      return;
2018
2019
0
    name = gnutls_ecc_curve_get_name(curve);
2020
0
    bits = 0;
2021
0
  } else {
2022
0
    name = gnutls_pk_get_name(err);
2023
0
  }
2024
2025
0
  if (name == NULL)
2026
0
    return;
2027
2028
0
  sha1_size = sizeof(sha1_buffer);
2029
0
  err = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA1,
2030
0
           sha1_buffer, &sha1_size);
2031
0
  if (err == GNUTLS_E_UNIMPLEMENTED_FEATURE) /* unsupported algo */
2032
0
    return;
2033
0
}
2034
2035
static void print_other(gnutls_buffer_st *str, gnutls_x509_crt_t cert,
2036
      gnutls_certificate_print_formats_t format)
2037
0
{
2038
0
  if (format != GNUTLS_CRT_PRINT_UNSIGNED_FULL) {
2039
0
    print_fingerprint(str, cert);
2040
0
  }
2041
0
  print_keyid(str, cert);
2042
0
}
2043
2044
static void print_oneline(gnutls_buffer_st *str, gnutls_x509_crt_t cert)
2045
0
{
2046
0
  int err;
2047
2048
  /* Subject. */
2049
0
  {
2050
0
    gnutls_datum_t dn;
2051
2052
0
    err = gnutls_x509_crt_get_dn3(cert, &dn, 0);
2053
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2054
0
      addf(str, _("no subject,"));
2055
0
    } else if (err < 0) {
2056
0
      addf(str, "unknown subject (%s), ",
2057
0
           gnutls_strerror(err));
2058
0
    } else {
2059
0
      addf(str, "subject `%s', ", dn.data);
2060
0
      gnutls_free(dn.data);
2061
0
    }
2062
0
  }
2063
2064
  /* Issuer. */
2065
0
  {
2066
0
    gnutls_datum_t dn;
2067
2068
0
    err = gnutls_x509_crt_get_issuer_dn3(cert, &dn, 0);
2069
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2070
0
      addf(str, _("no issuer,"));
2071
0
    } else if (err < 0) {
2072
0
      addf(str, "unknown issuer (%s), ",
2073
0
           gnutls_strerror(err));
2074
0
    } else {
2075
0
      addf(str, "issuer `%s', ", dn.data);
2076
0
      gnutls_free(dn.data);
2077
0
    }
2078
0
  }
2079
2080
0
  {
2081
0
    char serial[128];
2082
0
    size_t serial_size = sizeof(serial);
2083
2084
0
    err = gnutls_x509_crt_get_serial(cert, serial, &serial_size);
2085
0
    if (err >= 0) {
2086
0
      adds(str, "serial 0x");
2087
0
      _gnutls_buffer_hexprint(str, serial, serial_size);
2088
0
      adds(str, ", ");
2089
0
    }
2090
0
  }
2091
2092
  /* Key algorithm and size. */
2093
0
  {
2094
0
    unsigned int bits;
2095
0
    const char *p;
2096
0
    char *name = get_pk_name(cert, &bits);
2097
0
    if (name == NULL)
2098
0
      p = _("unknown");
2099
0
    else
2100
0
      p = name;
2101
0
    addf(str, "%s key %d bits, ", p, bits);
2102
0
    gnutls_free(name);
2103
0
  }
2104
2105
  /* Signature Algorithm. */
2106
0
  {
2107
0
    char *name = get_sign_name(cert, &err);
2108
0
    const char *p;
2109
2110
0
    if (name == NULL)
2111
0
      p = _("unknown");
2112
0
    else
2113
0
      p = name;
2114
2115
0
    if (err != GNUTLS_SIGN_UNKNOWN &&
2116
0
        gnutls_sign_is_secure2(
2117
0
          err, GNUTLS_SIGN_FLAG_SECURE_FOR_CERTS) == 0)
2118
0
      addf(str, _("signed using %s (broken!), "), p);
2119
0
    else
2120
0
      addf(str, _("signed using %s, "), p);
2121
0
    gnutls_free(name);
2122
0
  }
2123
2124
  /* Validity. */
2125
0
  {
2126
0
    time_t tim;
2127
2128
0
    tim = gnutls_x509_crt_get_activation_time(cert);
2129
0
    {
2130
0
      char s[42];
2131
0
      size_t max = sizeof(s);
2132
0
      struct tm t;
2133
2134
0
      if (gmtime_r(&tim, &t) == NULL)
2135
0
        addf(str, "unknown activation (%ld), ",
2136
0
             (unsigned long)tim);
2137
0
      else if (strftime(s, max, "%Y-%m-%d %H:%M:%S UTC",
2138
0
            &t) == 0)
2139
0
        addf(str, "failed activation (%ld), ",
2140
0
             (unsigned long)tim);
2141
0
      else
2142
0
        addf(str, "activated `%s', ", s);
2143
0
    }
2144
2145
0
    tim = gnutls_x509_crt_get_expiration_time(cert);
2146
0
    {
2147
0
      char s[42];
2148
0
      size_t max = sizeof(s);
2149
0
      struct tm t;
2150
2151
0
      if (gmtime_r(&tim, &t) == NULL)
2152
0
        addf(str, "unknown expiry (%ld), ",
2153
0
             (unsigned long)tim);
2154
0
      else if (strftime(s, max, "%Y-%m-%d %H:%M:%S UTC",
2155
0
            &t) == 0)
2156
0
        addf(str, "failed expiry (%ld), ",
2157
0
             (unsigned long)tim);
2158
0
      else
2159
0
        addf(str, "expires `%s', ", s);
2160
0
    }
2161
0
  }
2162
2163
0
  {
2164
0
    int pathlen;
2165
0
    char *policyLanguage;
2166
2167
0
    err = gnutls_x509_crt_get_proxy(cert, NULL, &pathlen,
2168
0
            &policyLanguage, NULL, NULL);
2169
0
    if (err == 0) {
2170
0
      addf(str, "proxy certificate (policy=");
2171
0
      if (strcmp(policyLanguage, "1.3.6.1.5.5.7.21.1") == 0)
2172
0
        addf(str, "id-ppl-inheritALL");
2173
0
      else if (strcmp(policyLanguage, "1.3.6.1.5.5.7.21.2") ==
2174
0
         0)
2175
0
        addf(str, "id-ppl-independent");
2176
0
      else
2177
0
        addf(str, "%s", policyLanguage);
2178
0
      if (pathlen >= 0)
2179
0
        addf(str, ", pathlen=%d), ", pathlen);
2180
0
      else
2181
0
        addf(str, "), ");
2182
0
      gnutls_free(policyLanguage);
2183
0
    }
2184
0
  }
2185
2186
0
  {
2187
0
    unsigned char buffer[MAX_HASH_SIZE];
2188
0
    size_t size = sizeof(buffer);
2189
2190
0
    err = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256,
2191
0
             buffer, &size);
2192
0
    if (err >= 0) {
2193
0
      addf(str, "pin-sha256=\"");
2194
0
      _gnutls_buffer_base64print(str, buffer, size);
2195
0
      adds(str, "\"");
2196
0
    }
2197
0
  }
2198
0
}
2199
2200
/**
2201
 * gnutls_x509_crt_print:
2202
 * @cert: The data to be printed
2203
 * @format: Indicate the format to use
2204
 * @out: Newly allocated datum with null terminated string.
2205
 *
2206
 * This function will pretty print a X.509 certificate, suitable for
2207
 * display to a human.
2208
 *
2209
 * If the format is %GNUTLS_CRT_PRINT_FULL then all fields of the
2210
 * certificate will be output, on multiple lines.  The
2211
 * %GNUTLS_CRT_PRINT_ONELINE format will generate one line with some
2212
 * selected fields, which is useful for logging purposes.
2213
 *
2214
 * The output @out needs to be deallocated using gnutls_free().
2215
 *
2216
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2217
 *   negative error value.
2218
 **/
2219
int gnutls_x509_crt_print(gnutls_x509_crt_t cert,
2220
        gnutls_certificate_print_formats_t format,
2221
        gnutls_datum_t *out)
2222
0
{
2223
0
  gnutls_buffer_st str;
2224
0
  int ret;
2225
2226
0
  if (format == GNUTLS_CRT_PRINT_COMPACT) {
2227
0
    _gnutls_buffer_init(&str);
2228
2229
0
    print_oneline(&str, cert);
2230
2231
0
    ret = _gnutls_buffer_append_data(&str, "\n", 1);
2232
0
    if (ret < 0)
2233
0
      return gnutls_assert_val(ret);
2234
2235
0
    print_keyid(&str, cert);
2236
2237
0
    return _gnutls_buffer_to_datum(&str, out, 1);
2238
0
  } else if (format == GNUTLS_CRT_PRINT_ONELINE) {
2239
0
    _gnutls_buffer_init(&str);
2240
2241
0
    print_oneline(&str, cert);
2242
2243
0
    return _gnutls_buffer_to_datum(&str, out, 1);
2244
0
  } else {
2245
0
    _gnutls_buffer_init(&str);
2246
2247
0
    _gnutls_buffer_append_str(
2248
0
      &str, _("X.509 Certificate Information:\n"));
2249
2250
0
    print_cert(&str, cert, format);
2251
2252
0
    _gnutls_buffer_append_str(&str, _("Other Information:\n"));
2253
2254
0
    print_other(&str, cert, format);
2255
2256
0
    return _gnutls_buffer_to_datum(&str, out, 1);
2257
0
  }
2258
0
}
2259
2260
static void print_crl(gnutls_buffer_st *str, gnutls_x509_crl_t crl,
2261
          int notsigned)
2262
0
{
2263
  /* Version. */
2264
0
  {
2265
0
    int version = gnutls_x509_crl_get_version(crl);
2266
0
    if (version < 0)
2267
0
      addf(str, "error: get_version: %s\n",
2268
0
           gnutls_strerror(version));
2269
0
    else
2270
0
      addf(str, _("\tVersion: %d\n"), version);
2271
0
  }
2272
2273
  /* Issuer. */
2274
0
  if (!notsigned) {
2275
0
    gnutls_datum_t dn;
2276
0
    int err;
2277
2278
0
    err = gnutls_x509_crl_get_issuer_dn3(crl, &dn, 0);
2279
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2280
0
      addf(str, _("\tIssuer:\n"));
2281
0
    } else if (err < 0) {
2282
0
      addf(str, "error: get_issuer_dn: %s\n",
2283
0
           gnutls_strerror(err));
2284
0
    } else {
2285
0
      addf(str, _("\tIssuer: %s\n"), dn.data);
2286
0
      gnutls_free(dn.data);
2287
0
    }
2288
0
  }
2289
2290
  /* Validity. */
2291
0
  {
2292
0
    time_t tim;
2293
2294
0
    adds(str, _("\tUpdate dates:\n"));
2295
2296
0
    tim = gnutls_x509_crl_get_this_update(crl);
2297
0
    {
2298
0
      char s[42];
2299
0
      size_t max = sizeof(s);
2300
0
      struct tm t;
2301
2302
0
      if (gmtime_r(&tim, &t) == NULL)
2303
0
        addf(str, "error: gmtime_r (%ld)\n",
2304
0
             (unsigned long)tim);
2305
0
      else if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y",
2306
0
            &t) == 0)
2307
0
        addf(str, "error: strftime (%ld)\n",
2308
0
             (unsigned long)tim);
2309
0
      else
2310
0
        addf(str, _("\t\tIssued: %s\n"), s);
2311
0
    }
2312
2313
0
    tim = gnutls_x509_crl_get_next_update(crl);
2314
0
    {
2315
0
      char s[42];
2316
0
      size_t max = sizeof(s);
2317
0
      struct tm t;
2318
2319
0
      if (tim == -1)
2320
0
        addf(str, "\t\tNo next update time.\n");
2321
0
      else if (gmtime_r(&tim, &t) == NULL)
2322
0
        addf(str, "error: gmtime_r (%ld)\n",
2323
0
             (unsigned long)tim);
2324
0
      else if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y",
2325
0
            &t) == 0)
2326
0
        addf(str, "error: strftime (%ld)\n",
2327
0
             (unsigned long)tim);
2328
0
      else
2329
0
        addf(str, _("\t\tNext at: %s\n"), s);
2330
0
    }
2331
0
  }
2332
2333
  /* Extensions. */
2334
0
  if (gnutls_x509_crl_get_version(crl) >= 2) {
2335
0
    size_t i;
2336
0
    int err = 0;
2337
0
    int aki_idx = 0;
2338
0
    int crl_nr = 0;
2339
2340
0
    for (i = 0;; i++) {
2341
0
      char oid[MAX_OID_SIZE] = "";
2342
0
      size_t sizeof_oid = sizeof(oid);
2343
0
      unsigned int critical;
2344
2345
0
      err = gnutls_x509_crl_get_extension_info(
2346
0
        crl, i, oid, &sizeof_oid, &critical);
2347
0
      if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
2348
0
        break;
2349
0
      if (err < 0) {
2350
0
        addf(str, "error: get_extension_info: %s\n",
2351
0
             gnutls_strerror(err));
2352
0
        break;
2353
0
      }
2354
2355
0
      if (i == 0)
2356
0
        adds(str, _("\tExtensions:\n"));
2357
2358
0
      if (strcmp(oid, "2.5.29.20") == 0) {
2359
0
        char nr[128];
2360
0
        size_t nr_size = sizeof(nr);
2361
2362
0
        if (crl_nr) {
2363
0
          addf(str,
2364
0
               "warning: more than one CRL number\n");
2365
0
        }
2366
2367
0
        err = gnutls_x509_crl_get_number(
2368
0
          crl, nr, &nr_size, &critical);
2369
2370
0
        addf(str, _("\t\tCRL Number (%s): "),
2371
0
             critical ? _("critical") :
2372
0
            _("not critical"));
2373
2374
0
        if (err < 0)
2375
0
          addf(str, "error: get_number: %s\n",
2376
0
               gnutls_strerror(err));
2377
0
        else {
2378
0
          _gnutls_buffer_hexprint(str, nr,
2379
0
                nr_size);
2380
0
          addf(str, "\n");
2381
0
        }
2382
2383
0
        crl_nr++;
2384
0
      } else if (strcmp(oid, "2.5.29.35") == 0) {
2385
0
        gnutls_datum_t der;
2386
2387
0
        if (aki_idx) {
2388
0
          addf(str,
2389
0
               "warning: more than one AKI extension\n");
2390
0
        }
2391
2392
0
        addf(str,
2393
0
             _("\t\tAuthority Key Identifier (%s):\n"),
2394
0
             critical ? _("critical") :
2395
0
            _("not critical"));
2396
2397
0
        err = gnutls_x509_crl_get_extension_data2(
2398
0
          crl, i, &der);
2399
0
        if (err < 0) {
2400
0
          addf(str,
2401
0
               "error: get_extension_data2: %s\n",
2402
0
               gnutls_strerror(err));
2403
0
          continue;
2404
0
        }
2405
0
        print_aki(str, &der);
2406
0
        gnutls_free(der.data);
2407
2408
0
        aki_idx++;
2409
0
      } else {
2410
0
        gnutls_datum_t der;
2411
2412
0
        addf(str, _("\t\tUnknown extension %s (%s):\n"),
2413
0
             oid,
2414
0
             critical ? _("critical") :
2415
0
            _("not critical"));
2416
2417
0
        err = gnutls_x509_crl_get_extension_data2(
2418
0
          crl, i, &der);
2419
0
        if (err < 0) {
2420
0
          addf(str,
2421
0
               "error: get_extension_data2: %s\n",
2422
0
               gnutls_strerror(err));
2423
0
          continue;
2424
0
        }
2425
2426
0
        adds(str, _("\t\t\tASCII: "));
2427
0
        _gnutls_buffer_asciiprint(str, (char *)der.data,
2428
0
                der.size);
2429
0
        adds(str, "\n");
2430
2431
0
        adds(str, _("\t\t\tHexdump: "));
2432
0
        _gnutls_buffer_hexprint(str, der.data,
2433
0
              der.size);
2434
0
        adds(str, "\n");
2435
2436
0
        gnutls_free(der.data);
2437
0
      }
2438
0
    }
2439
0
  }
2440
2441
  /* Revoked certificates. */
2442
0
  {
2443
0
    int num = gnutls_x509_crl_get_crt_count(crl);
2444
0
    gnutls_x509_crl_iter_t iter = NULL;
2445
0
    int j;
2446
2447
0
    if (num)
2448
0
      addf(str, _("\tRevoked certificates (%d):\n"), num);
2449
0
    else
2450
0
      adds(str, _("\tNo revoked certificates.\n"));
2451
2452
0
    for (j = 0; j < num; j++) {
2453
0
      unsigned char serial[128];
2454
0
      size_t serial_size = sizeof(serial);
2455
0
      int err;
2456
0
      time_t tim;
2457
2458
0
      err = gnutls_x509_crl_iter_crt_serial(
2459
0
        crl, &iter, serial, &serial_size, &tim);
2460
0
      if (err < 0) {
2461
0
        addf(str, "error: iter_crt_serial: %s\n",
2462
0
             gnutls_strerror(err));
2463
0
        break;
2464
0
      } else {
2465
0
        char s[42];
2466
0
        size_t max = sizeof(s);
2467
0
        struct tm t;
2468
2469
0
        adds(str, _("\t\tSerial Number (hex): "));
2470
0
        _gnutls_buffer_hexprint(str, serial,
2471
0
              serial_size);
2472
0
        adds(str, "\n");
2473
2474
0
        if (gmtime_r(&tim, &t) == NULL)
2475
0
          addf(str, "error: gmtime_r (%ld)\n",
2476
0
               (unsigned long)tim);
2477
0
        else if (strftime(s, max,
2478
0
              "%a %b %d %H:%M:%S UTC %Y",
2479
0
              &t) == 0)
2480
0
          addf(str, "error: strftime (%ld)\n",
2481
0
               (unsigned long)tim);
2482
0
        else
2483
0
          addf(str, _("\t\tRevoked at: %s\n"), s);
2484
0
      }
2485
0
    }
2486
0
    gnutls_x509_crl_iter_deinit(iter);
2487
0
  }
2488
2489
  /* Signature. */
2490
0
  if (!notsigned) {
2491
0
    int err;
2492
0
    size_t size = 0;
2493
0
    char *buffer = NULL;
2494
0
    char *name;
2495
0
    const char *p;
2496
2497
0
    name = crl_get_sign_name(crl, &err);
2498
0
    if (name == NULL)
2499
0
      p = _("unknown");
2500
0
    else
2501
0
      p = name;
2502
2503
0
    addf(str, _("\tSignature Algorithm: %s\n"), p);
2504
0
    gnutls_free(name);
2505
2506
0
    if (err != GNUTLS_SIGN_UNKNOWN &&
2507
0
        gnutls_sign_is_secure2(
2508
0
          err, GNUTLS_SIGN_FLAG_SECURE_FOR_CERTS) == 0) {
2509
0
      adds(str, _("warning: signed using a broken signature "
2510
0
            "algorithm that can be forged.\n"));
2511
0
    }
2512
2513
0
    err = gnutls_x509_crl_get_signature(crl, buffer, &size);
2514
0
    if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
2515
0
      addf(str, "error: get_signature: %s\n",
2516
0
           gnutls_strerror(err));
2517
0
      return;
2518
0
    }
2519
2520
0
    buffer = gnutls_malloc(size);
2521
0
    if (!buffer) {
2522
0
      addf(str, "error: malloc: %s\n",
2523
0
           gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
2524
0
      return;
2525
0
    }
2526
2527
0
    err = gnutls_x509_crl_get_signature(crl, buffer, &size);
2528
0
    if (err < 0) {
2529
0
      gnutls_free(buffer);
2530
0
      addf(str, "error: get_signature2: %s\n",
2531
0
           gnutls_strerror(err));
2532
0
      return;
2533
0
    }
2534
2535
0
    adds(str, _("\tSignature:\n"));
2536
0
    _gnutls_buffer_hexdump(str, buffer, size, "\t\t");
2537
2538
0
    gnutls_free(buffer);
2539
0
  }
2540
0
}
2541
2542
/**
2543
 * gnutls_x509_crl_print:
2544
 * @crl: The data to be printed
2545
 * @format: Indicate the format to use
2546
 * @out: Newly allocated datum with null terminated string.
2547
 *
2548
 * This function will pretty print a X.509 certificate revocation
2549
 * list, suitable for display to a human.
2550
 *
2551
 * The output @out needs to be deallocated using gnutls_free().
2552
 *
2553
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2554
 *   negative error value.
2555
 **/
2556
int gnutls_x509_crl_print(gnutls_x509_crl_t crl,
2557
        gnutls_certificate_print_formats_t format,
2558
        gnutls_datum_t *out)
2559
0
{
2560
0
  gnutls_buffer_st str;
2561
2562
0
  _gnutls_buffer_init(&str);
2563
2564
0
  _gnutls_buffer_append_str(
2565
0
    &str, _("X.509 Certificate Revocation List Information:\n"));
2566
2567
0
  print_crl(&str, crl, format == GNUTLS_CRT_PRINT_UNSIGNED_FULL);
2568
2569
0
  return _gnutls_buffer_to_datum(&str, out, 1);
2570
0
}
2571
2572
static int print_crq_sig_params(gnutls_buffer_st *str, gnutls_x509_crq_t crt,
2573
        gnutls_certificate_print_formats_t format)
2574
0
{
2575
0
  int ret;
2576
0
  gnutls_pk_algorithm_t pk;
2577
0
  gnutls_x509_spki_st params;
2578
0
  gnutls_sign_algorithm_t sign;
2579
2580
0
  sign = gnutls_x509_crq_get_signature_algorithm(crt);
2581
0
  pk = gnutls_sign_get_pk_algorithm(sign);
2582
0
  if (pk == GNUTLS_PK_RSA_PSS) {
2583
0
    ret = _gnutls_x509_read_sign_params(
2584
0
      crt->crq, "signatureAlgorithm", &params);
2585
0
    if (ret < 0) {
2586
0
      addf(str, "error: read_pss_params: %s\n",
2587
0
           gnutls_strerror(ret));
2588
0
    } else
2589
0
      addf(str, "\t\tSalt Length: %d\n", params.salt_size);
2590
0
  }
2591
2592
0
  return 0;
2593
0
}
2594
2595
static int print_crq_pubkey(gnutls_buffer_st *str, gnutls_x509_crq_t crq,
2596
          gnutls_certificate_print_formats_t format)
2597
0
{
2598
0
  gnutls_pubkey_t pubkey;
2599
0
  gnutls_x509_spki_st params;
2600
0
  int ret;
2601
2602
0
  ret = _gnutls_x509_crq_read_spki_params(crq, &params);
2603
0
  if (ret < 0)
2604
0
    return ret;
2605
2606
0
  ret = gnutls_pubkey_init(&pubkey);
2607
0
  if (ret < 0)
2608
0
    return ret;
2609
2610
0
  ret = gnutls_pubkey_import_x509_crq(pubkey, crq, 0);
2611
0
  if (ret < 0)
2612
0
    goto cleanup;
2613
2614
0
  print_pubkey(str, _("Subject "), pubkey, &params, format);
2615
0
  ret = 0;
2616
2617
0
cleanup:
2618
0
  gnutls_pubkey_deinit(pubkey);
2619
2620
0
  if (ret < 0) { /* print only name */
2621
0
    const char *p;
2622
0
    char *name = crq_get_pk_name(crq);
2623
0
    if (name == NULL)
2624
0
      p = _("unknown");
2625
0
    else
2626
0
      p = name;
2627
2628
0
    addf(str, "\tSubject Public Key Algorithm: %s\n", p);
2629
0
    gnutls_free(name);
2630
0
    ret = 0;
2631
0
  }
2632
2633
0
  return ret;
2634
0
}
2635
2636
static void print_crq(gnutls_buffer_st *str, gnutls_x509_crq_t cert,
2637
          gnutls_certificate_print_formats_t format)
2638
0
{
2639
  /* Version. */
2640
0
  {
2641
0
    int version = gnutls_x509_crq_get_version(cert);
2642
0
    if (version < 0)
2643
0
      addf(str, "error: get_version: %s\n",
2644
0
           gnutls_strerror(version));
2645
0
    else
2646
0
      addf(str, _("\tVersion: %d\n"), version);
2647
0
  }
2648
2649
  /* Subject */
2650
0
  {
2651
0
    gnutls_datum_t dn;
2652
0
    int err;
2653
2654
0
    err = gnutls_x509_crq_get_dn3(cert, &dn, 0);
2655
0
    if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2656
0
      addf(str, _("\tSubject:\n"));
2657
0
    } else if (err < 0) {
2658
0
      addf(str, "error: get_dn: %s\n", gnutls_strerror(err));
2659
0
    } else {
2660
0
      addf(str, _("\tSubject: %s\n"), dn.data);
2661
0
      gnutls_free(dn.data);
2662
0
    }
2663
0
  }
2664
2665
0
  {
2666
0
    char *name;
2667
0
    const char *p;
2668
2669
0
    print_crq_pubkey(str, cert, format);
2670
2671
0
    name = crq_get_sign_name(cert);
2672
0
    if (name == NULL)
2673
0
      p = _("unknown");
2674
0
    else
2675
0
      p = name;
2676
2677
0
    addf(str, _("\tSignature Algorithm: %s\n"), p);
2678
2679
0
    gnutls_free(name);
2680
2681
0
    print_crq_sig_params(str, cert, format);
2682
0
  }
2683
2684
  /* parse attributes */
2685
0
  {
2686
0
    size_t i;
2687
0
    int err = 0;
2688
0
    int extensions = 0;
2689
0
    int challenge = 0;
2690
2691
0
    for (i = 0;; i++) {
2692
0
      char oid[MAX_OID_SIZE] = "";
2693
0
      size_t sizeof_oid = sizeof(oid);
2694
2695
0
      err = gnutls_x509_crq_get_attribute_info(cert, i, oid,
2696
0
                 &sizeof_oid);
2697
0
      if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
2698
0
        break;
2699
0
      if (err < 0) {
2700
0
        addf(str, "error: get_extension_info: %s\n",
2701
0
             gnutls_strerror(err));
2702
0
        break;
2703
0
      }
2704
2705
0
      if (i == 0)
2706
0
        adds(str, _("\tAttributes:\n"));
2707
2708
0
      if (strcmp(oid, "1.2.840.113549.1.9.14") == 0) {
2709
0
        cert_type_t ccert;
2710
2711
0
        if (extensions) {
2712
0
          addf(str,
2713
0
               "warning: more than one extensionsRequest\n");
2714
0
        }
2715
2716
0
        ccert.crq = cert;
2717
0
        print_extensions(str, "\t", TYPE_CRQ, ccert);
2718
2719
0
        extensions++;
2720
0
      } else if (strcmp(oid, "1.2.840.113549.1.9.7") == 0) {
2721
0
        char *pass;
2722
0
        size_t size;
2723
2724
0
        if (challenge) {
2725
0
          adds(str,
2726
0
               "warning: more than one Challenge password attribute\n");
2727
0
        }
2728
2729
0
        err = gnutls_x509_crq_get_challenge_password(
2730
0
          cert, NULL, &size);
2731
0
        if (err < 0 &&
2732
0
            err != GNUTLS_E_SHORT_MEMORY_BUFFER) {
2733
0
          addf(str,
2734
0
               "error: get_challenge_password: %s\n",
2735
0
               gnutls_strerror(err));
2736
0
          continue;
2737
0
        }
2738
2739
0
        size++;
2740
2741
0
        pass = gnutls_malloc(size);
2742
0
        if (!pass) {
2743
0
          addf(str, "error: malloc: %s\n",
2744
0
               gnutls_strerror(
2745
0
                 GNUTLS_E_MEMORY_ERROR));
2746
0
          continue;
2747
0
        }
2748
2749
0
        err = gnutls_x509_crq_get_challenge_password(
2750
0
          cert, pass, &size);
2751
0
        if (err < 0)
2752
0
          addf(str,
2753
0
               "error: get_challenge_password: %s\n",
2754
0
               gnutls_strerror(err));
2755
0
        else
2756
0
          addf(str,
2757
0
               _("\t\tChallenge password: %s\n"),
2758
0
               pass);
2759
2760
0
        gnutls_free(pass);
2761
2762
0
        challenge++;
2763
0
      } else {
2764
0
        char *buffer;
2765
0
        size_t extlen = 0;
2766
2767
0
        addf(str, _("\t\tUnknown attribute %s:\n"),
2768
0
             oid);
2769
2770
0
        err = gnutls_x509_crq_get_attribute_data(
2771
0
          cert, i, NULL, &extlen);
2772
0
        if (err < 0) {
2773
0
          addf(str,
2774
0
               "error: get_attribute_data: %s\n",
2775
0
               gnutls_strerror(err));
2776
0
          continue;
2777
0
        }
2778
2779
0
        buffer = gnutls_malloc(extlen);
2780
0
        if (!buffer) {
2781
0
          addf(str, "error: malloc: %s\n",
2782
0
               gnutls_strerror(
2783
0
                 GNUTLS_E_MEMORY_ERROR));
2784
0
          continue;
2785
0
        }
2786
2787
0
        err = gnutls_x509_crq_get_attribute_data(
2788
0
          cert, i, buffer, &extlen);
2789
0
        if (err < 0) {
2790
0
          gnutls_free(buffer);
2791
0
          addf(str,
2792
0
               "error: get_attribute_data2: %s\n",
2793
0
               gnutls_strerror(err));
2794
0
          continue;
2795
0
        }
2796
2797
0
        adds(str, _("\t\t\tASCII: "));
2798
0
        _gnutls_buffer_asciiprint(str, buffer, extlen);
2799
0
        adds(str, "\n");
2800
2801
0
        adds(str, _("\t\t\tHexdump: "));
2802
0
        _gnutls_buffer_hexprint(str, buffer, extlen);
2803
0
        adds(str, "\n");
2804
2805
0
        gnutls_free(buffer);
2806
0
      }
2807
0
    }
2808
0
  }
2809
0
}
2810
2811
static void print_crq_other(gnutls_buffer_st *str, gnutls_x509_crq_t crq)
2812
0
{
2813
0
  int ret;
2814
2815
  /* on unknown public key algorithms don't print the key ID */
2816
0
  ret = gnutls_x509_crq_get_pk_algorithm(crq, NULL);
2817
0
  if (ret < 0)
2818
0
    return;
2819
2820
0
  print_obj_id(str, "\t", crq, (get_id_func *)gnutls_x509_crq_get_key_id);
2821
0
}
2822
2823
/**
2824
 * gnutls_x509_crq_print:
2825
 * @crq: The data to be printed
2826
 * @format: Indicate the format to use
2827
 * @out: Newly allocated datum with null terminated string.
2828
 *
2829
 * This function will pretty print a certificate request, suitable for
2830
 * display to a human.
2831
 *
2832
 * The output @out needs to be deallocated using gnutls_free().
2833
 *
2834
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2835
 *   negative error value.
2836
 *
2837
 * Since: 2.8.0
2838
 **/
2839
int gnutls_x509_crq_print(gnutls_x509_crq_t crq,
2840
        gnutls_certificate_print_formats_t format,
2841
        gnutls_datum_t *out)
2842
0
{
2843
0
  gnutls_buffer_st str;
2844
2845
0
  _gnutls_buffer_init(&str);
2846
2847
0
  _gnutls_buffer_append_str(
2848
0
    &str, _("PKCS #10 Certificate Request Information:\n"));
2849
2850
0
  print_crq(&str, crq, format);
2851
2852
0
  _gnutls_buffer_append_str(&str, _("Other Information:\n"));
2853
2854
0
  print_crq_other(&str, crq);
2855
2856
0
  return _gnutls_buffer_to_datum(&str, out, 1);
2857
0
}
2858
2859
static void print_pubkey_other(gnutls_buffer_st *str, gnutls_pubkey_t pubkey,
2860
             gnutls_certificate_print_formats_t format)
2861
0
{
2862
0
  int ret;
2863
0
  unsigned int usage;
2864
2865
0
  ret = gnutls_pubkey_get_key_usage(pubkey, &usage);
2866
0
  if (ret < 0) {
2867
0
    addf(str, "error: get_key_usage: %s\n", gnutls_strerror(ret));
2868
0
    return;
2869
0
  }
2870
2871
0
  adds(str, "\n");
2872
0
  if (pubkey->key_usage) {
2873
0
    adds(str, _("Public Key Usage:\n"));
2874
0
    print_key_usage2(str, "\t", pubkey->key_usage);
2875
0
  }
2876
2877
  /* on unknown public key algorithms don't print the key ID */
2878
0
  ret = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);
2879
0
  if (ret < 0)
2880
0
    return;
2881
2882
0
  print_obj_id(str, "", pubkey, (get_id_func *)gnutls_pubkey_get_key_id);
2883
0
}
2884
2885
/**
2886
 * gnutls_pubkey_print:
2887
 * @pubkey: The data to be printed
2888
 * @format: Indicate the format to use
2889
 * @out: Newly allocated datum with null terminated string.
2890
 *
2891
 * This function will pretty print public key information, suitable for
2892
 * display to a human.
2893
 *
2894
 * Only %GNUTLS_CRT_PRINT_FULL and %GNUTLS_CRT_PRINT_FULL_NUMBERS
2895
 * are implemented.
2896
 *
2897
 * The output @out needs to be deallocated using gnutls_free().
2898
 *
2899
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2900
 *   negative error value.
2901
 *
2902
 * Since: 3.1.5
2903
 **/
2904
int gnutls_pubkey_print(gnutls_pubkey_t pubkey,
2905
      gnutls_certificate_print_formats_t format,
2906
      gnutls_datum_t *out)
2907
0
{
2908
0
  gnutls_buffer_st str;
2909
2910
0
  _gnutls_buffer_init(&str);
2911
2912
0
  _gnutls_buffer_append_str(&str, _("Public Key Information:\n"));
2913
2914
0
  print_pubkey(&str, "", pubkey, NULL, format);
2915
0
  print_pubkey_other(&str, pubkey, format);
2916
2917
0
  return _gnutls_buffer_to_datum(&str, out, 1);
2918
0
}
2919
2920
/**
2921
 * gnutls_x509_ext_print:
2922
 * @exts: The data to be printed
2923
 * @exts_size: the number of available structures
2924
 * @format: Indicate the format to use
2925
 * @out: Newly allocated datum with null terminated string.
2926
 *
2927
 * This function will pretty print X.509 certificate extensions,
2928
 * suitable for display to a human.
2929
 *
2930
 * The output @out needs to be deallocated using gnutls_free().
2931
 *
2932
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2933
 *   negative error value.
2934
 **/
2935
int gnutls_x509_ext_print(gnutls_x509_ext_st *exts, unsigned int exts_size,
2936
        gnutls_certificate_print_formats_t format,
2937
        gnutls_datum_t *out)
2938
0
{
2939
0
  gnutls_buffer_st str;
2940
0
  struct ext_indexes_st idx;
2941
0
  unsigned i;
2942
2943
0
  memset(&idx, 0, sizeof(idx));
2944
0
  _gnutls_buffer_init(&str);
2945
2946
0
  for (i = 0; i < exts_size; i++)
2947
0
    print_extension(&str, "", &idx, (char *)exts[i].oid,
2948
0
        exts[i].critical, &exts[i].data);
2949
2950
0
  return _gnutls_buffer_to_datum(&str, out, 1);
2951
0
}