1/*	$OpenBSD: ikeca.c,v 1.51 2021/01/23 22:04:55 tobhe Exp $	*/
2
3/*
4 * Copyright (c) 2010 Jonathan Gray <jsg@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <sys/wait.h>
22#include <stdio.h>
23#include <unistd.h>
24#include <err.h>
25#include <errno.h>
26#include <string.h>
27#include <stdlib.h>
28#include <pwd.h>
29#include <fcntl.h>
30#include <fts.h>
31#include <dirent.h>
32#include <limits.h>
33
34#include <openssl/rand.h>
35#include <openssl/rsa.h>
36#include <openssl/pem.h>
37
38#include "types.h"
39#include "parser.h"
40
41#ifndef PREFIX
42#define PREFIX		""
43#endif
44#ifndef SSLDIR
45#define SSLDIR		PREFIX "/etc/ssl"
46#endif
47#define SSL_CNF		SSLDIR "/openssl.cnf"
48#define X509_CNF	SSLDIR "/x509v3.cnf"
49#define IKECA_CNF	SSLDIR "/ikeca.cnf"
50#define KEYBASE		PREFIX "/etc/iked"
51#ifndef EXPDIR
52#define EXPDIR		PREFIX "/usr/share/iked"
53#endif
54
55#ifndef PATH_OPENSSL
56#define PATH_OPENSSL	"/usr/bin/openssl"
57#endif
58#ifndef PATH_ZIP
59#define PATH_ZIP	"/usr/local/bin/zip"
60#endif
61#ifndef PATH_TAR
62#define PATH_TAR	"/bin/tar"
63#endif
64
65struct ca {
66	char	 sslpath[PATH_MAX];
67	char	 passfile[PATH_MAX + 5]; /* Includes the "file:" prefix */
68	char	 index[PATH_MAX];
69	char	 serial[PATH_MAX];
70	char	 sslcnf[PATH_MAX];
71	char	 extcnf[PATH_MAX];
72	char	*batch;
73	char	*caname;
74};
75
76struct {
77	char	*dir;
78	mode_t	 mode;
79} hier[] = {
80	{ "",		0755 },
81	{ "/ca",	0755 },
82	{ "/certs",	0755 },
83	{ "/crls",	0755 },
84	{ "/export",	0755 },
85	{ "/private",	0700 }
86};
87
88/* explicitly list allowed variables */
89char *ca_env[][2] = {
90	{ "$ENV::CADB", NULL },
91	{ "$ENV::CASERIAL", NULL },
92	{ "$ENV::CERTFQDN", NULL },
93	{ "$ENV::CERTIP", NULL },
94	{ "$ENV::CERTPATHLEN", NULL },
95	{ "$ENV::CERTUSAGE", NULL },
96	{ "$ENV::CERT_C", NULL },
97	{ "$ENV::CERT_CN", NULL },
98	{ "$ENV::CERT_EMAIL", NULL },
99	{ "$ENV::CERT_L", NULL },
100	{ "$ENV::CERT_O", NULL },
101	{ "$ENV::CERT_OU", NULL },
102	{ "$ENV::CERT_ST", NULL },
103	{ "$ENV::EXTCERTUSAGE", NULL },
104	{ "$ENV::NSCERTTYPE", NULL },
105	{ "$ENV::REQ_EXT", NULL },
106	{ NULL }
107};
108
109int		 ca_sign(struct ca *, char *, int);
110int		 ca_request(struct ca *, char *, int);
111void		 ca_newpass(char *, char *);
112int		 fcopy(char *, char *, mode_t);
113void		 fcopy_env(const char *, const char *, mode_t);
114int		 rm_dir(char *);
115void		 ca_hier(char *);
116void		 ca_setenv(const char *, const char *);
117void		 ca_clrenv(void);
118void		 ca_setcnf(struct ca *, const char *);
119void		 ca_create_index(struct ca *);
120int static	 ca_execv(char *const []);
121
122/* util.c */
123int		 expand_string(char *, size_t, const char *, const char *);
124
125int
126ca_delete(struct ca *ca)
127{
128	return (rm_dir(ca->sslpath));
129}
130
131int
132ca_key_create(struct ca *ca, char *keyname)
133{
134	struct stat		 st;
135	char			 path[PATH_MAX];
136	int			 len;
137
138	len = snprintf(path, sizeof(path), "%s/private/%s.key",
139	    ca->sslpath, keyname);
140	if (len < 0 || (size_t)len >= sizeof(path))
141		err(1, "%s: snprintf", __func__);
142
143	/* don't recreate key if one is already present */
144	if (stat(path, &st) == 0) {
145		return (0);
146	}
147
148	char *cmd[] = { PATH_OPENSSL, "genrsa", "-out", path, "2048", NULL };
149	ca_execv(cmd);
150	chmod(path, 0600);
151
152	return (0);
153}
154
155int
156ca_key_import(struct ca *ca, char *keyname, char *import)
157{
158	struct stat		 st;
159	char			 dst[PATH_MAX];
160	int			 len;
161
162	if (stat(import, &st) != 0) {
163		warn("could not access keyfile %s", import);
164		return (1);
165	}
166
167	len = snprintf(dst, sizeof(dst), "%s/private/%s.key", ca->sslpath, keyname);
168	if (len < 0 || (size_t)len >= sizeof(dst))
169		err(1, "%s: snprintf", __func__);
170
171	fcopy(import, dst, 0600);
172
173	return (0);
174}
175
176int
177ca_key_delete(struct ca *ca, char *keyname)
178{
179	char			 path[PATH_MAX];
180	int			 len;
181
182	len = snprintf(path, sizeof(path), "%s/private/%s.key",
183	    ca->sslpath, keyname);
184	if (len < 0 || (size_t)len >= sizeof(path))
185		err(1, "%s: snprintf", __func__);
186	unlink(path);
187
188	return (0);
189}
190
191int
192ca_delkey(struct ca *ca, char *keyname)
193{
194	char		file[PATH_MAX];
195	int		len;
196
197	len = snprintf(file, sizeof(file), "%s/%s.crt", ca->sslpath, keyname);
198	if (len < 0 || (size_t)len >= sizeof(file))
199		err(1, "%s: snprintf", __func__);
200	unlink(file);
201
202	len = snprintf(file, sizeof(file), "%s/private/%s.key", ca->sslpath, keyname);
203	if (len < 0 || (size_t)len >= sizeof(file))
204		err(1, "%s: snprintf", __func__);
205	unlink(file);
206
207	len = snprintf(file, sizeof(file), "%s/private/%s.csr", ca->sslpath, keyname);
208	if (len < 0 || (size_t)len >= sizeof(file))
209		err(1, "%s: snprintf", __func__);
210	unlink(file);
211
212	len = snprintf(file, sizeof(file), "%s/private/%s.pfx", ca->sslpath, keyname);
213	if (len < 0 || (size_t)len >= sizeof(file))
214		err(1, "%s: snprintf", __func__);
215	unlink(file);
216
217	return (0);
218}
219
220int
221ca_request(struct ca *ca, char *keyname, int type)
222{
223	char		hostname[HOST_NAME_MAX+1];
224	char		name[128];
225	char		key[PATH_MAX];
226	char		path[PATH_MAX];
227	int		len;
228
229	ca_setenv("$ENV::CERT_CN", keyname);
230
231	strlcpy(name, keyname, sizeof(name));
232
233	if (type == HOST_IPADDR) {
234		ca_setenv("$ENV::CERTIP", name);
235		ca_setenv("$ENV::REQ_EXT", "x509v3_IPAddr");
236	} else if (type == HOST_FQDN) {
237		if (!strcmp(keyname, "local")) {
238			if (gethostname(hostname, sizeof(hostname)))
239				err(1, "gethostname");
240			strlcpy(name, hostname, sizeof(name));
241		}
242		ca_setenv("$ENV::CERTFQDN", name);
243		ca_setenv("$ENV::REQ_EXT", "x509v3_FQDN");
244	} else {
245		errx(1, "unknown host type %d", type);
246	}
247
248	ca_setcnf(ca, keyname);
249
250	len = snprintf(key, sizeof(key), "%s/private/%s.key", ca->sslpath, keyname);
251	if (len < 0 || (size_t)len >= sizeof(key))
252		err(1, "%s: snprintf", __func__);
253	len = snprintf(path, sizeof(path), "%s/private/%s.csr", ca->sslpath, keyname);
254	if (len < 0 || (size_t)len >= sizeof(path))
255		err(1, "%s: snprintf", __func__);
256
257	char *cmd[] = { PATH_OPENSSL, "req", "-new", "-key", key, "-out", path,
258	    "-config", ca->sslcnf, ca->batch, NULL };
259	ca_execv(cmd);
260	chmod(path, 0600);
261
262	return (0);
263}
264
265int
266ca_sign(struct ca *ca, char *keyname, int type)
267{
268	char		cakey[PATH_MAX];
269	char		cacrt[PATH_MAX];
270	char		out[PATH_MAX];
271	char		in[PATH_MAX];
272	char		*extensions = NULL;
273	int		len;
274
275	if (type == HOST_IPADDR) {
276		extensions = "x509v3_IPAddr";
277	} else if (type == HOST_FQDN) {
278		extensions = "x509v3_FQDN";
279	} else {
280		errx(1, "unknown host type %d", type);
281	}
282
283	ca_create_index(ca);
284
285	ca_setenv("$ENV::CADB", ca->index);
286	ca_setenv("$ENV::CASERIAL", ca->serial);
287	ca_setcnf(ca, keyname);
288
289	len = snprintf(cakey, sizeof(cakey), "%s/private/ca.key", ca->sslpath);
290	if (len < 0 || (size_t)len >= sizeof(cakey))
291		err(1, "%s: snprintf", __func__);
292	len = snprintf(cacrt, sizeof(cacrt), "%s/ca.crt", ca->sslpath);
293	if (len < 0 || (size_t)len >= sizeof(cacrt))
294		err(1, "%s: snprintf", __func__);
295	len = snprintf(out, sizeof(out), "%s/%s.crt", ca->sslpath, keyname);
296	if (len < 0 || (size_t)len >= sizeof(out))
297		err(1, "%s: snprintf", __func__);
298	len = snprintf(in, sizeof(in), "%s/private/%s.csr", ca->sslpath, keyname);
299	if (len < 0 || (size_t)len >= sizeof(in))
300		err(1, "%s: snprintf", __func__);
301
302	char *cmd[] = { PATH_OPENSSL, "ca", "-config", ca->sslcnf,
303	    "-keyfile", cakey, "-cert", cacrt, "-extfile", ca->extcnf,
304	    "-extensions", extensions, "-out", out, "-in", in,
305	    "-passin", ca->passfile, "-outdir", ca->sslpath, "-batch", NULL };
306	ca_execv(cmd);
307
308	return (0);
309}
310
311int
312ca_certificate(struct ca *ca, char *keyname, int type, int action)
313{
314	ca_clrenv();
315
316	switch (action) {
317	case CA_SERVER:
318		ca_setenv("$ENV::EXTCERTUSAGE", "serverAuth");
319		ca_setenv("$ENV::NSCERTTYPE", "server");
320		ca_setenv("$ENV::CERTUSAGE",
321		    "digitalSignature,keyEncipherment");
322		break;
323	case CA_CLIENT:
324		ca_setenv("$ENV::EXTCERTUSAGE", "clientAuth");
325		ca_setenv("$ENV::NSCERTTYPE", "client");
326		ca_setenv("$ENV::CERTUSAGE",
327		    "digitalSignature,keyAgreement");
328		break;
329	case CA_OCSP:
330		ca_setenv("$ENV::EXTCERTUSAGE", "OCSPSigning");
331		ca_setenv("$ENV::CERTUSAGE",
332		    "nonRepudiation,digitalSignature,keyEncipherment");
333		break;
334	default:
335		break;
336	}
337
338	ca_key_create(ca, keyname);
339	ca_request(ca, keyname, type);
340	ca_sign(ca, keyname, type);
341
342	return (0);
343}
344
345int
346ca_key_install(struct ca *ca, char *keyname, char *dir)
347{
348	struct stat	 st;
349	char		 src[PATH_MAX];
350	char		 dst[PATH_MAX];
351	char		 out[PATH_MAX];
352	char		*p = NULL;
353	int		 len;
354
355	len = snprintf(src, sizeof(src), "%s/private/%s.key", ca->sslpath, keyname);
356	if (len < 0 || (size_t)len >= sizeof(src))
357		err(1, "%s: snprintf", __func__);
358	if (stat(src, &st) == -1) {
359		if (errno == ENOENT)
360			printf("key for '%s' does not exist\n", ca->caname);
361		else
362			warn("could not access key");
363		return (1);
364	}
365
366	if (dir == NULL)
367		p = dir = strdup(KEYBASE);
368
369	ca_hier(dir);
370
371	len = snprintf(dst, sizeof(dst), "%s/private/local.key", dir);
372	if (len < 0 || (size_t)len >= sizeof(dst))
373		err(1, "%s: snprintf", __func__);
374	fcopy(src, dst, 0600);
375
376	len = snprintf(out, sizeof(out), "%s/local.pub", dir);
377	if (len < 0 || (size_t)len >= sizeof(out))
378		err(1, "%s: snprintf", __func__);
379
380	char *cmd[] = { PATH_OPENSSL, "rsa", "-out", out, "-in", dst,
381	    "-pubout", NULL };
382	ca_execv(cmd);
383
384	free(p);
385
386	return (0);
387}
388
389int
390ca_cert_install(struct ca *ca, char *keyname, char *dir)
391{
392	char		 src[PATH_MAX];
393	char		 dst[PATH_MAX];
394	int		 r;
395	char		*p = NULL;
396	int		 len;
397
398	if (dir == NULL)
399		p = dir = strdup(KEYBASE);
400
401	ca_hier(dir);
402
403	if ((r = ca_key_install(ca, keyname, dir)) != 0) {
404		free(dir);
405		return (r);
406	}
407
408	len = snprintf(src, sizeof(src), "%s/%s.crt", ca->sslpath, keyname);
409	if (len < 0 || (size_t)len >= sizeof(src))
410		err(1, "%s: snprintf", __func__);
411	len = snprintf(dst, sizeof(dst), "%s/certs/%s.crt", dir, keyname);
412	if (len < 0 || (size_t)len >= sizeof(dst))
413		err(1, "%s: snprintf", __func__);
414	fcopy(src, dst, 0644);
415
416	free(p);
417
418	return (0);
419}
420
421void
422ca_newpass(char *passfile, char *password)
423{
424	FILE	*f;
425	char	*pass;
426	char	 prev[_PASSWORD_LEN + 1];
427
428	if (password != NULL) {
429		pass = password;
430		goto done;
431	}
432
433	pass = getpass("CA passphrase:");
434	if (pass == NULL || *pass == '\0')
435		err(1, "password not set");
436
437	strlcpy(prev, pass, sizeof(prev));
438	pass = getpass("Retype CA passphrase:");
439	if (pass == NULL || strcmp(prev, pass) != 0)
440		errx(1, "passphrase does not match!");
441
442 done:
443	if ((f = fopen(passfile, "wb")) == NULL)
444		err(1, "could not open passfile %s", passfile);
445	chmod(passfile, 0600);
446
447	fprintf(f, "%s\n%s\n", pass, pass);
448
449	fclose(f);
450}
451
452int
453ca_create(struct ca *ca)
454{
455	char			 key[PATH_MAX];
456	char			 csr[PATH_MAX];
457	char			 crt[PATH_MAX];
458	int			 len;
459
460	ca_clrenv();
461
462	len = snprintf(key, sizeof(key), "%s/private/ca.key", ca->sslpath);
463	if (len < 0 || (size_t)len >= sizeof(key))
464		err(1, "%s: snprintf", __func__);
465	char *genrsa[] = { PATH_OPENSSL, "genrsa", "-aes256", "-out", key,
466	    "-passout", ca->passfile, "2048", NULL };
467	ca_execv(genrsa);
468
469	chmod(key, 0600);
470
471	ca_setenv("$ENV::CERT_CN", "VPN CA");
472	ca_setenv("$ENV::REQ_EXT", "x509v3_CA");
473	ca_setcnf(ca, "ca");
474
475	len = snprintf(csr, sizeof(csr), "%s/private/ca.csr", ca->sslpath);
476	if (len < 0 || (size_t)len >= sizeof(csr))
477		err(1, "%s: snprintf", __func__);
478	char *reqcmd[] = { PATH_OPENSSL, "req", "-new", "-key", key,
479	    "-config", ca->sslcnf, "-out", csr,
480	    "-passin", ca->passfile, ca->batch, NULL };
481	ca_execv(reqcmd);
482	chmod(csr, 0600);
483
484	len = snprintf(crt, sizeof(crt), "%s/ca.crt", ca->sslpath);
485	if (len < 0 || (size_t)len >= sizeof(crt))
486		err(1, "%s: snprintf", __func__);
487	char *x509[] = { PATH_OPENSSL, "x509", "-req", "-days", "4500",
488	    "-in", csr, "-signkey", key, "-sha256",
489	    "-extfile", ca->extcnf, "-extensions", "x509v3_CA",
490	    "-out", crt, "-passin", ca->passfile, NULL };
491	ca_execv(x509);
492
493	/* Create the CRL revocation list */
494	ca_revoke(ca, NULL);
495
496	return (0);
497}
498
499int
500ca_install(struct ca *ca, char *dir)
501{
502	struct stat	 st;
503	char		 src[PATH_MAX];
504	char		 dst[PATH_MAX];
505	char		*p = NULL;
506	int		 len;
507
508	len = snprintf(src, sizeof(src), "%s/ca.crt", ca->sslpath);
509	if (len < 0 || (size_t)len >= sizeof(src))
510		err(1, "%s: snprintf", __func__);
511	if (stat(src, &st) == -1) {
512		printf("CA '%s' does not exist\n", ca->caname);
513		return (1);
514	}
515
516	if (dir == NULL)
517		p = dir = strdup(KEYBASE);
518
519	ca_hier(dir);
520
521	len = snprintf(dst, sizeof(dst), "%s/ca/ca.crt", dir);
522	if (len < 0 || (size_t)len >= sizeof(dst))
523		err(1, "%s: snprintf", __func__);
524	if (fcopy(src, dst, 0644) == 0)
525		printf("certificate for CA '%s' installed into %s\n",
526		    ca->caname, dst);
527
528	len = snprintf(src, sizeof(src), "%s/ca.crl", ca->sslpath);
529	if (len < 0 || (size_t)len >= sizeof(src))
530		err(1, "%s: snprintf", __func__);
531	if (stat(src, &st) == 0) {
532		len = snprintf(dst, sizeof(dst), "%s/crls/ca.crl", dir);
533		if (len < 0 || (size_t)len >= sizeof(dst))
534			err(1, "%s: snprintf", __func__);
535		if (fcopy(src, dst, 0644) == 0)
536			printf("CRL for CA '%s' installed to %s\n",
537			    ca->caname, dst);
538	}
539
540	free(p);
541
542	return (0);
543}
544
545int
546ca_show_certs(struct ca *ca, char *name)
547{
548	DIR		*dir;
549	struct dirent	*de;
550	char		 path[PATH_MAX];
551	char		*p;
552	struct stat	 st;
553	int		 len;
554
555	if (name != NULL) {
556		len = snprintf(path, sizeof(path), "%s/%s.crt",
557		    ca->sslpath, name);
558		if (len < 0 || (size_t)len >= sizeof(path))
559			err(1, "%s: snprintf", __func__);
560		if (stat(path, &st) != 0)
561			err(1, "could not open file %s.crt", name);
562		char *cmd[] = { PATH_OPENSSL, "x509", "-text",
563		    "-in", path, NULL };
564		ca_execv(cmd);
565		printf("\n");
566		return (0);
567	}
568
569	if ((dir = opendir(ca->sslpath)) == NULL)
570		err(1, "could not open directory %s", ca->sslpath);
571
572	while ((de = readdir(dir)) != NULL) {
573		if (de->d_namlen > 4) {
574			p = de->d_name + de->d_namlen - 4;
575			if (strcmp(".crt", p) != 0)
576				continue;
577			len = snprintf(path, sizeof(path), "%s/%s", ca->sslpath,
578			    de->d_name);
579			if (len < 0 || (size_t)len >= sizeof(path))
580				err(1, "%s: snprintf", __func__);
581			char *cmd[] = { PATH_OPENSSL, "x509", "-subject",
582			    "-fingerprint", "-dates", "-noout", "-in", path,
583			    NULL };
584			ca_execv(cmd);
585			printf("\n");
586		}
587	}
588
589	closedir(dir);
590
591	return (0);
592}
593
594int
595fcopy(char *src, char *dst, mode_t mode)
596{
597	int		ifd, ofd;
598	uint8_t		buf[BUFSIZ];
599	ssize_t		r;
600
601	if ((ifd = open(src, O_RDONLY)) == -1)
602		err(1, "open %s", src);
603
604	if ((ofd = open(dst, O_WRONLY|O_CREAT|O_TRUNC, mode)) == -1) {
605		int saved_errno = errno;
606		close(ifd);
607		errc(1, saved_errno, "open %s", dst);
608	}
609
610	while ((r = read(ifd, buf, sizeof(buf))) > 0) {
611		if (write(ofd, buf, r) == -1)
612			err(1, "%s: write", __func__);
613	}
614
615	close(ofd);
616	close(ifd);
617
618	return (r == -1);
619}
620
621void
622fcopy_env(const char *src, const char *dst, mode_t mode)
623{
624	int		 ofd = -1, i;
625	uint8_t		 buf[BUFSIZ];
626	ssize_t		 r = -1, len;
627	FILE		*ifp = NULL;
628	int		 saved_errno;
629
630	if ((ifp = fopen(src, "r")) == NULL)
631		err(1, "fopen %s", src);
632
633	if ((ofd = open(dst, O_WRONLY|O_CREAT|O_TRUNC, mode)) == -1)
634		goto done;
635
636	while (fgets(buf, sizeof(buf), ifp) != NULL) {
637		for (i = 0; ca_env[i][0] != NULL; i++) {
638			if (ca_env[i][1] == NULL)
639				continue;
640			if (expand_string(buf, sizeof(buf),
641			    ca_env[i][0], ca_env[i][1]) == -1)
642				errx(1, "env %s value too long", ca_env[i][0]);
643		}
644		len = strlen(buf);
645		if (write(ofd, buf, len) != len)
646			goto done;
647	}
648
649	r = 0;
650
651 done:
652	saved_errno = errno;
653	close(ofd);
654	if (ifp != NULL)
655		fclose(ifp);
656	if (r == -1)
657		errc(1, saved_errno, "open %s", dst);
658}
659
660int
661rm_dir(char *path)
662{
663	FTS		*fts;
664	FTSENT		*p;
665	static char	*fpath[] = { NULL, NULL };
666
667	fpath[0] = path;
668	if ((fts = fts_open(fpath, FTS_PHYSICAL, NULL)) == NULL) {
669		warn("fts_open %s", path);
670		return (1);
671	}
672
673	while ((p = fts_read(fts)) != NULL) {
674		switch (p->fts_info) {
675		case FTS_DP:
676		case FTS_DNR:
677			if (rmdir(p->fts_accpath) == -1)
678				warn("rmdir %s", p->fts_accpath);
679			break;
680		case FTS_F:
681			if (unlink(p->fts_accpath) == -1)
682				warn("unlink %s", p->fts_accpath);
683			break;
684		case FTS_D:
685		case FTS_DOT:
686		default:
687			continue;
688		}
689	}
690	fts_close(fts);
691
692	return (0);
693}
694
695void
696ca_hier(char *path)
697{
698	struct stat	 st;
699	char		 dst[PATH_MAX];
700	unsigned int	 i;
701
702	for (i = 0; i < nitems(hier); i++) {
703		strlcpy(dst, path, sizeof(dst));
704		strlcat(dst, hier[i].dir, sizeof(dst));
705		if (stat(dst, &st) != 0 && errno == ENOENT &&
706		    mkdir(dst, hier[i].mode) != 0)
707			err(1, "failed to create dir %s", dst);
708	}
709}
710
711int
712ca_export(struct ca *ca, char *keyname, char *myname, char *password)
713{
714	DIR		*dexp;
715	struct dirent	*de;
716	struct stat	 st;
717	char		*pass;
718	char		 prev[_PASSWORD_LEN + 1];
719	char		 passenv[_PASSWORD_LEN + 8];
720	char		 oname[PATH_MAX];
721	char		 src[PATH_MAX];
722	char		 dst[PATH_MAX];
723	char		 cacrt[PATH_MAX];
724	char		 capfx[PATH_MAX];
725	char		 key[PATH_MAX];
726	char		 crt[PATH_MAX];
727	char		 pfx[PATH_MAX];
728	char		*p;
729	char		 tpl[] = "/tmp/ikectl.XXXXXXXXXX";
730	unsigned int	 i;
731	int		 fd;
732	int		 len;
733
734	if (keyname != NULL) {
735		if (strlcpy(oname, keyname, sizeof(oname)) >= sizeof(oname))
736			errx(1, "name too long");
737	} else {
738		strlcpy(oname, "ca", sizeof(oname));
739	}
740
741	/* colons are not valid characters in windows filenames... */
742	while ((p = strchr(oname, ':')) != NULL)
743		*p = '_';
744
745	if (password != NULL)
746		pass = password;
747	else {
748		pass = getpass("Export passphrase:");
749		if (pass == NULL || *pass == '\0')
750			err(1, "password not set");
751
752		strlcpy(prev, pass, sizeof(prev));
753		pass = getpass("Retype export passphrase:");
754		if (pass == NULL || strcmp(prev, pass) != 0)
755			errx(1, "passphrase does not match!");
756	}
757
758	len = snprintf(cacrt, sizeof(cacrt), "%s/ca.crt", ca->sslpath);
759	if (len < 0 || (size_t)len >= sizeof(cacrt))
760		err(1, "%s: snprintf", __func__);
761	len = snprintf(capfx, sizeof(capfx), "%s/ca.pfx", ca->sslpath);
762	if (len < 0 || (size_t)len >= sizeof(capfx))
763		err(1, "%s: snprintf", __func__);
764	len = snprintf(key, sizeof(key), "%s/private/%s.key", ca->sslpath, keyname);
765	if (len < 0 || (size_t)len >= sizeof(key))
766		err(1, "%s: snprintf", __func__);
767	len = snprintf(crt, sizeof(crt), "%s/%s.crt", ca->sslpath, keyname);
768	if (len < 0 || (size_t)len >= sizeof(crt))
769		err(1, "%s: snprintf", __func__);
770	len = snprintf(pfx, sizeof(pfx), "%s/private/%s.pfx", ca->sslpath, oname);
771	if (len < 0 || (size_t)len >= sizeof(pfx))
772		err(1, "%s: snprintf", __func__);
773
774	len = snprintf(passenv, sizeof(passenv), "EXPASS=%s", pass);
775	if (len < 0 || (size_t)len >= sizeof(passenv))
776		err(1, "%s: snprintf", __func__);
777	putenv(passenv);
778
779	if (keyname != NULL) {
780		char *cmd[] = { PATH_OPENSSL, "pkcs12", "-export",
781		    "-name", keyname, "-CAfile", cacrt, "-inkey", key,
782		    "-in", crt, "-out", pfx, "-passout", "env:EXPASS",
783		    "-passin", ca->passfile, NULL };
784		ca_execv(cmd);
785	}
786
787	char *pkcscmd[] = { PATH_OPENSSL, "pkcs12", "-export",
788	    "-caname", ca->caname, "-name", ca->caname, "-cacerts",
789	    "-nokeys", "-in", cacrt, "-out", capfx,
790	    "-passout", "env:EXPASS", "-passin", ca->passfile, NULL };
791	ca_execv(pkcscmd);
792
793	unsetenv("EXPASS");
794	explicit_bzero(passenv, sizeof(passenv));
795
796	if ((p = mkdtemp(tpl)) == NULL)
797		err(1, "could not create temp dir");
798
799	chmod(p, 0755);
800
801	for (i = 0; i < nitems(hier); i++) {
802		strlcpy(dst, p, sizeof(dst));
803		strlcat(dst, hier[i].dir, sizeof(dst));
804		if (stat(dst, &st) != 0 && errno == ENOENT &&
805		    mkdir(dst, hier[i].mode) != 0)
806			err(1, "failed to create dir %s", dst);
807	}
808
809	/* create a file with the address of the peer to connect to */
810	if (myname != NULL) {
811		len = snprintf(dst, sizeof(dst), "%s/export/peer.txt", p);
812		if (len < 0 || (size_t)len >= sizeof(dst))
813			err(1, "%s: snprintf", __func__);
814		if ((fd = open(dst, O_WRONLY|O_CREAT, 0644)) == -1)
815			err(1, "open %s", dst);
816		if (write(fd, myname, strlen(myname)) == -1)
817			err(1, "%s: write", __func__);
818		close(fd);
819	}
820
821	len = snprintf(src, sizeof(src), "%s/ca.pfx", ca->sslpath);
822	if (len < 0 || (size_t)len >= sizeof(src))
823		err(1, "%s: snprintf", __func__);
824	len = snprintf(dst, sizeof(dst), "%s/export/ca.pfx", p);
825	if (len < 0 || (size_t)len >= sizeof(dst))
826		err(1, "%s: snprintf", __func__);
827	fcopy(src, dst, 0644);
828
829	len = snprintf(src, sizeof(src), "%s/ca.crt", ca->sslpath);
830	if (len < 0 || (size_t)len >= sizeof(src))
831		err(1, "%s: snprintf", __func__);
832	len = snprintf(dst, sizeof(dst), "%s/ca/ca.crt", p);
833	if (len < 0 || (size_t)len >= sizeof(dst))
834		err(1, "%s: snprintf", __func__);
835	fcopy(src, dst, 0644);
836
837	len = snprintf(src, sizeof(src), "%s/ca.crl", ca->sslpath);
838	if (len < 0 || (size_t)len >= sizeof(src))
839		err(1, "%s: snprintf", __func__);
840	if (stat(src, &st) == 0) {
841		len = snprintf(dst, sizeof(dst), "%s/crls/ca.crl", p);
842		if (len < 0 || (size_t)len >= sizeof(dst))
843			err(1, "%s: snprintf", __func__);
844		fcopy(src, dst, 0644);
845	}
846
847	if (keyname != NULL) {
848		len = snprintf(src, sizeof(src), "%s/private/%s.pfx",
849		    ca->sslpath, oname);
850		if (len < 0 || (size_t)len >= sizeof(src))
851			err(1, "%s: snprintf", __func__);
852		len = snprintf(dst, sizeof(dst), "%s/export/%s.pfx", p, oname);
853		if (len < 0 || (size_t)len >= sizeof(dst))
854			err(1, "%s: snprintf", __func__);
855		fcopy(src, dst, 0644);
856
857		len = snprintf(src, sizeof(src), "%s/private/%s.key",
858		    ca->sslpath, keyname);
859		if (len < 0 || (size_t)len >= sizeof(src))
860			err(1, "%s: snprintf", __func__);
861		len = snprintf(dst, sizeof(dst), "%s/private/%s.key", p, keyname);
862		if (len < 0 || (size_t)len >= sizeof(dst))
863			err(1, "%s: snprintf", __func__);
864		fcopy(src, dst, 0600);
865		len = snprintf(dst, sizeof(dst), "%s/private/local.key", p);
866		if (len < 0 || (size_t)len >= sizeof(dst))
867			err(1, "%s: snprintf", __func__);
868		fcopy(src, dst, 0600);
869
870		len = snprintf(src, sizeof(src), "%s/%s.crt", ca->sslpath,
871		    keyname);
872		if (len < 0 || (size_t)len >= sizeof(src))
873			err(1, "%s: snprintf", __func__);
874		len = snprintf(dst, sizeof(dst), "%s/certs/%s.crt", p, keyname);
875		if (len < 0 || (size_t)len >= sizeof(dst))
876			err(1, "%s: snprintf", __func__);
877		fcopy(src, dst, 0644);
878
879		len = snprintf(dst, sizeof(dst), "%s/local.pub", p);
880		if (len < 0 || (size_t)len >= sizeof(dst))
881			err(1, "%s: snprintf", __func__);
882		char *cmd[] = { PATH_OPENSSL, "rsa", "-out", dst, "-in", key,
883		    "-pubout", NULL };
884		ca_execv(cmd);
885	}
886
887	if (stat(PATH_TAR, &st) == 0) {
888		len = snprintf(src, sizeof(src), "%s.tgz", oname);
889		if (len < 0 || (size_t)len >= sizeof(src))
890			err(1, "%s: snprintf", __func__);
891		if (keyname == NULL) {
892			char *cmd[] = { PATH_TAR, "-zcf", src,
893			    "-C", ca->sslpath, ".", NULL };
894			ca_execv(cmd);
895		} else {
896			char *cmd[] = { PATH_TAR, "-zcf", src, "-C", p, ".",
897			    NULL };
898			ca_execv(cmd);
899		}
900		if (realpath(src, dst) != NULL)
901			printf("exported files in %s\n", dst);
902	}
903
904	if (stat(PATH_ZIP, &st) == 0) {
905		dexp = opendir(EXPDIR);
906		if (dexp) {
907			while ((de = readdir(dexp)) != NULL) {
908				if (!strcmp(de->d_name, ".") ||
909				    !strcmp(de->d_name, ".."))
910					continue;
911				len = snprintf(src, sizeof(src), "%s/%s",
912				    EXPDIR, de->d_name);
913				if (len < 0 || (size_t)len >= sizeof(src))
914					err(1, "%s: snprintf", __func__);
915				len = snprintf(dst, sizeof(dst), "%s/export/%s",
916				    p, de->d_name);
917				if (len < 0 || (size_t)len >= sizeof(dst))
918					err(1, "%s: snprintf", __func__);
919				fcopy(src, dst, 0644);
920			}
921			closedir(dexp);
922		}
923
924		len = snprintf(dst, sizeof(dst), "%s/export", p);
925		if (len < 0 || (size_t)len >= sizeof(dst))
926			err(1, "%s: snprintf", __func__);
927		if (getcwd(src, sizeof(src)) == NULL)
928			err(1, "could not get cwd");
929
930		if (chdir(dst) == -1)
931			err(1, "could not change %s", dst);
932
933		len = snprintf(dst, sizeof(dst), "%s/%s.zip", src, oname);
934		if (len < 0 || (size_t)len >= sizeof(dst))
935			err(1, "%s: snprintf", __func__);
936		char *cmd[] = { PATH_ZIP, "-qr", dst, ".", NULL };
937		ca_execv(cmd);
938		printf("exported files in %s\n", dst);
939
940		if (chdir(src) == -1)
941			err(1, "could not change %s", dst);
942	}
943
944	rm_dir(p);
945
946	return (0);
947}
948
949/* create index if it doesn't already exist */
950void
951ca_create_index(struct ca *ca)
952{
953	struct stat	 st;
954	int		 fd;
955	int		 len;
956
957	len = snprintf(ca->index, sizeof(ca->index), "%s/index.txt",
958	    ca->sslpath);
959	if (len < 0 || (size_t)len >= sizeof(ca->index))
960		err(1, "%s: snprintf", __func__);
961	if (stat(ca->index, &st) != 0) {
962		if  (errno == ENOENT) {
963			if ((fd = open(ca->index, O_WRONLY | O_CREAT, 0644))
964			    == -1)
965				err(1, "could not create file %s", ca->index);
966			close(fd);
967		} else
968			err(1, "could not access %s", ca->index);
969	}
970
971	len = snprintf(ca->serial, sizeof(ca->serial), "%s/serial.txt",
972	    ca->sslpath);
973	if (len < 0 || (size_t)len >= sizeof(ca->serial))
974		err(1, "%s: snprintf", __func__);
975	if (stat(ca->serial, &st) != 0) {
976		if  (errno == ENOENT) {
977			if ((fd = open(ca->serial, O_WRONLY | O_CREAT, 0644))
978			    == -1)
979				err(1, "could not create file %s", ca->serial);
980			/* serial file must be created with a number */
981			if (write(fd, "01\n", 3) != 3)
982				err(1, "write %s", ca->serial);
983			close(fd);
984		} else
985			err(1, "could not access %s", ca->serial);
986	}
987}
988
989int
990ca_revoke(struct ca *ca, char *keyname)
991{
992	struct stat	 st;
993	char		 path[PATH_MAX];
994	char		 cakey[PATH_MAX];
995	char		 cacrt[PATH_MAX];
996	size_t		 len;
997
998	if (keyname) {
999		len = snprintf(path, sizeof(path), "%s/%s.crt",
1000		    ca->sslpath, keyname);
1001		if (len < 0 || (size_t)len >= sizeof(path))
1002			err(1, "%s: snprintf", __func__);
1003		if (stat(path, &st) != 0) {
1004			warn("Problem with certificate for '%s'", keyname);
1005			return (1);
1006		}
1007	}
1008
1009	ca_create_index(ca);
1010
1011	ca_setenv("$ENV::CADB", ca->index);
1012	ca_setenv("$ENV::CASERIAL", ca->serial);
1013	if (keyname)
1014		ca_setenv("$ENV::REQ_EXT", "");
1015
1016	ca_setcnf(ca, "ca-revoke");
1017
1018	len = snprintf(cakey, sizeof(cakey), "%s/private/ca.key", ca->sslpath);
1019	if (len < 0 || (size_t)len >= sizeof(cakey))
1020		err(1, "%s: snprintf", __func__);
1021	len = snprintf(cacrt, sizeof(cacrt), "%s/ca.crt", ca->sslpath);
1022	if (len < 0 || (size_t)len >= sizeof(cacrt))
1023		err(1, "%s: snprintf", __func__);
1024
1025	if (keyname) {
1026		char *cmd[] = { PATH_OPENSSL, "ca", "-config", ca->sslcnf,
1027		    "-keyfile", cakey, "-passin", ca->passfile, "-cert", cacrt,
1028		    "-revoke", path, ca->batch, NULL };
1029		ca_execv(cmd);
1030	}
1031
1032	len = snprintf(path, sizeof(path), "%s/ca.crl", ca->sslpath);
1033	if (len < 0 || (size_t)len >= sizeof(path))
1034		err(1, "%s: snprintf", __func__);
1035	char *cmd[] = { PATH_OPENSSL, "ca", "-config", ca->sslcnf,
1036	    "-keyfile", cakey, "-passin", ca->passfile, "-gencrl",
1037	    "-cert", cacrt, "-crldays", "365", "-out", path, ca->batch, NULL };
1038	ca_execv(cmd);
1039
1040	return (0);
1041}
1042
1043void
1044ca_clrenv(void)
1045{
1046	int	 i;
1047	for (i = 0; ca_env[i][0] != NULL; i++) {
1048		free(ca_env[i][1]);
1049		ca_env[i][1] = NULL;
1050	}
1051}
1052
1053void
1054ca_setenv(const char *key, const char *value)
1055{
1056	int	 i;
1057	char	*p = NULL;
1058
1059	for (i = 0; ca_env[i][0] != NULL; i++) {
1060		if (strcmp(ca_env[i][0], key) == 0) {
1061			if (ca_env[i][1] != NULL)
1062				errx(1, "env %s already set: %s", key, value);
1063			p = strdup(value);
1064			if (p == NULL)
1065				err(1, NULL);
1066			ca_env[i][1] = p;
1067			return;
1068		}
1069	}
1070	errx(1, "env %s invalid", key);
1071}
1072
1073void
1074ca_setcnf(struct ca *ca, const char *keyname)
1075{
1076	struct stat	 st;
1077	const char	*extcnf, *sslcnf;
1078	int		 len;
1079
1080	if (stat(IKECA_CNF, &st) == 0) {
1081		extcnf = IKECA_CNF;
1082		sslcnf = IKECA_CNF;
1083	} else {
1084		extcnf = X509_CNF;
1085		sslcnf = SSL_CNF;
1086	}
1087
1088	len = snprintf(ca->extcnf, sizeof(ca->extcnf), "%s/%s-ext.cnf",
1089	    ca->sslpath, keyname);
1090	if (len < 0 || (size_t)len >= sizeof(ca->extcnf))
1091		err(1, "%s: snprintf", __func__);
1092	len = snprintf(ca->sslcnf, sizeof(ca->sslcnf), "%s/%s-ssl.cnf",
1093	    ca->sslpath, keyname);
1094	if (len < 0 || (size_t)len >= sizeof(ca->sslcnf))
1095		err(1, "%s: snprintf", __func__);
1096
1097	fcopy_env(extcnf, ca->extcnf, 0400);
1098	fcopy_env(sslcnf, ca->sslcnf, 0400);
1099}
1100
1101struct ca *
1102ca_setup(char *caname, int create, int quiet, char *pass)
1103{
1104	struct stat	 st;
1105	struct ca	*ca;
1106	char		 path[PATH_MAX];
1107	int		 len;
1108
1109	if (stat(PATH_OPENSSL, &st) == -1)
1110		err(1, "openssl binary not available");
1111
1112	if ((ca = calloc(1, sizeof(struct ca))) == NULL)
1113		err(1, "calloc");
1114
1115	ca->caname = strdup(caname);
1116	len = snprintf(ca->sslpath, sizeof(ca->sslpath), SSLDIR "/%s", caname);
1117	if (len < 0 || (size_t)len >= sizeof(ca->sslpath))
1118		err(1, "%s: snprintf", __func__);
1119
1120	if (quiet)
1121		ca->batch = "-batch";
1122
1123	if (create == 0 && stat(ca->sslpath, &st) == -1) {
1124		free(ca->caname);
1125		free(ca);
1126		errx(1, "CA '%s' does not exist", caname);
1127	}
1128
1129	strlcpy(path, ca->sslpath, sizeof(path));
1130	if (mkdir(path, 0777) == -1 && errno != EEXIST)
1131		err(1, "failed to create dir %s", path);
1132	strlcat(path, "/private", sizeof(path));
1133	if (mkdir(path, 0700) == -1 && errno != EEXIST)
1134		err(1, "failed to create dir %s", path);
1135
1136	len = snprintf(path, sizeof(path), "%s/ikeca.passwd", ca->sslpath);
1137	if (len < 0 || (size_t)len >= sizeof(path))
1138		err(1, "%s: snprintf", __func__);
1139	if (create && stat(path, &st) == -1 && errno == ENOENT)
1140		ca_newpass(path, pass);
1141	len = snprintf(ca->passfile, sizeof(ca->passfile), "file:%s", path);
1142	if (len < 0 || (size_t)len >= sizeof(ca->passfile))
1143		err(1, "%s: snprintf", __func__);
1144
1145	return (ca);
1146}
1147
1148int static
1149ca_execv(char *const argv[])
1150{
1151	pid_t pid, cpid;
1152	int status;
1153
1154	switch (cpid = fork()) {
1155	case -1:
1156		return -1;
1157	case 0:
1158		execv(argv[0], argv);
1159		_exit(127);
1160	}
1161
1162	do {
1163		pid = waitpid(cpid, &status, 0);
1164	} while (pid == -1 && errno == EINTR);
1165
1166	return (pid == -1 ? -1 : WEXITSTATUS(status));
1167}
1168