cgdconfig.c revision 1.18 1 /* $NetBSD: cgdconfig.c,v 1.18 2007/02/06 14:04:01 cbiere 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.18 2007/02/06 14:04:01 cbiere 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 *, int);
104 static bits_t *getkey_storedkey(const char *, struct keygen *, int);
105 static bits_t *getkey_randomkey(const char *, struct keygen *, int, int);
106 static bits_t *getkey_pkcs5_pbkdf2(const char *, struct keygen *, int, 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) printf y
121
122 static void
123 usage(void)
124 {
125
126 fprintf(stderr, "usage: %s [-nv] [-V vmeth] cgd dev [paramsfile]\n",
127 getprogname());
128 fprintf(stderr, " %s -C [-nv] [-f configfile]\n", getprogname());
129 fprintf(stderr, " %s -U [-nv] [-f configfile]\n", getprogname());
130 fprintf(stderr, " %s -G [-nv] [-i ivmeth] [-k kgmeth] "
131 "[-o outfile] paramsfile\n", getprogname());
132 fprintf(stderr, " %s -g [-nv] [-i ivmeth] [-k kgmeth] "
133 "[-o outfile] alg [keylen]\n", getprogname());
134 fprintf(stderr, " %s -s [-nv] [-i ivmeth] cgd dev alg "
135 "[keylen]\n", getprogname());
136 fprintf(stderr, " %s -u [-nv] cgd\n", getprogname());
137 exit(EXIT_FAILURE);
138 }
139
140 static int
141 parse_int(const char *s)
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 return v;
159 }
160
161 static void
162 set_action(enum action *action, enum action value)
163 {
164 if (*action != ACTION_DEFAULT)
165 usage();
166 *action = value;
167 }
168
169 int
170 main(int argc, char **argv)
171 {
172 struct params *p;
173 struct params *tp;
174 struct keygen *kg;
175 enum action action = ACTION_DEFAULT;
176 int ch;
177 const char *cfile = NULL;
178 const char *outfile = NULL;
179
180 setprogname(*argv);
181 eliminate_cores();
182 if (mlockall(MCL_FUTURE))
183 err(EXIT_FAILURE, "Can't lock memory");
184 p = params_new();
185 kg = NULL;
186
187 while ((ch = getopt(argc, argv, "CGUV:b:f:gi:k:no:usv")) != -1)
188 switch (ch) {
189 case 'C':
190 set_action(&action, ACTION_CONFIGALL);
191 break;
192 case 'G':
193 set_action(&action, ACTION_GENERATE_CONVERT);
194 break;
195 case 'U':
196 set_action(&action, ACTION_UNCONFIGALL);
197 break;
198 case 'V':
199 tp = params_verify_method(string_fromcharstar(optarg));
200 if (!tp)
201 usage();
202 p = params_combine(p, tp);
203 break;
204 case 'b':
205 {
206 int size;
207
208 size = parse_int(optarg);
209 if (size == -1 && errno)
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 }
285 errx(EXIT_FAILURE, "undefined action");
286 /* NOTREACHED */
287 }
288
289 static bits_t *
290 getkey(const char *dev, struct keygen *kg, int len)
291 {
292 bits_t *ret = NULL;
293 bits_t *tmp;
294
295 VPRINTF(3, ("getkey(\"%s\", %p, %d) called\n", dev, kg, len));
296 for (; kg; kg=kg->next) {
297 switch (kg->kg_method) {
298 case KEYGEN_STOREDKEY:
299 tmp = getkey_storedkey(dev, kg, len);
300 break;
301 case KEYGEN_RANDOMKEY:
302 tmp = getkey_randomkey(dev, kg, len, 1);
303 break;
304 case KEYGEN_URANDOMKEY:
305 tmp = getkey_randomkey(dev, kg, len, 0);
306 break;
307 case KEYGEN_PKCS5_PBKDF2_SHA1:
308 tmp = getkey_pkcs5_pbkdf2(dev, kg, len, 0);
309 break;
310 /* provide backwards compatibility for old config files */
311 case KEYGEN_PKCS5_PBKDF2_OLD:
312 tmp = getkey_pkcs5_pbkdf2(dev, kg, len, 1);
313 break;
314 default:
315 warnx("unrecognised keygen method %d in getkey()",
316 kg->kg_method);
317 if (ret)
318 bits_free(ret);
319 return NULL;
320 }
321
322 if (ret)
323 ret = bits_xor_d(tmp, ret);
324 else
325 ret = tmp;
326 }
327
328 return ret;
329 }
330
331 /*ARGSUSED*/
332 static bits_t *
333 getkey_storedkey(const char *target, struct keygen *kg, int keylen)
334 {
335
336 (void) target;
337 (void) keylen;
338 return bits_dup(kg->kg_key);
339 }
340
341 /*ARGSUSED*/
342 static bits_t *
343 getkey_randomkey(const char *target, struct keygen *kg, int keylen, int hard)
344 {
345
346 (void) target;
347 (void) kg;
348 return bits_getrandombits(keylen, hard);
349 }
350
351 /*ARGSUSED*/
352 /*
353 * XXX take, and pass through, a compat flag that indicates whether we
354 * provide backwards compatibility with a previous bug. The previous
355 * behaviour is indicated by the keygen method pkcs5_pbkdf2, and a
356 * non-zero compat flag. The new default, and correct keygen method is
357 * called pcks5_pbkdf2/sha1. When the old method is removed, so will
358 * be the compat argument.
359 */
360 static bits_t *
361 getkey_pkcs5_pbkdf2(const char *target, struct keygen *kg, int keylen, int compat)
362 {
363 bits_t *ret;
364 char *passp;
365 char buf[1024];
366 u_int8_t *tmp;
367
368 snprintf(buf, sizeof(buf), "%s's passphrase:", target);
369 passp = getpass(buf);
370 if (pkcs5_pbkdf2(&tmp, BITS2BYTES(keylen), passp, strlen(passp),
371 bits_getbuf(kg->kg_salt), BITS2BYTES(bits_len(kg->kg_salt)),
372 kg->kg_iterations, compat)) {
373 warnx("failed to generate PKCS#5 PBKDF2 key");
374 return NULL;
375 }
376
377 ret = bits_new(tmp, keylen);
378 kg->kg_key = bits_dup(ret);
379 free(tmp);
380 return ret;
381 }
382
383 /*ARGSUSED*/
384 static int
385 unconfigure(int argc, char **argv, struct params *inparams, int flags)
386 {
387 int fd;
388 int ret;
389 char buf[MAXPATHLEN] = "";
390
391 (void) inparams;
392
393 /* only complain about additional arguments, if called from main() */
394 if (flags == CONFIG_FLAGS_FROMMAIN && argc != 1)
395 usage();
396
397 /* if called from do_all(), then ensure that 2 or 3 args exist */
398 if (flags == CONFIG_FLAGS_FROMALL && (argc < 2 || argc > 3))
399 return -1;
400
401 fd = opendisk(*argv, O_RDWR, buf, sizeof(buf), 1);
402 if (fd == -1) {
403 int saved_errno = errno;
404
405 warn("can't open cgd \"%s\", \"%s\"", *argv, buf);
406
407 /* this isn't fatal with nflag != 0 */
408 if (!nflag)
409 return saved_errno;
410 }
411
412 VPRINTF(1, ("%s (%s): clearing\n", *argv, buf));
413
414 if (nflag)
415 return 0;
416
417 ret = unconfigure_fd(fd);
418 close(fd);
419 return ret;
420 }
421
422 static int
423 unconfigure_fd(int fd)
424 {
425 struct cgd_ioctl ci;
426
427 if (ioctl(fd, CGDIOCCLR, &ci) == -1) {
428 warn("ioctl");
429 return -1;
430 }
431
432 return 0;
433 }
434
435 /*ARGSUSED*/
436 static int
437 configure(int argc, char **argv, struct params *inparams, int flags)
438 {
439 struct params *p;
440 int fd;
441 int ret;
442 char cgdname[PATH_MAX];
443
444 if (argc == 2) {
445 char *pfile;
446
447 if (asprintf(&pfile, "%s/%s",
448 CGDCONFIG_DIR, basename(argv[1])) == -1)
449 return -1;
450
451 p = params_cget(pfile);
452 free(pfile);
453 } else if (argc == 3) {
454 p = params_cget(argv[2]);
455 } else {
456 /* print usage and exit, only if called from main() */
457 if (flags == CONFIG_FLAGS_FROMMAIN) {
458 warnx("wrong number of args");
459 usage();
460 }
461 return -1;
462 }
463
464 if (!p)
465 return -1;
466
467 /*
468 * over-ride with command line specifications and fill in default
469 * values.
470 */
471
472 p = params_combine(p, inparams);
473 ret = params_filldefaults(p);
474 if (ret) {
475 params_free(p);
476 return ret;
477 }
478
479 if (!params_verify(p)) {
480 warnx("params invalid");
481 return -1;
482 }
483
484 /*
485 * loop over configuring the disk and checking to see if it
486 * verifies properly. We open and close the disk device each
487 * time, because if the user passes us the block device we
488 * need to flush the buffer cache.
489 */
490
491 for (;;) {
492 fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname));
493 if (fd == -1)
494 return -1;
495
496 if (p->key)
497 bits_free(p->key);
498
499 p->key = getkey(argv[1], p->keygen, p->keylen);
500 if (!p->key)
501 goto bail_err;
502
503 ret = configure_params(fd, cgdname, argv[1], p);
504 if (ret)
505 goto bail_err;
506
507 ret = verify(p, fd);
508 if (ret == -1)
509 goto bail_err;
510 if (!ret)
511 break;
512
513 warnx("verification failed, please reenter passphrase");
514
515 unconfigure_fd(fd);
516 close(fd);
517 }
518
519 params_free(p);
520 close(fd);
521 return 0;
522 bail_err:
523 params_free(p);
524 close(fd);
525 return -1;
526 }
527
528 static int
529 configure_stdin(struct params *p, int argc, char **argv)
530 {
531 int fd;
532 int ret;
533 char cgdname[PATH_MAX];
534
535 if (argc < 3 || argc > 4)
536 usage();
537
538 p->algorithm = string_fromcharstar(argv[2]);
539 if (argc > 3) {
540 int keylen;
541
542 keylen = parse_int(argv[3]);
543 if (keylen == -1 && errno) {
544 warn("failed to parse key length");
545 return -1;
546 }
547 p->keylen = keylen;
548 }
549
550 ret = params_filldefaults(p);
551 if (ret)
552 return ret;
553
554 fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname));
555 if (fd == -1)
556 return -1;
557
558 p->key = bits_fget(stdin, p->keylen);
559 if (!p->key) {
560 warnx("failed to read key from stdin");
561 return -1;
562 }
563
564 return configure_params(fd, cgdname, argv[1], p);
565 }
566
567 static int
568 opendisk_werror(const char *cgd, char *buf, size_t buflen)
569 {
570 int fd;
571
572 VPRINTF(3, ("opendisk_werror(%s, %s, %zu) called.\n", cgd, buf, buflen));
573
574 /* sanity */
575 if (!cgd || !buf)
576 return -1;
577
578 if (nflag) {
579 if (strlcpy(buf, cgd, buflen) >= buflen)
580 return -1;
581 return 0;
582 }
583
584 fd = opendisk(cgd, O_RDWR, buf, buflen, 0);
585 if (fd == -1)
586 warnx("can't open cgd \"%s\", \"%s\"", cgd, buf);
587
588 return fd;
589 }
590
591 static int
592 configure_params(int fd, const char *cgd, const char *dev, struct params *p)
593 {
594 struct cgd_ioctl ci;
595
596 /* sanity */
597 if (!cgd || !dev)
598 return -1;
599
600 memset(&ci, 0x0, sizeof(ci));
601 ci.ci_disk = dev;
602 ci.ci_alg = string_tocharstar(p->algorithm);
603 ci.ci_ivmethod = string_tocharstar(p->ivmeth);
604 ci.ci_key = bits_getbuf(p->key);
605 ci.ci_keylen = p->keylen;
606 ci.ci_blocksize = p->bsize;
607
608 VPRINTF(1, (" with alg %s keylen %d blocksize %d ivmethod %s\n",
609 string_tocharstar(p->algorithm), p->keylen, p->bsize,
610 string_tocharstar(p->ivmeth)));
611 VPRINTF(2, ("key: "));
612 VERBOSE(2, bits_fprint(stdout, p->key));
613 VPRINTF(2, ("\n"));
614
615 if (nflag)
616 return 0;
617
618 if (ioctl(fd, CGDIOCSET, &ci) == -1) {
619 int saved_errno = errno;
620 warn("ioctl");
621 return saved_errno;
622 }
623
624 return 0;
625 }
626
627 /*
628 * verify returns 0 for success, -1 for unrecoverable error, or 1 for retry.
629 */
630
631 #define SCANSIZE 8192
632
633 static int
634 verify(struct params *p, int fd)
635 {
636
637 switch (p->verify_method) {
638 case VERIFY_NONE:
639 return 0;
640 case VERIFY_DISKLABEL:
641 return verify_disklabel(fd);
642 case VERIFY_FFS:
643 return verify_ffs(fd);
644 case VERIFY_REENTER:
645 return verify_reenter(p);
646 default:
647 warnx("unimplemented verification method");
648 return -1;
649 }
650 }
651
652 static int
653 verify_disklabel(int fd)
654 {
655 struct disklabel l;
656 ssize_t ret;
657 char buf[SCANSIZE];
658
659 /*
660 * we simply scan the first few blocks for a disklabel, ignoring
661 * any MBR/filecore sorts of logic. MSDOS and RiscOS can't read
662 * a cgd, anyway, so it is unlikely that there will be non-native
663 * partition information.
664 */
665
666 ret = pread(fd, buf, 8192, 0);
667 if (ret < 0) {
668 warn("can't read disklabel area");
669 return -1;
670 }
671
672 /* now scan for the disklabel */
673
674 return disklabel_scan(&l, buf, (size_t)ret);
675 }
676
677 static off_t sblock_try[] = SBLOCKSEARCH;
678
679 static int
680 verify_ffs(int fd)
681 {
682 int i;
683
684 for (i = 0; sblock_try[i] != -1; i++) {
685 char buf[SBLOCKSIZE];
686 struct fs fs;
687 ssize_t ret;
688
689 ret = pread(fd, buf, sizeof(buf), sblock_try[i]);
690 if (ret < 0) {
691 warn("pread");
692 break;
693 } else if ((size_t)ret < sizeof(fs)) {
694 warnx("pread: incomplete block");
695 break;
696 }
697 memcpy(&fs, buf, sizeof(fs));
698 switch (fs.fs_magic) {
699 case FS_UFS1_MAGIC:
700 case FS_UFS2_MAGIC:
701 case FS_UFS1_MAGIC_SWAPPED:
702 case FS_UFS2_MAGIC_SWAPPED:
703 return 0;
704 default:
705 continue;
706 }
707 }
708
709 return 1; /* failure */
710 }
711
712 static int
713 verify_reenter(struct params *p)
714 {
715 struct keygen *kg;
716 bits_t *orig_key, *key;
717 int ret;
718
719 ret = 0;
720 for (kg = p->keygen; kg && !ret; kg = kg->next) {
721 if ((kg->kg_method != KEYGEN_PKCS5_PBKDF2_SHA1) &&
722 (kg->kg_method != KEYGEN_PKCS5_PBKDF2_OLD ))
723 continue;
724
725 orig_key = kg->kg_key;
726 kg->kg_key = NULL;
727
728 /* add a compat flag till the _OLD method goes away */
729 key = getkey_pkcs5_pbkdf2("re-enter device", kg,
730 bits_len(orig_key), kg->kg_method == KEYGEN_PKCS5_PBKDF2_OLD);
731 ret = !bits_match(key, orig_key);
732
733 bits_free(key);
734 bits_free(kg->kg_key);
735 kg->kg_key = orig_key;
736 }
737
738 return ret;
739 }
740
741 static int
742 generate(struct params *p, int argc, char **argv, const char *outfile)
743 {
744 int ret;
745
746 if (argc < 1 || argc > 2)
747 usage();
748
749 p->algorithm = string_fromcharstar(argv[0]);
750 if (argc > 1) {
751 int keylen;
752
753 keylen = parse_int(argv[1]);
754 if (keylen == -1 && errno) {
755 warn("Failed to parse key length");
756 return -1;
757 }
758 p->keylen = keylen;
759 }
760
761 ret = params_filldefaults(p);
762 if (ret)
763 return ret;
764
765 if (!p->keygen) {
766 p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2_SHA1);
767 if (!p->keygen)
768 return -1;
769 }
770
771 if (keygen_filldefaults(p->keygen, p->keylen)) {
772 warnx("Failed to generate defaults for keygen");
773 return -1;
774 }
775
776 if (!params_verify(p)) {
777 warnx("invalid parameters generated");
778 return -1;
779 }
780
781 return params_cput(p, outfile);
782 }
783
784 static int
785 generate_convert(struct params *p, int argc, char **argv, const char *outfile)
786 {
787 struct params *oldp;
788 struct keygen *kg;
789
790 if (argc != 1)
791 usage();
792
793 oldp = params_cget(*argv);
794 if (!oldp)
795 return -1;
796
797 /* for sanity, we ensure that none of the keygens are randomkey */
798 for (kg=p->keygen; kg; kg=kg->next)
799 if (kg->kg_method == KEYGEN_RANDOMKEY)
800 goto bail;
801 for (kg=oldp->keygen; kg; kg=kg->next)
802 if (kg->kg_method == KEYGEN_RANDOMKEY)
803 goto bail;
804
805 if (!params_verify(oldp)) {
806 warnx("invalid old parameters file \"%s\"", *argv);
807 return -1;
808 }
809
810 oldp->key = getkey("old file", oldp->keygen, oldp->keylen);
811
812 /* we copy across the non-keygen info, here. */
813
814 string_free(p->algorithm);
815 string_free(p->ivmeth);
816
817 p->algorithm = string_dup(oldp->algorithm);
818 p->ivmeth = string_dup(oldp->ivmeth);
819 p->keylen = oldp->keylen;
820 p->bsize = oldp->bsize;
821 if (p->verify_method == VERIFY_UNKNOWN)
822 p->verify_method = oldp->verify_method;
823
824 params_free(oldp);
825
826 if (!p->keygen) {
827 p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2_SHA1);
828 if (!p->keygen)
829 return -1;
830 }
831 params_filldefaults(p);
832 keygen_filldefaults(p->keygen, p->keylen);
833 p->key = getkey("new file", p->keygen, p->keylen);
834
835 kg = keygen_generate(KEYGEN_STOREDKEY);
836 kg->kg_key = bits_xor(p->key, oldp->key);
837 keygen_addlist(&p->keygen, kg);
838
839 if (!params_verify(p)) {
840 warnx("can't generate new parameters file");
841 return -1;
842 }
843
844 return params_cput(p, outfile);
845 bail:
846 params_free(oldp);
847 return -1;
848 }
849
850 static int
851 do_all(const char *cfile, int argc, char **argv,
852 int (*conf)(int, char **, struct params *, int))
853 {
854 FILE *f;
855 size_t len;
856 size_t lineno;
857 int my_argc;
858 int ret;
859 const char *fn;
860 char *line;
861 char **my_argv;
862
863 (void) argv;
864 if (argc > 0)
865 usage();
866
867 if (!cfile[0])
868 fn = CGDCONFIG_CFILE;
869 else
870 fn = cfile;
871
872 f = fopen(fn, "r");
873 if (!f) {
874 warn("could not open config file \"%s\"", fn);
875 return -1;
876 }
877
878 ret = chdir(CGDCONFIG_DIR);
879 if (ret == -1)
880 warn("could not chdir to %s", CGDCONFIG_DIR);
881
882 ret = 0;
883 lineno = 0;
884 for (;;) {
885 line = fparseln(f, &len, &lineno, "\\\\#", FPARSELN_UNESCALL);
886 if (!line)
887 break;
888 if (!*line)
889 continue;
890
891 my_argv = words(line, &my_argc);
892 ret = conf(my_argc, my_argv, NULL, CONFIG_FLAGS_FROMALL);
893 if (ret) {
894 warnx("action failed on \"%s\" line %lu", fn,
895 (u_long)lineno);
896 break;
897 }
898 words_free(my_argv, my_argc);
899 }
900 return ret;
901 }
902
903 static void
904 eliminate_cores(void)
905 {
906 struct rlimit rlp;
907
908 rlp.rlim_cur = 0;
909 rlp.rlim_max = 0;
910 if (setrlimit(RLIMIT_CORE, &rlp) == -1)
911 err(EXIT_FAILURE, "Can't disable cores");
912 }
913