Home | History | Annotate | Line # | Download | only in cgdconfig
cgdconfig.c revision 1.40.2.1
      1 /* $NetBSD: cgdconfig.c,v 1.40.2.1 2017/03/20 06:57:01 pgoyette 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  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 #ifndef lint
     34 __COPYRIGHT("@(#) Copyright (c) 2002, 2003\
     35  The NetBSD Foundation, Inc.  All rights reserved.");
     36 __RCSID("$NetBSD: cgdconfig.c,v 1.40.2.1 2017/03/20 06:57:01 pgoyette Exp $");
     37 #endif
     38 
     39 #include <err.h>
     40 #include <errno.h>
     41 #include <fcntl.h>
     42 #include <libgen.h>
     43 #include <stdio.h>
     44 #include <stdlib.h>
     45 #include <string.h>
     46 #include <unistd.h>
     47 #include <util.h>
     48 #include <paths.h>
     49 #include <dirent.h>
     50 
     51 #include <sys/ioctl.h>
     52 #include <sys/stat.h>
     53 #include <sys/bootblock.h>
     54 #include <sys/disklabel.h>
     55 #include <sys/disklabel_gpt.h>
     56 #include <sys/mman.h>
     57 #include <sys/param.h>
     58 #include <sys/resource.h>
     59 #include <sys/statvfs.h>
     60 #include <sys/bitops.h>
     61 
     62 #include <dev/cgdvar.h>
     63 
     64 #include <ufs/ffs/fs.h>
     65 
     66 #include "params.h"
     67 #include "pkcs5_pbkdf2.h"
     68 #include "utils.h"
     69 #include "cgdconfig.h"
     70 #include "prog_ops.h"
     71 
     72 #define CGDCONFIG_CFILE		CGDCONFIG_DIR "/cgd.conf"
     73 
     74 enum action {
     75 	 ACTION_DEFAULT,		/* default -> configure */
     76 	 ACTION_CONFIGURE,		/* configure, with paramsfile */
     77 	 ACTION_UNCONFIGURE,		/* unconfigure */
     78 	 ACTION_GENERATE,		/* generate a paramsfile */
     79 	 ACTION_GENERATE_CONVERT,	/* generate a ``dup'' paramsfile */
     80 	 ACTION_CONFIGALL,		/* configure all from config file */
     81 	 ACTION_UNCONFIGALL,		/* unconfigure all from config file */
     82 	 ACTION_CONFIGSTDIN,		/* configure, key from stdin */
     83 	 ACTION_LIST			/* list configured devices */
     84 };
     85 
     86 /* if nflag is set, do not configure/unconfigure the cgd's */
     87 
     88 int	nflag = 0;
     89 
     90 /* if pflag is set to PFLAG_STDIN read from stdin rather than getpass(3) */
     91 
     92 #define	PFLAG_GETPASS	0x01
     93 #define	PFLAG_STDIN	0x02
     94 int	pflag = PFLAG_GETPASS;
     95 
     96 static int	configure(int, char **, struct params *, int);
     97 static int	configure_stdin(struct params *, int argc, char **);
     98 static int	generate(struct params *, int, char **, const char *);
     99 static int	generate_convert(struct params *, int, char **, const char *);
    100 static int	unconfigure(int, char **, struct params *, int);
    101 static int	do_all(const char *, int, char **,
    102 		       int (*)(int, char **, struct params *, int));
    103 static int	do_list(int, char **);
    104 
    105 #define CONFIG_FLAGS_FROMALL	1	/* called from configure_all() */
    106 #define CONFIG_FLAGS_FROMMAIN	2	/* called from main() */
    107 
    108 static int	 configure_params(int, const char *, const char *,
    109 				  struct params *);
    110 static void	 eliminate_cores(void);
    111 static bits_t	*getkey(const char *, struct keygen *, size_t);
    112 static bits_t	*getkey_storedkey(const char *, struct keygen *, size_t);
    113 static bits_t	*getkey_randomkey(const char *, struct keygen *, size_t, int);
    114 static bits_t	*getkey_pkcs5_pbkdf2(const char *, struct keygen *, size_t,
    115 				     int);
    116 static bits_t	*getkey_shell_cmd(const char *, struct keygen *, size_t);
    117 static char	*maybe_getpass(char *);
    118 static int	 opendisk_werror(const char *, char *, size_t);
    119 static int	 unconfigure_fd(int);
    120 static int	 verify(struct params *, int);
    121 static int	 verify_disklabel(int);
    122 static int	 verify_ffs(int);
    123 static int	 verify_reenter(struct params *);
    124 static int	 verify_mbr(int);
    125 static int	 verify_gpt(int);
    126 
    127 __dead static void	 usage(void);
    128 
    129 /* Verbose Framework */
    130 unsigned	verbose = 0;
    131 
    132 #define VERBOSE(x,y)	if (verbose >= x) y
    133 #define VPRINTF(x,y)	if (verbose >= x) (void)printf y
    134 
    135 static void
    136 usage(void)
    137 {
    138 
    139 	(void)fprintf(stderr, "usage: %s [-nv] [-V vmeth] cgd dev [paramsfile]\n",
    140 	    getprogname());
    141 	(void)fprintf(stderr, "       %s -C [-nv] [-f configfile]\n", getprogname());
    142 	(void)fprintf(stderr, "       %s -G [-nv] [-i ivmeth] [-k kgmeth] "
    143 	    "[-o outfile] paramsfile\n", getprogname());
    144 	(void)fprintf(stderr, "       %s -g [-nv] [-i ivmeth] [-k kgmeth] "
    145 	    "[-o outfile] alg [keylen]\n", getprogname());
    146 	(void)fprintf(stderr, "       %s -l\n", getprogname());
    147 	(void)fprintf(stderr, "       %s -s [-nv] [-i ivmeth] cgd dev alg "
    148 	    "[keylen]\n", getprogname());
    149 	(void)fprintf(stderr, "       %s -U [-nv] [-f configfile]\n", getprogname());
    150 	(void)fprintf(stderr, "       %s -u [-nv] cgd\n", getprogname());
    151 	exit(EXIT_FAILURE);
    152 }
    153 
    154 static int
    155 parse_size_t(const char *s, size_t *l)
    156 {
    157 	char *endptr;
    158 	long v;
    159 
    160 	errno = 0;
    161 	v = strtol(s, &endptr, 10);
    162 	if ((v == LONG_MIN || v == LONG_MAX) && errno)
    163 		return -1;
    164 	if (v < INT_MIN || v > INT_MAX) {
    165 		errno = ERANGE;
    166 		return -1;
    167 	}
    168 	if (endptr == s) {
    169 		errno = EINVAL;
    170 		return -1;
    171 	}
    172 	*l = (size_t)v;
    173 	return 0;
    174 }
    175 
    176 static void
    177 set_action(enum action *action, enum action value)
    178 {
    179 	if (*action != ACTION_DEFAULT)
    180 		usage();
    181 	*action = value;
    182 }
    183 
    184 int
    185 main(int argc, char **argv)
    186 {
    187 	struct params *p;
    188 	struct params *tp;
    189 	struct keygen *kg;
    190 	enum action action = ACTION_DEFAULT;
    191 	int	ch;
    192 	const char	*cfile = NULL;
    193 	const char	*outfile = NULL;
    194 
    195 	setprogname(*argv);
    196 	eliminate_cores();
    197 	if (mlockall(MCL_FUTURE))
    198 		err(EXIT_FAILURE, "Can't lock memory");
    199 	p = params_new();
    200 	kg = NULL;
    201 
    202 	while ((ch = getopt(argc, argv, "CGUV:b:f:gi:k:lno:spuv")) != -1)
    203 		switch (ch) {
    204 		case 'C':
    205 			set_action(&action, ACTION_CONFIGALL);
    206 			break;
    207 		case 'G':
    208 			set_action(&action, ACTION_GENERATE_CONVERT);
    209 			break;
    210 		case 'U':
    211 			set_action(&action, ACTION_UNCONFIGALL);
    212 			break;
    213 		case 'V':
    214 			tp = params_verify_method(string_fromcharstar(optarg));
    215 			if (!tp)
    216 				usage();
    217 			p = params_combine(p, tp);
    218 			break;
    219 		case 'b':
    220 			{
    221 				size_t size;
    222 
    223 				if (parse_size_t(optarg, &size) == -1)
    224 					usage();
    225 				tp = params_bsize(size);
    226 				if (!tp)
    227 					usage();
    228 				p = params_combine(p, tp);
    229 			}
    230 			break;
    231 		case 'f':
    232 			if (cfile)
    233 				usage();
    234 			cfile = estrdup(optarg);
    235 			break;
    236 		case 'g':
    237 			set_action(&action, ACTION_GENERATE);
    238 			break;
    239 		case 'i':
    240 			tp = params_ivmeth(string_fromcharstar(optarg));
    241 			p = params_combine(p, tp);
    242 			break;
    243 		case 'k':
    244 			kg = keygen_method(string_fromcharstar(optarg));
    245 			if (!kg)
    246 				usage();
    247 			keygen_addlist(&p->keygen, kg);
    248 			break;
    249 		case 'l':
    250 			set_action(&action, ACTION_LIST);
    251 			break;
    252 		case 'n':
    253 			nflag = 1;
    254 			break;
    255 		case 'o':
    256 			if (outfile)
    257 				usage();
    258 			outfile = estrdup(optarg);
    259 			break;
    260 		case 'p':
    261 			pflag = PFLAG_STDIN;
    262 			break;
    263 		case 's':
    264 			set_action(&action, ACTION_CONFIGSTDIN);
    265 			break;
    266 
    267 		case 'u':
    268 			set_action(&action, ACTION_UNCONFIGURE);
    269 			break;
    270 		case 'v':
    271 			verbose++;
    272 			break;
    273 		default:
    274 			usage();
    275 			/* NOTREACHED */
    276 		}
    277 
    278 	argc -= optind;
    279 	argv += optind;
    280 
    281 	if (!outfile)
    282 		outfile = "";
    283 	if (!cfile)
    284 		cfile = "";
    285 
    286 	if (prog_init && prog_init() == -1)
    287 		err(1, "init failed");
    288 
    289 	/* validate the consistency of the arguments */
    290 
    291 	switch (action) {
    292 	case ACTION_DEFAULT:	/* ACTION_CONFIGURE is the default */
    293 	case ACTION_CONFIGURE:
    294 		return configure(argc, argv, p, CONFIG_FLAGS_FROMMAIN);
    295 	case ACTION_UNCONFIGURE:
    296 		return unconfigure(argc, argv, NULL, CONFIG_FLAGS_FROMMAIN);
    297 	case ACTION_GENERATE:
    298 		return generate(p, argc, argv, outfile);
    299 	case ACTION_GENERATE_CONVERT:
    300 		return generate_convert(p, argc, argv, outfile);
    301 	case ACTION_CONFIGALL:
    302 		return do_all(cfile, argc, argv, configure);
    303 	case ACTION_UNCONFIGALL:
    304 		return do_all(cfile, argc, argv, unconfigure);
    305 	case ACTION_CONFIGSTDIN:
    306 		return configure_stdin(p, argc, argv);
    307 	case ACTION_LIST:
    308 		return do_list(argc, argv);
    309 	default:
    310 		errx(EXIT_FAILURE, "undefined action");
    311 		/* NOTREACHED */
    312 	}
    313 }
    314 
    315 static bits_t *
    316 getkey(const char *dev, struct keygen *kg, size_t len)
    317 {
    318 	bits_t	*ret = NULL;
    319 	bits_t	*tmp;
    320 
    321 	VPRINTF(3, ("getkey(\"%s\", %p, %zu) called\n", dev, kg, len));
    322 	for (; kg; kg=kg->next) {
    323 		switch (kg->kg_method) {
    324 		case KEYGEN_STOREDKEY:
    325 			tmp = getkey_storedkey(dev, kg, len);
    326 			break;
    327 		case KEYGEN_RANDOMKEY:
    328 			tmp = getkey_randomkey(dev, kg, len, 1);
    329 			break;
    330 		case KEYGEN_URANDOMKEY:
    331 			tmp = getkey_randomkey(dev, kg, len, 0);
    332 			break;
    333 		case KEYGEN_PKCS5_PBKDF2_SHA1:
    334 			tmp = getkey_pkcs5_pbkdf2(dev, kg, len, 0);
    335 			break;
    336 		/* provide backwards compatibility for old config files */
    337 		case KEYGEN_PKCS5_PBKDF2_OLD:
    338 			tmp = getkey_pkcs5_pbkdf2(dev, kg, len, 1);
    339 			break;
    340 		case KEYGEN_SHELL_CMD:
    341 			tmp = getkey_shell_cmd(dev, kg, len);
    342 			break;
    343 		default:
    344 			warnx("unrecognised keygen method %d in getkey()",
    345 			    kg->kg_method);
    346 			if (ret)
    347 				bits_free(ret);
    348 			return NULL;
    349 		}
    350 
    351 		if (ret)
    352 			ret = bits_xor_d(tmp, ret);
    353 		else
    354 			ret = tmp;
    355 	}
    356 
    357 	return ret;
    358 }
    359 
    360 /*ARGSUSED*/
    361 static bits_t *
    362 getkey_storedkey(const char *target, struct keygen *kg, size_t keylen)
    363 {
    364 	return bits_dup(kg->kg_key);
    365 }
    366 
    367 /*ARGSUSED*/
    368 static bits_t *
    369 getkey_randomkey(const char *target, struct keygen *kg, size_t keylen, int hard)
    370 {
    371 	return bits_getrandombits(keylen, hard);
    372 }
    373 
    374 static char *
    375 maybe_getpass(char *prompt)
    376 {
    377 	char	 buf[1024];
    378 	char	*p = buf;
    379 	char	*tmp;
    380 
    381 	switch (pflag) {
    382 	case PFLAG_GETPASS:
    383 		p = getpass(prompt);
    384 		break;
    385 
    386 	case PFLAG_STDIN:
    387 		p = fgets(buf, sizeof(buf), stdin);
    388 		if (p) {
    389 			tmp = strchr(p, '\n');
    390 			if (tmp)
    391 				*tmp = '\0';
    392 		}
    393 		break;
    394 
    395 	default:
    396 		errx(EXIT_FAILURE, "pflag set inappropriately?");
    397 	}
    398 
    399 	if (!p)
    400 		err(EXIT_FAILURE, "failed to read passphrase");
    401 
    402 	return estrdup(p);
    403 }
    404 
    405 /*ARGSUSED*/
    406 /*
    407  * XXX take, and pass through, a compat flag that indicates whether we
    408  * provide backwards compatibility with a previous bug.  The previous
    409  * behaviour is indicated by the keygen method pkcs5_pbkdf2, and a
    410  * non-zero compat flag. The new default, and correct keygen method is
    411  * called pcks5_pbkdf2/sha1.  When the old method is removed, so will
    412  * be the compat argument.
    413  */
    414 static bits_t *
    415 getkey_pkcs5_pbkdf2(const char *target, struct keygen *kg, size_t keylen,
    416     int compat)
    417 {
    418 	bits_t		*ret;
    419 	char		*passp;
    420 	char		 buf[1024];
    421 	u_int8_t	*tmp;
    422 
    423 	snprintf(buf, sizeof(buf), "%s's passphrase:", target);
    424 	passp = maybe_getpass(buf);
    425 	if (pkcs5_pbkdf2(&tmp, BITS2BYTES(keylen), (uint8_t *)passp,
    426 	    strlen(passp),
    427 	    bits_getbuf(kg->kg_salt), BITS2BYTES(bits_len(kg->kg_salt)),
    428 	    kg->kg_iterations, compat)) {
    429 		warnx("failed to generate PKCS#5 PBKDF2 key");
    430 		return NULL;
    431 	}
    432 
    433 	ret = bits_new(tmp, keylen);
    434 	kg->kg_key = bits_dup(ret);
    435 	memset(passp, 0, strlen(passp));
    436 	free(passp);
    437 	free(tmp);
    438 	return ret;
    439 }
    440 
    441 /*ARGSUSED*/
    442 static bits_t *
    443 getkey_shell_cmd(const char *target, struct keygen *kg, size_t keylen)
    444 {
    445 	FILE	*f;
    446 	bits_t	*ret;
    447 
    448 	f = popen(string_tocharstar(kg->kg_cmd), "r");
    449 	ret = bits_fget(f, keylen);
    450 	pclose(f);
    451 
    452 	return ret;
    453 }
    454 
    455 /*ARGSUSED*/
    456 static int
    457 unconfigure(int argc, char **argv, struct params *inparams, int flags)
    458 {
    459 	int	fd;
    460 	int	ret;
    461 	char	buf[MAXPATHLEN] = "";
    462 
    463 	/* only complain about additional arguments, if called from main() */
    464 	if (flags == CONFIG_FLAGS_FROMMAIN && argc != 1)
    465 		usage();
    466 
    467 	/* if called from do_all(), then ensure that 2 or 3 args exist */
    468 	if (flags == CONFIG_FLAGS_FROMALL && (argc < 2 || argc > 3))
    469 		return -1;
    470 
    471 	fd = opendisk1(*argv, O_RDWR, buf, sizeof(buf), 1, prog_open);
    472 	if (fd == -1) {
    473 		int saved_errno = errno;
    474 
    475 		warn("can't open cgd \"%s\", \"%s\"", *argv, buf);
    476 
    477 		/* this isn't fatal with nflag != 0 */
    478 		if (!nflag)
    479 			return saved_errno;
    480 	}
    481 
    482 	VPRINTF(1, ("%s (%s): clearing\n", *argv, buf));
    483 
    484 	if (nflag)
    485 		return 0;
    486 
    487 	ret = unconfigure_fd(fd);
    488 	(void)prog_close(fd);
    489 	return ret;
    490 }
    491 
    492 static int
    493 unconfigure_fd(int fd)
    494 {
    495 	struct	cgd_ioctl ci;
    496 
    497 	if (prog_ioctl(fd, CGDIOCCLR, &ci) == -1) {
    498 		warn("ioctl");
    499 		return -1;
    500 	}
    501 
    502 	return 0;
    503 }
    504 
    505 /*ARGSUSED*/
    506 static int
    507 configure(int argc, char **argv, struct params *inparams, int flags)
    508 {
    509 	struct params	*p;
    510 	struct keygen	*kg;
    511 	int		 fd;
    512 	int		 loop = 0;
    513 	int		 ret;
    514 	char		 cgdname[PATH_MAX];
    515 	char		 devicename[PATH_MAX];
    516 	const char	*dev = NULL;	/* XXX: gcc */
    517 
    518 	if (argc == 2 || argc == 3) {
    519 		dev = getfsspecname(devicename, sizeof(devicename), argv[1]);
    520 		if (dev == NULL) {
    521 			warnx("getfsspecname failed: %s", devicename);
    522 			return -1;
    523 		}
    524 	}
    525 
    526 	if (argc == 2) {
    527 		char pfile[MAXPATHLEN];
    528 
    529 		/* make string writable for basename */
    530 		strlcpy(pfile, dev, sizeof(pfile));
    531 		p = params_cget(basename(pfile));
    532 	} else if (argc == 3) {
    533 		p = params_cget(argv[2]);
    534 	} else {
    535 		/* print usage and exit, only if called from main() */
    536 		if (flags == CONFIG_FLAGS_FROMMAIN) {
    537 			warnx("wrong number of args");
    538 			usage();
    539 		}
    540 		return -1;
    541 	}
    542 
    543 	if (!p)
    544 		return -1;
    545 
    546 	/*
    547 	 * over-ride with command line specifications and fill in default
    548 	 * values.
    549 	 */
    550 
    551 	p = params_combine(p, inparams);
    552 	ret = params_filldefaults(p);
    553 	if (ret) {
    554 		params_free(p);
    555 		return ret;
    556 	}
    557 
    558 	if (!params_verify(p)) {
    559 		warnx("params invalid");
    560 		return -1;
    561 	}
    562 
    563 	/*
    564 	 * loop over configuring the disk and checking to see if it
    565 	 * verifies properly.  We open and close the disk device each
    566 	 * time, because if the user passes us the block device we
    567 	 * need to flush the buffer cache.
    568 	 *
    569 	 * We only loop if one of the verification methods prompts for
    570 	 * a password.
    571 	 */
    572 
    573 	for (kg = p->keygen; pflag == PFLAG_GETPASS && kg; kg = kg->next)
    574 		if ((kg->kg_method == KEYGEN_PKCS5_PBKDF2_SHA1) ||
    575 		    (kg->kg_method == KEYGEN_PKCS5_PBKDF2_OLD )) {
    576 			loop = 1;
    577 			break;
    578 		}
    579 
    580 	for (;;) {
    581 		fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname));
    582 		if (fd == -1)
    583 			return -1;
    584 
    585 		if (p->key)
    586 			bits_free(p->key);
    587 
    588 		p->key = getkey(argv[1], p->keygen, p->keylen);
    589 		if (!p->key)
    590 			goto bail_err;
    591 
    592 		ret = configure_params(fd, cgdname, dev, p);
    593 		if (ret)
    594 			goto bail_err;
    595 
    596 		ret = verify(p, fd);
    597 		if (ret == -1)
    598 			goto bail_err;
    599 		if (!ret)
    600 			break;
    601 
    602 		(void)unconfigure_fd(fd);
    603 		(void)prog_close(fd);
    604 
    605 		if (!loop) {
    606 			warnx("verification failed permanently");
    607 			goto bail_err;
    608 		}
    609 
    610 		warnx("verification failed, please reenter passphrase");
    611 	}
    612 
    613 	params_free(p);
    614 	(void)prog_close(fd);
    615 	return 0;
    616 bail_err:
    617 	params_free(p);
    618 	(void)prog_close(fd);
    619 	return -1;
    620 }
    621 
    622 static int
    623 configure_stdin(struct params *p, int argc, char **argv)
    624 {
    625 	int		 fd;
    626 	int		 ret;
    627 	char		 cgdname[PATH_MAX];
    628 	char		 devicename[PATH_MAX];
    629 	const char	*dev;
    630 
    631 	if (argc < 3 || argc > 4)
    632 		usage();
    633 
    634 	dev = getfsspecname(devicename, sizeof(devicename), argv[1]);
    635 	if (dev == NULL) {
    636 		warnx("getfsspecname failed: %s", devicename);
    637 		return -1;
    638 	}
    639 
    640 	p->algorithm = string_fromcharstar(argv[2]);
    641 	if (argc > 3) {
    642 		size_t keylen;
    643 
    644 		if (parse_size_t(argv[3], &keylen) == -1) {
    645 			warn("failed to parse key length");
    646 			return -1;
    647 		}
    648 		p->keylen = keylen;
    649 	}
    650 
    651 	ret = params_filldefaults(p);
    652 	if (ret)
    653 		return ret;
    654 
    655 	fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname));
    656 	if (fd == -1)
    657 		return -1;
    658 
    659 	p->key = bits_fget(stdin, p->keylen);
    660 	if (!p->key) {
    661 		warnx("failed to read key from stdin");
    662 		return -1;
    663 	}
    664 
    665 	return configure_params(fd, cgdname, dev, p);
    666 }
    667 
    668 static int
    669 opendisk_werror(const char *cgd, char *buf, size_t buflen)
    670 {
    671 	int	fd;
    672 
    673 	VPRINTF(3, ("opendisk_werror(%s, %s, %zu) called.\n", cgd, buf, buflen));
    674 
    675 	/* sanity */
    676 	if (!cgd || !buf)
    677 		return -1;
    678 
    679 	if (nflag) {
    680 		if (strlcpy(buf, cgd, buflen) >= buflen)
    681 			return -1;
    682 		return 0;
    683 	}
    684 
    685 	fd = opendisk1(cgd, O_RDWR, buf, buflen, 0, prog_open);
    686 	if (fd == -1)
    687 		warnx("can't open cgd \"%s\", \"%s\"", cgd, buf);
    688 
    689 	return fd;
    690 }
    691 
    692 static int
    693 configure_params(int fd, const char *cgd, const char *dev, struct params *p)
    694 {
    695 	struct cgd_ioctl ci;
    696 
    697 	/* sanity */
    698 	if (!cgd || !dev)
    699 		return -1;
    700 
    701 	(void)memset(&ci, 0x0, sizeof(ci));
    702 	ci.ci_disk = dev;
    703 	ci.ci_alg = string_tocharstar(p->algorithm);
    704 	ci.ci_ivmethod = string_tocharstar(p->ivmeth);
    705 	ci.ci_key = bits_getbuf(p->key);
    706 	ci.ci_keylen = p->keylen;
    707 	ci.ci_blocksize = p->bsize;
    708 
    709 	VPRINTF(1, ("    with alg %s keylen %zu blocksize %zu ivmethod %s\n",
    710 	    string_tocharstar(p->algorithm), p->keylen, p->bsize,
    711 	    string_tocharstar(p->ivmeth)));
    712 	VPRINTF(2, ("key: "));
    713 	VERBOSE(2, bits_fprint(stdout, p->key));
    714 	VPRINTF(2, ("\n"));
    715 
    716 	if (nflag)
    717 		return 0;
    718 
    719 	if (prog_ioctl(fd, CGDIOCSET, &ci) == -1) {
    720 		int saved_errno = errno;
    721 		warn("ioctl");
    722 		return saved_errno;
    723 	}
    724 
    725 	return 0;
    726 }
    727 
    728 /*
    729  * verify returns 0 for success, -1 for unrecoverable error, or 1 for retry.
    730  */
    731 
    732 #define SCANSIZE	8192
    733 
    734 static int
    735 verify(struct params *p, int fd)
    736 {
    737 
    738 	switch (p->verify_method) {
    739 	case VERIFY_NONE:
    740 		return 0;
    741 	case VERIFY_DISKLABEL:
    742 		return verify_disklabel(fd);
    743 	case VERIFY_FFS:
    744 		return verify_ffs(fd);
    745 	case VERIFY_REENTER:
    746 		return verify_reenter(p);
    747 	case VERIFY_MBR:
    748 		return verify_mbr(fd);
    749 	case VERIFY_GPT:
    750 		return verify_gpt(fd);
    751 	default:
    752 		warnx("unimplemented verification method");
    753 		return -1;
    754 	}
    755 }
    756 
    757 static int
    758 verify_disklabel(int fd)
    759 {
    760 	struct	disklabel l;
    761 	ssize_t	ret;
    762 	char	buf[SCANSIZE];
    763 
    764 	/*
    765 	 * we simply scan the first few blocks for a disklabel, ignoring
    766 	 * any MBR/filecore sorts of logic.  MSDOS and RiscOS can't read
    767 	 * a cgd, anyway, so it is unlikely that there will be non-native
    768 	 * partition information.
    769 	 */
    770 
    771 	ret = prog_pread(fd, buf, SCANSIZE, 0);
    772 	if (ret < 0) {
    773 		warn("can't read disklabel area");
    774 		return -1;
    775 	}
    776 
    777 	/* now scan for the disklabel */
    778 
    779 	return disklabel_scan(&l, buf, (size_t)ret);
    780 }
    781 
    782 static int
    783 verify_mbr(int fd)
    784 {
    785 	struct mbr_sector mbr;
    786 	ssize_t	ret;
    787 	char	buf[SCANSIZE];
    788 
    789 	/*
    790 	 * we read the first blocks to avoid sector size issues and
    791 	 * verify the MBR in the beginning
    792 	 */
    793 
    794 	ret = prog_pread(fd, buf, SCANSIZE, 0);
    795 	if (ret < 0) {
    796 		warn("can't read mbr area");
    797 		return -1;
    798 	}
    799 
    800 	memcpy(&mbr, buf, sizeof(mbr));
    801 	if (le16toh(mbr.mbr_magic) != MBR_MAGIC)
    802 		return -1;
    803 
    804 	return 0;
    805 }
    806 
    807 static uint32_t crc32_tab[] = {
    808 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
    809 	0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
    810 	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
    811 	0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    812 	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
    813 	0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
    814 	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
    815 	0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    816 	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
    817 	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    818 	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
    819 	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    820 	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
    821 	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
    822 	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    823 	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    824 	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
    825 	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
    826 	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
    827 	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    828 	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
    829 	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
    830 	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
    831 	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    832 	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    833 	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
    834 	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
    835 	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    836 	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
    837 	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    838 	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
    839 	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    840 	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
    841 	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
    842 	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    843 	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    844 	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
    845 	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
    846 	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
    847 	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    848 	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
    849 	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
    850 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
    851 };
    852 
    853 static uint32_t
    854 crc32(const void *buf, size_t size)
    855 {
    856 	const uint8_t *p;
    857 	uint32_t crc;
    858 
    859 	p = buf;
    860 	crc = ~0U;
    861 
    862 	while (size--)
    863 		crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
    864 
    865 	return crc ^ ~0U;
    866 }
    867 
    868 static int
    869 verify_gpt(int fd)
    870 {
    871 	struct	 gpt_hdr hdr;
    872 	ssize_t	 ret;
    873 	char	 buf[SCANSIZE];
    874 	unsigned blksize;
    875 	size_t	 off;
    876 
    877 	/*
    878 	 * we read the first blocks to avoid sector size issues and
    879 	 * verify the GPT header.
    880 	 */
    881 
    882 	ret = prog_pread(fd, buf, SCANSIZE, 0);
    883 	if (ret < 0) {
    884 		warn("can't read gpt area");
    885 		return -1;
    886 	}
    887 
    888 	ret = -1;
    889 	for (blksize=DEV_BSIZE;
    890              (off = blksize * GPT_HDR_BLKNO) <= SCANSIZE - sizeof(hdr);
    891              blksize <<= 1) {
    892 
    893 		memcpy(&hdr, &buf[off], sizeof(hdr));
    894 		if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) == 0 &&
    895 		    le32toh(hdr.hdr_revision) == GPT_HDR_REVISION &&
    896 		    le32toh(hdr.hdr_size) == GPT_HDR_SIZE) {
    897 
    898 			hdr.hdr_crc_self = 0;
    899 			if (crc32(&hdr, sizeof(hdr))) {
    900 				ret = 0;
    901 				break;
    902 			}
    903 		}
    904 	}
    905 
    906 	return ret;
    907 }
    908 
    909 static off_t sblock_try[] = SBLOCKSEARCH;
    910 
    911 static int
    912 verify_ffs(int fd)
    913 {
    914 	size_t	i;
    915 
    916 	for (i = 0; sblock_try[i] != -1; i++) {
    917 		union {
    918 		    char	buf[SBLOCKSIZE];
    919 		    struct	fs fs;
    920 		} u;
    921 		ssize_t ret;
    922 
    923 		ret = prog_pread(fd, &u, sizeof(u), sblock_try[i]);
    924 		if (ret < 0) {
    925 			warn("pread");
    926 			break;
    927 		} else if ((size_t)ret < sizeof(u)) {
    928 			warnx("pread: incomplete block");
    929 			break;
    930 		}
    931 		switch (u.fs.fs_magic) {
    932 		case FS_UFS1_MAGIC:
    933 		case FS_UFS2_MAGIC:
    934 		case FS_UFS1_MAGIC_SWAPPED:
    935 		case FS_UFS2_MAGIC_SWAPPED:
    936 			return 0;
    937 		default:
    938 			continue;
    939 		}
    940 	}
    941 
    942 	return 1;	/* failure */
    943 }
    944 
    945 static int
    946 verify_reenter(struct params *p)
    947 {
    948 	struct keygen *kg;
    949 	bits_t *orig_key, *key;
    950 	int ret;
    951 
    952 	ret = 0;
    953 	for (kg = p->keygen; kg && !ret; kg = kg->next) {
    954 		if ((kg->kg_method != KEYGEN_PKCS5_PBKDF2_SHA1) &&
    955 		    (kg->kg_method != KEYGEN_PKCS5_PBKDF2_OLD ))
    956 			continue;
    957 
    958 		orig_key = kg->kg_key;
    959 		kg->kg_key = NULL;
    960 
    961 		/* add a compat flag till the _OLD method goes away */
    962 		key = getkey_pkcs5_pbkdf2("re-enter device", kg,
    963 			bits_len(orig_key), kg->kg_method == KEYGEN_PKCS5_PBKDF2_OLD);
    964 		ret = !bits_match(key, orig_key);
    965 
    966 		bits_free(key);
    967 		bits_free(kg->kg_key);
    968 		kg->kg_key = orig_key;
    969 	}
    970 
    971 	return ret;
    972 }
    973 
    974 static int
    975 generate(struct params *p, int argc, char **argv, const char *outfile)
    976 {
    977 	int	 ret;
    978 
    979 	if (argc < 1 || argc > 2)
    980 		usage();
    981 
    982 	p->algorithm = string_fromcharstar(argv[0]);
    983 	if (argc > 1) {
    984 		size_t keylen;
    985 
    986 		if (parse_size_t(argv[1], &keylen) == -1) {
    987 			warn("Failed to parse key length");
    988 			return -1;
    989 		}
    990 		p->keylen = keylen;
    991 	}
    992 
    993 	ret = params_filldefaults(p);
    994 	if (ret)
    995 		return ret;
    996 
    997 	if (!p->keygen) {
    998 		p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2_SHA1);
    999 		if (!p->keygen)
   1000 			return -1;
   1001 	}
   1002 
   1003 	if (keygen_filldefaults(p->keygen, p->keylen)) {
   1004 		warnx("Failed to generate defaults for keygen");
   1005 		return -1;
   1006 	}
   1007 
   1008 	if (!params_verify(p)) {
   1009 		warnx("invalid parameters generated");
   1010 		return -1;
   1011 	}
   1012 
   1013 	return params_cput(p, outfile);
   1014 }
   1015 
   1016 static int
   1017 generate_convert(struct params *p, int argc, char **argv, const char *outfile)
   1018 {
   1019 	struct params	*oldp;
   1020 	struct keygen	*kg;
   1021 
   1022 	if (argc != 1)
   1023 		usage();
   1024 
   1025 	oldp = params_cget(*argv);
   1026 	if (!oldp)
   1027 		return -1;
   1028 
   1029 	/* for sanity, we ensure that none of the keygens are randomkey */
   1030 	for (kg=p->keygen; kg; kg=kg->next)
   1031 		if ((kg->kg_method == KEYGEN_RANDOMKEY) ||
   1032 		    (kg->kg_method == KEYGEN_URANDOMKEY)) {
   1033 			warnx("can't preserve randomly generated key");
   1034 			goto bail;
   1035 		}
   1036 	for (kg=oldp->keygen; kg; kg=kg->next)
   1037 		if ((kg->kg_method == KEYGEN_RANDOMKEY) ||
   1038 		    (kg->kg_method == KEYGEN_URANDOMKEY)) {
   1039 			warnx("can't preserve randomly generated key");
   1040 			goto bail;
   1041 		}
   1042 
   1043 	if (!params_verify(oldp)) {
   1044 		warnx("invalid old parameters file \"%s\"", *argv);
   1045 		return -1;
   1046 	}
   1047 
   1048 	oldp->key = getkey("old file", oldp->keygen, oldp->keylen);
   1049 
   1050 	/* we copy across the non-keygen info, here. */
   1051 
   1052 	string_free(p->algorithm);
   1053 	string_free(p->ivmeth);
   1054 
   1055 	p->algorithm = string_dup(oldp->algorithm);
   1056 	p->ivmeth = string_dup(oldp->ivmeth);
   1057 	p->keylen = oldp->keylen;
   1058 	p->bsize = oldp->bsize;
   1059 	if (p->verify_method == VERIFY_UNKNOWN)
   1060 		p->verify_method = oldp->verify_method;
   1061 
   1062 	params_free(oldp);
   1063 
   1064 	if (!p->keygen) {
   1065 		p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2_SHA1);
   1066 		if (!p->keygen)
   1067 			return -1;
   1068 	}
   1069 	(void)params_filldefaults(p);
   1070 	(void)keygen_filldefaults(p->keygen, p->keylen);
   1071 	p->key = getkey("new file", p->keygen, p->keylen);
   1072 
   1073 	kg = keygen_generate(KEYGEN_STOREDKEY);
   1074 	kg->kg_key = bits_xor(p->key, oldp->key);
   1075 	keygen_addlist(&p->keygen, kg);
   1076 
   1077 	if (!params_verify(p)) {
   1078 		warnx("can't generate new parameters file");
   1079 		return -1;
   1080 	}
   1081 
   1082 	return params_cput(p, outfile);
   1083 bail:
   1084 	params_free(oldp);
   1085 	return -1;
   1086 }
   1087 
   1088 static int
   1089 /*ARGSUSED*/
   1090 do_all(const char *cfile, int argc, char **argv,
   1091        int (*conf)(int, char **, struct params *, int))
   1092 {
   1093 	FILE		 *f;
   1094 	size_t		  len;
   1095 	size_t		  lineno;
   1096 	int		  my_argc;
   1097 	int		  ret;
   1098 	const char	 *fn;
   1099 	char		 *line;
   1100 	char		**my_argv;
   1101 
   1102 	if (argc > 0)
   1103 		usage();
   1104 
   1105 	if (!cfile[0])
   1106 		fn = CGDCONFIG_CFILE;
   1107 	else
   1108 		fn = cfile;
   1109 
   1110 	f = fopen(fn, "r");
   1111 	if (!f) {
   1112 		warn("could not open config file \"%s\"", fn);
   1113 		return -1;
   1114 	}
   1115 
   1116 	ret = 0;
   1117 	lineno = 0;
   1118 	for (;;) {
   1119 		line = fparseln(f, &len, &lineno, "\\\\#", FPARSELN_UNESCALL);
   1120 		if (!line)
   1121 			break;
   1122 		if (!*line)
   1123 			continue;
   1124 
   1125 		my_argv = words(line, &my_argc);
   1126 		ret = conf(my_argc, my_argv, NULL, CONFIG_FLAGS_FROMALL);
   1127 		if (ret) {
   1128 			warnx("action failed on \"%s\" line %lu", fn,
   1129 			    (u_long)lineno);
   1130 			break;
   1131 		}
   1132 		words_free(my_argv, my_argc);
   1133 	}
   1134 	return ret;
   1135 }
   1136 
   1137 static const char *
   1138 iv_method(int mode)
   1139 {
   1140 
   1141 	switch (mode) {
   1142 	case CGD_CIPHER_CBC_ENCBLKNO8:
   1143 		return "encblkno8";
   1144 	case CGD_CIPHER_CBC_ENCBLKNO1:
   1145 		return "encblkno1";
   1146 	default:
   1147 		return "unknown";
   1148 	}
   1149 }
   1150 
   1151 
   1152 static void
   1153 show(const char *dev) {
   1154 	char path[64];
   1155 	struct cgd_user cgu;
   1156 	int fd;
   1157 
   1158 	fd = opendisk(dev, O_RDONLY, path, sizeof(path), 0);
   1159 	if (fd == -1) {
   1160 		warn("open: %s", dev);
   1161 		return;
   1162 	}
   1163 
   1164 	cgu.cgu_unit = -1;
   1165 	if (prog_ioctl(fd, CGDIOCGET, &cgu) == -1) {
   1166 		close(fd);
   1167 		err(1, "CGDIOCGET");
   1168 	}
   1169 
   1170 	printf("%s: ", dev);
   1171 
   1172 	if (cgu.cgu_dev == 0) {
   1173 		printf("not in use");
   1174 		goto out;
   1175 	}
   1176 
   1177 	dev = devname(cgu.cgu_dev, S_IFBLK);
   1178 	if (dev != NULL)
   1179 		printf("%s ", dev);
   1180 	else
   1181 		printf("dev %llu,%llu ", (unsigned long long)major(cgu.cgu_dev),
   1182 		    (unsigned long long)minor(cgu.cgu_dev));
   1183 
   1184 	if (verbose)
   1185 		printf("%s ", cgu.cgu_alg);
   1186 	if (verbose > 1) {
   1187 		printf("keylen %d ", cgu.cgu_keylen);
   1188 		printf("blksize %zd ", cgu.cgu_blocksize);
   1189 		printf("%s ", iv_method(cgu.cgu_mode));
   1190 	}
   1191 
   1192 out:
   1193 	putchar('\n');
   1194 	close(fd);
   1195 }
   1196 
   1197 static int
   1198 do_list(int argc, char **argv)
   1199 {
   1200 
   1201 	if (argc != 0 && argc != 1)
   1202 		usage();
   1203 
   1204 	if (argc) {
   1205 		show(argv[0]);
   1206 		return 0;
   1207 	}
   1208 
   1209 	DIR *dirp;
   1210 	struct dirent *dp;
   1211 	__BITMAP_TYPE(, uint32_t, 65536) bm;
   1212 
   1213 	__BITMAP_ZERO(&bm);
   1214 
   1215 	if ((dirp = opendir(_PATH_DEV)) == NULL)
   1216 		err(1, "opendir: %s", _PATH_DEV);
   1217 
   1218 	while ((dp = readdir(dirp)) != NULL) {
   1219 		char *ep;
   1220 		if (strncmp(dp->d_name, "rcgd", 4) != 0)
   1221 			continue;
   1222 		errno = 0;
   1223 		int n = (int)strtol(dp->d_name + 4, &ep, 0);
   1224 		if (ep == dp->d_name + 4 || errno != 0) {
   1225 			warnx("bad name %s", dp->d_name);
   1226 			continue;
   1227 		}
   1228 		*ep = '\0';
   1229 		if (__BITMAP_ISSET(n, &bm))
   1230 			continue;
   1231 		__BITMAP_SET(n, &bm);
   1232 		show(dp->d_name + 1);
   1233 	}
   1234 
   1235 	closedir(dirp);
   1236 	return 0;
   1237 }
   1238 
   1239 static void
   1240 eliminate_cores(void)
   1241 {
   1242 	struct rlimit	rlp;
   1243 
   1244 	rlp.rlim_cur = 0;
   1245 	rlp.rlim_max = 0;
   1246 	if (setrlimit(RLIMIT_CORE, &rlp) == -1)
   1247 		err(EXIT_FAILURE, "Can't disable cores");
   1248 }
   1249