1/* $NetBSD: cgdconfig.c,v 1.32 2010/12/14 17:46:21 pooka 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.32 2010/12/14 17:46:21 pooka 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 49#include <sys/ioctl.h> 50#include <sys/disklabel.h> 51#include <sys/mman.h> 52#include <sys/param.h> 53#include <sys/resource.h> 54 55#include <dev/cgdvar.h> 56 57#include <ufs/ffs/fs.h> 58 59#include "params.h" 60#include "pkcs5_pbkdf2.h" 61#include "utils.h" 62#include "cgdconfig.h" 63#include "prog_ops.h" 64 65#define CGDCONFIG_DIR "/etc/cgd" 66#define CGDCONFIG_CFILE CGDCONFIG_DIR "/cgd.conf" 67 68enum action { 69 ACTION_DEFAULT, /* default -> configure */ 70 ACTION_CONFIGURE, /* configure, with paramsfile */ 71 ACTION_UNCONFIGURE, /* unconfigure */ 72 ACTION_GENERATE, /* generate a paramsfile */ 73 ACTION_GENERATE_CONVERT, /* generate a ``dup'' paramsfile */ 74 ACTION_CONFIGALL, /* configure all from config file */ 75 ACTION_UNCONFIGALL, /* unconfigure all from config file */ 76 ACTION_CONFIGSTDIN /* configure, key from stdin */ 77}; 78 79/* if nflag is set, do not configure/unconfigure the cgd's */ 80 81int nflag = 0; 82 83/* if pflag is set to PFLAG_STDIN read from stdin rather than getpass(3) */ 84 85#define PFLAG_GETPASS 0x01 86#define PFLAG_STDIN 0x02 87int pflag = PFLAG_GETPASS; 88 89static int configure(int, char **, struct params *, int); 90static int configure_stdin(struct params *, int argc, char **); 91static int generate(struct params *, int, char **, const char *); 92static int generate_convert(struct params *, int, char **, const char *); 93static int unconfigure(int, char **, struct params *, int); 94static int do_all(const char *, int, char **, 95 int (*)(int, char **, struct params *, int)); 96 97#define CONFIG_FLAGS_FROMALL 1 /* called from configure_all() */ 98#define CONFIG_FLAGS_FROMMAIN 2 /* called from main() */ 99 100static int configure_params(int, const char *, const char *, 101 struct params *); 102static void eliminate_cores(void); 103static bits_t *getkey(const char *, struct keygen *, size_t); 104static bits_t *getkey_storedkey(const char *, struct keygen *, size_t); 105static bits_t *getkey_randomkey(const char *, struct keygen *, size_t, int); 106static bits_t *getkey_pkcs5_pbkdf2(const char *, struct keygen *, size_t, 107 int); 108static bits_t *getkey_shell_cmd(const char *, struct keygen *, size_t); 109static char *maybe_getpass(char *); 110static int opendisk_werror(const char *, char *, size_t); 111static int unconfigure_fd(int); 112static int verify(struct params *, int); 113static int verify_disklabel(int); 114static int verify_ffs(int); 115static int verify_reenter(struct params *); 116 117__dead static void usage(void); 118 119/* Verbose Framework */ 120unsigned verbose = 0; 121 122#define VERBOSE(x,y) if (verbose >= x) y 123#define VPRINTF(x,y) if (verbose >= x) (void)printf y 124 125static void 126usage(void) 127{ 128 129 (void)fprintf(stderr, "usage: %s [-nv] [-V vmeth] cgd dev [paramsfile]\n", 130 getprogname()); 131 (void)fprintf(stderr, " %s -C [-nv] [-f configfile]\n", getprogname()); 132 (void)fprintf(stderr, " %s -U [-nv] [-f configfile]\n", getprogname()); 133 (void)fprintf(stderr, " %s -G [-nv] [-i ivmeth] [-k kgmeth] " 134 "[-o outfile] paramsfile\n", getprogname()); 135 (void)fprintf(stderr, " %s -g [-nv] [-i ivmeth] [-k kgmeth] " 136 "[-o outfile] alg [keylen]\n", getprogname()); 137 (void)fprintf(stderr, " %s -s [-nv] [-i ivmeth] cgd dev alg " 138 "[keylen]\n", getprogname()); 139 (void)fprintf(stderr, " %s -u [-nv] cgd\n", getprogname()); 140 exit(EXIT_FAILURE); 141} 142 143static int 144parse_size_t(const char *s, size_t *l) 145{ 146 char *endptr; 147 long v; 148 149 errno = 0; 150 v = strtol(s, &endptr, 10); 151 if ((v == LONG_MIN || v == LONG_MAX) && errno) 152 return -1; 153 if (v < INT_MIN || v > INT_MAX) { 154 errno = ERANGE; 155 return -1; 156 } 157 if (endptr == s) { 158 errno = EINVAL; 159 return -1; 160 } 161 *l = (size_t)v; 162 return 0; 163} 164 165static void 166set_action(enum action *action, enum action value) 167{ 168 if (*action != ACTION_DEFAULT) 169 usage(); 170 *action = value; 171} 172 173int 174main(int argc, char **argv) 175{ 176 struct params *p; 177 struct params *tp; 178 struct keygen *kg; 179 enum action action = ACTION_DEFAULT; 180 int ch; 181 const char *cfile = NULL; 182 const char *outfile = NULL; 183 184 setprogname(*argv); 185 eliminate_cores(); 186 if (mlockall(MCL_FUTURE)) 187 err(EXIT_FAILURE, "Can't lock memory"); 188 p = params_new(); 189 kg = NULL; 190 191 while ((ch = getopt(argc, argv, "CGUV:b:f:gi:k:no:spuv")) != -1) 192 switch (ch) { 193 case 'C': 194 set_action(&action, ACTION_CONFIGALL); 195 break; 196 case 'G': 197 set_action(&action, ACTION_GENERATE_CONVERT); 198 break; 199 case 'U': 200 set_action(&action, ACTION_UNCONFIGALL); 201 break; 202 case 'V': 203 tp = params_verify_method(string_fromcharstar(optarg)); 204 if (!tp) 205 usage(); 206 p = params_combine(p, tp); 207 break; 208 case 'b': 209 { 210 size_t size; 211 212 if (parse_size_t(optarg, &size) == -1) 213 usage(); 214 tp = params_bsize(size); 215 if (!tp) 216 usage(); 217 p = params_combine(p, tp); 218 } 219 break; 220 case 'f': 221 if (cfile) 222 usage(); 223 cfile = estrdup(optarg); 224 break; 225 case 'g': 226 set_action(&action, ACTION_GENERATE); 227 break; 228 case 'i': 229 tp = params_ivmeth(string_fromcharstar(optarg)); 230 p = params_combine(p, tp); 231 break; 232 case 'k': 233 kg = keygen_method(string_fromcharstar(optarg)); 234 if (!kg) 235 usage(); 236 keygen_addlist(&p->keygen, kg); 237 break; 238 case 'n': 239 nflag = 1; 240 break; 241 case 'o': 242 if (outfile) 243 usage(); 244 outfile = estrdup(optarg); 245 break; 246 case 'p': 247 pflag = PFLAG_STDIN; 248 break; 249 case 's': 250 set_action(&action, ACTION_CONFIGSTDIN); 251 break; 252 253 case 'u': 254 set_action(&action, ACTION_UNCONFIGURE); 255 break; 256 case 'v': 257 verbose++; 258 break; 259 default: 260 usage(); 261 /* NOTREACHED */ 262 } 263 264 argc -= optind; 265 argv += optind; 266 267 if (!outfile) 268 outfile = ""; 269 if (!cfile) 270 cfile = ""; 271 272 if (prog_init && prog_init() == -1) 273 err(1, "init failed"); 274 275 /* validate the consistency of the arguments */ 276 277 switch (action) { 278 case ACTION_DEFAULT: /* ACTION_CONFIGURE is the default */ 279 case ACTION_CONFIGURE: 280 return configure(argc, argv, p, CONFIG_FLAGS_FROMMAIN); 281 case ACTION_UNCONFIGURE: 282 return unconfigure(argc, argv, NULL, CONFIG_FLAGS_FROMMAIN); 283 case ACTION_GENERATE: 284 return generate(p, argc, argv, outfile); 285 case ACTION_GENERATE_CONVERT: 286 return generate_convert(p, argc, argv, outfile); 287 case ACTION_CONFIGALL: 288 return do_all(cfile, argc, argv, configure); 289 case ACTION_UNCONFIGALL: 290 return do_all(cfile, argc, argv, unconfigure); 291 case ACTION_CONFIGSTDIN: 292 return configure_stdin(p, argc, argv); 293 default: 294 errx(EXIT_FAILURE, "undefined action"); 295 /* NOTREACHED */ 296 } 297} 298 299static bits_t * 300getkey(const char *dev, struct keygen *kg, size_t len) 301{ 302 bits_t *ret = NULL; 303 bits_t *tmp; 304 305 VPRINTF(3, ("getkey(\"%s\", %p, %zu) called\n", dev, kg, len)); 306 for (; kg; kg=kg->next) { 307 switch (kg->kg_method) { 308 case KEYGEN_STOREDKEY: 309 tmp = getkey_storedkey(dev, kg, len); 310 break; 311 case KEYGEN_RANDOMKEY: 312 tmp = getkey_randomkey(dev, kg, len, 1); 313 break; 314 case KEYGEN_URANDOMKEY: 315 tmp = getkey_randomkey(dev, kg, len, 0); 316 break; 317 case KEYGEN_PKCS5_PBKDF2_SHA1: 318 tmp = getkey_pkcs5_pbkdf2(dev, kg, len, 0); 319 break; 320 /* provide backwards compatibility for old config files */ 321 case KEYGEN_PKCS5_PBKDF2_OLD: 322 tmp = getkey_pkcs5_pbkdf2(dev, kg, len, 1); 323 break; 324 case KEYGEN_SHELL_CMD: 325 tmp = getkey_shell_cmd(dev, kg, len); 326 break; 327 default: 328 warnx("unrecognised keygen method %d in getkey()", 329 kg->kg_method); 330 if (ret) 331 bits_free(ret); 332 return NULL; 333 } 334 335 if (ret) 336 ret = bits_xor_d(tmp, ret); 337 else 338 ret = tmp; 339 } 340 341 return ret; 342} 343 344/*ARGSUSED*/ 345static bits_t * 346getkey_storedkey(const char *target, struct keygen *kg, size_t keylen) 347{ 348 return bits_dup(kg->kg_key); 349} 350 351/*ARGSUSED*/ 352static bits_t * 353getkey_randomkey(const char *target, struct keygen *kg, size_t keylen, int hard) 354{ 355 return bits_getrandombits(keylen, hard); 356} 357 358static char * 359maybe_getpass(char *prompt) 360{ 361 char buf[1024]; 362 char *p = buf; 363 char *tmp; 364 365 switch (pflag) { 366 case PFLAG_GETPASS: 367 p = getpass(prompt); 368 break; 369 370 case PFLAG_STDIN: 371 p = fgets(buf, sizeof(buf), stdin); 372 if (p) { 373 tmp = strchr(p, '\n'); 374 if (tmp) 375 *tmp = '\0'; 376 } 377 break; 378 379 default: 380 errx(EXIT_FAILURE, "pflag set inappropriately?"); 381 } 382 383 if (!p) 384 err(EXIT_FAILURE, "failed to read passphrase"); 385 386 return estrdup(p); 387} 388 389/*ARGSUSED*/ 390/* 391 * XXX take, and pass through, a compat flag that indicates whether we 392 * provide backwards compatibility with a previous bug. The previous 393 * behaviour is indicated by the keygen method pkcs5_pbkdf2, and a 394 * non-zero compat flag. The new default, and correct keygen method is 395 * called pcks5_pbkdf2/sha1. When the old method is removed, so will 396 * be the compat argument. 397 */ 398static bits_t * 399getkey_pkcs5_pbkdf2(const char *target, struct keygen *kg, size_t keylen, 400 int compat) 401{ 402 bits_t *ret; 403 char *passp; 404 char buf[1024]; 405 u_int8_t *tmp; 406 407 snprintf(buf, sizeof(buf), "%s's passphrase:", target); 408 passp = maybe_getpass(buf); 409 if (pkcs5_pbkdf2(&tmp, BITS2BYTES(keylen), (uint8_t *)passp, 410 strlen(passp), 411 bits_getbuf(kg->kg_salt), BITS2BYTES(bits_len(kg->kg_salt)), 412 kg->kg_iterations, compat)) { 413 warnx("failed to generate PKCS#5 PBKDF2 key"); 414 return NULL; 415 } 416 417 ret = bits_new(tmp, keylen); 418 kg->kg_key = bits_dup(ret); 419 memset(passp, 0, strlen(passp)); 420 free(passp); 421 free(tmp); 422 return ret; 423} 424 425/*ARGSUSED*/ 426static bits_t * 427getkey_shell_cmd(const char *target, struct keygen *kg, size_t keylen) 428{ 429 FILE *f; 430 bits_t *ret; 431 432 f = popen(string_tocharstar(kg->kg_cmd), "r"); 433 ret = bits_fget(f, keylen); 434 pclose(f); 435 436 return ret; 437} 438 439/*ARGSUSED*/ 440static int 441unconfigure(int argc, char **argv, struct params *inparams, int flags) 442{ 443 int fd; 444 int ret; 445 char buf[MAXPATHLEN] = ""; 446 447 /* only complain about additional arguments, if called from main() */ 448 if (flags == CONFIG_FLAGS_FROMMAIN && argc != 1) 449 usage(); 450 451 /* if called from do_all(), then ensure that 2 or 3 args exist */ 452 if (flags == CONFIG_FLAGS_FROMALL && (argc < 2 || argc > 3)) 453 return -1; 454 455 fd = opendisk1(*argv, O_RDWR, buf, sizeof(buf), 1, prog_open); 456 if (fd == -1) { 457 int saved_errno = errno; 458 459 warn("can't open cgd \"%s\", \"%s\"", *argv, buf); 460 461 /* this isn't fatal with nflag != 0 */ 462 if (!nflag) 463 return saved_errno; 464 } 465 466 VPRINTF(1, ("%s (%s): clearing\n", *argv, buf)); 467 468 if (nflag) 469 return 0; 470 471 ret = unconfigure_fd(fd); 472 (void)prog_close(fd); 473 return ret; 474} 475 476static int 477unconfigure_fd(int fd) 478{ 479 struct cgd_ioctl ci; 480 481 if (prog_ioctl(fd, CGDIOCCLR, &ci) == -1) { 482 warn("ioctl"); 483 return -1; 484 } 485 486 return 0; 487} 488 489/*ARGSUSED*/ 490static int 491configure(int argc, char **argv, struct params *inparams, int flags) 492{ 493 struct params *p; 494 struct keygen *kg; 495 int fd; 496 int loop = 0; 497 int ret; 498 char cgdname[PATH_MAX]; 499 500 if (argc == 2) { 501 char *pfile; 502 503 if (asprintf(&pfile, "%s/%s", 504 CGDCONFIG_DIR, basename(argv[1])) == -1) 505 return -1; 506 507 p = params_cget(pfile); 508 free(pfile); 509 } else if (argc == 3) { 510 p = params_cget(argv[2]); 511 } else { 512 /* print usage and exit, only if called from main() */ 513 if (flags == CONFIG_FLAGS_FROMMAIN) { 514 warnx("wrong number of args"); 515 usage(); 516 } 517 return -1; 518 } 519 520 if (!p) 521 return -1; 522 523 /* 524 * over-ride with command line specifications and fill in default 525 * values. 526 */ 527 528 p = params_combine(p, inparams); 529 ret = params_filldefaults(p); 530 if (ret) { 531 params_free(p); 532 return ret; 533 } 534 535 if (!params_verify(p)) { 536 warnx("params invalid"); 537 return -1; 538 } 539 540 /* 541 * loop over configuring the disk and checking to see if it 542 * verifies properly. We open and close the disk device each 543 * time, because if the user passes us the block device we 544 * need to flush the buffer cache. 545 * 546 * We only loop if one of the verification methods prompts for 547 * a password. 548 */ 549 550 for (kg = p->keygen; pflag == PFLAG_GETPASS && kg; kg = kg->next) 551 if ((kg->kg_method == KEYGEN_PKCS5_PBKDF2_SHA1) || 552 (kg->kg_method == KEYGEN_PKCS5_PBKDF2_OLD )) { 553 loop = 1; 554 break; 555 } 556 557 for (;;) { 558 fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname)); 559 if (fd == -1) 560 return -1; 561 562 if (p->key) 563 bits_free(p->key); 564 565 p->key = getkey(argv[1], p->keygen, p->keylen); 566 if (!p->key) 567 goto bail_err; 568 569 ret = configure_params(fd, cgdname, argv[1], p); 570 if (ret) 571 goto bail_err; 572 573 ret = verify(p, fd); 574 if (ret == -1) 575 goto bail_err; 576 if (!ret) 577 break; 578 579 (void)unconfigure_fd(fd); 580 (void)prog_close(fd); 581 582 if (!loop) { 583 warnx("verification failed permanently"); 584 goto bail_err; 585 } 586 587 warnx("verification failed, please reenter passphrase"); 588 } 589 590 params_free(p); 591 (void)prog_close(fd); 592 return 0; 593bail_err: 594 params_free(p); 595 (void)prog_close(fd); 596 return -1; 597} 598 599static int 600configure_stdin(struct params *p, int argc, char **argv) 601{ 602 int fd; 603 int ret; 604 char cgdname[PATH_MAX]; 605 606 if (argc < 3 || argc > 4) 607 usage(); 608 609 p->algorithm = string_fromcharstar(argv[2]); 610 if (argc > 3) { 611 size_t keylen; 612 613 if (parse_size_t(argv[3], &keylen) == -1) { 614 warn("failed to parse key length"); 615 return -1; 616 } 617 p->keylen = keylen; 618 } 619 620 ret = params_filldefaults(p); 621 if (ret) 622 return ret; 623 624 fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname)); 625 if (fd == -1) 626 return -1; 627 628 p->key = bits_fget(stdin, p->keylen); 629 if (!p->key) { 630 warnx("failed to read key from stdin"); 631 return -1; 632 } 633 634 return configure_params(fd, cgdname, argv[1], p); 635} 636 637static int 638opendisk_werror(const char *cgd, char *buf, size_t buflen) 639{ 640 int fd; 641 642 VPRINTF(3, ("opendisk_werror(%s, %s, %zu) called.\n", cgd, buf, buflen)); 643 644 /* sanity */ 645 if (!cgd || !buf) 646 return -1; 647 648 if (nflag) { 649 if (strlcpy(buf, cgd, buflen) >= buflen) 650 return -1; 651 return 0; 652 } 653 654 fd = opendisk1(cgd, O_RDWR, buf, buflen, 0, prog_open); 655 if (fd == -1) 656 warnx("can't open cgd \"%s\", \"%s\"", cgd, buf); 657 658 return fd; 659} 660 661static int 662configure_params(int fd, const char *cgd, const char *dev, struct params *p) 663{ 664 struct cgd_ioctl ci; 665 666 /* sanity */ 667 if (!cgd || !dev) 668 return -1; 669 670 (void)memset(&ci, 0x0, sizeof(ci)); 671 ci.ci_disk = dev; 672 ci.ci_alg = string_tocharstar(p->algorithm); 673 ci.ci_ivmethod = string_tocharstar(p->ivmeth); 674 ci.ci_key = bits_getbuf(p->key); 675 ci.ci_keylen = p->keylen; 676 ci.ci_blocksize = p->bsize; 677 678 VPRINTF(1, (" with alg %s keylen %zu blocksize %zu ivmethod %s\n", 679 string_tocharstar(p->algorithm), p->keylen, p->bsize, 680 string_tocharstar(p->ivmeth))); 681 VPRINTF(2, ("key: ")); 682 VERBOSE(2, bits_fprint(stdout, p->key)); 683 VPRINTF(2, ("\n")); 684 685 if (nflag) 686 return 0; 687 688 if (prog_ioctl(fd, CGDIOCSET, &ci) == -1) { 689 int saved_errno = errno; 690 warn("ioctl"); 691 return saved_errno; 692 } 693 694 return 0; 695} 696 697/* 698 * verify returns 0 for success, -1 for unrecoverable error, or 1 for retry. 699 */ 700 701#define SCANSIZE 8192 702 703static int 704verify(struct params *p, int fd) 705{ 706 707 switch (p->verify_method) { 708 case VERIFY_NONE: 709 return 0; 710 case VERIFY_DISKLABEL: 711 return verify_disklabel(fd); 712 case VERIFY_FFS: 713 return verify_ffs(fd); 714 case VERIFY_REENTER: 715 return verify_reenter(p); 716 default: 717 warnx("unimplemented verification method"); 718 return -1; 719 } 720} 721 722static int 723verify_disklabel(int fd) 724{ 725 struct disklabel l; 726 ssize_t ret; 727 char buf[SCANSIZE]; 728 729 /* 730 * we simply scan the first few blocks for a disklabel, ignoring 731 * any MBR/filecore sorts of logic. MSDOS and RiscOS can't read 732 * a cgd, anyway, so it is unlikely that there will be non-native 733 * partition information. 734 */ 735 736 ret = prog_pread(fd, buf, 8192, 0); 737 if (ret < 0) { 738 warn("can't read disklabel area"); 739 return -1; 740 } 741 742 /* now scan for the disklabel */ 743 744 return disklabel_scan(&l, buf, (size_t)ret); 745} 746 747static off_t sblock_try[] = SBLOCKSEARCH; 748 749static int 750verify_ffs(int fd) 751{ 752 size_t i; 753 754 for (i = 0; sblock_try[i] != -1; i++) { 755 union { 756 char buf[SBLOCKSIZE]; 757 struct fs fs; 758 } u; 759 ssize_t ret; 760 761 ret = prog_pread(fd, &u, sizeof(u), sblock_try[i]); 762 if (ret < 0) { 763 warn("pread"); 764 break; 765 } else if ((size_t)ret < sizeof(u)) { 766 warnx("pread: incomplete block"); 767 break; 768 } 769 switch (u.fs.fs_magic) { 770 case FS_UFS1_MAGIC: 771 case FS_UFS2_MAGIC: 772 case FS_UFS1_MAGIC_SWAPPED: 773 case FS_UFS2_MAGIC_SWAPPED: 774 return 0; 775 default: 776 continue; 777 } 778 } 779 780 return 1; /* failure */ 781} 782 783static int 784verify_reenter(struct params *p) 785{ 786 struct keygen *kg; 787 bits_t *orig_key, *key; 788 int ret; 789 790 ret = 0; 791 for (kg = p->keygen; kg && !ret; kg = kg->next) { 792 if ((kg->kg_method != KEYGEN_PKCS5_PBKDF2_SHA1) && 793 (kg->kg_method != KEYGEN_PKCS5_PBKDF2_OLD )) 794 continue; 795 796 orig_key = kg->kg_key; 797 kg->kg_key = NULL; 798 799 /* add a compat flag till the _OLD method goes away */ 800 key = getkey_pkcs5_pbkdf2("re-enter device", kg, 801 bits_len(orig_key), kg->kg_method == KEYGEN_PKCS5_PBKDF2_OLD); 802 ret = !bits_match(key, orig_key); 803 804 bits_free(key); 805 bits_free(kg->kg_key); 806 kg->kg_key = orig_key; 807 } 808 809 return ret; 810} 811 812static int 813generate(struct params *p, int argc, char **argv, const char *outfile) 814{ 815 int ret; 816 817 if (argc < 1 || argc > 2) 818 usage(); 819 820 p->algorithm = string_fromcharstar(argv[0]); 821 if (argc > 1) { 822 size_t keylen; 823 824 if (parse_size_t(argv[1], &keylen) == -1) { 825 warn("Failed to parse key length"); 826 return -1; 827 } 828 p->keylen = keylen; 829 } 830 831 ret = params_filldefaults(p); 832 if (ret) 833 return ret; 834 835 if (!p->keygen) { 836 p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2_SHA1); 837 if (!p->keygen) 838 return -1; 839 } 840 841 if (keygen_filldefaults(p->keygen, p->keylen)) { 842 warnx("Failed to generate defaults for keygen"); 843 return -1; 844 } 845 846 if (!params_verify(p)) { 847 warnx("invalid parameters generated"); 848 return -1; 849 } 850 851 return params_cput(p, outfile); 852} 853 854static int 855generate_convert(struct params *p, int argc, char **argv, const char *outfile) 856{ 857 struct params *oldp; 858 struct keygen *kg; 859 860 if (argc != 1) 861 usage(); 862 863 oldp = params_cget(*argv); 864 if (!oldp) 865 return -1; 866 867 /* for sanity, we ensure that none of the keygens are randomkey */ 868 for (kg=p->keygen; kg; kg=kg->next) 869 if ((kg->kg_method == KEYGEN_RANDOMKEY) || 870 (kg->kg_method == KEYGEN_URANDOMKEY)) { 871 warnx("can't preserve randomly generated key"); 872 goto bail; 873 } 874 for (kg=oldp->keygen; kg; kg=kg->next) 875 if ((kg->kg_method == KEYGEN_RANDOMKEY) || 876 (kg->kg_method == KEYGEN_URANDOMKEY)) { 877 warnx("can't preserve randomly generated key"); 878 goto bail; 879 } 880 881 if (!params_verify(oldp)) { 882 warnx("invalid old parameters file \"%s\"", *argv); 883 return -1; 884 } 885 886 oldp->key = getkey("old file", oldp->keygen, oldp->keylen); 887 888 /* we copy across the non-keygen info, here. */ 889 890 string_free(p->algorithm); 891 string_free(p->ivmeth); 892 893 p->algorithm = string_dup(oldp->algorithm); 894 p->ivmeth = string_dup(oldp->ivmeth); 895 p->keylen = oldp->keylen; 896 p->bsize = oldp->bsize; 897 if (p->verify_method == VERIFY_UNKNOWN) 898 p->verify_method = oldp->verify_method; 899 900 params_free(oldp); 901 902 if (!p->keygen) { 903 p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2_SHA1); 904 if (!p->keygen) 905 return -1; 906 } 907 (void)params_filldefaults(p); 908 (void)keygen_filldefaults(p->keygen, p->keylen); 909 p->key = getkey("new file", p->keygen, p->keylen); 910 911 kg = keygen_generate(KEYGEN_STOREDKEY); 912 kg->kg_key = bits_xor(p->key, oldp->key); 913 keygen_addlist(&p->keygen, kg); 914 915 if (!params_verify(p)) { 916 warnx("can't generate new parameters file"); 917 return -1; 918 } 919 920 return params_cput(p, outfile); 921bail: 922 params_free(oldp); 923 return -1; 924} 925 926static int 927/*ARGSUSED*/ 928do_all(const char *cfile, int argc, char **argv, 929 int (*conf)(int, char **, struct params *, int)) 930{ 931 FILE *f; 932 size_t len; 933 size_t lineno; 934 int my_argc; 935 int ret; 936 const char *fn; 937 char *line; 938 char **my_argv; 939 940 if (argc > 0) 941 usage(); 942 943 if (!cfile[0]) 944 fn = CGDCONFIG_CFILE; 945 else 946 fn = cfile; 947 948 f = fopen(fn, "r"); 949 if (!f) { 950 warn("could not open config file \"%s\"", fn); 951 return -1; 952 } 953 954 ret = chdir(CGDCONFIG_DIR); 955 if (ret == -1) 956 warn("could not chdir to %s", CGDCONFIG_DIR); 957 958 ret = 0; 959 lineno = 0; 960 for (;;) { 961 line = fparseln(f, &len, &lineno, "\\\\#", FPARSELN_UNESCALL); 962 if (!line) 963 break; 964 if (!*line) 965 continue; 966 967 my_argv = words(line, &my_argc); 968 ret = conf(my_argc, my_argv, NULL, CONFIG_FLAGS_FROMALL); 969 if (ret) { 970 warnx("action failed on \"%s\" line %lu", fn, 971 (u_long)lineno); 972 break; 973 } 974 words_free(my_argv, my_argc); 975 } 976 return ret; 977} 978 979static void 980eliminate_cores(void) 981{ 982 struct rlimit rlp; 983 984 rlp.rlim_cur = 0; 985 rlp.rlim_max = 0; 986 if (setrlimit(RLIMIT_CORE, &rlp) == -1) 987 err(EXIT_FAILURE, "Can't disable cores"); 988} 989