Home | History | Annotate | Line # | Download | only in cgdconfig
cgdconfig.c revision 1.5
      1 /* $NetBSD: cgdconfig.c,v 1.5 2003/03/24 02:02:50 elric Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Roland C. Dowdeswell.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 #include <sys/cdefs.h>
     40 #ifndef lint
     41 __COPYRIGHT(
     42 "@(#) Copyright (c) 2002, 2003\
     43 	The NetBSD Foundation, Inc.  All rights reserved.");
     44 __RCSID("$NetBSD: cgdconfig.c,v 1.5 2003/03/24 02:02:50 elric Exp $");
     45 #endif
     46 
     47 #include <err.h>
     48 #include <errno.h>
     49 #include <fcntl.h>
     50 #include <libgen.h>
     51 #include <stdio.h>
     52 #include <stdlib.h>
     53 #include <string.h>
     54 #include <unistd.h>
     55 #include <util.h>
     56 
     57 #include <sys/ioctl.h>
     58 #include <sys/disklabel.h>
     59 #include <sys/param.h>
     60 
     61 #include <dev/cgdvar.h>
     62 
     63 #include <ufs/ffs/fs.h>
     64 
     65 #include "params.h"
     66 #include "pkcs5_pbkdf2.h"
     67 #include "utils.h"
     68 
     69 #define CGDCONFIG_DIR		"/etc/cgd"
     70 #define CGDCONFIG_CFILE		CGDCONFIG_DIR "/cgd.conf"
     71 
     72 #define ACTION_CONFIGURE	0x1	/* configure, with paramsfile */
     73 #define ACTION_UNCONFIGURE	0x2	/* unconfigure */
     74 #define ACTION_GENERATE		0x3	/* generate a paramsfile */
     75 #define ACTION_GENERATE_CONVERT	0x4	/* generate a ``dup'' paramsfile */
     76 #define ACTION_CONFIGALL	0x5	/* configure all from config file */
     77 #define ACTION_UNCONFIGALL	0x6	/* unconfigure all from config file */
     78 #define ACTION_CONFIGSTDIN	0x7	/* configure, key from stdin */
     79 
     80 /* if nflag is set, do not configure/unconfigure the cgd's */
     81 
     82 int	nflag = 0;
     83 
     84 static int	configure(int, char **, struct params *, int);
     85 static int	configure_stdin(struct params *, int argc, char **);
     86 static int	generate(struct params *, int, char **, const char *);
     87 static int	generate_convert(struct params *, int, char **, const char *);
     88 static int	unconfigure(int, char **, struct params *, int);
     89 static int	do_all(const char *, int, char **,
     90 		       int (*)(int, char **, struct params *, int));
     91 
     92 #define CONFIG_FLAGS_FROMALL	1	/* called from configure_all() */
     93 #define CONFIG_FLAGS_FROMMAIN	2	/* called from main() */
     94 
     95 static int	 configure_params(int, const char *, const char *,
     96 				  struct params *);
     97 static bits_t	*getkey(const char *, struct keygen *, int);
     98 static bits_t	*getkey_storedkey(const char *, struct keygen *, int);
     99 static bits_t	*getkey_randomkey(const char *, struct keygen *, int);
    100 static bits_t	*getkey_pkcs5_pbkdf2(const char *, struct keygen *, int);
    101 static int	 opendisk_werror(const char *, char *, int);
    102 static int	 unconfigure_fd(int);
    103 static int	 verify(struct params *, int);
    104 static int	 verify_disklabel(int);
    105 static int	 verify_ffs(int);
    106 
    107 static void	 usage(void);
    108 
    109 /* Verbose Framework */
    110 int	verbose = 0;
    111 
    112 #define VERBOSE(x,y)	if (verbose >= x) y
    113 #define VPRINTF(x,y)	if (verbose >= x) printf y
    114 
    115 static void
    116 usage(void)
    117 {
    118 
    119 	fprintf(stderr, "usage: %s [-nv] [-V vmeth] cgd dev [paramsfile]\n",
    120 	    getprogname());
    121 	fprintf(stderr, "       %s -C [-nv] [-f configfile]\n", getprogname());
    122 	fprintf(stderr, "       %s -U [-nv] [-f configfile]\n", getprogname());
    123 	fprintf(stderr, "       %s -G [-nv] [-i ivmeth] [-k kgmeth] "
    124 	    "[-o outfile] paramsfile\n", getprogname());
    125 	fprintf(stderr, "       %s -g [-nv] [-i ivmeth] [-k kgmeth] "
    126 	    "[-o outfile] alg [keylen]\n", getprogname());
    127 	fprintf(stderr, "       %s -s [-nv] [-i ivmeth] cgd dev alg "
    128 	    "[keylen]\n", getprogname());
    129 	fprintf(stderr, "       %s -u [-nv] cgd\n", getprogname());
    130 	exit(1);
    131 }
    132 
    133 int
    134 main(int argc, char **argv)
    135 {
    136 	struct params *p;
    137 	struct params *tp;
    138 	struct keygen *kg;
    139 	int	action = ACTION_CONFIGURE;
    140 	int	actions = 0;
    141 	int	ch;
    142 	char	cfile[FILENAME_MAX] = "";
    143 	char	outfile[FILENAME_MAX] = "";
    144 
    145 	setprogname(*argv);
    146 	p = params_new();
    147 	kg = NULL;
    148 
    149 	while ((ch = getopt(argc, argv, "CGUV:b:f:gi:k:no:usv")) != -1)
    150 		switch (ch) {
    151 		case 'C':
    152 			action = ACTION_CONFIGALL;
    153 			actions++;
    154 			break;
    155 		case 'G':
    156 			action = ACTION_GENERATE_CONVERT;
    157 			actions++;
    158 			break;
    159 		case 'U':
    160 			action = ACTION_UNCONFIGALL;
    161 			actions++;
    162 			break;
    163 		case 'V':
    164 			tp = params_verify_method(string_fromcharstar(optarg));
    165 			if (!tp)
    166 				usage();
    167 			p = params_combine(p, tp);
    168 			break;
    169 		case 'b':
    170 			tp = params_bsize(atoi(optarg));
    171 			if (!tp)
    172 				usage();
    173 			p = params_combine(p, tp);
    174 			break;
    175 		case 'f':
    176 			strncpy(cfile, optarg, FILENAME_MAX);
    177 			break;
    178 		case 'g':
    179 			action = ACTION_GENERATE;
    180 			actions++;
    181 			break;
    182 		case 'i':
    183 			tp = params_ivmeth(string_fromcharstar(optarg));
    184 			p = params_combine(p, tp);
    185 			break;
    186 		case 'k':
    187 			kg = keygen_method(string_fromcharstar(optarg));
    188 			if (!kg)
    189 				usage();
    190 			keygen_addlist(&p->keygen, kg);
    191 			break;
    192 		case 'n':
    193 			nflag = 1;
    194 			break;
    195 		case 'o':
    196 			strncpy(outfile, optarg, FILENAME_MAX);
    197 			break;
    198 		case 's':
    199 			action = ACTION_CONFIGSTDIN;
    200 			actions++;
    201 			break;
    202 
    203 		case 'u':
    204 			action = ACTION_UNCONFIGURE;
    205 			actions++;
    206 			break;
    207 		case 'v':
    208 			verbose++;
    209 			break;
    210 		default:
    211 			usage();
    212 			/* NOTREACHED */
    213 		}
    214 
    215 	argc -= optind;
    216 	argv += optind;
    217 
    218 	/* validate the consistency of the arguments */
    219 
    220 	if (actions > 1)
    221 		usage();
    222 
    223 	switch (action) {
    224 	case ACTION_CONFIGURE:
    225 		return configure(argc, argv, p, CONFIG_FLAGS_FROMMAIN);
    226 	case ACTION_UNCONFIGURE:
    227 		return unconfigure(argc, argv, NULL, CONFIG_FLAGS_FROMMAIN);
    228 	case ACTION_GENERATE:
    229 		return generate(p, argc, argv, outfile);
    230 	case ACTION_GENERATE_CONVERT:
    231 		return generate_convert(p, argc, argv, outfile);
    232 	case ACTION_CONFIGALL:
    233 		return do_all(cfile, argc, argv, configure);
    234 	case ACTION_UNCONFIGALL:
    235 		return do_all(cfile, argc, argv, unconfigure);
    236 	case ACTION_CONFIGSTDIN:
    237 		return configure_stdin(p, argc, argv);
    238 	default:
    239 		errx(EXIT_FAILURE, "undefined action");
    240 	}
    241 	/* NOTREACHED */
    242 }
    243 
    244 static bits_t *
    245 getkey(const char *dev, struct keygen *kg, int len)
    246 {
    247 	bits_t	*ret = NULL;
    248 	bits_t	*tmp;
    249 
    250 	VPRINTF(3, ("getkey(\"%s\", %p, %d) called\n", dev, kg, len));
    251 	for (; kg; kg=kg->next) {
    252 		switch (kg->kg_method) {
    253 		case KEYGEN_STOREDKEY:
    254 			tmp = getkey_storedkey(dev, kg, len);
    255 			break;
    256 		case KEYGEN_RANDOMKEY:
    257 			tmp = getkey_randomkey(dev, kg, len);
    258 			break;
    259 		case KEYGEN_PKCS5_PBKDF2:
    260 			tmp = getkey_pkcs5_pbkdf2(dev, kg, len);
    261 			break;
    262 		default:
    263 			warnx("unrecognised keygen method %d in getkey()",
    264 			    kg->kg_method);
    265 			if (ret)
    266 				bits_free(ret);
    267 			return NULL;
    268 		}
    269 
    270 		if (ret)
    271 			ret = bits_xor_d(tmp, ret);
    272 		else
    273 			ret = tmp;
    274 	}
    275 
    276 	return ret;
    277 }
    278 
    279 /*ARGSUSED*/
    280 static bits_t *
    281 getkey_storedkey(const char *target, struct keygen *kg, int keylen)
    282 {
    283 
    284 	return bits_dup(kg->kg_key);
    285 }
    286 
    287 /*ARGSUSED*/
    288 static bits_t *
    289 getkey_randomkey(const char *target, struct keygen *kg, int keylen)
    290 {
    291 
    292 	return bits_getrandombits(keylen);
    293 }
    294 
    295 /*ARGSUSED*/
    296 static bits_t *
    297 getkey_pkcs5_pbkdf2(const char *target, struct keygen *kg, int keylen)
    298 {
    299 	bits_t		*ret;
    300 	char		*passp;
    301 	char		 buf[1024];
    302 	u_int8_t	*tmp;
    303 
    304 	snprintf(buf, sizeof(buf), "%s's passphrase:", target);
    305 	passp = getpass(buf);
    306 	if (pkcs5_pbkdf2(&tmp, BITS2BYTES(keylen), passp, strlen(passp),
    307 	    bits_getbuf(kg->kg_salt), BITS2BYTES(bits_len(kg->kg_salt)),
    308 	    kg->kg_iterations)) {
    309 		warnx("failed to generate PKCS#5 PBKDF2 key");
    310 		return NULL;
    311 	}
    312 
    313 	ret = bits_new(tmp, keylen);
    314 	free(tmp);
    315 	return ret;
    316 }
    317 
    318 /*ARGSUSED*/
    319 static int
    320 unconfigure(int argc, char **argv, struct params *inparams, int flags)
    321 {
    322 	int	fd;
    323 	int	ret;
    324 	char	buf[MAXPATHLEN] = "";
    325 
    326 	/* only complain about additional arguments, if called from main() */
    327 	if (flags == CONFIG_FLAGS_FROMMAIN && argc != 1)
    328 		usage();
    329 
    330 	/* if called from do_all(), then ensure that 2 or 3 args exist */
    331 	if (flags == CONFIG_FLAGS_FROMALL && (argc < 2 || argc > 3))
    332 		return -1;
    333 
    334 	fd = opendisk(*argv, O_RDWR, buf, sizeof(buf), 1);
    335 	if (fd == -1) {
    336 		warn("can't open cgd \"%s\", \"%s\"", *argv, buf);
    337 
    338 		/* this isn't fatal with nflag != 0 */
    339 		if (!nflag)
    340 			return errno;
    341 	}
    342 
    343 	VPRINTF(1, ("%s (%s): clearing\n", *argv, buf));
    344 
    345 	if (nflag)
    346 		return 0;
    347 
    348 	ret = unconfigure_fd(fd);
    349 	close(fd);
    350 	return ret;
    351 }
    352 
    353 static int
    354 unconfigure_fd(int fd)
    355 {
    356 	struct	cgd_ioctl ci;
    357 	int	ret;
    358 
    359 	ret = ioctl(fd, CGDIOCCLR, &ci);
    360 	if (ret == -1) {
    361 		perror("ioctl");
    362 		return -1;
    363 	}
    364 
    365 	return 0;
    366 }
    367 
    368 /*ARGSUSED*/
    369 static int
    370 configure(int argc, char **argv, struct params *inparams, int flags)
    371 {
    372 	struct params	*p;
    373 	int		 fd;
    374 	int		 ret;
    375 	char		 pfile[FILENAME_MAX];
    376 	char		 cgdname[PATH_MAX];
    377 
    378 	switch (argc) {
    379 	case 2:
    380 		strlcpy(pfile, CGDCONFIG_DIR, FILENAME_MAX);
    381 		strlcat(pfile, "/", FILENAME_MAX);
    382 		strlcat(pfile, basename(argv[1]), FILENAME_MAX);
    383 		break;
    384 	case 3:
    385 		strlcpy(pfile, argv[2], FILENAME_MAX);
    386 		break;
    387 	default:
    388 		/* print usage and exit, only if called from main() */
    389 		if (flags == CONFIG_FLAGS_FROMMAIN) {
    390 			warnx("wrong number of args");
    391 			usage();
    392 		}
    393 		return -1;
    394 		/* NOTREACHED */
    395 	}
    396 
    397 	p = params_cget(pfile);
    398 	if (!p)
    399 		return -1;
    400 
    401 	/*
    402 	 * over-ride with command line specifications and fill in default
    403 	 * values.
    404 	 */
    405 
    406 	p = params_combine(p, inparams);
    407 	ret = params_filldefaults(p);
    408 	if (ret) {
    409 		params_free(p);
    410 		return ret;
    411 	}
    412 
    413 	if (!params_verify(p)) {
    414 		warnx("params invalid");
    415 		return -1;
    416 	}
    417 
    418 	/*
    419 	 * loop over configuring the disk and checking to see if it
    420 	 * verifies properly.  We open and close the disk device each
    421 	 * time, because if the user passes us the block device we
    422 	 * need to flush the buffer cache.
    423 	 */
    424 
    425 	for (;;) {
    426 		fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname));
    427 		if (fd == -1)
    428 			return -1;
    429 
    430 		if (p->key)
    431 			bits_free(p->key);
    432 
    433 		p->key = getkey(argv[1], p->keygen, p->keylen);
    434 		if (!p->key)
    435 			goto bail_err;
    436 
    437 		ret = configure_params(fd, cgdname, argv[1], p);
    438 		if (ret)
    439 			goto bail_err;
    440 
    441 		ret = verify(p, fd);
    442 		if (ret == -1)
    443 			goto bail_err;
    444 		if (!ret)
    445 			break;
    446 
    447 		fprintf(stderr, "verification failed, please reenter "
    448 		    "passphrase\n");
    449 
    450 		unconfigure_fd(fd);
    451 		close(fd);
    452 	}
    453 
    454 	params_free(p);
    455 	close(fd);
    456 	return 0;
    457 bail_err:
    458 	params_free(p);
    459 	close(fd);
    460 	return -1;
    461 }
    462 
    463 static int
    464 configure_stdin(struct params *p, int argc, char **argv)
    465 {
    466 	int	fd;
    467 	int	ret;
    468 	char	cgdname[PATH_MAX];
    469 
    470 	if (argc < 3 || argc > 4)
    471 		usage();
    472 
    473 	p->algorithm = string_fromcharstar(argv[2]);
    474 	if (argc > 3)
    475 		p->keylen = atoi(argv[3]);
    476 
    477 	ret = params_filldefaults(p);
    478 	if (ret)
    479 		return ret;
    480 
    481 	fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname));
    482 	if (fd == -1)
    483 		return -1;
    484 
    485 	p->key = bits_fget(stdin, p->keylen);
    486 	if (!p->key) {
    487 		warnx("failed to read key from stdin");
    488 		return -1;
    489 	}
    490 
    491 	return configure_params(fd, cgdname, argv[1], p);
    492 }
    493 
    494 static int
    495 opendisk_werror(const char *cgd, char *buf, int buflen)
    496 {
    497 	int	fd;
    498 
    499 	VPRINTF(3, ("opendisk_werror(%s, %s, %d) called.\n", cgd, buf, buflen));
    500 
    501 	/* sanity */
    502 	if (!cgd || !buf)
    503 		return -1;
    504 
    505 	if (nflag) {
    506 		strncpy(buf, cgd, buflen);
    507 		return 0;
    508 	}
    509 
    510 	fd = opendisk(cgd, O_RDWR, buf, buflen, 0);
    511 	if (fd == -1)
    512 		warnx("can't open cgd \"%s\", \"%s\"", cgd, buf);
    513 
    514 	return fd;
    515 }
    516 
    517 static int
    518 configure_params(int fd, const char *cgd, const char *dev, struct params *p)
    519 {
    520 	struct cgd_ioctl ci;
    521 	int	  ret;
    522 
    523 	/* sanity */
    524 	if (!cgd || !dev)
    525 		return -1;
    526 
    527 	memset(&ci, 0x0, sizeof(ci));
    528 	ci.ci_disk = (char *)dev;
    529 	ci.ci_alg = (char *)string_tocharstar(p->algorithm);
    530 	ci.ci_ivmethod = (char *)string_tocharstar(p->ivmeth);
    531 	ci.ci_key = (char *)bits_getbuf(p->key);
    532 	ci.ci_keylen = p->keylen;
    533 	ci.ci_blocksize = p->bsize;
    534 
    535 	VPRINTF(1, ("    with alg %s keylen %d blocksize %d ivmethod %s\n",
    536 	    string_tocharstar(p->algorithm), p->keylen, p->bsize,
    537 	    string_tocharstar(p->ivmeth)));
    538 	VPRINTF(2, ("key: "));
    539 	VERBOSE(2, bits_fprint(stdout, p->key));
    540 	VPRINTF(2, ("\n"));
    541 
    542 	if (nflag)
    543 		return 0;
    544 
    545 	ret = ioctl(fd, CGDIOCSET, &ci);
    546 	if (ret == -1) {
    547 		perror("ioctl");
    548 		return errno;
    549 	}
    550 
    551 	return 0;
    552 }
    553 
    554 /*
    555  * verify returns 0 for success, -1 for unrecoverable error, or 1 for retry.
    556  */
    557 
    558 #define SCANSIZE	8192
    559 
    560 static int
    561 verify(struct params *p, int fd)
    562 {
    563 
    564 	switch (p->verify_method) {
    565 	case VERIFY_NONE:
    566 		return 0;
    567 	case VERIFY_DISKLABEL:
    568 		return verify_disklabel(fd);
    569 	case VERIFY_FFS:
    570 		return verify_ffs(fd);
    571 	default:
    572 		warnx("unimplemented verification method");
    573 		return -1;
    574 	}
    575 }
    576 
    577 static int
    578 verify_disklabel(int fd)
    579 {
    580 	struct	disklabel l;
    581 	int	ret;
    582 	char	buf[SCANSIZE];
    583 
    584 	/*
    585 	 * we simply scan the first few blocks for a disklabel, ignoring
    586 	 * any MBR/filecore sorts of logic.  MSDOS and RiscOS can't read
    587 	 * a cgd, anyway, so it is unlikely that there will be non-native
    588 	 * partition information.
    589 	 */
    590 
    591 	ret = pread(fd, buf, 8192, 0);
    592 	if (ret == -1) {
    593 		warn("can't read disklabel area");
    594 		return -1;
    595 	}
    596 
    597 	/* now scan for the disklabel */
    598 
    599 	return disklabel_scan(&l, buf, sizeof(buf));
    600 }
    601 
    602 static int
    603 verify_ffs(int fd)
    604 {
    605 	struct	fs *fs;
    606 	int	ret;
    607 	char	buf[SBSIZE];
    608 
    609 	ret = pread(fd, buf, SBSIZE, SBOFF);
    610 	fs = (struct fs *)buf;
    611 	if (ret == -1) {
    612 		warn("pread");
    613 		return 0;
    614 	}
    615 	if (fs->fs_magic == FS_MAGIC)
    616 		return 0;
    617 	if (fs->fs_magic == bswap32(FS_MAGIC))
    618 		return 0;
    619 	return 1;
    620 }
    621 
    622 static int
    623 generate(struct params *p, int argc, char **argv, const char *outfile)
    624 {
    625 	int	 ret;
    626 
    627 	if (argc < 1 || argc > 2)
    628 		usage();
    629 
    630 	p->algorithm = string_fromcharstar(argv[0]);
    631 	if (argc > 1)
    632 		p->keylen = atoi(argv[1]);
    633 
    634 	ret = params_filldefaults(p);
    635 	if (ret)
    636 		return ret;
    637 
    638 	if (!p->keygen) {
    639 		p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2);
    640 		if (!p->keygen)
    641 			return -1;
    642 	}
    643 
    644 	if (keygen_filldefaults(p->keygen, p->keylen)) {
    645 		warnx("Failed to generate defaults for keygen");
    646 		return -1;
    647 	}
    648 
    649 	if (!params_verify(p)) {
    650 		warnx("invalid parameters generated");
    651 		return -1;
    652 	}
    653 
    654 	return params_cput(p, outfile);
    655 }
    656 
    657 static int
    658 generate_convert(struct params *p, int argc, char **argv, const char *outfile)
    659 {
    660 	struct params	*oldp;
    661 	struct keygen	*kg;
    662 
    663 	if (argc != 1)
    664 		usage();
    665 
    666 	oldp = params_cget(*argv);
    667 	if (!oldp)
    668 		return -1;
    669 
    670 	/* for sanity, we ensure that none of the keygens are randomkey */
    671 	for (kg=p->keygen; kg; kg=kg->next)
    672 		if (kg->kg_method == KEYGEN_RANDOMKEY)
    673 			goto bail;
    674 	for (kg=oldp->keygen; kg; kg=kg->next)
    675 		if (kg->kg_method == KEYGEN_RANDOMKEY)
    676 			goto bail;
    677 
    678 	if (!params_verify(oldp)) {
    679 		warnx("invalid old parameters file \"%s\"", *argv);
    680 		return -1;
    681 	}
    682 
    683 	oldp->key = getkey("old file", oldp->keygen, oldp->keylen);
    684 
    685 	/* we copy across the non-keygen info, here. */
    686 
    687 	string_free(p->algorithm);
    688 	string_free(p->ivmeth);
    689 
    690 	p->algorithm = string_dup(oldp->algorithm);
    691 	p->ivmeth = string_dup(oldp->ivmeth);
    692 	p->keylen = oldp->keylen;
    693 	p->bsize = oldp->bsize;
    694 	if (p->verify_method == VERIFY_UNKNOWN)
    695 		p->verify_method = oldp->verify_method;
    696 
    697 	params_free(oldp);
    698 
    699 	if (!p->keygen) {
    700 		p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2);
    701 		if (!p->keygen)
    702 			return -1;
    703 		keygen_filldefaults(p->keygen, p->keylen);
    704 	}
    705 	params_filldefaults(p);
    706 	p->key = getkey("new file", p->keygen, p->keylen);
    707 
    708 	kg = keygen_generate(KEYGEN_STOREDKEY);
    709 	kg->kg_key = bits_xor(p->key, oldp->key);
    710 	keygen_addlist(&p->keygen, kg);
    711 
    712 	if (!params_verify(p)) {
    713 		warnx("can't generate new parameters file");
    714 		return -1;
    715 	}
    716 
    717 	return params_cput(p, outfile);
    718 bail:
    719 	params_free(oldp);
    720 	return -1;
    721 }
    722 
    723 static int
    724 do_all(const char *cfile, int argc, char **argv,
    725        int (*conf)(int, char **, struct params *, int))
    726 {
    727 	FILE		 *f;
    728 	size_t		  len;
    729 	size_t		  lineno;
    730 	int		  my_argc;
    731 	int		  ret;
    732 	const char	 *fn;
    733 	char		 *line;
    734 	char		**my_argv;
    735 
    736 	if (argc > 0)
    737 		usage();
    738 
    739 	if (!cfile[0])
    740 		fn = CGDCONFIG_CFILE;
    741 	else
    742 		fn = cfile;
    743 
    744 	f = fopen(fn, "r");
    745 	if (!f) {
    746 		warn("could not open config file \"%s\"", fn);
    747 		return -1;
    748 	}
    749 
    750 	ret = chdir(CGDCONFIG_DIR);
    751 	if (ret == -1)
    752 		warn("could not chdir to %s", CGDCONFIG_DIR);
    753 
    754 	ret = 0;
    755 	lineno = 0;
    756 	for (;;) {
    757 		line = fparseln(f, &len, &lineno, "\\\\#", FPARSELN_UNESCALL);
    758 		if (!line)
    759 			break;
    760 		if (!*line)
    761 			continue;
    762 
    763 		my_argv = words(line, &my_argc);
    764 		ret = conf(my_argc, my_argv, NULL, CONFIG_FLAGS_FROMALL);
    765 		if (ret) {
    766 			warnx("action failed on \"%s\" line %lu", fn,
    767 			    (u_long)lineno);
    768 			break;
    769 		}
    770 		words_free(my_argv, my_argc);
    771 	}
    772 	return ret;
    773 }
    774