[BACK]Return to cgdconfig.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sbin / cgdconfig

Annotation of src/sbin/cgdconfig/cgdconfig.c, Revision 1.17

1.17    ! cbiere      1: /* $NetBSD: cgdconfig.c,v 1.16 2005/06/27 03:07:45 christos Exp $ */
1.1       elric       2:
                      3: /*-
1.5       elric       4:  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
1.1       elric       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(
1.5       elric      42: "@(#) Copyright (c) 2002, 2003\
1.1       elric      43:        The NetBSD Foundation, Inc.  All rights reserved.");
1.17    ! cbiere     44: __RCSID("$NetBSD: cgdconfig.c,v 1.16 2005/06/27 03:07:45 christos Exp $");
1.1       elric      45: #endif
                     46:
1.5       elric      47: #include <err.h>
1.1       elric      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>
1.3       elric      58: #include <sys/disklabel.h>
1.14      elric      59: #include <sys/mman.h>
1.1       elric      60: #include <sys/param.h>
1.13      elric      61: #include <sys/resource.h>
1.1       elric      62:
                     63: #include <dev/cgdvar.h>
                     64:
1.5       elric      65: #include <ufs/ffs/fs.h>
                     66:
1.1       elric      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:
1.17    ! cbiere     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: };
1.1       elric      84:
                     85: /* if nflag is set, do not configure/unconfigure the cgd's */
                     86:
                     87: int    nflag = 0;
                     88:
1.3       elric      89: static int     configure(int, char **, struct params *, int);
1.1       elric      90: static int     configure_stdin(struct params *, int argc, char **);
                     91: static int     generate(struct params *, int, char **, const char *);
1.5       elric      92: static int     generate_convert(struct params *, int, char **, const char *);
1.3       elric      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));
1.1       elric      96:
                     97: #define CONFIG_FLAGS_FROMALL   1       /* called from configure_all() */
                     98: #define CONFIG_FLAGS_FROMMAIN  2       /* called from main() */
                     99:
1.2       elric     100: static int      configure_params(int, const char *, const char *,
                    101:                                  struct params *);
1.13      elric     102: static void     eliminate_cores(void);
1.5       elric     103: static bits_t  *getkey(const char *, struct keygen *, int);
                    104: static bits_t  *getkey_storedkey(const char *, struct keygen *, int);
1.12      tv        105: static bits_t  *getkey_randomkey(const char *, struct keygen *, int, int);
1.10      dan       106: static bits_t  *getkey_pkcs5_pbkdf2(const char *, struct keygen *, int, int);
1.17    ! cbiere    107: static int      opendisk_werror(const char *, char *, size_t);
1.3       elric     108: static int      unconfigure_fd(int);
                    109: static int      verify(struct params *, int);
1.5       elric     110: static int      verify_disklabel(int);
                    111: static int      verify_ffs(int);
1.9       cb        112: static int      verify_reenter(struct params *);
1.1       elric     113:
1.3       elric     114: static void     usage(void);
1.1       elric     115:
                    116: /* Verbose Framework */
1.17    ! cbiere    117: unsigned       verbose = 0;
1.1       elric     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:
1.3       elric     126:        fprintf(stderr, "usage: %s [-nv] [-V vmeth] cgd dev [paramsfile]\n",
1.1       elric     127:            getprogname());
                    128:        fprintf(stderr, "       %s -C [-nv] [-f configfile]\n", getprogname());
                    129:        fprintf(stderr, "       %s -U [-nv] [-f configfile]\n", getprogname());
1.5       elric     130:        fprintf(stderr, "       %s -G [-nv] [-i ivmeth] [-k kgmeth] "
                    131:            "[-o outfile] paramsfile\n", getprogname());
1.1       elric     132:        fprintf(stderr, "       %s -g [-nv] [-i ivmeth] [-k kgmeth] "
1.5       elric     133:            "[-o outfile] alg [keylen]\n", getprogname());
1.1       elric     134:        fprintf(stderr, "       %s -s [-nv] [-i ivmeth] cgd dev alg "
                    135:            "[keylen]\n", getprogname());
                    136:        fprintf(stderr, "       %s -u [-nv] cgd\n", getprogname());
1.17    ! cbiere    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;
1.1       elric     167: }
                    168:
                    169: int
                    170: main(int argc, char **argv)
                    171: {
1.5       elric     172:        struct params *p;
                    173:        struct params *tp;
                    174:        struct keygen *kg;
1.17    ! cbiere    175:        enum action action = ACTION_DEFAULT;
1.1       elric     176:        int     ch;
1.17    ! cbiere    177:        const char      *cfile = NULL;
        !           178:        const char      *outfile = NULL;
1.1       elric     179:
1.15      elric     180:        setprogname(*argv);
1.13      elric     181:        eliminate_cores();
1.14      elric     182:        if (mlockall(MCL_FUTURE))
                    183:                err(EXIT_FAILURE, "Can't lock memory");
1.5       elric     184:        p = params_new();
                    185:        kg = NULL;
1.1       elric     186:
1.5       elric     187:        while ((ch = getopt(argc, argv, "CGUV:b:f:gi:k:no:usv")) != -1)
1.1       elric     188:                switch (ch) {
                    189:                case 'C':
1.17    ! cbiere    190:                        set_action(&action, ACTION_CONFIGALL);
1.1       elric     191:                        break;
1.5       elric     192:                case 'G':
1.17    ! cbiere    193:                        set_action(&action, ACTION_GENERATE_CONVERT);
1.5       elric     194:                        break;
1.1       elric     195:                case 'U':
1.17    ! cbiere    196:                        set_action(&action, ACTION_UNCONFIGALL);
1.1       elric     197:                        break;
1.3       elric     198:                case 'V':
1.5       elric     199:                        tp = params_verify_method(string_fromcharstar(optarg));
                    200:                        if (!tp)
1.3       elric     201:                                usage();
1.5       elric     202:                        p = params_combine(p, tp);
1.3       elric     203:                        break;
1.1       elric     204:                case 'b':
1.17    ! cbiere    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:                        }
1.1       elric     216:                        break;
                    217:                case 'f':
1.17    ! cbiere    218:                        if (cfile)
        !           219:                                usage();
        !           220:                        cfile = estrdup(optarg);
1.1       elric     221:                        break;
                    222:                case 'g':
1.17    ! cbiere    223:                        set_action(&action, ACTION_GENERATE);
1.1       elric     224:                        break;
                    225:                case 'i':
1.5       elric     226:                        tp = params_ivmeth(string_fromcharstar(optarg));
                    227:                        p = params_combine(p, tp);
1.1       elric     228:                        break;
                    229:                case 'k':
1.5       elric     230:                        kg = keygen_method(string_fromcharstar(optarg));
                    231:                        if (!kg)
1.1       elric     232:                                usage();
1.5       elric     233:                        keygen_addlist(&p->keygen, kg);
1.1       elric     234:                        break;
                    235:                case 'n':
                    236:                        nflag = 1;
                    237:                        break;
                    238:                case 'o':
1.17    ! cbiere    239:                        if (outfile)
        !           240:                                usage();
        !           241:                        outfile = estrdup(optarg);
1.1       elric     242:                        break;
                    243:                case 's':
1.17    ! cbiere    244:                        set_action(&action, ACTION_CONFIGSTDIN);
1.1       elric     245:                        break;
                    246:
                    247:                case 'u':
1.17    ! cbiere    248:                        set_action(&action, ACTION_UNCONFIGURE);
1.1       elric     249:                        break;
                    250:                case 'v':
                    251:                        verbose++;
                    252:                        break;
                    253:                default:
                    254:                        usage();
                    255:                        /* NOTREACHED */
                    256:                }
                    257:
                    258:        argc -= optind;
                    259:        argv += optind;
                    260:
1.17    ! cbiere    261:        if (!outfile)
        !           262:                outfile = "";
        !           263:        if (!cfile)
        !           264:                cfile = "";
        !           265:
1.1       elric     266:        /* validate the consistency of the arguments */
                    267:
                    268:        switch (action) {
1.17    ! cbiere    269:        case ACTION_DEFAULT:    /* ACTION_CONFIGURE is the default */
1.1       elric     270:        case ACTION_CONFIGURE:
1.5       elric     271:                return configure(argc, argv, p, CONFIG_FLAGS_FROMMAIN);
1.1       elric     272:        case ACTION_UNCONFIGURE:
1.3       elric     273:                return unconfigure(argc, argv, NULL, CONFIG_FLAGS_FROMMAIN);
1.1       elric     274:        case ACTION_GENERATE:
1.5       elric     275:                return generate(p, argc, argv, outfile);
                    276:        case ACTION_GENERATE_CONVERT:
                    277:                return generate_convert(p, argc, argv, outfile);
1.1       elric     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:
1.5       elric     283:                return configure_stdin(p, argc, argv);
1.1       elric     284:        }
1.17    ! cbiere    285:        errx(EXIT_FAILURE, "undefined action");
1.1       elric     286:        /* NOTREACHED */
                    287: }
                    288:
1.5       elric     289: static bits_t *
                    290: getkey(const char *dev, struct keygen *kg, int len)
1.1       elric     291: {
1.5       elric     292:        bits_t  *ret = NULL;
                    293:        bits_t  *tmp;
1.1       elric     294:
1.5       elric     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:
1.12      tv        302:                        tmp = getkey_randomkey(dev, kg, len, 1);
                    303:                        break;
                    304:                case KEYGEN_URANDOMKEY:
                    305:                        tmp = getkey_randomkey(dev, kg, len, 0);
1.5       elric     306:                        break;
1.10      dan       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);
1.5       elric     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;
1.1       elric     326:        }
1.5       elric     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:
1.17    ! cbiere    336:        (void) target;
        !           337:        (void) keylen;
1.5       elric     338:        return bits_dup(kg->kg_key);
1.1       elric     339: }
                    340:
1.5       elric     341: /*ARGSUSED*/
                    342: static bits_t *
1.12      tv        343: getkey_randomkey(const char *target, struct keygen *kg, int keylen, int hard)
1.1       elric     344: {
                    345:
1.17    ! cbiere    346:        (void) target;
        !           347:        (void) kg;
1.12      tv        348:        return bits_getrandombits(keylen, hard);
1.1       elric     349: }
                    350:
1.5       elric     351: /*ARGSUSED*/
1.10      dan       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:  */
1.5       elric     360: static bits_t *
1.10      dan       361: getkey_pkcs5_pbkdf2(const char *target, struct keygen *kg, int keylen, int compat)
1.1       elric     362: {
1.5       elric     363:        bits_t          *ret;
                    364:        char            *passp;
                    365:        char             buf[1024];
                    366:        u_int8_t        *tmp;
1.1       elric     367:
1.5       elric     368:        snprintf(buf, sizeof(buf), "%s's passphrase:", target);
1.1       elric     369:        passp = getpass(buf);
1.5       elric     370:        if (pkcs5_pbkdf2(&tmp, BITS2BYTES(keylen), passp, strlen(passp),
                    371:            bits_getbuf(kg->kg_salt), BITS2BYTES(bits_len(kg->kg_salt)),
1.10      dan       372:            kg->kg_iterations, compat)) {
1.5       elric     373:                warnx("failed to generate PKCS#5 PBKDF2 key");
                    374:                return NULL;
                    375:        }
                    376:
                    377:        ret = bits_new(tmp, keylen);
1.9       cb        378:        kg->kg_key = bits_dup(ret);
1.5       elric     379:        free(tmp);
1.1       elric     380:        return ret;
                    381: }
                    382:
1.5       elric     383: /*ARGSUSED*/
1.1       elric     384: static int
1.3       elric     385: unconfigure(int argc, char **argv, struct params *inparams, int flags)
1.1       elric     386: {
                    387:        int     fd;
                    388:        int     ret;
                    389:        char    buf[MAXPATHLEN] = "";
                    390:
1.17    ! cbiere    391:        (void) inparams;
        !           392:
1.1       elric     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) {
1.17    ! cbiere    403:                int saved_errno = errno;
        !           404:
1.5       elric     405:                warn("can't open cgd \"%s\", \"%s\"", *argv, buf);
1.1       elric     406:
                    407:                /* this isn't fatal with nflag != 0 */
                    408:                if (!nflag)
1.17    ! cbiere    409:                        return saved_errno;
1.1       elric     410:        }
                    411:
                    412:        VPRINTF(1, ("%s (%s): clearing\n", *argv, buf));
                    413:
                    414:        if (nflag)
                    415:                return 0;
                    416:
1.3       elric     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:
1.17    ! cbiere    427:        if (ioctl(fd, CGDIOCCLR, &ci) == -1) {
        !           428:                warn("ioctl");
1.3       elric     429:                return -1;
1.1       elric     430:        }
                    431:
                    432:        return 0;
                    433: }
                    434:
1.5       elric     435: /*ARGSUSED*/
1.1       elric     436: static int
1.3       elric     437: configure(int argc, char **argv, struct params *inparams, int flags)
1.1       elric     438: {
1.5       elric     439:        struct params   *p;
                    440:        int              fd;
                    441:        int              ret;
                    442:        char             cgdname[PATH_MAX];
1.1       elric     443:
1.17    ! cbiere    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 {
1.1       elric     456:                /* print usage and exit, only if called from main() */
1.5       elric     457:                if (flags == CONFIG_FLAGS_FROMMAIN) {
                    458:                        warnx("wrong number of args");
1.1       elric     459:                        usage();
1.5       elric     460:                }
1.1       elric     461:                return -1;
                    462:        }
                    463:
1.5       elric     464:        if (!p)
                    465:                return -1;
1.2       elric     466:
1.3       elric     467:        /*
1.5       elric     468:         * over-ride with command line specifications and fill in default
                    469:         * values.
1.3       elric     470:         */
                    471:
1.5       elric     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:        }
1.3       elric     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:
1.5       elric     496:                if (p->key)
                    497:                        bits_free(p->key);
                    498:
                    499:                p->key = getkey(argv[1], p->keygen, p->keylen);
                    500:                if (!p->key)
1.3       elric     501:                        goto bail_err;
                    502:
1.5       elric     503:                ret = configure_params(fd, cgdname, argv[1], p);
1.3       elric     504:                if (ret)
                    505:                        goto bail_err;
                    506:
1.5       elric     507:                ret = verify(p, fd);
1.3       elric     508:                if (ret == -1)
                    509:                        goto bail_err;
                    510:                if (!ret)
                    511:                        break;
1.2       elric     512:
1.17    ! cbiere    513:                warnx("verification failed, please reenter passphrase");
1.1       elric     514:
1.3       elric     515:                unconfigure_fd(fd);
                    516:                close(fd);
                    517:        }
1.2       elric     518:
1.5       elric     519:        params_free(p);
1.3       elric     520:        close(fd);
                    521:        return 0;
                    522: bail_err:
1.5       elric     523:        params_free(p);
1.3       elric     524:        close(fd);
                    525:        return -1;
1.1       elric     526: }
                    527:
                    528: static int
                    529: configure_stdin(struct params *p, int argc, char **argv)
                    530: {
1.2       elric     531:        int     fd;
1.1       elric     532:        int     ret;
1.2       elric     533:        char    cgdname[PATH_MAX];
1.1       elric     534:
                    535:        if (argc < 3 || argc > 4)
                    536:                usage();
                    537:
1.5       elric     538:        p->algorithm = string_fromcharstar(argv[2]);
1.17    ! cbiere    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:        }
1.1       elric     549:
                    550:        ret = params_filldefaults(p);
                    551:        if (ret)
                    552:                return ret;
                    553:
1.2       elric     554:        fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname));
                    555:        if (fd == -1)
                    556:                return -1;
                    557:
1.5       elric     558:        p->key = bits_fget(stdin, p->keylen);
                    559:        if (!p->key) {
                    560:                warnx("failed to read key from stdin");
1.1       elric     561:                return -1;
1.5       elric     562:        }
1.1       elric     563:
1.2       elric     564:        return configure_params(fd, cgdname, argv[1], p);
1.1       elric     565: }
                    566:
                    567: static int
1.17    ! cbiere    568: opendisk_werror(const char *cgd, char *buf, size_t buflen)
1.2       elric     569: {
                    570:        int     fd;
                    571:
1.5       elric     572:        VPRINTF(3, ("opendisk_werror(%s, %s, %d) called.\n", cgd, buf, buflen));
                    573:
1.2       elric     574:        /* sanity */
                    575:        if (!cgd || !buf)
                    576:                return -1;
                    577:
                    578:        if (nflag) {
1.17    ! cbiere    579:                if (strlcpy(buf, cgd, buflen) >= buflen)
        !           580:                        return -1;
1.2       elric     581:                return 0;
                    582:        }
                    583:
1.3       elric     584:        fd = opendisk(cgd, O_RDWR, buf, buflen, 0);
1.2       elric     585:        if (fd == -1)
1.5       elric     586:                warnx("can't open cgd \"%s\", \"%s\"", cgd, buf);
                    587:
1.2       elric     588:        return fd;
                    589: }
                    590:
                    591: static int
                    592: configure_params(int fd, const char *cgd, const char *dev, struct params *p)
1.1       elric     593: {
                    594:        struct cgd_ioctl ci;
                    595:
                    596:        /* sanity */
                    597:        if (!cgd || !dev)
                    598:                return -1;
                    599:
                    600:        memset(&ci, 0x0, sizeof(ci));
1.16      christos  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);
1.1       elric     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",
1.5       elric     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"));
1.1       elric     614:
                    615:        if (nflag)
                    616:                return 0;
                    617:
1.17    ! cbiere    618:        if (ioctl(fd, CGDIOCSET, &ci) == -1) {
        !           619:                int saved_errno = errno;
        !           620:                warn("ioctl");
        !           621:                return saved_errno;
1.1       elric     622:        }
                    623:
                    624:        return 0;
                    625: }
                    626:
1.3       elric     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:
1.5       elric     641:                return verify_disklabel(fd);
                    642:        case VERIFY_FFS:
                    643:                return verify_ffs(fd);
1.9       cb        644:        case VERIFY_REENTER:
                    645:                return verify_reenter(p);
1.3       elric     646:        default:
1.5       elric     647:                warnx("unimplemented verification method");
1.3       elric     648:                return -1;
                    649:        }
1.5       elric     650: }
                    651:
                    652: static int
                    653: verify_disklabel(int fd)
                    654: {
                    655:        struct  disklabel l;
1.17    ! cbiere    656:        ssize_t ret;
1.5       elric     657:        char    buf[SCANSIZE];
1.3       elric     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);
1.17    ! cbiere    667:        if (ret < 0) {
1.5       elric     668:                warn("can't read disklabel area");
1.3       elric     669:                return -1;
                    670:        }
                    671:
                    672:        /* now scan for the disklabel */
                    673:
1.17    ! cbiere    674:        return disklabel_scan(&l, buf, (size_t)ret);
1.3       elric     675: }
                    676:
1.7       fvdl      677: static off_t sblock_try[] = SBLOCKSEARCH;
                    678:
1.1       elric     679: static int
1.5       elric     680: verify_ffs(int fd)
                    681: {
1.17    ! cbiere    682:        int     i;
1.5       elric     683:
1.7       fvdl      684:        for (i = 0; sblock_try[i] != -1; i++) {
1.17    ! cbiere    685:                char    buf[SBLOCKSIZE];
        !           686:                struct  fs fs;
        !           687:                ssize_t ret;
        !           688:
1.7       fvdl      689:                ret = pread(fd, buf, sizeof(buf), sblock_try[i]);
1.17    ! cbiere    690:                if (ret < 0) {
1.7       fvdl      691:                        warn("pread");
1.17    ! cbiere    692:                        break;
        !           693:                } else if ((size_t)ret < sizeof(fs)) {
        !           694:                        warnx("pread: incomplete block");
        !           695:                        break;
1.7       fvdl      696:                }
1.17    ! cbiere    697:                memcpy(&fs, buf, sizeof(fs));
        !           698:                switch (fs.fs_magic) {
1.7       fvdl      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:                }
1.5       elric     707:        }
1.17    ! cbiere    708:
        !           709:        return 1;       /* failure */
1.9       cb        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) {
1.10      dan       721:                if ((kg->kg_method != KEYGEN_PKCS5_PBKDF2_SHA1) &&
                    722:                    (kg->kg_method != KEYGEN_PKCS5_PBKDF2_OLD ))
1.9       cb        723:                        continue;
                    724:
                    725:                orig_key = kg->kg_key;
                    726:                kg->kg_key = NULL;
                    727:
1.10      dan       728:                /* add a compat flag till the _OLD method goes away */
1.9       cb        729:                key = getkey_pkcs5_pbkdf2("re-enter device", kg,
1.10      dan       730:                        bits_len(orig_key), kg->kg_method == KEYGEN_PKCS5_PBKDF2_OLD);
1.9       cb        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;
1.5       elric     739: }
                    740:
                    741: static int
1.1       elric     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:
1.5       elric     749:        p->algorithm = string_fromcharstar(argv[0]);
1.17    ! cbiere    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:        }
1.5       elric     760:
                    761:        ret = params_filldefaults(p);
1.1       elric     762:        if (ret)
                    763:                return ret;
1.5       elric     764:
                    765:        if (!p->keygen) {
1.10      dan       766:                p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2_SHA1);
1.5       elric     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;
1.1       elric     808:        }
                    809:
1.5       elric     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);
1.1       elric     825:
1.5       elric     826:        if (!p->keygen) {
1.10      dan       827:                p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2_SHA1);
1.5       elric     828:                if (!p->keygen)
1.1       elric     829:                        return -1;
1.5       elric     830:        }
                    831:        params_filldefaults(p);
1.6       elric     832:        keygen_filldefaults(p->keygen, p->keylen);
1.5       elric     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;
1.1       elric     842:        }
                    843:
1.5       elric     844:        return params_cput(p, outfile);
                    845: bail:
                    846:        params_free(oldp);
                    847:        return -1;
1.1       elric     848: }
                    849:
                    850: static int
                    851: do_all(const char *cfile, int argc, char **argv,
1.3       elric     852:        int (*conf)(int, char **, struct params *, int))
1.1       elric     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:
1.17    ! cbiere    863:        (void) argv;
1.1       elric     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) {
1.5       elric     874:                warn("could not open config file \"%s\"", fn);
1.1       elric     875:                return -1;
                    876:        }
                    877:
1.5       elric     878:        ret = chdir(CGDCONFIG_DIR);
                    879:        if (ret == -1)
                    880:                warn("could not chdir to %s", CGDCONFIG_DIR);
                    881:
1.1       elric     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);
1.3       elric     892:                ret = conf(my_argc, my_argv, NULL, CONFIG_FLAGS_FROMALL);
1.1       elric     893:                if (ret) {
1.5       elric     894:                        warnx("action failed on \"%s\" line %lu", fn,
1.1       elric     895:                            (u_long)lineno);
                    896:                        break;
                    897:                }
                    898:                words_free(my_argv, my_argc);
                    899:        }
                    900:        return ret;
                    901: }
1.13      elric     902:
                    903: static void
                    904: eliminate_cores(void)
                    905: {
                    906:        struct rlimit   rlp;
                    907:
                    908:        rlp.rlim_cur = 0;
                    909:        rlp.rlim_max = 0;
1.17    ! cbiere    910:        if (setrlimit(RLIMIT_CORE, &rlp) == -1)
1.13      elric     911:                err(EXIT_FAILURE, "Can't disable cores");
                    912: }

CVSweb <webmaster@jp.NetBSD.org>