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