GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/isakmpd/x509.c Lines: 0 534 0.0 %
Date: 2016-12-06 Branches: 0 391 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: x509.c,v 1.118 2015/01/16 06:39:59 deraadt Exp $	 */
2
/* $EOM: x509.c,v 1.54 2001/01/16 18:42:16 ho Exp $	 */
3
4
/*
5
 * Copyright (c) 1998, 1999 Niels Provos.  All rights reserved.
6
 * Copyright (c) 1999, 2000, 2001 Niklas Hallqvist.  All rights reserved.
7
 * Copyright (c) 1999, 2000, 2001 Angelos D. Keromytis.  All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29
30
/*
31
 * This code was written under funding by Ericsson Radio Systems.
32
 */
33
34
#include <sys/types.h>
35
#include <sys/stat.h>
36
#include <dirent.h>
37
#include <errno.h>
38
#include <fcntl.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <string.h>
42
#include <unistd.h>
43
#include <limits.h>
44
45
#include <regex.h>
46
#include <keynote.h>
47
48
#include "cert.h"
49
#include "conf.h"
50
#include "exchange.h"
51
#include "hash.h"
52
#include "ike_auth.h"
53
#include "ipsec.h"
54
#include "log.h"
55
#include "dh.h"
56
#include "monitor.h"
57
#include "policy.h"
58
#include "sa.h"
59
#include "util.h"
60
#include "x509.h"
61
62
static u_int16_t x509_hash(u_int8_t *, size_t);
63
static void	 x509_hash_init(void);
64
static X509	*x509_hash_find(u_int8_t *, size_t);
65
static int	 x509_hash_enter(X509 *);
66
67
/*
68
 * X509_STOREs do not support subjectAltNames, so we have to build
69
 * our own hash table.
70
 */
71
72
/*
73
 * XXX Actually this store is not really useful, we never use it as we have
74
 * our own hash table.  It also gets collisions if we have several certificates
75
 * only differing in subjectAltName.
76
 */
77
static X509_STORE *x509_certs = 0;
78
static X509_STORE *x509_cas = 0;
79
80
static int n_x509_cas = 0;
81
82
/* Initial number of bits used as hash.  */
83
#define INITIAL_BUCKET_BITS 6
84
85
struct x509_hash {
86
	LIST_ENTRY(x509_hash) link;
87
88
	X509		*cert;
89
};
90
91
static LIST_HEAD(x509_list, x509_hash) *x509_tab = 0;
92
93
/* Works both as a maximum index and a mask.  */
94
static int	bucket_mask;
95
96
/*
97
 * Given an X509 certificate, create a KeyNote assertion where
98
 * Issuer/Subject -> Authorizer/Licensees.
99
 * XXX RSA-specific.
100
 */
101
int
102
x509_generate_kn(int id, X509 *cert)
103
{
104
	static const char fmt[] = "Authorizer: \"rsa-hex:%s\"\nLicensees: \"rsa-hex:%s"
105
		    "\"\nConditions: %s >= \"%s\" && %s <= \"%s\";\n";
106
	char	*ikey = NULL, *skey = NULL, *buf = NULL;
107
	char	isname[256], subname[256];
108
	static const char fmt2[] = "Authorizer: \"DN:%s\"\nLicensees: \"DN:%s\"\n"
109
		    "Conditions: %s >= \"%s\" && %s <= \"%s\";\n";
110
	X509_NAME *issuer, *subject;
111
	struct keynote_deckey dc;
112
	X509_STORE_CTX csc;
113
	X509_OBJECT obj;
114
	X509	*icert;
115
	RSA	*key = NULL;
116
	time_t	tt;
117
	char	before[15], after[15], *timecomp, *timecomp2;
118
	ASN1_TIME *tm;
119
	int	i;
120
121
	LOG_DBG((LOG_POLICY, 90,
122
	    "x509_generate_kn: generating KeyNote policy for certificate %p",
123
	    cert));
124
125
	issuer = X509_get_issuer_name(cert);
126
	subject = X509_get_subject_name(cert);
127
128
	/* Missing or self-signed, ignore cert but don't report failure.  */
129
	if (!issuer || !subject || !X509_name_cmp(issuer, subject))
130
		return 1;
131
132
	if (!x509_cert_get_key(cert, &key)) {
133
		LOG_DBG((LOG_POLICY, 30,
134
		    "x509_generate_kn: failed to get public key from cert"));
135
		return 0;
136
	}
137
	dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA;
138
	dc.dec_key = key;
139
	ikey = kn_encode_key(&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX,
140
	    KEYNOTE_PUBLIC_KEY);
141
	if (keynote_errno == ERROR_MEMORY) {
142
		log_print("x509_generate_kn: failed to get memory for "
143
		    "public key");
144
		LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get "
145
		    "subject key"));
146
		goto fail;
147
	}
148
	if (!ikey) {
149
		LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get "
150
		    "subject key"));
151
		goto fail;
152
	}
153
154
	RSA_free(key);
155
	key = NULL;
156
157
	/* Now find issuer's certificate so we can get the public key.  */
158
	X509_STORE_CTX_init(&csc, x509_cas, cert, NULL);
159
	if (X509_STORE_get_by_subject(&csc, X509_LU_X509, issuer, &obj) !=
160
	    X509_LU_X509) {
161
		X509_STORE_CTX_cleanup(&csc);
162
		X509_STORE_CTX_init(&csc, x509_certs, cert, NULL);
163
		if (X509_STORE_get_by_subject(&csc, X509_LU_X509, issuer, &obj)
164
		    != X509_LU_X509) {
165
			X509_STORE_CTX_cleanup(&csc);
166
			LOG_DBG((LOG_POLICY, 30,
167
			    "x509_generate_kn: no certificate found for "
168
			    "issuer"));
169
			goto fail;
170
		}
171
	}
172
	X509_STORE_CTX_cleanup(&csc);
173
	icert = obj.data.x509;
174
175
	if (icert == NULL) {
176
		LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: "
177
		    "missing certificates, cannot construct X509 chain"));
178
		goto fail;
179
	}
180
	if (!x509_cert_get_key(icert, &key)) {
181
		LOG_DBG((LOG_POLICY, 30,
182
		    "x509_generate_kn: failed to get public key from cert"));
183
		goto fail;
184
	}
185
	X509_OBJECT_free_contents(&obj);
186
187
	dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA;
188
	dc.dec_key = key;
189
	skey = kn_encode_key(&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX,
190
	    KEYNOTE_PUBLIC_KEY);
191
	if (keynote_errno == ERROR_MEMORY) {
192
		log_error("x509_generate_kn: failed to get memory for public "
193
		    "key");
194
		LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer "
195
		    "key"));
196
		goto fail;
197
	}
198
	if (!skey) {
199
		LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer "
200
		    "key"));
201
		goto fail;
202
	}
203
204
	RSA_free(key);
205
	key = NULL;
206
207
	if (((tm = X509_get_notBefore(cert)) == NULL) ||
208
	    (tm->type != V_ASN1_UTCTIME &&
209
		tm->type != V_ASN1_GENERALIZEDTIME)) {
210
		tt = time(0);
211
		strftime(before, 14, "%Y%m%d%H%M%S", localtime(&tt));
212
		timecomp = "LocalTimeOfDay";
213
	} else {
214
		if (tm->data[tm->length - 1] == 'Z') {
215
			timecomp = "GMTTimeOfDay";
216
			i = tm->length - 2;
217
		} else {
218
			timecomp = "LocalTimeOfDay";
219
			i = tm->length - 1;
220
		}
221
222
		for (; i >= 0; i--) {
223
			if (tm->data[i] < '0' || tm->data[i] > '9') {
224
				LOG_DBG((LOG_POLICY, 30,
225
				    "x509_generate_kn: invalid data in "
226
				    "NotValidBefore time field"));
227
				goto fail;
228
			}
229
		}
230
231
		if (tm->type == V_ASN1_UTCTIME) {
232
			if ((tm->length < 10) || (tm->length > 13)) {
233
				LOG_DBG((LOG_POLICY, 30,
234
				    "x509_generate_kn: invalid length "
235
				    "of NotValidBefore time field (%d)",
236
				    tm->length));
237
				goto fail;
238
			}
239
			/* Validity checks.  */
240
			if ((tm->data[2] != '0' && tm->data[2] != '1') ||
241
			    (tm->data[2] == '0' && tm->data[3] == '0') ||
242
			    (tm->data[2] == '1' && tm->data[3] > '2') ||
243
			    (tm->data[4] > '3') ||
244
			    (tm->data[4] == '0' && tm->data[5] == '0') ||
245
			    (tm->data[4] == '3' && tm->data[5] > '1') ||
246
			    (tm->data[6] > '2') ||
247
			    (tm->data[6] == '2' && tm->data[7] > '3') ||
248
			    (tm->data[8] > '5')) {
249
				LOG_DBG((LOG_POLICY, 30,
250
				    "x509_generate_kn: invalid value in "
251
				    "NotValidBefore time field"));
252
				goto fail;
253
			}
254
			/* Stupid UTC tricks.  */
255
			if (tm->data[0] < '5')
256
				snprintf(before, sizeof before, "20%s",
257
				    tm->data);
258
			else
259
				snprintf(before, sizeof before, "19%s",
260
				    tm->data);
261
		} else {	/* V_ASN1_GENERICTIME */
262
			if ((tm->length < 12) || (tm->length > 15)) {
263
				LOG_DBG((LOG_POLICY, 30,
264
				    "x509_generate_kn: invalid length of "
265
				    "NotValidBefore time field (%d)",
266
				    tm->length));
267
				goto fail;
268
			}
269
			/* Validity checks.  */
270
			if ((tm->data[4] != '0' && tm->data[4] != '1') ||
271
			    (tm->data[4] == '0' && tm->data[5] == '0') ||
272
			    (tm->data[4] == '1' && tm->data[5] > '2') ||
273
			    (tm->data[6] > '3') ||
274
			    (tm->data[6] == '0' && tm->data[7] == '0') ||
275
			    (tm->data[6] == '3' && tm->data[7] > '1') ||
276
			    (tm->data[8] > '2') ||
277
			    (tm->data[8] == '2' && tm->data[9] > '3') ||
278
			    (tm->data[10] > '5')) {
279
				LOG_DBG((LOG_POLICY, 30,
280
				    "x509_generate_kn: invalid value in "
281
				    "NotValidBefore time field"));
282
				goto fail;
283
			}
284
			snprintf(before, sizeof before, "%s", tm->data);
285
		}
286
287
		/* Fix missing seconds.  */
288
		if (tm->length < 12) {
289
			before[12] = '0';
290
			before[13] = '0';
291
		}
292
		/* This will overwrite trailing 'Z'.  */
293
		before[14] = '\0';
294
	}
295
296
	tm = X509_get_notAfter(cert);
297
	if (tm == NULL ||
298
	    (tm->type != V_ASN1_UTCTIME &&
299
		tm->type != V_ASN1_GENERALIZEDTIME)) {
300
		tt = time(0);
301
		strftime(after, 14, "%Y%m%d%H%M%S", localtime(&tt));
302
		timecomp2 = "LocalTimeOfDay";
303
	} else {
304
		if (tm->data[tm->length - 1] == 'Z') {
305
			timecomp2 = "GMTTimeOfDay";
306
			i = tm->length - 2;
307
		} else {
308
			timecomp2 = "LocalTimeOfDay";
309
			i = tm->length - 1;
310
		}
311
312
		for (; i >= 0; i--) {
313
			if (tm->data[i] < '0' || tm->data[i] > '9') {
314
				LOG_DBG((LOG_POLICY, 30,
315
				    "x509_generate_kn: invalid data in "
316
				    "NotValidAfter time field"));
317
				goto fail;
318
			}
319
		}
320
321
		if (tm->type == V_ASN1_UTCTIME) {
322
			if ((tm->length < 10) || (tm->length > 13)) {
323
				LOG_DBG((LOG_POLICY, 30,
324
				    "x509_generate_kn: invalid length of "
325
				    "NotValidAfter time field (%d)",
326
				    tm->length));
327
				goto fail;
328
			}
329
			/* Validity checks. */
330
			if ((tm->data[2] != '0' && tm->data[2] != '1') ||
331
			    (tm->data[2] == '0' && tm->data[3] == '0') ||
332
			    (tm->data[2] == '1' && tm->data[3] > '2') ||
333
			    (tm->data[4] > '3') ||
334
			    (tm->data[4] == '0' && tm->data[5] == '0') ||
335
			    (tm->data[4] == '3' && tm->data[5] > '1') ||
336
			    (tm->data[6] > '2') ||
337
			    (tm->data[6] == '2' && tm->data[7] > '3') ||
338
			    (tm->data[8] > '5')) {
339
				LOG_DBG((LOG_POLICY, 30,
340
				    "x509_generate_kn: invalid value in "
341
				    "NotValidAfter time field"));
342
				goto fail;
343
			}
344
			/* Stupid UTC tricks.  */
345
			if (tm->data[0] < '5')
346
				snprintf(after, sizeof after, "20%s",
347
				    tm->data);
348
			else
349
				snprintf(after, sizeof after, "19%s",
350
				    tm->data);
351
		} else {	/* V_ASN1_GENERICTIME */
352
			if ((tm->length < 12) || (tm->length > 15)) {
353
				LOG_DBG((LOG_POLICY, 30,
354
				    "x509_generate_kn: invalid length of "
355
				    "NotValidAfter time field (%d)",
356
				    tm->length));
357
				goto fail;
358
			}
359
			/* Validity checks.  */
360
			if ((tm->data[4] != '0' && tm->data[4] != '1') ||
361
			    (tm->data[4] == '0' && tm->data[5] == '0') ||
362
			    (tm->data[4] == '1' && tm->data[5] > '2') ||
363
			    (tm->data[6] > '3') ||
364
			    (tm->data[6] == '0' && tm->data[7] == '0') ||
365
			    (tm->data[6] == '3' && tm->data[7] > '1') ||
366
			    (tm->data[8] > '2') ||
367
			    (tm->data[8] == '2' && tm->data[9] > '3') ||
368
			    (tm->data[10] > '5')) {
369
				LOG_DBG((LOG_POLICY, 30,
370
				    "x509_generate_kn: invalid value in "
371
				    "NotValidAfter time field"));
372
				goto fail;
373
			}
374
			snprintf(after, sizeof after, "%s", tm->data);
375
		}
376
377
		/* Fix missing seconds.  */
378
		if (tm->length < 12) {
379
			after[12] = '0';
380
			after[13] = '0';
381
		}
382
		after[14] = '\0';	/* This will overwrite trailing 'Z' */
383
	}
384
385
	if (asprintf(&buf, fmt, skey, ikey, timecomp, before, timecomp2,
386
	    after) == -1) {
387
		log_error("x509_generate_kn: "
388
		    "failed to allocate memory for KeyNote credential");
389
		goto fail;
390
	}
391
392
	free(ikey);
393
	ikey = NULL;
394
	free(skey);
395
	skey = NULL;
396
397
	if (kn_add_assertion(id, buf, strlen(buf), ASSERT_FLAG_LOCAL) == -1) {
398
		LOG_DBG((LOG_POLICY, 30,
399
		    "x509_generate_kn: failed to add new KeyNote credential"));
400
		goto fail;
401
	}
402
	/* We could print the assertion here, but log_print() truncates...  */
403
	LOG_DBG((LOG_POLICY, 60, "x509_generate_kn: added credential"));
404
405
	free(buf);
406
	buf = NULL;
407
408
	if (!X509_NAME_oneline(issuer, isname, 256)) {
409
		LOG_DBG((LOG_POLICY, 50,
410
		    "x509_generate_kn: "
411
		    "X509_NAME_oneline (issuer, ...) failed"));
412
		goto fail;
413
	}
414
	if (!X509_NAME_oneline(subject, subname, 256)) {
415
		LOG_DBG((LOG_POLICY, 50,
416
		    "x509_generate_kn: "
417
		    "X509_NAME_oneline (subject, ...) failed"));
418
		goto fail;
419
	}
420
	if (asprintf(&buf, fmt2, isname, subname, timecomp, before,
421
	    timecomp2, after) == -1) {
422
		log_error("x509_generate_kn: malloc failed");
423
		return 0;
424
	}
425
426
	if (kn_add_assertion(id, buf, strlen(buf), ASSERT_FLAG_LOCAL) == -1) {
427
		LOG_DBG((LOG_POLICY, 30,
428
		    "x509_generate_kn: failed to add new KeyNote credential"));
429
		goto fail;
430
	}
431
	LOG_DBG((LOG_POLICY, 80, "x509_generate_kn: added credential:\n%s",
432
	    buf));
433
434
	free(buf);
435
	return 1;
436
437
fail:
438
	free(buf);
439
	free(skey);
440
	free(ikey);
441
	if (key)
442
		RSA_free(key);
443
444
	return 0;
445
}
446
447
static u_int16_t
448
x509_hash(u_int8_t *id, size_t len)
449
{
450
	u_int16_t bucket = 0;
451
	size_t	i;
452
453
	/* XXX We might resize if we are crossing a certain threshold.  */
454
	for (i = 4; i < (len & ~1); i += 2) {
455
		/* Doing it this way avoids alignment problems.  */
456
		bucket ^= (id[i] + 1) * (id[i + 1] + 257);
457
	}
458
	/* Hash in the last character of odd length IDs too.  */
459
	if (i < len)
460
		bucket ^= (id[i] + 1) * (id[i] + 257);
461
462
	bucket &= bucket_mask;
463
	return bucket;
464
}
465
466
static void
467
x509_hash_init(void)
468
{
469
	struct x509_hash *certh;
470
	int	i;
471
472
	bucket_mask = (1 << INITIAL_BUCKET_BITS) - 1;
473
474
	/* If reinitializing, free existing entries.  */
475
	if (x509_tab) {
476
		for (i = 0; i <= bucket_mask; i++)
477
			for (certh = LIST_FIRST(&x509_tab[i]); certh;
478
			    certh = LIST_FIRST(&x509_tab[i])) {
479
				LIST_REMOVE(certh, link);
480
				free(certh);
481
			}
482
		free(x509_tab);
483
	}
484
	x509_tab = calloc(bucket_mask + 1, sizeof(struct x509_list));
485
	if (!x509_tab)
486
		log_fatal("x509_hash_init: malloc (%lu) failed",
487
		    (bucket_mask + 1) *
488
		    (unsigned long)sizeof(struct x509_list));
489
	for (i = 0; i <= bucket_mask; i++) {
490
		LIST_INIT(&x509_tab[i]);
491
	}
492
}
493
494
/* Lookup a certificate by an ID blob.  */
495
static X509 *
496
x509_hash_find(u_int8_t *id, size_t len)
497
{
498
	struct x509_hash *cert;
499
	u_int8_t	**cid;
500
	u_int32_t	*clen;
501
	int	n, i, id_found;
502
503
	for (cert = LIST_FIRST(&x509_tab[x509_hash(id, len)]); cert;
504
	    cert = LIST_NEXT(cert, link)) {
505
		if (!x509_cert_get_subjects(cert->cert, &n, &cid, &clen))
506
			continue;
507
508
		id_found = 0;
509
		for (i = 0; i < n; i++) {
510
			LOG_DBG_BUF((LOG_CRYPTO, 70, "cert_cmp", id, len));
511
			LOG_DBG_BUF((LOG_CRYPTO, 70, "cert_cmp", cid[i],
512
			    clen[i]));
513
			/*
514
			 * XXX This identity predicate needs to be
515
			 * understood.
516
			 */
517
			if (clen[i] == len && id[0] == cid[i][0] &&
518
			    memcmp(id + 4, cid[i] + 4, len - 4) == 0) {
519
				id_found++;
520
				break;
521
			}
522
		}
523
		cert_free_subjects(n, cid, clen);
524
		if (!id_found)
525
			continue;
526
527
		LOG_DBG((LOG_CRYPTO, 70, "x509_hash_find: return X509 %p",
528
		    cert->cert));
529
		return cert->cert;
530
	}
531
532
	LOG_DBG((LOG_CRYPTO, 70,
533
	    "x509_hash_find: no certificate matched query"));
534
	return 0;
535
}
536
537
static int
538
x509_hash_enter(X509 *cert)
539
{
540
	u_int16_t	bucket = 0;
541
	u_int8_t	**id;
542
	u_int32_t	*len;
543
	struct x509_hash *certh;
544
	int	n, i;
545
546
	if (!x509_cert_get_subjects(cert, &n, &id, &len)) {
547
		log_print("x509_hash_enter: cannot retrieve subjects");
548
		return 0;
549
	}
550
	for (i = 0; i < n; i++) {
551
		certh = calloc(1, sizeof *certh);
552
		if (!certh) {
553
			cert_free_subjects(n, id, len);
554
			log_error("x509_hash_enter: calloc (1, %lu) failed",
555
			    (unsigned long)sizeof *certh);
556
			return 0;
557
		}
558
		certh->cert = cert;
559
560
		bucket = x509_hash(id[i], len[i]);
561
562
		LIST_INSERT_HEAD(&x509_tab[bucket], certh, link);
563
		LOG_DBG((LOG_CRYPTO, 70,
564
		    "x509_hash_enter: cert %p added to bucket %d",
565
		    cert, bucket));
566
	}
567
	cert_free_subjects(n, id, len);
568
569
	return 1;
570
}
571
572
/* X509 Certificate Handling functions.  */
573
574
int
575
x509_read_from_dir(X509_STORE *ctx, char *name, int hash, int *pcount)
576
{
577
	FILE		*certfp;
578
	X509		*cert;
579
	struct stat	sb;
580
	char		fullname[PATH_MAX];
581
	char		file[PATH_MAX];
582
	int		fd;
583
584
	if (strlen(name) >= sizeof fullname - 1) {
585
		log_print("x509_read_from_dir: directory name too long");
586
		return 0;
587
	}
588
	LOG_DBG((LOG_CRYPTO, 40, "x509_read_from_dir: reading certs from %s",
589
	    name));
590
591
	if (monitor_req_readdir(name) == -1) {
592
		LOG_DBG((LOG_CRYPTO, 10,
593
		    "x509_read_from_dir: opendir (\"%s\") failed: %s",
594
		    name, strerror(errno)));
595
		return 0;
596
	}
597
598
	while ((fd = monitor_readdir(file, sizeof file)) != -1) {
599
		LOG_DBG((LOG_CRYPTO, 60,
600
		    "x509_read_from_dir: reading certificate %s",
601
		    file));
602
603
		if (fstat(fd, &sb) == -1) {
604
			log_error("x509_read_from_dir: fstat failed");
605
			close(fd);
606
			continue;
607
		}
608
609
		if (!S_ISREG(sb.st_mode)) {
610
			close(fd);
611
			continue;
612
		}
613
614
		if ((certfp = fdopen(fd, "r")) == NULL) {
615
			log_error("x509_read_from_dir: fdopen failed");
616
			close(fd);
617
			continue;
618
		}
619
620
#if SSLEAY_VERSION_NUMBER >= 0x00904100L
621
		cert = PEM_read_X509(certfp, NULL, NULL, NULL);
622
#else
623
		cert = PEM_read_X509(certfp, NULL, NULL);
624
#endif
625
		fclose(certfp);
626
627
		if (cert == NULL) {
628
			log_print("x509_read_from_dir: PEM_read_X509 "
629
			    "failed for %s", file);
630
			continue;
631
		}
632
633
		if (pcount != NULL)
634
			(*pcount)++;
635
636
		if (!X509_STORE_add_cert(ctx, cert)) {
637
			/*
638
			 * This is actually expected if we have several
639
			 * certificates only differing in subjectAltName,
640
			 * which is not an something that is strange.
641
			 * Consider multi-homed machines.
642
			*/
643
			LOG_DBG((LOG_CRYPTO, 50,
644
			    "x509_read_from_dir: X509_STORE_add_cert failed "
645
			    "for %s", file));
646
		}
647
		if (hash)
648
			if (!x509_hash_enter(cert))
649
				log_print("x509_read_from_dir: "
650
				    "x509_hash_enter (%s) failed",
651
				    file);
652
	}
653
654
	return 1;
655
}
656
657
/* XXX share code with x509_read_from_dir() ?  */
658
int
659
x509_read_crls_from_dir(X509_STORE *ctx, char *name)
660
{
661
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
662
	FILE		*crlfp;
663
	X509_CRL	*crl;
664
	struct stat	sb;
665
	char		fullname[PATH_MAX];
666
	char		file[PATH_MAX];
667
	int		fd, off, size;
668
669
	if (strlen(name) >= sizeof fullname - 1) {
670
		log_print("x509_read_crls_from_dir: directory name too long");
671
		return 0;
672
	}
673
	LOG_DBG((LOG_CRYPTO, 40, "x509_read_crls_from_dir: reading CRLs "
674
	    "from %s", name));
675
676
	if (monitor_req_readdir(name) == -1) {
677
		LOG_DBG((LOG_CRYPTO, 10, "x509_read_crls_from_dir: opendir "
678
		    "(\"%s\") failed: %s", name, strerror(errno)));
679
		return 0;
680
	}
681
	strlcpy(fullname, name, sizeof fullname);
682
	off = strlen(fullname);
683
	size = sizeof fullname - off;
684
685
	while ((fd = monitor_readdir(file, sizeof file)) != -1) {
686
		LOG_DBG((LOG_CRYPTO, 60, "x509_read_crls_from_dir: reading "
687
		    "CRL %s", file));
688
689
		if (fstat(fd, &sb) == -1) {
690
			log_error("x509_read_crls_from_dir: fstat failed");
691
			close(fd);
692
			continue;
693
		}
694
695
		if (!S_ISREG(sb.st_mode)) {
696
			close(fd);
697
			continue;
698
		}
699
700
		if ((crlfp = fdopen(fd, "r")) == NULL) {
701
			log_error("x509_read_crls_from_dir: fdopen failed");
702
			close(fd);
703
			continue;
704
		}
705
706
		crl = PEM_read_X509_CRL(crlfp, NULL, NULL, NULL);
707
708
		fclose(crlfp);
709
710
		if (crl == NULL) {
711
			log_print("x509_read_crls_from_dir: "
712
			    "PEM_read_X509_CRL failed for %s",
713
			    file);
714
			continue;
715
		}
716
		if (!X509_STORE_add_crl(ctx, crl)) {
717
			LOG_DBG((LOG_CRYPTO, 50, "x509_read_crls_from_dir: "
718
			    "X509_STORE_add_crl failed for %s", file));
719
			continue;
720
		}
721
		/*
722
		 * XXX This is to make x509_cert_validate set this (and
723
		 * XXX another) flag when validating certificates. Currently,
724
		 * XXX OpenSSL defaults to reject an otherwise valid
725
		 * XXX certificate (chain) if these flags are set but there
726
		 * XXX are no CRLs to check. The current workaround is to only
727
		 * XXX set the flags if we actually loaded some CRL data.
728
		 */
729
		X509_STORE_set_flags(ctx, X509_V_FLAG_CRL_CHECK);
730
	}
731
732
#endif				/* OPENSSL_VERSION_NUMBER >= 0x00907000L */
733
734
	return 1;
735
}
736
737
/* Initialize our databases and load our own certificates.  */
738
int
739
x509_cert_init(void)
740
{
741
	char	*dirname;
742
743
	x509_hash_init();
744
745
	/* Process CA certificates we will trust.  */
746
	dirname = conf_get_str("X509-certificates", "CA-directory");
747
	if (!dirname) {
748
		log_print("x509_cert_init: no CA-directory");
749
		return 0;
750
	}
751
	/* Free if already initialized.  */
752
	if (x509_cas)
753
		X509_STORE_free(x509_cas);
754
755
	x509_cas = X509_STORE_new();
756
	if (!x509_cas) {
757
		log_print("x509_cert_init: creating new X509_STORE failed");
758
		return 0;
759
	}
760
	if (!x509_read_from_dir(x509_cas, dirname, 0, &n_x509_cas)) {
761
		log_print("x509_cert_init: x509_read_from_dir failed");
762
		return 0;
763
	}
764
	/* Process client certificates we will accept.  */
765
	dirname = conf_get_str("X509-certificates", "Cert-directory");
766
	if (!dirname) {
767
		log_print("x509_cert_init: no Cert-directory");
768
		return 0;
769
	}
770
	/* Free if already initialized.  */
771
	if (x509_certs)
772
		X509_STORE_free(x509_certs);
773
774
	x509_certs = X509_STORE_new();
775
	if (!x509_certs) {
776
		log_print("x509_cert_init: creating new X509_STORE failed");
777
		return 0;
778
	}
779
	if (!x509_read_from_dir(x509_certs, dirname, 1, NULL)) {
780
		log_print("x509_cert_init: x509_read_from_dir failed");
781
		return 0;
782
	}
783
	return 1;
784
}
785
786
int
787
x509_crl_init(void)
788
{
789
	/*
790
	 * XXX I'm not sure if the method to use CRLs in certificate validation
791
	 * is valid for OpenSSL versions prior to 0.9.7. For now, simply do not
792
	 * support it.
793
	 */
794
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
795
	char	*dirname;
796
	dirname = conf_get_str("X509-certificates", "CRL-directory");
797
	if (!dirname) {
798
		log_print("x509_crl_init: no CRL-directory");
799
		return 0;
800
	}
801
	if (!x509_read_crls_from_dir(x509_cas, dirname)) {
802
		LOG_DBG((LOG_MISC, 10,
803
		    "x509_crl_init: x509_read_crls_from_dir failed"));
804
		return 0;
805
	}
806
#else
807
	LOG_DBG((LOG_CRYPTO, 10, "x509_crl_init: CRL support only "
808
	    "with OpenSSL v0.9.7 or later"));
809
#endif
810
811
	return 1;
812
}
813
814
void *
815
x509_cert_get(u_int8_t *asn, u_int32_t len)
816
{
817
	return x509_from_asn(asn, len);
818
}
819
820
int
821
x509_cert_validate(void *scert)
822
{
823
	X509_STORE_CTX	csc;
824
	X509_NAME	*issuer, *subject;
825
	X509		*cert = (X509 *) scert;
826
	EVP_PKEY	*key;
827
	int		res, err;
828
829
	/*
830
	 * Validate the peer certificate by checking with the CA certificates
831
	 * we trust.
832
	 */
833
	X509_STORE_CTX_init(&csc, x509_cas, cert, NULL);
834
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
835
	/* XXX See comment in x509_read_crls_from_dir.  */
836
	if (x509_cas->param->flags & X509_V_FLAG_CRL_CHECK) {
837
		X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK);
838
		X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK_ALL);
839
	}
840
#elif OPENSSL_VERSION_NUMBER >= 0x00907000L
841
	/* XXX See comment in x509_read_crls_from_dir.  */
842
	if (x509_cas->flags & X509_V_FLAG_CRL_CHECK) {
843
		X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK);
844
		X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK_ALL);
845
	}
846
#endif
847
	res = X509_verify_cert(&csc);
848
	err = csc.error;
849
	X509_STORE_CTX_cleanup(&csc);
850
851
	/*
852
	 * Return if validation succeeded or self-signed certs are not
853
	 * accepted.
854
	 *
855
	 * XXX X509_verify_cert seems to return -1 if the validation should be
856
	 * retried somehow.  We take this as an error and give up.
857
	 */
858
	if (res > 0)
859
		return 1;
860
	else if (res < 0 ||
861
	    (res == 0 && err != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)) {
862
		if (err)
863
			log_print("x509_cert_validate: %.100s",
864
			    X509_verify_cert_error_string(err));
865
		return 0;
866
	} else if (!conf_get_str("X509-certificates", "Accept-self-signed")) {
867
		if (err)
868
			log_print("x509_cert_validate: %.100s",
869
			    X509_verify_cert_error_string(err));
870
		return 0;
871
	}
872
	issuer = X509_get_issuer_name(cert);
873
	subject = X509_get_subject_name(cert);
874
875
	if (!issuer || !subject || X509_name_cmp(issuer, subject))
876
		return 0;
877
878
	key = X509_get_pubkey(cert);
879
	if (!key) {
880
		log_print("x509_cert_validate: could not get public key from "
881
		    "self-signed cert");
882
		return 0;
883
	}
884
	if (X509_verify(cert, key) == -1) {
885
		log_print("x509_cert_validate: self-signed cert is bad");
886
		return 0;
887
	}
888
	return 1;
889
}
890
891
int
892
x509_cert_insert(int id, void *scert)
893
{
894
	X509	*cert;
895
	int	 res;
896
897
	cert = X509_dup((X509 *)scert);
898
	if (!cert) {
899
		log_print("x509_cert_insert: X509_dup failed");
900
		return 0;
901
	}
902
	if (x509_generate_kn(id, cert) == 0) {
903
		LOG_DBG((LOG_POLICY, 50,
904
		    "x509_cert_insert: x509_generate_kn failed"));
905
		X509_free(cert);
906
		return 0;
907
	}
908
909
	res = x509_hash_enter(cert);
910
	if (!res)
911
		X509_free(cert);
912
913
	return res;
914
}
915
916
static struct x509_hash *
917
x509_hash_lookup(X509 *cert)
918
{
919
	struct x509_hash *certh;
920
	int	i;
921
922
	for (i = 0; i <= bucket_mask; i++)
923
		for (certh = LIST_FIRST(&x509_tab[i]); certh;
924
		    certh = LIST_NEXT(certh, link))
925
			if (certh->cert == cert)
926
				return certh;
927
	return 0;
928
}
929
930
void
931
x509_cert_free(void *cert)
932
{
933
	struct x509_hash *certh = x509_hash_lookup((X509 *) cert);
934
935
	if (certh)
936
		LIST_REMOVE(certh, link);
937
	X509_free((X509 *) cert);
938
}
939
940
/* Validate the BER Encoding of a RDNSequence in the CERT_REQ payload.  */
941
int
942
x509_certreq_validate(u_int8_t *asn, u_int32_t len)
943
{
944
	int	res = 1;
945
#if 0
946
	struct norm_type name = SEQOF("issuer", RDNSequence);
947
948
	if (!asn_template_clone(&name, 1) ||
949
	    (asn = asn_decode_sequence(asn, len, &name)) == 0) {
950
		log_print("x509_certreq_validate: can not decode 'acceptable "
951
		    "CA' info");
952
		res = 0;
953
	}
954
	asn_free(&name);
955
#endif
956
957
	/* XXX - not supported directly in SSL - later.  */
958
959
	return res;
960
}
961
962
/* Decode the BER Encoding of a RDNSequence in the CERT_REQ payload.  */
963
int
964
x509_certreq_decode(void **pdata, u_int8_t *asn, u_int32_t len)
965
{
966
#if 0
967
	/* XXX This needs to be done later.  */
968
	struct norm_type aca = SEQOF("aca", RDNSequence);
969
	struct norm_type *tmp;
970
	struct x509_aca naca, *ret;
971
972
	if (!asn_template_clone(&aca, 1) ||
973
	    (asn = asn_decode_sequence(asn, len, &aca)) == 0) {
974
		log_print("x509_certreq_decode: can not decode 'acceptable "
975
		    "CA' info");
976
		goto fail;
977
	}
978
	bzero(&naca, sizeof(naca));
979
980
	tmp = asn_decompose("aca.RelativeDistinguishedName."
981
	    "AttributeValueAssertion", &aca);
982
	if (!tmp)
983
		goto fail;
984
	x509_get_attribval(tmp, &naca.name1);
985
986
	tmp = asn_decompose("aca.RelativeDistinguishedName[1]"
987
	    ".AttributeValueAssertion", &aca);
988
	if (tmp)
989
		x509_get_attribval(tmp, &naca.name2);
990
991
	asn_free(&aca);
992
993
	ret = malloc(sizeof(struct x509_aca));
994
	if (ret)
995
		memcpy(ret, &naca, sizeof(struct x509_aca));
996
	else {
997
		log_error("x509_certreq_decode: malloc (%lu) failed",
998
		    (unsigned long) sizeof(struct x509_aca));
999
		x509_free_aca(&aca);
1000
	}
1001
1002
	return ret;
1003
1004
fail:
1005
	asn_free(&aca);
1006
#endif
1007
	return 1;
1008
}
1009
1010
void
1011
x509_free_aca(void *blob)
1012
{
1013
	struct x509_aca *aca = blob;
1014
1015
	if (aca != NULL) {
1016
		free(aca->name1.type);
1017
		free(aca->name1.val);
1018
1019
		free(aca->name2.type);
1020
		free(aca->name2.val);
1021
	}
1022
}
1023
1024
X509 *
1025
x509_from_asn(u_char *asn, u_int len)
1026
{
1027
	BIO		*certh;
1028
	X509		*scert = 0;
1029
1030
	certh = BIO_new(BIO_s_mem());
1031
	if (!certh) {
1032
		log_error("x509_from_asn: BIO_new (BIO_s_mem ()) failed");
1033
		return 0;
1034
	}
1035
	if (BIO_write(certh, asn, len) == -1) {
1036
		log_error("x509_from_asn: BIO_write failed\n");
1037
		goto end;
1038
	}
1039
	scert = d2i_X509_bio(certh, NULL);
1040
	if (!scert) {
1041
		log_print("x509_from_asn: d2i_X509_bio failed\n");
1042
		goto end;
1043
	}
1044
end:
1045
	BIO_free(certh);
1046
	return scert;
1047
}
1048
1049
/*
1050
 * Obtain a certificate from an acceptable CA.
1051
 * XXX We don't check if the certificate we find is from an accepted CA.
1052
 */
1053
int
1054
x509_cert_obtain(u_int8_t *id, size_t id_len, void *data, u_int8_t **cert,
1055
    u_int32_t *certlen)
1056
{
1057
	struct x509_aca *aca = data;
1058
	X509		*scert;
1059
1060
	if (aca)
1061
		LOG_DBG((LOG_CRYPTO, 60, "x509_cert_obtain: "
1062
		    "acceptable certificate authorities here"));
1063
1064
	/* We need our ID to find a certificate.  */
1065
	if (!id) {
1066
		log_print("x509_cert_obtain: ID is missing");
1067
		return 0;
1068
	}
1069
	scert = x509_hash_find(id, id_len);
1070
	if (!scert)
1071
		return 0;
1072
1073
	x509_serialize(scert, cert, certlen);
1074
	if (!*cert)
1075
		return 0;
1076
	return 1;
1077
}
1078
1079
/* Returns a pointer to the subjectAltName information of X509 certificate.  */
1080
int
1081
x509_cert_subjectaltname(X509 *scert, u_int8_t **altname, u_int32_t *len)
1082
{
1083
	X509_EXTENSION	*subjectaltname;
1084
	u_int8_t	*sandata;
1085
	int		extpos, santype, sanlen;
1086
1087
	extpos = X509_get_ext_by_NID(scert, NID_subject_alt_name, -1);
1088
	if (extpos == -1) {
1089
		log_print("x509_cert_subjectaltname: "
1090
		    "certificate does not contain subjectAltName");
1091
		return 0;
1092
	}
1093
	subjectaltname = X509_get_ext(scert, extpos);
1094
1095
	if (!subjectaltname || !subjectaltname->value ||
1096
	    !subjectaltname->value->data ||
1097
	    subjectaltname->value->length < 4) {
1098
		log_print("x509_cert_subjectaltname: invalid "
1099
		    "subjectaltname extension");
1100
		return 0;
1101
	}
1102
	/* SSL does not handle unknown ASN stuff well, do it by hand.  */
1103
	sandata = subjectaltname->value->data;
1104
	santype = sandata[2] & 0x3f;
1105
	sanlen = sandata[3];
1106
	sandata += 4;
1107
1108
	/*
1109
	 * The test here used to be !=, but some certificates can include
1110
	 * extra stuff in subjectAltName, so we will just take the first
1111
	 * salen bytes, and not worry about what follows.
1112
	 */
1113
	if (sanlen + 4 > subjectaltname->value->length) {
1114
		log_print("x509_cert_subjectaltname: subjectaltname invalid "
1115
		    "length");
1116
		return 0;
1117
	}
1118
	*len = sanlen;
1119
	*altname = sandata;
1120
	return santype;
1121
}
1122
1123
int
1124
x509_cert_get_subjects(void *scert, int *cnt, u_int8_t ***id,
1125
    u_int32_t **id_len)
1126
{
1127
	X509		*cert = scert;
1128
	X509_NAME	*subject;
1129
	int		type;
1130
	u_int8_t	*altname;
1131
	u_int32_t	altlen;
1132
	u_int8_t	*buf = 0;
1133
	unsigned char	*ubuf;
1134
	int		i;
1135
1136
	*id = 0;
1137
	*id_len = 0;
1138
1139
	/*
1140
	 * XXX There can be a collection of subjectAltNames, but for now I
1141
	 * only return the subjectName and a single subjectAltName, if
1142
	 * present.
1143
	 */
1144
	type = x509_cert_subjectaltname(cert, &altname, &altlen);
1145
	if (!type) {
1146
		*cnt = 1;
1147
		altlen = 0;
1148
	} else
1149
		*cnt = 2;
1150
1151
	*id = calloc(*cnt, sizeof **id);
1152
	if (!*id) {
1153
		log_print("x509_cert_get_subject: malloc (%lu) failed",
1154
		    *cnt * (unsigned long)sizeof **id);
1155
		*cnt = 0;
1156
		goto fail;
1157
	}
1158
	*id_len = calloc(*cnt, sizeof **id_len);
1159
	if (!*id_len) {
1160
		log_print("x509_cert_get_subject: malloc (%lu) failed",
1161
		    *cnt * (unsigned long)sizeof **id_len);
1162
		goto fail;
1163
	}
1164
	/* Stash the subjectName into the first slot.  */
1165
	subject = X509_get_subject_name(cert);
1166
	if (!subject)
1167
		goto fail;
1168
1169
	(*id_len)[0] =
1170
		ISAKMP_ID_DATA_OFF + i2d_X509_NAME(subject, NULL) -
1171
		    ISAKMP_GEN_SZ;
1172
	(*id)[0] = malloc((*id_len)[0]);
1173
	if (!(*id)[0]) {
1174
		log_print("x509_cert_get_subject: malloc (%d) failed",
1175
		    (*id_len)[0]);
1176
		goto fail;
1177
	}
1178
	SET_ISAKMP_ID_TYPE((*id)[0] - ISAKMP_GEN_SZ, IPSEC_ID_DER_ASN1_DN);
1179
	ubuf = (*id)[0] + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ;
1180
	i2d_X509_NAME(subject, &ubuf);
1181
1182
	if (altlen) {
1183
		/* Stash the subjectAltName into the second slot.  */
1184
		buf = malloc(altlen + ISAKMP_ID_DATA_OFF);
1185
		if (!buf) {
1186
			log_print("x509_cert_get_subject: malloc (%d) failed",
1187
			    altlen + ISAKMP_ID_DATA_OFF);
1188
			goto fail;
1189
		}
1190
		switch (type) {
1191
		case X509v3_DNS_NAME:
1192
			SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_FQDN);
1193
			break;
1194
1195
		case X509v3_RFC_NAME:
1196
			SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_USER_FQDN);
1197
			break;
1198
1199
		case X509v3_IP_ADDR:
1200
			/*
1201
			 * XXX I dislike the numeric constants, but I don't
1202
			 * know what we should use otherwise.
1203
			 */
1204
			switch (altlen) {
1205
			case 4:
1206
				SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_IPV4_ADDR);
1207
				break;
1208
1209
			case 16:
1210
				SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_IPV6_ADDR);
1211
				break;
1212
1213
			default:
1214
				log_print("x509_cert_get_subject: invalid "
1215
				    "subjectAltName IPaddress length %d ",
1216
				    altlen);
1217
				goto fail;
1218
			}
1219
			break;
1220
		}
1221
1222
		SET_IPSEC_ID_PROTO(buf + ISAKMP_ID_DOI_DATA_OFF, 0);
1223
		SET_IPSEC_ID_PORT(buf + ISAKMP_ID_DOI_DATA_OFF, 0);
1224
		memcpy(buf + ISAKMP_ID_DATA_OFF, altname, altlen);
1225
1226
		(*id_len)[1] = ISAKMP_ID_DATA_OFF + altlen - ISAKMP_GEN_SZ;
1227
		(*id)[1] = malloc((*id_len)[1]);
1228
		if (!(*id)[1]) {
1229
			log_print("x509_cert_get_subject: malloc (%d) failed",
1230
			    (*id_len)[1]);
1231
			goto fail;
1232
		}
1233
		memcpy((*id)[1], buf + ISAKMP_GEN_SZ, (*id_len)[1]);
1234
1235
		free(buf);
1236
		buf = 0;
1237
	}
1238
	return 1;
1239
1240
fail:
1241
	for (i = 0; i < *cnt; i++)
1242
		free((*id)[i]);
1243
	free(*id);
1244
	free(*id_len);
1245
	free(buf);
1246
	return 0;
1247
}
1248
1249
int
1250
x509_cert_get_key(void *scert, void *keyp)
1251
{
1252
	X509		*cert = scert;
1253
	EVP_PKEY	*key;
1254
1255
	key = X509_get_pubkey(cert);
1256
1257
	/* Check if we got the right key type.  */
1258
	if (key->type != EVP_PKEY_RSA) {
1259
		log_print("x509_cert_get_key: public key is not a RSA key");
1260
		X509_free(cert);
1261
		return 0;
1262
	}
1263
	*(RSA **)keyp = RSAPublicKey_dup(key->pkey.rsa);
1264
1265
	return *(RSA **)keyp == NULL ? 0 : 1;
1266
}
1267
1268
void *
1269
x509_cert_dup(void *scert)
1270
{
1271
	return X509_dup(scert);
1272
}
1273
1274
void
1275
x509_serialize(void *scert, u_int8_t **data, u_int32_t *datalen)
1276
{
1277
	u_int8_t	*p;
1278
1279
	*datalen = i2d_X509((X509 *)scert, NULL);
1280
	*data = p = malloc(*datalen);
1281
	if (!p) {
1282
		log_error("x509_serialize: malloc (%d) failed", *datalen);
1283
		return;
1284
	}
1285
	*datalen = i2d_X509((X509 *)scert, &p);
1286
}
1287
1288
/* From cert to printable */
1289
char *
1290
x509_printable(void *cert)
1291
{
1292
	char		*s;
1293
	u_int8_t	*data;
1294
	u_int32_t	datalen;
1295
1296
	x509_serialize(cert, &data, &datalen);
1297
	if (!data)
1298
		return 0;
1299
1300
	s = raw2hex(data, datalen);
1301
	free(data);
1302
	return s;
1303
}
1304
1305
/* From printable to cert */
1306
void *
1307
x509_from_printable(char *cert)
1308
{
1309
	u_int8_t	*buf;
1310
	int		plen, ret;
1311
	void		*foo;
1312
1313
	plen = (strlen(cert) + 1) / 2;
1314
	buf = malloc(plen);
1315
	if (!buf) {
1316
		log_error("x509_from_printable: malloc (%d) failed", plen);
1317
		return 0;
1318
	}
1319
	ret = hex2raw(cert, buf, plen);
1320
	if (ret == -1) {
1321
		free(buf);
1322
		log_print("x509_from_printable: badly formatted cert");
1323
		return 0;
1324
	}
1325
	foo = x509_cert_get(buf, plen);
1326
	free(buf);
1327
	if (!foo)
1328
		log_print("x509_from_printable: "
1329
		    "could not retrieve certificate");
1330
	return foo;
1331
}
1332
1333
char *
1334
x509_DN_string(u_int8_t *asn1, size_t sz)
1335
{
1336
	X509_NAME	*name;
1337
	const u_int8_t	*p = asn1;
1338
	char		buf[256];	/* XXX Just a guess at a maximum length.  */
1339
	long len = sz;
1340
1341
	name = d2i_X509_NAME(NULL, &p, len);
1342
	if (!name) {
1343
		log_print("x509_DN_string: d2i_X509_NAME failed");
1344
		return 0;
1345
	}
1346
	if (!X509_NAME_oneline(name, buf, sizeof buf - 1)) {
1347
		log_print("x509_DN_string: X509_NAME_oneline failed");
1348
		X509_NAME_free(name);
1349
		return 0;
1350
	}
1351
	X509_NAME_free(name);
1352
	buf[sizeof buf - 1] = '\0';
1353
	return strdup(buf);
1354
}
1355
1356
/* Number of CAs we trust (to decide whether we can send CERT_REQ) */
1357
int
1358
x509_ca_count(void)
1359
{
1360
	return n_x509_cas;
1361
}