xref: /openbsd/sbin/isakmpd/x509.c (revision cecf84d4)
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 }
1362