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