Annotation of pgp/src/keymaint.c, revision 1.1

1.1     ! root        1: /*     keymaint.c  - Keyring maintenance pass routines for PGP.
        !             2:        PGP: Pretty Good(tm) Privacy - public key cryptography for the masses.
        !             3: 
        !             4:        (c) Copyright 1990-1992 by Philip Zimmermann.  All rights reserved.
        !             5:        The author assumes no liability for damages resulting from the use
        !             6:        of this software, even if the damage results from defects in this
        !             7:        software.  No warranty is expressed or implied.
        !             8: 
        !             9:        All the source code Philip Zimmermann wrote for PGP is available for
        !            10:        free under the "Copyleft" General Public License from the Free
        !            11:        Software Foundation.  A copy of that license agreement is included in
        !            12:        the source release package of PGP.  Code developed by others for PGP
        !            13:        is also freely available.  Other code that has been incorporated into
        !            14:        PGP from other sources was either originally published in the public
        !            15:        domain or was used with permission from the various authors.  See the
        !            16:        PGP User's Guide for more complete information about licensing,
        !            17:        patent restrictions on certain algorithms, trademarks, copyrights,
        !            18:        and export controls.  
        !            19: 
        !            20:        keymaint.c implemented by Branko Lankester.
        !            21: */
        !            22: 
        !            23: #include <stdio.h>
        !            24: #include <time.h>
        !            25: #include "mpilib.h"
        !            26: #include "random.h"
        !            27: #include "crypto.h"
        !            28: #include "fileio.h"
        !            29: #include "keymgmt.h"
        !            30: #include "mpiio.h"
        !            31: #include "language.h"
        !            32: #include "pgp.h"
        !            33: 
        !            34: 
        !            35: void setup_trust();
        !            36: int maint_pass1(FILE *f);
        !            37: int maint_trace_chain(FILE *f);
        !            38: int maint_cmpfiles(FILE *f, FILE *g);
        !            39: int trace_sig_chain(FILE *f, byte *fromID, int owner_trust, int depth);
        !            40: int check_secretkey(FILE *f, long keypos);
        !            41: int set_legit(FILE *f, long trustpos, int trust_count);
        !            42: long lookup_by_keyID(FILE *f, byte *srch_keyID);
        !            43: void show_userid(FILE *f, byte *keyID);
        !            44: int show_trust(byte, byte);
        !            45: int show_legit(byte, byte);
        !            46: void write_trust_pos(FILE *f, byte keyctrl, long pos);
        !            47: 
        !            48: /* returned when trying to do a maintenance pass on a secret keyring or keyfile */
        !            49: #define        ERR_NOTRUST             -7
        !            50: 
        !            51: #define TRUST_MASK             7       /* mask for userid/signature trust bytes */
        !            52: #define SET_TRUST(b,v) (*(b) = (*(b) & ~TRUST_MASK) | (v))
        !            53: #define TRUST_LEV(b)   ((b) & TRUST_MASK)
        !            54: 
        !            55: #define        TRUST_FAC(x)    (trust_tbl[TRUST_LEV(x)])
        !            56: 
        !            57: /*
        !            58:  * table for tuning user paranoia index.
        !            59:  * values represent contribution of one signature indexed by the
        !            60:  * SIGTRUST of a signature
        !            61:  */
        !            62: int trust_tbl[8];
        !            63: 
        !            64: static int marginal_min;
        !            65: static int complete_min;       /* total count needed for a fully legit key */
        !            66: 
        !            67: int marg_min = 2;              /* number of marginally trusted signatures needed for
        !            68:                                                   a fully legit key (can be set in config.pgp). */
        !            69: int compl_min = 1;             /* number of fully trusted signatures needed */
        !            70: 
        !            71: char trust_lst[8][16] = {
        !            72:        "undefined",            /* PSTR("undefined") */
        !            73:        "unknown",                      /* PSTR("unknown") */
        !            74:        "untrusted",            /* PSTR("untrusted") */
        !            75:        "<3>",                          /* unused */
        !            76:        "<4>",                          /* unused */
        !            77:        "marginal",                     /* PSTR("marginal") */
        !            78:        "complete",                     /* PSTR("complete") */
        !            79:        "ultimate",                     /* PSTR("ultimate") */
        !            80: };
        !            81: 
        !            82: char legit_lst[4][16] = {
        !            83:        "undefined",
        !            84:        "untrusted",
        !            85:        "marginal",
        !            86:        "complete"
        !            87: };
        !            88: 
        !            89: int trustlst_len = 9;  /* length of longest trust word */
        !            90: int legitlst_len = 9;  /* length of longest legit word */
        !            91: 
        !            92: char floppyring[MAX_PATH] = "";
        !            93: int max_cert_depth = 4;                /* maximum nesting of signatures */
        !            94: 
        !            95: static boolean check_only = FALSE;
        !            96: static boolean mverbose;
        !            97: static FILE *sec_fp;
        !            98: static FILE *floppy_fp = NULL;
        !            99: static int undefined_trust;    /* number of legit keys with undef. trust */
        !           100:   
        !           101: int
        !           102: maintenance(char *ringfile, int options)
        !           103: {
        !           104:        FILE *f, *g;
        !           105:        int status;
        !           106:        char *tmpring;
        !           107:        char secretkeyring[MAX_PATH];
        !           108: 
        !           109:        check_only = (options & MAINT_CHECK) != 0;
        !           110:        mverbose = (options & MAINT_VERBOSE) != 0;
        !           111:        undefined_trust = 0;
        !           112: 
        !           113:        if ((tmpring = tempfile(TMP_TMPDIR)) == NULL)
        !           114:                return(-1);
        !           115:        if ((g = fopenbin(tmpring, "w+")) == NULL)
        !           116:                return(-1);
        !           117: 
        !           118:        if ((f = fopenbin(ringfile,"r")) == NULL)
        !           119:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
        !           120:                fclose(g);
        !           121:                return(-1);
        !           122:        }
        !           123: 
        !           124:        buildfilename(secretkeyring, SECRET_KEYRING_FILENAME);
        !           125:        if ((sec_fp = fopenbin(secretkeyring, "r")) == NULL)
        !           126:                fprintf(pgpout,PSTR("\nCan't open secret key ring file '%s'\n"),
        !           127:                                secretkeyring);
        !           128: 
        !           129:        if (!(options & MAINT_SILENT) && *floppyring != '\0' &&
        !           130:                (floppy_fp = fopenbin(floppyring, "r")) == NULL)
        !           131:                fprintf(pgpout,PSTR("\nCan't open backup key ring file '%s'\n"),
        !           132:                                floppyring);
        !           133: 
        !           134:        if ((status = copyfile(f, g, -1L)) < 0)
        !           135:        {       fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"), ringfile);
        !           136:                goto failed;
        !           137:        }
        !           138: 
        !           139:        setup_trust();
        !           140:        if (mverbose)
        !           141:                fprintf(pgpout, PSTR("\nPass 1: Looking for the \"ultimately-trusted\" keys...\n"));
        !           142:        rewind(g);
        !           143:        if ((status = maint_pass1(g)) < 0)
        !           144:                goto failed;
        !           145: 
        !           146:        if (mverbose)
        !           147:                fprintf(pgpout, PSTR("\nPass 2: Tracing signature chains...\n"));
        !           148:        rewind(g);
        !           149:        if ((status = maint_trace_chain(g)) < 0)
        !           150:                goto failed;
        !           151: 
        !           152:        if (!(options & MAINT_SILENT))
        !           153:        {       if (mverbose)
        !           154:                        fprintf(pgpout, PSTR("\nPass 3: Comparing with original keyring...\n"));
        !           155:                rewind(f);
        !           156:                rewind(g);
        !           157:                if ((status = maint_cmpfiles(f, g)) < 0)
        !           158:                        goto failed;
        !           159:        } else
        !           160:                status = 1;
        !           161: 
        !           162:        fflush(g);
        !           163:        if (ferror(g))
        !           164:        {       status = -1;
        !           165:                goto failed;
        !           166:        }
        !           167:        fclose(f);
        !           168:        fclose(g);
        !           169:        if (sec_fp)
        !           170:                fclose(sec_fp);
        !           171:        if (floppy_fp)
        !           172:        {       fclose(floppy_fp);
        !           173:                floppy_fp = NULL;
        !           174:        }
        !           175: 
        !           176: #ifdef DEBUG
        !           177:        if (check_only)
        !           178:        {
        !           179:                if (undefined_trust)
        !           180:                        fprintf(pgpout, "\nKeyring contains %d fully validated key(s) with undefined trust.\n", undefined_trust);
        !           181:                else
        !           182:                        if (status == 0)
        !           183:                                fprintf(pgpout, "\nMaintenance check OK.\n");
        !           184:                rmtemp(tmpring);
        !           185:                return(0);
        !           186:        }
        !           187: #endif
        !           188: 
        !           189:        if (status > 0)         /* keyring is changed */
        !           190:        {
        !           191:                if (options & MAINT_SILENT)
        !           192:                {       /* implicit maintenance pass (after pgp -ka, -kr, -ks) */
        !           193:                        remove(ringfile);
        !           194:                        if (savetemp(tmpring, ringfile) == NULL)
        !           195:                                return(-1);
        !           196:                }
        !           197:                else
        !           198:                {       /* explicit maintenance pass */
        !           199:                        fprintf(pgpout, PSTR("Update public keyring '%s' (Y/n)? "), ringfile);
        !           200:                        if (!getyesno('y'))
        !           201:                        {
        !           202:                                rmtemp(tmpring);
        !           203:                                return(0);
        !           204:                        }
        !           205:                        if (savetempbak(tmpring, ringfile))
        !           206:                                return(-1);
        !           207:                }
        !           208:        }
        !           209:        else
        !           210:                rmtemp(tmpring);
        !           211: 
        !           212:        return(0);
        !           213: 
        !           214: failed:
        !           215:        if (sec_fp)
        !           216:                fclose(sec_fp);
        !           217:        if (floppy_fp)
        !           218:        {       fclose(floppy_fp);
        !           219:                floppy_fp = NULL;
        !           220:        }
        !           221:        fclose(f);
        !           222:        fclose(g);
        !           223: #ifdef DEBUG
        !           224:        savetempbak(tmpring, "tmpring.pub");
        !           225: #else
        !           226:        rmtemp(tmpring);
        !           227: #endif
        !           228:        return(status);
        !           229: }
        !           230: 
        !           231: 
        !           232: /*
        !           233:  * check if axiomatic keys are present in the secret keyring and
        !           234:  * clear userid and signature trust bytes
        !           235:  */
        !           236: int
        !           237: maint_pass1(FILE *f)
        !           238: {
        !           239:        int status;
        !           240:        char userid[256];
        !           241:        byte keyID[KEYFRAGSIZE];
        !           242:        byte ctb;
        !           243:        byte keyctrl;
        !           244:        boolean buckstop = FALSE, show_user = FALSE;
        !           245:        boolean compromised = FALSE;
        !           246:        int buckstopcount = 0;
        !           247:        int usercount = 0;
        !           248:        long keypos = 0;
        !           249: 
        !           250:        while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1)
        !           251:        {
        !           252:                if (status < 0)
        !           253:                        return(status);
        !           254: 
        !           255:                if (is_ctb_type(ctb, CTB_COMMENT_TYPE))
        !           256:                        continue;
        !           257:                if (compromised && is_ctb_type(ctb, CTB_SKE_TYPE) && !usercount)
        !           258:                        continue;       /* compromise certificate */
        !           259: 
        !           260:                /* other packets should have trust byte */
        !           261:                if (read_trust(f, &keyctrl) < 0)
        !           262:                        return(ERR_NOTRUST);            /* not a public keyring */
        !           263: 
        !           264:                if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
        !           265:                {
        !           266:                        if (compromised = is_compromised(f))
        !           267:                                keyctrl = KC_OWNERTRUST_NEVER;
        !           268:                        if ((keyctrl & KC_BUCKSTOP))
        !           269:                        {
        !           270:                                if (check_secretkey(f, keypos) == 0)
        !           271:                                {
        !           272:                                        ++buckstopcount;
        !           273:                                        buckstop = TRUE;
        !           274:                                        if (mverbose)
        !           275:                                                fprintf(pgpout, "* %s",keyIDstring(keyID));
        !           276:                                }
        !           277:                                else
        !           278:                                {       /* not in secret keyring */
        !           279:                                        keyctrl &= ~KC_BUCKSTOP;
        !           280:                                        if (TRUST_LEV(keyctrl) == KC_OWNERTRUST_ULTIMATE)
        !           281:                                                keyctrl = KC_OWNERTRUST_ALWAYS;
        !           282:                                        if (mverbose)
        !           283:                                                fprintf(pgpout, ". %s",keyIDstring(keyID));
        !           284:                                }
        !           285:                                show_user = mverbose;
        !           286:                        }
        !           287:                        else
        !           288:                        {
        !           289:                                buckstop = FALSE;
        !           290:                                show_user = FALSE;
        !           291:                        }
        !           292:                        usercount = 0;
        !           293:                        keyctrl &= ~KC_VISITED;
        !           294: 
        !           295:                }
        !           296:                else if (ctb == CTB_USERID)
        !           297:                {
        !           298:                        if (show_user)
        !           299:                        {
        !           300:                                if (usercount)          /* more than one user ID */
        !           301:                                        fprintf(pgpout, "        ");
        !           302:                                fprintf(pgpout, "  %s\n", EXTERNAL(userid));
        !           303:                        }
        !           304:                        if (buckstop)
        !           305:                                keyctrl = KC_LEGIT_COMPLETE;
        !           306:                        else
        !           307:                                keyctrl = KC_LEGIT_UNKNOWN;
        !           308:                        ++usercount;
        !           309:                }
        !           310:                else if (is_ctb_type(ctb, CTB_SKE_TYPE))
        !           311:                {
        !           312:                        keyctrl = KC_SIGTRUST_UNDEFINED;
        !           313:                }
        !           314:                fseek(f, -1L, SEEK_CUR);
        !           315:                fwrite(&keyctrl, 1, 1, f);
        !           316:                fseek(f, 0L, SEEK_CUR);
        !           317:                keypos = ftell(f);
        !           318:        }
        !           319:        if (buckstopcount == 0 && mverbose)
        !           320:        {
        !           321:                fprintf(pgpout, PSTR("No ultimately-trusted keys.\n"));
        !           322:        }
        !           323:        return(0);
        !           324: }
        !           325: 
        !           326: 
        !           327: /*
        !           328:  * scan keyring for buckstop keys and start the recursive trace_sig_chain()
        !           329:  * on them
        !           330:  */
        !           331: int
        !           332: maint_trace_chain(FILE *f)
        !           333: {
        !           334:        int status;
        !           335:        char userid[256];
        !           336:        byte keyID[KEYFRAGSIZE];
        !           337:        long trustpos = 0;
        !           338:        byte ctb;
        !           339:        byte own_trust;
        !           340:        boolean buckstop = FALSE;
        !           341: 
        !           342:        while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1)
        !           343:        {
        !           344:                if (status < 0)
        !           345:                        return status;
        !           346: 
        !           347:                if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
        !           348:                {
        !           349:                        trustpos = ftell(f);
        !           350:                        if ((status = read_trust(f, &own_trust)) < 0)
        !           351:                                return(status);
        !           352:                        buckstop = (own_trust & KC_BUCKSTOP) != 0;
        !           353:                        userid[0] = '\0';
        !           354:                }
        !           355:                else if (ctb == CTB_USERID)
        !           356:                {
        !           357:                        if (buckstop)
        !           358:                        {
        !           359:                                buckstop = FALSE;       /* only for first user id */
        !           360:                                if (mverbose)
        !           361:                                        fprintf(pgpout, "* %s\n", EXTERNAL(userid));
        !           362: 
        !           363:                                if (TRUST_LEV(own_trust) == KC_OWNERTRUST_UNDEFINED)
        !           364:                                {       SET_TRUST(&own_trust, ask_owntrust(userid, own_trust));
        !           365:                                        write_trust_pos(f, own_trust, trustpos);
        !           366:                                }
        !           367:                                if (trace_sig_chain(f, keyID, TRUST_LEV(own_trust), 0) < 0)
        !           368:                                        return(-1);
        !           369:                        }
        !           370:                }
        !           371:        }
        !           372:        return(0);
        !           373: }
        !           374: 
        !           375: 
        !           376: /* 
        !           377:  * check if the maintenance pass changed anything
        !           378:  * returns 0 if files f and g are equal.
        !           379:  */
        !           380: int
        !           381: maint_cmpfiles(FILE *f, FILE *g)
        !           382: {
        !           383:        int status;
        !           384:        char userid[256];
        !           385:        byte keyID[KEYFRAGSIZE];
        !           386:        byte sigkeyID[KEYFRAGSIZE];
        !           387:        byte ctb;
        !           388:        byte kc_orig, kc_new;
        !           389:        int usercount = 0;
        !           390:        int changed = 0;
        !           391: 
        !           392:        fprintf(pgpout, PSTR("  KeyID   Trust      Validity  User ID\n"));
        !           393:        while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) == 0)
        !           394:        {
        !           395:                if (is_ctb_type(ctb, CTB_COMMENT_TYPE))
        !           396:                        continue;
        !           397:                /* other packets should have trust byte */
        !           398: 
        !           399:                fseek(g, ftell(f), SEEK_SET);
        !           400:                if (read_trust(f, &kc_orig) < 0 || read_trust(g, &kc_new) < 0)
        !           401:                {       status = ERR_NOTRUST;
        !           402:                        break;
        !           403:                }
        !           404: 
        !           405:                if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
        !           406:                {
        !           407:                        if (is_compromised(f))
        !           408:                        {
        !           409:                                fprintf(pgpout, "# ");
        !           410:                                nextkeypacket(f, &ctb); /* skip compromise certificate */
        !           411:                                nextkeypacket(g, &ctb);
        !           412:                        }
        !           413:                        else if ((kc_new & KC_BUCKSTOP))
        !           414:                                fprintf(pgpout, "* ");
        !           415:                        else
        !           416:                                fprintf(pgpout, "  ");
        !           417: 
        !           418:                        fprintf(pgpout, "%s ",keyIDstring(keyID));
        !           419:                        changed += show_trust(kc_new, kc_orig);
        !           420:                        usercount = 0;
        !           421:                        userid[0] = '\0';
        !           422:                }
        !           423:                else if (ctb == CTB_USERID)
        !           424:                {
        !           425:                        if (usercount)          /* more than one user ID */
        !           426:                                fprintf(pgpout, "          %*s", trustlst_len, "");
        !           427:                        ++usercount;
        !           428:                        changed += show_legit(kc_new, kc_orig);
        !           429:                        fprintf(pgpout, "%s\n", EXTERNAL(userid));
        !           430:                }
        !           431:                else if (is_ctb_type(ctb, CTB_SKE_TYPE))
        !           432:                {
        !           433:                        if (kc_new & KC_CONTIG)
        !           434:                                fprintf(pgpout, "c        ");
        !           435:                        else
        !           436:                                fprintf(pgpout, "         ");
        !           437:                        changed += show_trust(kc_new, kc_orig);
        !           438:                        fprintf(pgpout, "  %*s", legitlst_len, "");
        !           439:                        show_userid(f, sigkeyID);
        !           440:                }
        !           441:        }
        !           442:        if (status >= -1 && changed)
        !           443:                fprintf(pgpout, PSTR("\n%d \"trust byte(s)\" changed.\n"), changed);
        !           444:        if (status < -1)        /* -1 is OK, EOF */
        !           445:                return(status);
        !           446:        return(changed);
        !           447: }
        !           448: 
        !           449: 
        !           450: void
        !           451: init_trust_lst()
        !           452: {
        !           453:        static int initialized = 0;
        !           454:        int i, len;
        !           455:        char *s;
        !           456: 
        !           457:        if (initialized)
        !           458:                return;
        !           459:        for (i = 0; i < 8; ++i)
        !           460:        {       if (trust_lst[i][0])
        !           461:                {       s = PSTR (trust_lst[i]);
        !           462:                        if (s != trust_lst[i])
        !           463:                                strncpy(trust_lst[i], s, sizeof(trust_lst[0]) - 1);
        !           464:                        len = strlen(s);
        !           465:                        if (len > trustlst_len)
        !           466:                                trustlst_len = len;
        !           467:                }
        !           468:        }
        !           469:        for (i = 0; i < 4; ++i)
        !           470:        {       s = PSTR (legit_lst[i]);
        !           471:                if (s != legit_lst[i])
        !           472:                        strncpy(legit_lst[i], s, sizeof(legit_lst[0]) - 1);
        !           473:                len = strlen(s);
        !           474:                if (len > legitlst_len)
        !           475:                        legitlst_len = len;
        !           476:        }
        !           477:        ++trustlst_len;
        !           478:        ++legitlst_len;
        !           479:        initialized = 1;
        !           480: }
        !           481: 
        !           482: int
        !           483: show_trust(byte kc_new, byte kc_orig)
        !           484: {
        !           485: #ifdef DEBUG
        !           486:        fprintf(pgpout, " %02x", kc_new);
        !           487:        if (kc_new != kc_orig)
        !           488:        {
        !           489:                fprintf(pgpout, " (%02x)    ", kc_orig);
        !           490:                return(1);
        !           491:        }
        !           492:        fprintf(pgpout, "        ");
        !           493:        return(0);
        !           494: #else
        !           495:        init_trust_lst();
        !           496:        fprintf(pgpout, "%c%-*s", (kc_new == kc_orig ? ' ' : '!'),
        !           497:                        trustlst_len, trust_lst[TRUST_LEV(kc_new)]);
        !           498:        return(kc_new != kc_orig);
        !           499: #endif
        !           500: }
        !           501: 
        !           502: int
        !           503: show_legit(byte kc_new, byte kc_orig)
        !           504: {
        !           505: #ifdef DEBUG
        !           506:        return(show_trust(kc_new, kc_orig));
        !           507: #else
        !           508:        init_trust_lst();
        !           509:        kc_new &= KC_LEGIT_MASK;
        !           510:        kc_orig &= KC_LEGIT_MASK;
        !           511:        fprintf(pgpout, "%c%-*s", (kc_new == kc_orig ? ' ' : '!'),
        !           512:                        legitlst_len, legit_lst[kc_new]);
        !           513:        return(kc_new != kc_orig);
        !           514: #endif
        !           515: }
        !           516: 
        !           517: 
        !           518: /*
        !           519:  * Find all signatures made with a key, fromID is the keyID of this key
        !           520:  * owner_trust is the trust level of this key.
        !           521:  * If a trusted signature makes a key fully legit then signatures made
        !           522:  * with this key are also recursively traced on down the tree.
        !           523:  */
        !           524: int
        !           525: trace_sig_chain(FILE *f, byte *fromID, int owner_trust, int depth)
        !           526: {
        !           527:        long filepos;
        !           528:        int status;
        !           529:        int trust_count = 0;
        !           530:        byte keyID[KEYFRAGSIZE];
        !           531:        byte sigkeyID[KEYFRAGSIZE];
        !           532:        byte ctb;
        !           533:        byte own_trust, sig_trust;
        !           534:        char userid[256];
        !           535:        int sig_count = 0;
        !           536:        int compromised = 0;
        !           537:        long usertrustpos = 0;
        !           538:        long ownt_pos = 0;
        !           539: 
        !           540:        if (max_cert_depth > 8)
        !           541:                max_cert_depth = 8;
        !           542:        if (depth > max_cert_depth)
        !           543:                return(0);
        !           544:        filepos = ftell(f);
        !           545:        rewind(f);
        !           546:        userid[0] = '\0';
        !           547:        while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) != -1)
        !           548:        {
        !           549:                if (status < 0)
        !           550:                        return status;
        !           551: 
        !           552:                if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
        !           553:                {
        !           554:                        compromised = is_compromised(f);
        !           555:                        ownt_pos = ftell(f);
        !           556:                        if (read_trust(f, &own_trust))
        !           557:                                return(ERR_NOTRUST);
        !           558:                        userid[0] = '\0';
        !           559:                }
        !           560:                else if (ctb == CTB_USERID)
        !           561:                {
        !           562:                        usertrustpos = ftell(f);
        !           563:                        trust_count = 0;
        !           564:                }
        !           565:                else if (is_ctb_type(ctb, CTB_SKE_TYPE))
        !           566:                {
        !           567:                        if (compromised)
        !           568:                                continue;
        !           569:                        read_trust(f, &sig_trust);
        !           570:                        if (memcmp(sigkeyID, fromID, sizeof(sigkeyID)) == 0)
        !           571:                        {
        !           572:                                ++sig_count;
        !           573:                                if (mverbose)
        !           574:                                        fprintf(pgpout, "%*s  > %s\n", 2*depth, "", EXTERNAL(userid));
        !           575:                                if (TRUST_LEV(sig_trust) != owner_trust)
        !           576:                                {
        !           577:                                        SET_TRUST(&sig_trust, owner_trust);
        !           578:                                }
        !           579:                                sig_trust |= KC_CONTIG;
        !           580:                                fseek(f, -1L, SEEK_CUR);
        !           581:                                fwrite(&sig_trust, 1, 1, f);
        !           582:                                fseek(f, 0L, SEEK_CUR);
        !           583:                        }
        !           584: 
        !           585:                        if (sig_trust & KC_CONTIG)
        !           586:                        {
        !           587:                                trust_count += TRUST_FAC(sig_trust);
        !           588: 
        !           589:                                switch (set_legit(f, usertrustpos, trust_count))
        !           590:                                {
        !           591:                                        case -1: return(-1);
        !           592:                                        case  1:
        !           593:                                                if ((own_trust & (KC_BUCKSTOP|KC_VISITED)) == 0)
        !           594:                                                {
        !           595:                                                        if (TRUST_LEV(own_trust) == KC_OWNERTRUST_UNDEFINED)
        !           596:                                                                SET_TRUST(&own_trust, ask_owntrust(userid, own_trust));
        !           597:                                                        own_trust |= KC_VISITED;
        !           598:                                                        write_trust_pos(f, own_trust, ownt_pos);
        !           599:                                                        trace_sig_chain(f, keyID, TRUST_LEV(own_trust), depth+1);
        !           600:                                                }
        !           601:                                }
        !           602:                        }
        !           603:                }
        !           604:        }
        !           605:        if (mverbose && sig_count == 0) /* no signatures from this user */
        !           606:                fprintf(pgpout, PSTR("%*s  (No signatures)\n"), 2*depth, "");
        !           607:        fseek(f, filepos, SEEK_SET);
        !           608:        return(0);
        !           609: }
        !           610: 
        !           611: 
        !           612: int
        !           613: check_secretkey(FILE *f, long keypos)
        !           614: {
        !           615:        int status = -1;
        !           616:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
        !           617:        unit nsec[MAX_UNIT_PRECISION], esec[MAX_UNIT_PRECISION];
        !           618:        char userid[256];
        !           619:        byte keyID[KEYFRAGSIZE];
        !           620:        long savepos, pktlen;
        !           621:        byte ctb;
        !           622: 
        !           623:        if (sec_fp == NULL)
        !           624:                return(-1);
        !           625: 
        !           626:        savepos = ftell(f);
        !           627:        fseek(f, keypos, SEEK_SET);
        !           628:        if (readkeypacket(f, FALSE, &ctb, NULL, NULL, n, e,
        !           629:                                        NULL, NULL, NULL, NULL, NULL, NULL) < 0)
        !           630:                goto ex;
        !           631:        extract_keyID(keyID, n);
        !           632: 
        !           633:        do      /* get userid */
        !           634:        {       if (readkpacket(f, &ctb, userid, NULL, NULL) < 0)
        !           635:                        goto ex;
        !           636:        } while (ctb != CTB_USERID);
        !           637: 
        !           638:        if (lookup_by_keyID(sec_fp, keyID) < 0)
        !           639:        {
        !           640: #if 0
        !           641:                if (!check_only)
        !           642:                {
        !           643:                        fprintf(pgpout, PSTR (
        !           644: "\nAn \"axiomatic\" key is one which does not need certifying by\n\
        !           645: anyone else.  Usually this special status is reserved only for your\n\
        !           646: own keys, which should also appear on your secret keyring.  The owner\n\
        !           647: of an axiomatic key (who is typically yourself) is \"ultimately trusted\"\n\
        !           648: by you to certify any or all other keys.\n"));
        !           649:                        fprintf(pgpout, PSTR ("\nKey for user ID: \"%s\"\n\
        !           650: is designated as an \"ultimately-trusted\" introducer, but the key\n\
        !           651: does not appear in the secret keyring.\n\
        !           652: Use this key as an ultimately-trusted introducer (y/N)? "), EXTERNAL(userid));
        !           653:                        status = (getyesno('n') ? 0 : 1);
        !           654:                }
        !           655: #else
        !           656:                status = 1;
        !           657: #endif
        !           658:        }
        !           659:        else
        !           660:        {
        !           661:                long kpos = ftell(sec_fp);
        !           662:                if (readkeypacket(sec_fp, FALSE, &ctb, NULL, NULL, nsec, esec,
        !           663:                                                NULL, NULL, NULL, NULL, NULL, NULL) < 0)
        !           664:                {
        !           665:                        fprintf(pgpout, PSTR("\n\007Cannot read from secret keyring.\n"));
        !           666:                        goto ex;
        !           667:                }
        !           668:                if (mp_compare(n, nsec) || mp_compare(e, esec))
        !           669:                {       /* Red Alert! */
        !           670:                        fprintf(pgpout, PSTR("\n\007WARNING: Public key for user ID: \"%s\"\n\
        !           671: does not match the corresponding key in the secret keyring.\n"), EXTERNAL(userid));
        !           672:                        fprintf(pgpout, PSTR("This is a serious condition, indicating possible keyring tampering.\n"));
        !           673:                        status = -2;
        !           674:                }
        !           675:                else
        !           676:                        status = 0;
        !           677: 
        !           678:                if (floppy_fp)
        !           679:                {
        !           680:                        if (lookup_by_keyID(floppy_fp, keyID) < 0)
        !           681:                        {
        !           682:                                fprintf(pgpout, PSTR("Public key for: \"%s\"\n\
        !           683: is not present in the backup keyring '%s'.\n"),
        !           684:                                                EXTERNAL(userid), floppyring);
        !           685:                        }
        !           686:                        else
        !           687:                        {
        !           688:                                pktlen = ftell(sec_fp) - kpos;
        !           689:                                fseek(sec_fp, kpos, SEEK_SET);
        !           690:                                while (--pktlen >= 0 && getc(sec_fp) == getc(floppy_fp)) ;
        !           691:                                if (pktlen != -1)
        !           692:                                {
        !           693:                                        fprintf(pgpout, PSTR("\n\007WARNING: Secret key for: \"%s\"\n\
        !           694: does not match the key in the backup keyring '%s'.\n"),
        !           695:                                                        EXTERNAL(userid), floppyring);
        !           696:                                        fprintf(pgpout, PSTR("This is a serious condition, indicating possible keyring tampering.\n"));
        !           697:                                        status = -2;
        !           698:                                }
        !           699:                        }
        !           700:                }
        !           701:        }
        !           702: ex:
        !           703:        fseek(f, savepos, SEEK_SET);
        !           704:        return(status);
        !           705: }
        !           706: 
        !           707: 
        !           708: void
        !           709: setup_trust()
        !           710: {      /* initialize trust table */
        !           711:        if (marg_min == 0)      /* marginally trusted signatures are ignored */
        !           712:        {
        !           713:                trust_tbl[5] = 0;
        !           714:                trust_tbl[6] = 1;
        !           715:                complete_min = compl_min;
        !           716:        }
        !           717:        else
        !           718:        {
        !           719:                if (marg_min < compl_min)
        !           720:                        marg_min = compl_min;
        !           721:                trust_tbl[5] = compl_min;
        !           722:                trust_tbl[6] = marg_min;
        !           723:                complete_min = compl_min * marg_min;
        !           724:        }
        !           725:        trust_tbl[7] = complete_min;    /* ultimate trust */
        !           726:        marginal_min = complete_min / 2;
        !           727: }
        !           728: 
        !           729: 
        !           730: /*
        !           731:  * set legit level of a userid
        !           732:  * returns 1 if the key/userid pair is fully legit.
        !           733:  */
        !           734: int
        !           735: set_legit(FILE *f, long trustpos, int trust_count)
        !           736: {
        !           737:        long filepos;
        !           738:        byte keyctrl;
        !           739: 
        !           740:        filepos = ftell(f);
        !           741:        fseek(f, trustpos, SEEK_SET);   /* user id trust byte */
        !           742:        if (read_trust(f, &keyctrl) < 0)
        !           743:                return(-1);
        !           744:        
        !           745:        if (trust_count < marginal_min)
        !           746:                keyctrl = KC_LEGIT_UNTRUSTED;
        !           747:        else if (trust_count < complete_min)
        !           748:                keyctrl = KC_LEGIT_MARGINAL;
        !           749:        else
        !           750:                keyctrl = KC_LEGIT_COMPLETE;
        !           751:        
        !           752:        fseek(f, trustpos, SEEK_SET);
        !           753:        write_trust(f, keyctrl);
        !           754: 
        !           755:        fseek(f, filepos, SEEK_SET);
        !           756: 
        !           757:        if ((keyctrl & KC_LEGIT_MASK) == KC_LEGIT_COMPLETE)
        !           758:                return(1);
        !           759:        else
        !           760:                return(0);
        !           761: }
        !           762: 
        !           763: 
        !           764: int ask_owntrust(char *userid, byte cur_trust)
        !           765: /* Ask for a wetware decision from the human on how much to trust 
        !           766: this key's owner to certify other keys.  Returns trust value. */
        !           767: {
        !           768:        char buf[8];
        !           769: 
        !           770:        if (check_only)
        !           771:        {       ++undefined_trust;
        !           772:                return(KC_OWNERTRUST_UNDEFINED);
        !           773:        }
        !           774: 
        !           775:        fprintf(pgpout, 
        !           776: PSTR("\nMake a determination in your own mind whether this key actually\n\
        !           777: belongs to the person whom you think it belongs to, based on available\n\
        !           778: evidence.  If you think it does, then based on your estimate of\n\
        !           779: that person's integrity and competence in key management, answer\n\
        !           780: the following question:\n"));  
        !           781:        fprintf(pgpout, PSTR("\nWould you trust \"%s\"\n\
        !           782: to act as an introducer and certify other people's public keys to you?\n\
        !           783: (1=I don't know. 2=No. 3=Usually. 4=Yes, always.) ? "), EXTERNAL(userid));
        !           784:        fflush(pgpout);
        !           785:        getstring(buf, sizeof(buf)-1, TRUE);
        !           786:        switch (buf[0])
        !           787:        {       case '1': return KC_OWNERTRUST_UNKNOWN;
        !           788:                case '2': return KC_OWNERTRUST_NEVER;
        !           789:                case '3': return KC_OWNERTRUST_USUALLY;
        !           790:                case '4': return KC_OWNERTRUST_ALWAYS;
        !           791:                default: return(TRUST_LEV(cur_trust));
        !           792:        }
        !           793: }      /* ask_owntrust */
        !           794: 
        !           795: 
        !           796: /* 
        !           797:  * compare all key packets in keyring file f with file g
        !           798:  * XXX: untested
        !           799:  */
        !           800: int
        !           801: keyring_cmp(FILE *f, FILE *g)
        !           802: {
        !           803:        int status, error = 0, badkeys = 0;
        !           804:        byte ctb;
        !           805:        byte keyID[KEYFRAGSIZE];
        !           806:        char userid[256];
        !           807:        long pktlen, keypos = 0;
        !           808: 
        !           809:        rewind(f);
        !           810:        while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) == 0)
        !           811:        {
        !           812:                if (is_key_ctb(ctb))
        !           813:                {
        !           814:                        pktlen = ftell(f) - keypos;
        !           815:                        fseek(f, keypos, SEEK_SET);
        !           816:                        if (lookup_by_keyID(g, keyID) < 0)
        !           817:                        {
        !           818:                                error = 1;
        !           819:                                continue;
        !           820:                        }
        !           821:                        while (--pktlen >= 0 && getc(f) == getc(g)) ;
        !           822:                        if (pktlen != -1)
        !           823:                        {
        !           824:                                error = 2;
        !           825:                                ++badkeys;
        !           826:                        }
        !           827: 
        !           828:                }
        !           829:                if (error && ctb == CTB_USERID)
        !           830:                {
        !           831:                        switch (error) {
        !           832:                                case 1: fprintf(pgpout, PSTR("\n\007Key for user ID \"%s\"\n\
        !           833: is not present in backup keyring\n"), EXTERNAL(userid));
        !           834:                                case 2: fprintf(pgpout, PSTR("\n\007Key for user ID \"%s\"\n\
        !           835: does not match key in backup keyring\n"), EXTERNAL(userid));
        !           836:                        }
        !           837:                        error = 0;
        !           838:                }
        !           839:                keypos = ftell(f);
        !           840:        }
        !           841:        if (error)
        !           842:                status = -5;
        !           843:        return(status < 0 ? status : badkeys);
        !           844: }
        !           845: 
        !           846: 
        !           847: int
        !           848: readkpacket(FILE *f, byte *ctb, char *userid, byte *keyID, byte *sigkeyID)
        !           849: {
        !           850:        int status;
        !           851:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
        !           852: 
        !           853:        status = readkeypacket(f, FALSE, ctb, NULL, userid, n, e,
        !           854:                                        NULL, NULL, NULL, NULL, sigkeyID, NULL);
        !           855: 
        !           856:        if (status < 0)
        !           857:        {
        !           858: #ifdef DEBUG
        !           859:                if (status < -1)
        !           860:                        fprintf(stderr, "readkeypacket returned %d\n", status);
        !           861: #endif
        !           862:                return(status);
        !           863:        }
        !           864: 
        !           865:        if (keyID && is_key_ctb(*ctb))
        !           866:                extract_keyID(keyID, n);
        !           867: 
        !           868:        if (userid && *ctb == CTB_USERID)
        !           869:                PascalToC(userid);
        !           870: 
        !           871:        return(0);
        !           872: }
        !           873: 
        !           874: long
        !           875: lookup_by_keyID(FILE *f, byte *srch_keyID)
        !           876: {
        !           877:        int status;
        !           878:        long keypos = 0;
        !           879:        byte keyID[KEYFRAGSIZE];
        !           880:        byte ctb;
        !           881: 
        !           882:        rewind(f);
        !           883:        while ((status = readkpacket(f, &ctb, NULL, keyID, NULL)) == 0)
        !           884:        {
        !           885:                if (is_key_ctb(ctb) && memcmp(keyID, srch_keyID, KEYFRAGSIZE) == 0)
        !           886:                {
        !           887:                        fseek(f, keypos, SEEK_SET);
        !           888:                        return(keypos);
        !           889:                }
        !           890:                keypos = ftell(f);
        !           891:        }
        !           892:        return(status);
        !           893: }
        !           894: 
        !           895: 
        !           896: void
        !           897: show_userid(FILE *f, byte *keyID)
        !           898: {
        !           899:        long filepos;
        !           900:        char userid[256];
        !           901:        byte ctb;
        !           902: 
        !           903:        filepos = ftell(f);
        !           904:        if (lookup_by_keyID(f, keyID) >= 0)
        !           905:                while (readkpacket(f, &ctb, userid, NULL, NULL) == 0)
        !           906:                        if (ctb == CTB_USERID)
        !           907:                        {
        !           908:                                fprintf(pgpout, "%s\n", EXTERNAL(userid));
        !           909:                                fseek(f, filepos, SEEK_SET);
        !           910:                                return;
        !           911:                        }
        !           912: 
        !           913:        fprintf(pgpout, "(KeyID: %s)\n",keyIDstring(keyID));
        !           914:        fseek(f, filepos, SEEK_SET);
        !           915: }
        !           916: 
        !           917: /*
        !           918:  * show the key in file f at file position keypos.
        !           919:  * 'what' controls the info that will be shown:
        !           920:  *   SHOW_TRUST: show trust byte info
        !           921:  *   SHOW_SIGS:  show signatures
        !           922:  * these constants can be or'ed to get both
        !           923:  */
        !           924: int
        !           925: show_key(FILE *f, long keypos, int what)
        !           926: {
        !           927:        int status;
        !           928:        long filepos;
        !           929:        char userid[256];
        !           930:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
        !           931:        byte sigkeyID[KEYFRAGSIZE];
        !           932:        word32 timestamp;
        !           933:        byte ctb, keyctrl;
        !           934:        int userids = 0;
        !           935:        boolean print_trust = FALSE;
        !           936:        int precision = global_precision;
        !           937: 
        !           938:        filepos = ftell(f);
        !           939:        fseek(f, keypos, SEEK_SET);
        !           940:        while ((status = readkeypacket(f, FALSE, &ctb, (byte *)&timestamp, userid,
        !           941:                                        n, e, NULL, NULL, NULL, NULL, sigkeyID, &keyctrl)) == 0)
        !           942:        {
        !           943:                if (is_key_ctb(ctb))
        !           944:                {       if (userids)
        !           945:                                break;
        !           946:                }
        !           947:                else if (ctb == CTB_KEYCTRL)  /* trust bytes only in public keyrings */
        !           948:                {
        !           949:                        if (what & SHOW_TRUST)
        !           950:                                print_trust = TRUE;
        !           951:                }
        !           952:                else if (ctb == CTB_USERID)
        !           953:                {       if (userids == 0)
        !           954:                        {       PascalToC(userid);      /* for display */
        !           955:                                fprintf(pgpout,PSTR("\nKey for user ID: %s\n"),EXTERNAL(userid));
        !           956:                                fprintf(pgpout,PSTR("%d-bit key, Key ID %s, created %s\n"),
        !           957:                                        countbits(n), key2IDstring(n), cdate(&timestamp) );
        !           958:                                if (print_trust)
        !           959:                                {
        !           960:                                        switch (TRUST_LEV(keyctrl))
        !           961:                                        {
        !           962:                                                case KC_OWNERTRUST_UNDEFINED:
        !           963:                                                case KC_OWNERTRUST_UNKNOWN:
        !           964:                                                        /* Just don't say anything in this case */
        !           965:                                                        break;
        !           966:                                                case KC_OWNERTRUST_NEVER:       /* untrusted */
        !           967:                                                        fprintf(pgpout, PSTR("This user is untrusted to certify other keys.\n"));
        !           968:                                                        break;
        !           969:                                                case KC_OWNERTRUST_USUALLY:     /* marginal trust */
        !           970:                                                        fprintf(pgpout, PSTR("This user is generally trusted to certify other keys.\n"));
        !           971:                                                        break;
        !           972:                                                case KC_OWNERTRUST_ALWAYS:      /* complete trust */
        !           973:                                                        fprintf(pgpout, PSTR("This user is completely trusted to certify other keys.\n"));
        !           974:                                                        break;
        !           975:                                                case KC_OWNERTRUST_ULTIMATE:    /* axiomatic, ultimate trust */
        !           976:                                                        fprintf(pgpout, PSTR("This axiomatic key is ultimately trusted to certify other keys.\n"));
        !           977:                                                        break;
        !           978:                                                default:
        !           979:                                                        break;
        !           980:                                        }       /* switch */
        !           981:                                }
        !           982:                                ++userids;
        !           983:                        }
        !           984:                        else
        !           985:                        {       PascalToC(userid);
        !           986:                                if (what != 0)
        !           987:                                        fprintf(pgpout, "\n");
        !           988:                                fprintf(pgpout,PSTR("Also known as: %s\n"), EXTERNAL(userid));
        !           989:                        }
        !           990:                        if (print_trust)
        !           991:                        {
        !           992:                                read_trust(f, &keyctrl);
        !           993:                                switch (keyctrl & KC_LEGIT_MASK)
        !           994:                                {
        !           995:                                        case 0:         /* undefined certification level */
        !           996:                                        case 1:         /* uncertified */
        !           997:                                                fprintf(pgpout, PSTR("This key/userID association is not certified.\n"));
        !           998:                                                break;
        !           999:                                        case 2:         /* marginal certification */
        !          1000:                                                fprintf(pgpout, PSTR("This key/userID association is marginally certified.\n"));
        !          1001:                                                break;
        !          1002:                                        case 3:         /* complete certification */
        !          1003:                                                fprintf(pgpout, PSTR("This key/userID association is fully certified.\n"));
        !          1004:                                                break;
        !          1005:                                        default:        /* can't get here, right? */
        !          1006:                                                break;
        !          1007:                                }       /* switch */
        !          1008:                        }       /* print_trust */
        !          1009:                }
        !          1010:                else if ((what & SHOW_SIGS) && is_ctb_type(ctb, CTB_SKE_TYPE))
        !          1011:                {
        !          1012:                        if (print_trust)
        !          1013:                        {
        !          1014:                                read_trust(f, &keyctrl);
        !          1015:                                switch (TRUST_LEV(keyctrl))
        !          1016:                                {
        !          1017:                                        case KC_SIGTRUST_UNDEFINED:     /* undefined trust level */
        !          1018:                                        case KC_SIGTRUST_UNKNOWN:
        !          1019:                                                /* Just don't say anything in this case */
        !          1020:                                                fprintf(pgpout, PSTR("  Questionable certification from:\n  "));
        !          1021:                                                break;
        !          1022:                                        case KC_SIGTRUST_UNTRUSTED:     /* untrusted */
        !          1023:                                                fprintf(pgpout, PSTR("  Untrusted certification from:\n  "));
        !          1024:                                                break;
        !          1025:                                        case KC_SIGTRUST_MARGINAL:      /* marginal trust */
        !          1026:                                                fprintf(pgpout, PSTR("  Generally trusted certification from:\n  "));
        !          1027:                                                break;
        !          1028:                                        case KC_SIGTRUST_COMPLETE:      /* complete trust */
        !          1029:                                                fprintf(pgpout, PSTR("  Completely trusted certification from:\n  "));
        !          1030:                                                break;
        !          1031:                                        case KC_SIGTRUST_ULTIMATE:      /* axiomatic, ultimate trust */
        !          1032:                                                fprintf(pgpout, PSTR("  Axiomatically trusted certification from:\n  "));
        !          1033:                                                break;
        !          1034:                                        default:        /* can't get here, right? */
        !          1035:                                                break;
        !          1036:                                }       /* switch */
        !          1037:                        }
        !          1038:                        else
        !          1039:                                fprintf(pgpout, PSTR("  Certified by: "));
        !          1040:                        show_userid(f, sigkeyID);
        !          1041:                }
        !          1042:        }
        !          1043:        if (status == -1 && userids)
        !          1044:                status = 0;
        !          1045:        set_precision(precision);
        !          1046:        fseek(f, filepos, SEEK_SET);
        !          1047:        return(status);
        !          1048: }
        !          1049: 
        !          1050: 
        !          1051: void
        !          1052: write_trust_pos(FILE *f, byte keyctrl, long pos)
        !          1053: {
        !          1054:        long fpos;
        !          1055: 
        !          1056:        fpos = ftell(f);
        !          1057:        fseek(f, pos, SEEK_SET);
        !          1058:        write_trust(f, keyctrl);
        !          1059:        fseek(f, fpos, SEEK_SET);
        !          1060: }
        !          1061: 
        !          1062: int
        !          1063: read_trust(FILE *f, byte *keyctrl)
        !          1064: {
        !          1065:        unsigned char buf[3];
        !          1066: 
        !          1067:        if (fread(buf, 1, 3, f) != 3)
        !          1068:                return -1;
        !          1069:        if (buf[0] != CTB_KEYCTRL)
        !          1070:        {
        !          1071:                if (is_ctb(buf[0]))
        !          1072:                        return(ERR_NOTRUST);
        !          1073:                 else
        !          1074:                        return(-3);             /* bad data */
        !          1075:        }
        !          1076:        if (buf[1] != 1)                /* length must be 1 */
        !          1077:                return(-3);
        !          1078:        if (keyctrl)
        !          1079:                *keyctrl = buf[2];
        !          1080:        return(0);
        !          1081: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.