[BACK]Return to dst_parse.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / mpl / bind / dist / lib / dns

Annotation of src/external/mpl/bind/dist/lib/dns/dst_parse.c, Revision 1.4.2.2

1.4.2.2 ! christos    1: /*     $NetBSD: dst_parse.c,v 1.4 2019/02/24 20:01:30 christos Exp $   */
        !             2:
        !             3: /*
        !             4:  * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
        !             5:  *
        !             6:  * This Source Code Form is subject to the terms of the Mozilla Public
        !             7:  * License, v. 2.0. If a copy of the MPL was not distributed with this
        !             8:  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
        !             9:  *
        !            10:  * See the COPYRIGHT file distributed with this work for additional
        !            11:  * information regarding copyright ownership.
        !            12:  *
        !            13:  * Portions Copyright (C) Network Associates, Inc.
        !            14:  *
        !            15:  * Permission to use, copy, modify, and/or distribute this software for any
        !            16:  * purpose with or without fee is hereby granted, provided that the above
        !            17:  * copyright notice and this permission notice appear in all copies.
        !            18:  *
        !            19:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
        !            20:  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
        !            21:  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
        !            22:  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            23:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            24:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
        !            25:  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            26:  */
        !            27:
        !            28: #include <config.h>
        !            29:
        !            30: #include <inttypes.h>
        !            31: #include <stdbool.h>
        !            32:
        !            33: #include <isc/base64.h>
        !            34: #include <isc/dir.h>
        !            35: #include <isc/file.h>
        !            36: #include <isc/fsaccess.h>
        !            37: #include <isc/lex.h>
        !            38: #include <isc/mem.h>
        !            39: #include <isc/print.h>
        !            40: #include <isc/stdtime.h>
        !            41: #include <isc/string.h>
        !            42: #include <isc/util.h>
        !            43:
        !            44: #include <pk11/site.h>
        !            45:
        !            46: #include <dns/time.h>
        !            47: #include <dns/log.h>
        !            48:
        !            49: #include "dst_internal.h"
        !            50: #include "dst_parse.h"
        !            51: #include "dst/result.h"
        !            52:
        !            53: #define DST_AS_STR(t) ((t).value.as_textregion.base)
        !            54:
        !            55: #define PRIVATE_KEY_STR "Private-key-format:"
        !            56: #define ALGORITHM_STR "Algorithm:"
        !            57:
        !            58: #define TIMING_NTAGS (DST_MAX_TIMES + 1)
        !            59: static const char *timetags[TIMING_NTAGS] = {
        !            60:        "Created:",
        !            61:        "Publish:",
        !            62:        "Activate:",
        !            63:        "Revoke:",
        !            64:        "Inactive:",
        !            65:        "Delete:",
        !            66:        "DSPublish:",
        !            67:        "SyncPublish:",
        !            68:        "SyncDelete:"
        !            69: };
        !            70:
        !            71: #define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1)
        !            72: static const char *numerictags[NUMERIC_NTAGS] = {
        !            73:        "Predecessor:",
        !            74:        "Successor:",
        !            75:        "MaxTTL:",
        !            76:        "RollPeriod:"
        !            77: };
        !            78:
        !            79: struct parse_map {
        !            80:        const int value;
        !            81:        const char *tag;
        !            82: };
        !            83:
        !            84: static struct parse_map map[] = {
        !            85:        {TAG_RSA_MODULUS, "Modulus:"},
        !            86:        {TAG_RSA_PUBLICEXPONENT, "PublicExponent:"},
        !            87:        {TAG_RSA_PRIVATEEXPONENT, "PrivateExponent:"},
        !            88:        {TAG_RSA_PRIME1, "Prime1:"},
        !            89:        {TAG_RSA_PRIME2, "Prime2:"},
        !            90:        {TAG_RSA_EXPONENT1, "Exponent1:"},
        !            91:        {TAG_RSA_EXPONENT2, "Exponent2:"},
        !            92:        {TAG_RSA_COEFFICIENT, "Coefficient:"},
        !            93:        {TAG_RSA_ENGINE, "Engine:" },
        !            94:        {TAG_RSA_LABEL, "Label:" },
        !            95:
        !            96:        {TAG_DH_PRIME, "Prime(p):"},
        !            97:        {TAG_DH_GENERATOR, "Generator(g):"},
        !            98:        {TAG_DH_PRIVATE, "Private_value(x):"},
        !            99:        {TAG_DH_PUBLIC, "Public_value(y):"},
        !           100:
        !           101:        {TAG_ECDSA_PRIVATEKEY, "PrivateKey:"},
        !           102:        {TAG_ECDSA_ENGINE, "Engine:" },
        !           103:        {TAG_ECDSA_LABEL, "Label:" },
        !           104:
        !           105:        {TAG_EDDSA_PRIVATEKEY, "PrivateKey:"},
        !           106:        {TAG_EDDSA_ENGINE, "Engine:" },
        !           107:        {TAG_EDDSA_LABEL, "Label:" },
        !           108:
        !           109:        {TAG_HMACMD5_KEY, "Key:"},
        !           110:        {TAG_HMACMD5_BITS, "Bits:"},
        !           111:
        !           112:        {TAG_HMACSHA1_KEY, "Key:"},
        !           113:        {TAG_HMACSHA1_BITS, "Bits:"},
        !           114:
        !           115:        {TAG_HMACSHA224_KEY, "Key:"},
        !           116:        {TAG_HMACSHA224_BITS, "Bits:"},
        !           117:
        !           118:        {TAG_HMACSHA256_KEY, "Key:"},
        !           119:        {TAG_HMACSHA256_BITS, "Bits:"},
        !           120:
        !           121:        {TAG_HMACSHA384_KEY, "Key:"},
        !           122:        {TAG_HMACSHA384_BITS, "Bits:"},
        !           123:
        !           124:        {TAG_HMACSHA512_KEY, "Key:"},
        !           125:        {TAG_HMACSHA512_BITS, "Bits:"},
        !           126:
        !           127:        {0, NULL}
        !           128: };
        !           129:
        !           130: static int
        !           131: find_value(const char *s, const unsigned int alg) {
        !           132:        int i;
        !           133:
        !           134:        for (i = 0; map[i].tag != NULL; i++) {
        !           135:                if (strcasecmp(s, map[i].tag) == 0 &&
        !           136:                    (TAG_ALG(map[i].value) == alg))
        !           137:                        return (map[i].value);
        !           138:        }
        !           139:        return (-1);
        !           140: }
        !           141:
        !           142: static const char *
        !           143: find_tag(const int value) {
        !           144:        int i;
        !           145:
        !           146:        for (i = 0; ; i++) {
        !           147:                if (map[i].tag == NULL)
        !           148:                        return (NULL);
        !           149:                else if (value == map[i].value)
        !           150:                        return (map[i].tag);
        !           151:        }
        !           152: }
        !           153:
        !           154: static int
        !           155: find_metadata(const char *s, const char *tags[], int ntags) {
        !           156:        int i;
        !           157:
        !           158:        for (i = 0; i < ntags; i++) {
        !           159:                if (tags[i] != NULL && strcasecmp(s, tags[i]) == 0)
        !           160:                        return (i);
        !           161:        }
        !           162:
        !           163:        return (-1);
        !           164: }
        !           165:
        !           166: static int
        !           167: find_timedata(const char *s) {
        !           168:        return (find_metadata(s, timetags, TIMING_NTAGS));
        !           169: }
        !           170:
        !           171: static int
        !           172: find_numericdata(const char *s) {
        !           173:        return (find_metadata(s, numerictags, NUMERIC_NTAGS));
        !           174: }
        !           175:
        !           176: static int
        !           177: check_rsa(const dst_private_t *priv, bool external) {
        !           178:        int i, j;
        !           179:        bool have[RSA_NTAGS];
        !           180:        bool ok;
        !           181:        unsigned int mask;
        !           182:
        !           183:        if (external)
        !           184:                return ((priv->nelements == 0) ? 0 : -1);
        !           185:
        !           186:        for (i = 0; i < RSA_NTAGS; i++)
        !           187:                have[i] = false;
        !           188:
        !           189:        for (j = 0; j < priv->nelements; j++) {
        !           190:                for (i = 0; i < RSA_NTAGS; i++)
        !           191:                        if (priv->elements[j].tag == TAG(DST_ALG_RSA, i))
        !           192:                                break;
        !           193:                if (i == RSA_NTAGS)
        !           194:                        return (-1);
        !           195:                have[i] = true;
        !           196:        }
        !           197:
        !           198:        mask = (1ULL << TAG_SHIFT) - 1;
        !           199:
        !           200:        if (have[TAG_RSA_ENGINE & mask])
        !           201:                ok = have[TAG_RSA_MODULUS & mask] &&
        !           202:                     have[TAG_RSA_PUBLICEXPONENT & mask] &&
        !           203:                     have[TAG_RSA_LABEL & mask];
        !           204:        else
        !           205:                ok = have[TAG_RSA_MODULUS & mask] &&
        !           206:                     have[TAG_RSA_PUBLICEXPONENT & mask] &&
        !           207:                     have[TAG_RSA_PRIVATEEXPONENT & mask] &&
        !           208:                     have[TAG_RSA_PRIME1 & mask] &&
        !           209:                     have[TAG_RSA_PRIME2 & mask] &&
        !           210:                     have[TAG_RSA_EXPONENT1 & mask] &&
        !           211:                     have[TAG_RSA_EXPONENT2 & mask] &&
        !           212:                     have[TAG_RSA_COEFFICIENT & mask];
        !           213:        return (ok ? 0 : -1 );
        !           214: }
        !           215:
        !           216: static int
        !           217: check_dh(const dst_private_t *priv) {
        !           218:        int i, j;
        !           219:        if (priv->nelements != DH_NTAGS)
        !           220:                return (-1);
        !           221:        for (i = 0; i < DH_NTAGS; i++) {
        !           222:                for (j = 0; j < priv->nelements; j++)
        !           223:                        if (priv->elements[j].tag == TAG(DST_ALG_DH, i))
        !           224:                                break;
        !           225:                if (j == priv->nelements)
        !           226:                        return (-1);
        !           227:        }
        !           228:        return (0);
        !           229: }
        !           230:
        !           231: static int
        !           232: check_ecdsa(const dst_private_t *priv, bool external) {
        !           233:        int i, j;
        !           234:        bool have[ECDSA_NTAGS];
        !           235:        bool ok;
        !           236:        unsigned int mask;
        !           237:
        !           238:        if (external)
        !           239:                return ((priv->nelements == 0) ? 0 : -1);
        !           240:
        !           241:        for (i = 0; i < ECDSA_NTAGS; i++)
        !           242:                have[i] = false;
        !           243:        for (j = 0; j < priv->nelements; j++) {
        !           244:                for (i = 0; i < ECDSA_NTAGS; i++)
        !           245:                        if (priv->elements[j].tag == TAG(DST_ALG_ECDSA256, i))
        !           246:                                break;
        !           247:                if (i == ECDSA_NTAGS)
        !           248:                        return (-1);
        !           249:                have[i] = true;
        !           250:        }
        !           251:
        !           252:        mask = (1ULL << TAG_SHIFT) - 1;
        !           253:
        !           254:        if (have[TAG_ECDSA_ENGINE & mask])
        !           255:                ok = have[TAG_ECDSA_LABEL & mask];
        !           256:        else
        !           257:                ok = have[TAG_ECDSA_PRIVATEKEY & mask];
        !           258:        return (ok ? 0 : -1 );
        !           259: }
        !           260:
        !           261: static int
        !           262: check_eddsa(const dst_private_t *priv, bool external) {
        !           263:        int i, j;
        !           264:        bool have[EDDSA_NTAGS];
        !           265:        bool ok;
        !           266:        unsigned int mask;
        !           267:
        !           268:        if (external)
        !           269:                return ((priv->nelements == 0) ? 0 : -1);
        !           270:
        !           271:        for (i = 0; i < EDDSA_NTAGS; i++)
        !           272:                have[i] = false;
        !           273:        for (j = 0; j < priv->nelements; j++) {
        !           274:                for (i = 0; i < EDDSA_NTAGS; i++)
        !           275:                        if (priv->elements[j].tag == TAG(DST_ALG_ED25519, i))
        !           276:                                break;
        !           277:                if (i == EDDSA_NTAGS)
        !           278:                        return (-1);
        !           279:                have[i] = true;
        !           280:        }
        !           281:
        !           282:        mask = (1ULL << TAG_SHIFT) - 1;
        !           283:
        !           284:        if (have[TAG_EDDSA_ENGINE & mask])
        !           285:                ok = have[TAG_EDDSA_LABEL & mask];
        !           286:        else
        !           287:                ok = have[TAG_EDDSA_PRIVATEKEY & mask];
        !           288:        return (ok ? 0 : -1 );
        !           289: }
        !           290:
        !           291: static int
        !           292: check_hmac_md5(const dst_private_t *priv, bool old) {
        !           293:        int i, j;
        !           294:
        !           295:        if (priv->nelements != HMACMD5_NTAGS) {
        !           296:                /*
        !           297:                 * If this is a good old format and we are accepting
        !           298:                 * the old format return success.
        !           299:                 */
        !           300:                if (old && priv->nelements == OLD_HMACMD5_NTAGS &&
        !           301:                    priv->elements[0].tag == TAG_HMACMD5_KEY)
        !           302:                        return (0);
        !           303:                return (-1);
        !           304:        }
        !           305:        /*
        !           306:         * We must be new format at this point.
        !           307:         */
        !           308:        for (i = 0; i < HMACMD5_NTAGS; i++) {
        !           309:                for (j = 0; j < priv->nelements; j++)
        !           310:                        if (priv->elements[j].tag == TAG(DST_ALG_HMACMD5, i))
        !           311:                                break;
        !           312:                if (j == priv->nelements)
        !           313:                        return (-1);
        !           314:        }
        !           315:        return (0);
        !           316: }
        !           317:
        !           318: static int
        !           319: check_hmac_sha(const dst_private_t *priv, unsigned int ntags,
        !           320:               unsigned int alg)
        !           321: {
        !           322:        unsigned int i, j;
        !           323:        if (priv->nelements != ntags)
        !           324:                return (-1);
        !           325:        for (i = 0; i < ntags; i++) {
        !           326:                for (j = 0; j < priv->nelements; j++)
        !           327:                        if (priv->elements[j].tag == TAG(alg, i))
        !           328:                                break;
        !           329:                if (j == priv->nelements)
        !           330:                        return (-1);
        !           331:        }
        !           332:        return (0);
        !           333: }
        !           334:
        !           335: static int
        !           336: check_data(const dst_private_t *priv, const unsigned int alg,
        !           337:           bool old, bool external)
        !           338: {
        !           339:        /* XXXVIX this switch statement is too sparse to gen a jump table. */
        !           340:        switch (alg) {
        !           341:        case DST_ALG_RSA:
        !           342:        case DST_ALG_RSASHA1:
        !           343:        case DST_ALG_NSEC3RSASHA1:
        !           344:        case DST_ALG_RSASHA256:
        !           345:        case DST_ALG_RSASHA512:
        !           346:                return (check_rsa(priv, external));
        !           347:        case DST_ALG_DH:
        !           348:                return (check_dh(priv));
        !           349:        case DST_ALG_ECDSA256:
        !           350:        case DST_ALG_ECDSA384:
        !           351:                return (check_ecdsa(priv, external));
        !           352:        case DST_ALG_ED25519:
        !           353:        case DST_ALG_ED448:
        !           354:                return (check_eddsa(priv, external));
        !           355:        case DST_ALG_HMACMD5:
        !           356:                return (check_hmac_md5(priv, old));
        !           357:        case DST_ALG_HMACSHA1:
        !           358:                return (check_hmac_sha(priv, HMACSHA1_NTAGS, alg));
        !           359:        case DST_ALG_HMACSHA224:
        !           360:                return (check_hmac_sha(priv, HMACSHA224_NTAGS, alg));
        !           361:        case DST_ALG_HMACSHA256:
        !           362:                return (check_hmac_sha(priv, HMACSHA256_NTAGS, alg));
        !           363:        case DST_ALG_HMACSHA384:
        !           364:                return (check_hmac_sha(priv, HMACSHA384_NTAGS, alg));
        !           365:        case DST_ALG_HMACSHA512:
        !           366:                return (check_hmac_sha(priv, HMACSHA512_NTAGS, alg));
        !           367:        default:
        !           368:                return (DST_R_UNSUPPORTEDALG);
        !           369:        }
        !           370: }
        !           371:
        !           372: void
        !           373: dst__privstruct_free(dst_private_t *priv, isc_mem_t *mctx) {
        !           374:        int i;
        !           375:
        !           376:        if (priv == NULL)
        !           377:                return;
        !           378:        for (i = 0; i < priv->nelements; i++) {
        !           379:                if (priv->elements[i].data == NULL)
        !           380:                        continue;
        !           381:                memset(priv->elements[i].data, 0, MAXFIELDSIZE);
        !           382:                isc_mem_put(mctx, priv->elements[i].data, MAXFIELDSIZE);
        !           383:        }
        !           384:        priv->nelements = 0;
        !           385: }
        !           386:
        !           387: isc_result_t
        !           388: dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
        !           389:                      isc_mem_t *mctx, dst_private_t *priv)
        !           390: {
        !           391:        int n = 0, major, minor, check;
        !           392:        isc_buffer_t b;
        !           393:        isc_token_t token;
        !           394:        unsigned char *data = NULL;
        !           395:        unsigned int opt = ISC_LEXOPT_EOL;
        !           396:        isc_stdtime_t when;
        !           397:        isc_result_t ret;
        !           398:        bool external = false;
        !           399:
        !           400:        REQUIRE(priv != NULL);
        !           401:
        !           402:        priv->nelements = 0;
        !           403:        memset(priv->elements, 0, sizeof(priv->elements));
        !           404:
        !           405: #define NEXTTOKEN(lex, opt, token)                             \
        !           406:        do {                                                    \
        !           407:                ret = isc_lex_gettoken(lex, opt, token);        \
        !           408:                if (ret != ISC_R_SUCCESS)                       \
        !           409:                        goto fail;                              \
        !           410:        } while (/*CONSTCOND*/0)
        !           411:
        !           412: #define READLINE(lex, opt, token)                              \
        !           413:        do {                                                    \
        !           414:                ret = isc_lex_gettoken(lex, opt, token);        \
        !           415:                if (ret == ISC_R_EOF)                           \
        !           416:                        break;                                  \
        !           417:                else if (ret != ISC_R_SUCCESS)                  \
        !           418:                        goto fail;                              \
        !           419:        } while ((*token).type != isc_tokentype_eol)
        !           420:
        !           421:        /*
        !           422:         * Read the description line.
        !           423:         */
        !           424:        NEXTTOKEN(lex, opt, &token);
        !           425:        if (token.type != isc_tokentype_string ||
        !           426:            strcmp(DST_AS_STR(token), PRIVATE_KEY_STR) != 0)
        !           427:        {
        !           428:                ret = DST_R_INVALIDPRIVATEKEY;
        !           429:                goto fail;
        !           430:        }
        !           431:
        !           432:        NEXTTOKEN(lex, opt, &token);
        !           433:        if (token.type != isc_tokentype_string ||
        !           434:            (DST_AS_STR(token))[0] != 'v')
        !           435:        {
        !           436:                ret = DST_R_INVALIDPRIVATEKEY;
        !           437:                goto fail;
        !           438:        }
        !           439:        if (sscanf(DST_AS_STR(token), "v%d.%d", &major, &minor) != 2)
        !           440:        {
        !           441:                ret = DST_R_INVALIDPRIVATEKEY;
        !           442:                goto fail;
        !           443:        }
        !           444:
        !           445:        if (major > DST_MAJOR_VERSION) {
        !           446:                ret = DST_R_INVALIDPRIVATEKEY;
        !           447:                goto fail;
        !           448:        }
        !           449:
        !           450:        /*
        !           451:         * Store the private key format version number
        !           452:         */
        !           453:        dst_key_setprivateformat(key, major, minor);
        !           454:
        !           455:        READLINE(lex, opt, &token);
        !           456:
        !           457:        /*
        !           458:         * Read the algorithm line.
        !           459:         */
        !           460:        NEXTTOKEN(lex, opt, &token);
        !           461:        if (token.type != isc_tokentype_string ||
        !           462:            strcmp(DST_AS_STR(token), ALGORITHM_STR) != 0)
        !           463:        {
        !           464:                ret = DST_R_INVALIDPRIVATEKEY;
        !           465:                goto fail;
        !           466:        }
        !           467:
        !           468:        NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
        !           469:        if (token.type != isc_tokentype_number ||
        !           470:            token.value.as_ulong != (unsigned long) dst_key_alg(key))
        !           471:        {
        !           472:                ret = DST_R_INVALIDPRIVATEKEY;
        !           473:                goto fail;
        !           474:        }
        !           475:
        !           476:        READLINE(lex, opt, &token);
        !           477:
        !           478:        /*
        !           479:         * Read the key data.
        !           480:         */
        !           481:        for (n = 0; n < MAXFIELDS; n++) {
        !           482:                int tag;
        !           483:                isc_region_t r;
        !           484:                do {
        !           485:                        ret = isc_lex_gettoken(lex, opt, &token);
        !           486:                        if (ret == ISC_R_EOF)
        !           487:                                goto done;
        !           488:                        if (ret != ISC_R_SUCCESS)
        !           489:                                goto fail;
        !           490:                } while (token.type == isc_tokentype_eol);
        !           491:
        !           492:                if (token.type != isc_tokentype_string) {
        !           493:                        ret = DST_R_INVALIDPRIVATEKEY;
        !           494:                        goto fail;
        !           495:                }
        !           496:
        !           497:                if (strcmp(DST_AS_STR(token), "External:") == 0) {
        !           498:                        external = true;
        !           499:                        goto next;
        !           500:                }
        !           501:
        !           502:                /* Numeric metadata */
        !           503:                tag = find_numericdata(DST_AS_STR(token));
        !           504:                if (tag >= 0) {
        !           505:                        INSIST(tag < NUMERIC_NTAGS);
        !           506:
        !           507:                        NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
        !           508:                        if (token.type != isc_tokentype_number) {
        !           509:                                ret = DST_R_INVALIDPRIVATEKEY;
        !           510:                                goto fail;
        !           511:                        }
        !           512:
        !           513:                        dst_key_setnum(key, tag, token.value.as_ulong);
        !           514:                        goto next;
        !           515:                }
        !           516:
        !           517:                /* Timing metadata */
        !           518:                tag = find_timedata(DST_AS_STR(token));
        !           519:                if (tag >= 0) {
        !           520:                        INSIST(tag < TIMING_NTAGS);
        !           521:
        !           522:                        NEXTTOKEN(lex, opt, &token);
        !           523:                        if (token.type != isc_tokentype_string) {
        !           524:                                ret = DST_R_INVALIDPRIVATEKEY;
        !           525:                                goto fail;
        !           526:                        }
        !           527:
        !           528:                        ret = dns_time32_fromtext(DST_AS_STR(token), &when);
        !           529:                        if (ret != ISC_R_SUCCESS)
        !           530:                                goto fail;
        !           531:
        !           532:                        dst_key_settime(key, tag, when);
        !           533:
        !           534:                        goto next;
        !           535:                }
        !           536:
        !           537:                /* Key data */
        !           538:                tag = find_value(DST_AS_STR(token), alg);
        !           539:                if (tag < 0 && minor > DST_MINOR_VERSION)
        !           540:                        goto next;
        !           541:                else if (tag < 0) {
        !           542:                        ret = DST_R_INVALIDPRIVATEKEY;
        !           543:                        goto fail;
        !           544:                }
        !           545:
        !           546:                priv->elements[n].tag = tag;
        !           547:
        !           548:                data = (unsigned char *) isc_mem_get(mctx, MAXFIELDSIZE);
        !           549:                if (data == NULL)
        !           550:                        goto fail;
        !           551:
        !           552:                isc_buffer_init(&b, data, MAXFIELDSIZE);
        !           553:                ret = isc_base64_tobuffer(lex, &b, -1);
        !           554:                if (ret != ISC_R_SUCCESS)
        !           555:                        goto fail;
        !           556:
        !           557:                isc_buffer_usedregion(&b, &r);
        !           558:                priv->elements[n].length = r.length;
        !           559:                priv->elements[n].data = r.base;
        !           560:                priv->nelements++;
        !           561:
        !           562:          next:
        !           563:                READLINE(lex, opt, &token);
        !           564:                data = NULL;
        !           565:        }
        !           566:
        !           567:  done:
        !           568:        if (external && priv->nelements != 0) {
        !           569:                ret = DST_R_INVALIDPRIVATEKEY;
        !           570:                goto fail;
        !           571:        }
        !           572:
        !           573:        check = check_data(priv, alg, true, external);
        !           574:        if (check < 0) {
        !           575:                ret = DST_R_INVALIDPRIVATEKEY;
        !           576:                goto fail;
        !           577:        } else if (check != ISC_R_SUCCESS) {
        !           578:                ret = check;
        !           579:                goto fail;
        !           580:        }
        !           581:
        !           582:        key->external = external;
        !           583:
        !           584:        return (ISC_R_SUCCESS);
        !           585:
        !           586: fail:
        !           587:        dst__privstruct_free(priv, mctx);
        !           588:        if (data != NULL)
        !           589:                isc_mem_put(mctx, data, MAXFIELDSIZE);
        !           590:
        !           591:        return (ret);
        !           592: }
        !           593:
        !           594: isc_result_t
        !           595: dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
        !           596:                          const char *directory)
        !           597: {
        !           598:        FILE *fp;
        !           599:        isc_result_t result;
        !           600:        char filename[NAME_MAX];
        !           601:        char buffer[MAXFIELDSIZE * 2];
        !           602:        isc_fsaccess_t access;
        !           603:        isc_stdtime_t when;
        !           604:        uint32_t value;
        !           605:        isc_buffer_t b;
        !           606:        isc_region_t r;
        !           607:        int major, minor;
        !           608:        mode_t mode;
        !           609:        int i, ret;
        !           610:
        !           611:        REQUIRE(priv != NULL);
        !           612:
        !           613:        ret = check_data(priv, dst_key_alg(key), false, key->external);
        !           614:        if (ret < 0)
        !           615:                return (DST_R_INVALIDPRIVATEKEY);
        !           616:        else if (ret != ISC_R_SUCCESS)
        !           617:                return (ret);
        !           618:
        !           619:        isc_buffer_init(&b, filename, sizeof(filename));
        !           620:        result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &b);
        !           621:        if (result != ISC_R_SUCCESS)
        !           622:                return (result);
        !           623:
        !           624:        result = isc_file_mode(filename, &mode);
        !           625:        if (result == ISC_R_SUCCESS && mode != 0600) {
        !           626:                /* File exists; warn that we are changing its permissions */
        !           627:                int level;
        !           628:
        !           629: #ifdef _WIN32
        !           630:                /* Windows security model is pretty different,
        !           631:                 * e.g., there is no umask... */
        !           632:                level = ISC_LOG_NOTICE;
        !           633: #else
        !           634:                level = ISC_LOG_WARNING;
        !           635: #endif
        !           636:                isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
        !           637:                              DNS_LOGMODULE_DNSSEC, level,
        !           638:                              "Permissions on the file %s "
        !           639:                              "have changed from 0%o to 0600 as "
        !           640:                              "a result of this operation.",
        !           641:                              filename, (unsigned int)mode);
        !           642:        }
        !           643:
        !           644:        if ((fp = fopen(filename, "w")) == NULL)
        !           645:                return (DST_R_WRITEERROR);
        !           646:
        !           647:        access = 0;
        !           648:        isc_fsaccess_add(ISC_FSACCESS_OWNER,
        !           649:                         ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
        !           650:                         &access);
        !           651:        (void)isc_fsaccess_set(filename, access);
        !           652:
        !           653:        dst_key_getprivateformat(key, &major, &minor);
        !           654:        if (major == 0 && minor == 0) {
        !           655:                major = DST_MAJOR_VERSION;
        !           656:                minor = DST_MINOR_VERSION;
        !           657:        }
        !           658:
        !           659:        /* XXXDCL return value should be checked for full filesystem */
        !           660:        fprintf(fp, "%s v%d.%d\n", PRIVATE_KEY_STR, major, minor);
        !           661:
        !           662:        fprintf(fp, "%s %u ", ALGORITHM_STR, dst_key_alg(key));
        !           663:
        !           664:        /* XXXVIX this switch statement is too sparse to gen a jump table. */
        !           665:        switch (dst_key_alg(key)) {
        !           666:        case DST_ALG_DH:
        !           667:                fprintf(fp, "(DH)\n");
        !           668:                break;
        !           669:        case DST_ALG_RSASHA1:
        !           670:                fprintf(fp, "(RSASHA1)\n");
        !           671:                break;
        !           672:        case DST_ALG_NSEC3RSASHA1:
        !           673:                fprintf(fp, "(NSEC3RSASHA1)\n");
        !           674:                break;
        !           675:        case DST_ALG_RSASHA256:
        !           676:                fprintf(fp, "(RSASHA256)\n");
        !           677:                break;
        !           678:        case DST_ALG_RSASHA512:
        !           679:                fprintf(fp, "(RSASHA512)\n");
        !           680:                break;
        !           681:        case DST_ALG_ECDSA256:
        !           682:                fprintf(fp, "(ECDSAP256SHA256)\n");
        !           683:                break;
        !           684:        case DST_ALG_ECDSA384:
        !           685:                fprintf(fp, "(ECDSAP384SHA384)\n");
        !           686:                break;
        !           687:        case DST_ALG_ED25519:
        !           688:                fprintf(fp, "(ED25519)\n");
        !           689:                break;
        !           690:        case DST_ALG_ED448:
        !           691:                fprintf(fp, "(ED448)\n");
        !           692:                break;
        !           693:        case DST_ALG_HMACMD5:
        !           694:                fprintf(fp, "(HMAC_MD5)\n");
        !           695:                break;
        !           696:        case DST_ALG_HMACSHA1:
        !           697:                fprintf(fp, "(HMAC_SHA1)\n");
        !           698:                break;
        !           699:        case DST_ALG_HMACSHA224:
        !           700:                fprintf(fp, "(HMAC_SHA224)\n");
        !           701:                break;
        !           702:        case DST_ALG_HMACSHA256:
        !           703:                fprintf(fp, "(HMAC_SHA256)\n");
        !           704:                break;
        !           705:        case DST_ALG_HMACSHA384:
        !           706:                fprintf(fp, "(HMAC_SHA384)\n");
        !           707:                break;
        !           708:        case DST_ALG_HMACSHA512:
        !           709:                fprintf(fp, "(HMAC_SHA512)\n");
        !           710:                break;
        !           711:        default:
        !           712:                fprintf(fp, "(?)\n");
        !           713:                break;
        !           714:        }
        !           715:
        !           716:        for (i = 0; i < priv->nelements; i++) {
        !           717:                const char *s;
        !           718:
        !           719:                s = find_tag(priv->elements[i].tag);
        !           720:
        !           721:                r.base = priv->elements[i].data;
        !           722:                r.length = priv->elements[i].length;
        !           723:                isc_buffer_init(&b, buffer, sizeof(buffer));
        !           724:                result = isc_base64_totext(&r, sizeof(buffer), "", &b);
        !           725:                if (result != ISC_R_SUCCESS) {
        !           726:                        fclose(fp);
        !           727:                        return (DST_R_INVALIDPRIVATEKEY);
        !           728:                }
        !           729:                isc_buffer_usedregion(&b, &r);
        !           730:
        !           731:               fprintf(fp, "%s %.*s\n", s, (int)r.length, r.base);
        !           732:        }
        !           733:
        !           734:        if (key->external)
        !           735:               fprintf(fp, "External:\n");
        !           736:
        !           737:        /* Add the metadata tags */
        !           738:        if (major > 1 || (major == 1 && minor >= 3)) {
        !           739:                for (i = 0; i < NUMERIC_NTAGS; i++) {
        !           740:                        result = dst_key_getnum(key, i, &value);
        !           741:                        if (result != ISC_R_SUCCESS)
        !           742:                                continue;
        !           743:                        fprintf(fp, "%s %u\n", numerictags[i], value);
        !           744:                }
        !           745:                for (i = 0; i < TIMING_NTAGS; i++) {
        !           746:                        result = dst_key_gettime(key, i, &when);
        !           747:                        if (result != ISC_R_SUCCESS)
        !           748:                                continue;
        !           749:
        !           750:                        isc_buffer_init(&b, buffer, sizeof(buffer));
        !           751:                        result = dns_time32_totext(when, &b);
        !           752:                        if (result != ISC_R_SUCCESS) {
        !           753:                               fclose(fp);
        !           754:                               return (DST_R_INVALIDPRIVATEKEY);
        !           755:                        }
        !           756:
        !           757:                        isc_buffer_usedregion(&b, &r);
        !           758:
        !           759:                        fprintf(fp, "%s %.*s\n", timetags[i], (int)r.length,
        !           760:                                r.base);
        !           761:                }
        !           762:        }
        !           763:
        !           764:        fflush(fp);
        !           765:        result = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS;
        !           766:        fclose(fp);
        !           767:        return (result);
        !           768: }
        !           769:
        !           770: /*! \file */

CVSweb <webmaster@jp.NetBSD.org>