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