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