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

1.1.1.2 ! 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: /*
        !           102:  * do a maintenance pass on keyring "ringfile"
        !           103:  * options can be:
        !           104:  *     MAINT_CHECK             check keyring only, "ringfile" will not be changed
        !           105:  *     MAINT_SILENT    used for implicit maintenance pass, does not print keyring contents
        !           106:  *     MAINT_VERBOSE   verbose output, shows signature chains
        !           107:  */
        !           108: int
        !           109: maintenance(char *ringfile, int options)
        !           110: {
        !           111:        FILE *f, *g;
        !           112:        int status;
        !           113:        char *tmpring;
        !           114:        char secretkeyring[MAX_PATH];
        !           115:        extern boolean moreflag;
        !           116: 
        !           117:        check_only = (options & MAINT_CHECK) != 0;
        !           118:        mverbose = (options & MAINT_VERBOSE) != 0;
        !           119:        undefined_trust = 0;
        !           120:        if (max_cert_depth > 8)
        !           121:                max_cert_depth = 8;
        !           122: 
        !           123:        if ((tmpring = tempfile(TMP_TMPDIR)) == NULL)
        !           124:                return(-1);
        !           125:        if ((g = fopen(tmpring, FOPWPBIN)) == NULL)
        !           126:                return(-1);
        !           127: 
        !           128:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
        !           129:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
        !           130:                fclose(g);
        !           131:                return(-1);
        !           132:        }
        !           133: 
        !           134:        buildfilename(secretkeyring, SECRET_KEYRING_FILENAME);
        !           135:        if ((sec_fp = fopen(secretkeyring, FOPRBIN)) == NULL)
        !           136:                fprintf(pgpout,PSTR("\nCan't open secret key ring file '%s'\n"),
        !           137:                                secretkeyring);
        !           138: 
        !           139:        if (!(options & MAINT_SILENT) && *floppyring != '\0' &&
        !           140:                (floppy_fp = fopen(floppyring, FOPRBIN)) == NULL)
        !           141:                fprintf(pgpout,PSTR("\nCan't open backup key ring file '%s'\n"),
        !           142:                                floppyring);
        !           143: 
        !           144:        if ((status = copyfile(f, g, -1L)) < 0)
        !           145:        {       fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"), ringfile);
        !           146:                goto failed;
        !           147:        }
        !           148:   
        !           149:        if (moreflag && !(options & MAINT_SILENT))
        !           150:                open_more();
        !           151: 
        !           152:        setup_trust();
        !           153:        if (mverbose)
        !           154:                fprintf(pgpout, PSTR("\nPass 1: Looking for the \"ultimately-trusted\" keys...\n"));
        !           155:        rewind(g);
        !           156:        if ((status = maint_pass1(g)) < 0)
        !           157:                goto failed;
        !           158: 
        !           159:        if (mverbose)
        !           160:                fprintf(pgpout, PSTR("\nPass 2: Tracing signature chains...\n"));
        !           161:        rewind(g);
        !           162:        if ((status = maint_trace_chain(g)) < 0)
        !           163:                goto failed;
        !           164: 
        !           165:        if (!(options & MAINT_SILENT))
        !           166:        {       if (mverbose)
        !           167:                        fprintf(pgpout, PSTR("\nPass 3: Comparing with original keyring...\n"));
        !           168:                rewind(f);
        !           169:                rewind(g);
        !           170:                if ((status = maint_cmpfiles(f, g)) < 0)
        !           171:                        goto failed;
        !           172:        } else
        !           173:                status = 1;
        !           174: 
        !           175:        close_more();
        !           176:        if (write_error(g))
        !           177:        {       status = -1;
        !           178:                goto failed;
        !           179:        }
        !           180:        fclose(f);
        !           181:        fclose(g);
        !           182:        if (sec_fp)
        !           183:                fclose(sec_fp);
        !           184:        if (floppy_fp)
        !           185:        {       fclose(floppy_fp);
        !           186:                floppy_fp = NULL;
        !           187:        }
        !           188: 
        !           189: #ifdef DEBUG
        !           190:        if (check_only)
        !           191:        {
        !           192:                if (undefined_trust)
        !           193:                        fprintf(pgpout, "\nKeyring contains %d fully validated key(s) with undefined trust.\n", undefined_trust);
        !           194:                else
        !           195:                        if (status == 0)
        !           196:                                fprintf(pgpout, "\nMaintenance check OK.\n");
        !           197:                rmtemp(tmpring);
        !           198:                return(0);
        !           199:        }
        !           200: #endif
        !           201: 
        !           202:        if (status > 0)         /* keyring is changed */
        !           203:        {
        !           204:                if (options & MAINT_SILENT)
        !           205:                {       /* implicit maintenance pass (after pgp -ka, -kr, -ks) */
        !           206:                        remove(ringfile);
        !           207:                        if (savetemp(tmpring, ringfile) == NULL)
        !           208:                                return(-1);
        !           209:                }
        !           210:                else
        !           211:                {       /* explicit maintenance pass */
        !           212:                        fprintf(pgpout, PSTR("Update public keyring '%s' (Y/n)? "), ringfile);
        !           213:                        if (!getyesno('y'))
        !           214:                        {
        !           215:                                rmtemp(tmpring);
        !           216:                                return(0);
        !           217:                        }
        !           218:                        if (savetempbak(tmpring, ringfile))
        !           219:                                return(-1);
        !           220:                }
        !           221:        }
        !           222:        else
        !           223:                rmtemp(tmpring);
        !           224: 
        !           225:        return(0);
        !           226: 
        !           227: failed:
        !           228:        close_more();
        !           229:        if (sec_fp)
        !           230:                fclose(sec_fp);
        !           231:        if (floppy_fp)
        !           232:        {       fclose(floppy_fp);
        !           233:                floppy_fp = NULL;
        !           234:        }
        !           235:        fclose(f);
        !           236:        fclose(g);
        !           237: #ifdef DEBUG
        !           238:        savetempbak(tmpring, "tmpring.pub");
        !           239: #else
        !           240:        rmtemp(tmpring);
        !           241: #endif
        !           242:        return(status);
        !           243: }      /* maintenance */
        !           244: 
        !           245: 
        !           246: /*
        !           247:  * check if axiomatic keys are present in the secret keyring and
        !           248:  * clear userid and signature trust bytes
        !           249:  */
        !           250: int
        !           251: maint_pass1(FILE *f)
        !           252: {
        !           253:        int status;
        !           254:        char userid[256];
        !           255:        byte keyID[KEYFRAGSIZE];
        !           256:        byte ctb;
        !           257:        byte keyctrl;
        !           258:        boolean buckstop = FALSE, show_user = FALSE;
        !           259:        boolean compromised = FALSE;
        !           260:        int buckstopcount = 0;
        !           261:        int usercount = 0;
        !           262:        long keypos = 0;
        !           263: 
        !           264:        while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1)
        !           265:        {
        !           266:                if (status == -3)
        !           267:                        return(status);
        !           268:                if (status < 0)
        !           269:                        continue;
        !           270: 
        !           271:                if (is_ctb_type(ctb, CTB_COMMENT_TYPE) || ctb == CTB_KEYCTRL)
        !           272:                        continue;
        !           273:                if (compromised && is_ctb_type(ctb, CTB_SKE_TYPE) && !usercount)
        !           274:                        continue;       /* compromise certificate */
        !           275: 
        !           276:                /* other packets should have trust byte */
        !           277:                if (read_trust(f, &keyctrl) < 0)
        !           278:                        return(ERR_NOTRUST);            /* not a public keyring */
        !           279: 
        !           280:                if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
        !           281:                {
        !           282:                        if (compromised = is_compromised(f))
        !           283:                                keyctrl = KC_OWNERTRUST_NEVER;
        !           284:                        if ((keyctrl & KC_BUCKSTOP))
        !           285:                        {
        !           286:                                if (check_secretkey(f, keypos) == 0)
        !           287:                                {
        !           288:                                        ++buckstopcount;
        !           289:                                        buckstop = TRUE;
        !           290:                                        if (mverbose)
        !           291:                                                fprintf(pgpout, "* %s",keyIDstring(keyID));
        !           292:                                }
        !           293:                                else
        !           294:                                {       /* not in secret keyring */
        !           295:                                        keyctrl &= ~KC_BUCKSTOP;
        !           296:                                        if (TRUST_LEV(keyctrl) == KC_OWNERTRUST_ULTIMATE)
        !           297:                                                keyctrl = KC_OWNERTRUST_ALWAYS;
        !           298:                                        if (mverbose)
        !           299:                                                fprintf(pgpout, ". %s",keyIDstring(keyID));
        !           300:                                }
        !           301:                                show_user = mverbose;
        !           302:                        }
        !           303:                        else
        !           304:                        {
        !           305:                                buckstop = FALSE;
        !           306:                                show_user = FALSE;
        !           307:                        }
        !           308:                        usercount = 0;
        !           309:                        keyctrl &= ~KC_VISITED;
        !           310: 
        !           311:                }
        !           312:                else if (ctb == CTB_USERID)
        !           313:                {
        !           314:                        if (show_user)
        !           315:                        {
        !           316:                                if (usercount)          /* more than one user ID */
        !           317:                                        fprintf(pgpout, "        ");
        !           318:                                fprintf(pgpout, "  %s\n", LOCAL_CHARSET(userid));
        !           319:                        }
        !           320:                        keyctrl &= ~KC_LEGIT_MASK;
        !           321:                        if (buckstop)
        !           322:                                keyctrl |= KC_LEGIT_COMPLETE;
        !           323:                        else
        !           324:                                keyctrl |= KC_LEGIT_UNKNOWN;
        !           325:                        ++usercount;
        !           326:                }
        !           327:                else if (is_ctb_type(ctb, CTB_SKE_TYPE))
        !           328:                {
        !           329:                        keyctrl = KC_SIGTRUST_UNDEFINED;
        !           330:                }
        !           331:                fseek(f, -1L, SEEK_CUR);
        !           332:                fwrite(&keyctrl, 1, 1, f);
        !           333:                fseek(f, 0L, SEEK_CUR);
        !           334:                keypos = ftell(f);
        !           335:        }
        !           336:        if (buckstopcount == 0 && mverbose)
        !           337:        {
        !           338:                fprintf(pgpout, PSTR("No ultimately-trusted keys.\n"));
        !           339:        }
        !           340:        return(0);
        !           341: }
        !           342: 
        !           343: 
        !           344: /*
        !           345:  * scan keyring for buckstop keys and start the recursive trace_sig_chain()
        !           346:  * on them
        !           347:  */
        !           348: int
        !           349: maint_trace_chain(FILE *f)
        !           350: {
        !           351:        int status;
        !           352:        char userid[256];
        !           353:        byte keyID[KEYFRAGSIZE];
        !           354:        long trustpos = 0;
        !           355:        byte ctb;
        !           356:        byte own_trust;
        !           357:        boolean buckstop = FALSE;
        !           358: 
        !           359:        while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1)
        !           360:        {
        !           361:                if (status == -3)
        !           362:                        return(status);
        !           363:                if (status < 0)
        !           364:                        continue;
        !           365: 
        !           366:                if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
        !           367:                {
        !           368:                        trustpos = ftell(f);
        !           369:                        if ((status = read_trust(f, &own_trust)) < 0)
        !           370:                                return(status);
        !           371:                        buckstop = (own_trust & KC_BUCKSTOP) != 0;
        !           372:                        userid[0] = '\0';
        !           373:                }
        !           374:                else if (ctb == CTB_USERID)
        !           375:                {
        !           376:                        if (buckstop)
        !           377:                        {
        !           378:                                buckstop = FALSE;       /* only for first user id */
        !           379:                                if (mverbose)
        !           380:                                        fprintf(pgpout, "* %s\n", LOCAL_CHARSET(userid));
        !           381: 
        !           382:                                if (TRUST_LEV(own_trust) == KC_OWNERTRUST_UNDEFINED)
        !           383:                                {       SET_TRUST(&own_trust, ask_owntrust(userid, own_trust));
        !           384:                                        write_trust_pos(f, own_trust, trustpos);
        !           385:                                }
        !           386:                                if (trace_sig_chain(f, keyID, TRUST_LEV(own_trust), 0) < 0)
        !           387:                                        return(-1);
        !           388:                        }
        !           389:                }
        !           390:        }
        !           391:        return(0);
        !           392: }
        !           393: 
        !           394: 
        !           395: /* 
        !           396:  * check if the maintenance pass changed anything
        !           397:  * returns 0 if files f and g are equal and the number of changed
        !           398:  * trust bytes if the files are different or a negative value on error
        !           399:  */
        !           400: int
        !           401: maint_cmpfiles(FILE *f, FILE *g)
        !           402: {
        !           403:        int status;
        !           404:        char userid[256];
        !           405:        byte keyID[KEYFRAGSIZE];
        !           406:        byte sigkeyID[KEYFRAGSIZE];
        !           407:        byte ctb;
        !           408:        byte kc_orig, kc_new;
        !           409:        int usercount = 0;
        !           410:        int changed = 0;
        !           411: 
        !           412:        fprintf(pgpout, PSTR("  KeyID   Trust      Validity  User ID\n"));
        !           413:        while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) != -1)
        !           414:        {
        !           415:                if (status == -3)
        !           416:                        break;
        !           417:                if (status < 0)
        !           418:                        continue;
        !           419:                if (is_ctb_type(ctb, CTB_COMMENT_TYPE))
        !           420:                        continue;
        !           421:                 /* unexpected trust packet, probably after version error */
        !           422:                if (ctb == CTB_KEYCTRL)
        !           423:                        continue;
        !           424: 
        !           425:                /* other packets should have trust byte */
        !           426:                fseek(g, ftell(f), SEEK_SET);
        !           427:                if (read_trust(f, &kc_orig) < 0 || read_trust(g, &kc_new) < 0)
        !           428:                {       status = ERR_NOTRUST;
        !           429:                        break;
        !           430:                }
        !           431: 
        !           432:                if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
        !           433:                {
        !           434:                        if (is_compromised(f))
        !           435:                        {
        !           436:                                fprintf(pgpout, "# ");
        !           437:                                nextkeypacket(f, &ctb); /* skip compromise certificate */
        !           438:                                nextkeypacket(g, &ctb);
        !           439:                        }
        !           440:                        else if ((kc_new & KC_BUCKSTOP))
        !           441:                                fprintf(pgpout, "* ");
        !           442:                        else
        !           443:                                fprintf(pgpout, "  ");
        !           444: 
        !           445:                        fprintf(pgpout, "%s ",keyIDstring(keyID));
        !           446:                        changed += show_trust(kc_new, kc_orig);
        !           447:                        usercount = 0;
        !           448:                        userid[0] = '\0';
        !           449:                }
        !           450:                else if (ctb == CTB_USERID)
        !           451:                {
        !           452:                        if (usercount)          /* more than one user ID */
        !           453:                                fprintf(pgpout, "         %*s ", trustlst_len, "");
        !           454:                        ++usercount;
        !           455:                        changed += show_legit(kc_new, kc_orig);
        !           456:                        fprintf(pgpout, "%s\n", LOCAL_CHARSET(userid));
        !           457:                }
        !           458:                else if (is_ctb_type(ctb, CTB_SKE_TYPE))
        !           459:                {
        !           460:                        if (kc_new & KC_CONTIG)
        !           461:                                fprintf(pgpout, "c        ");
        !           462:                        else
        !           463:                                fprintf(pgpout, "         ");
        !           464:                        changed += show_trust(kc_new, kc_orig);
        !           465:                        fprintf(pgpout, "%*s   ", legitlst_len, "");
        !           466:                        show_userid(f, sigkeyID);
        !           467:                }
        !           468:        }
        !           469:        if (status >= -1 && changed)
        !           470:                fprintf(pgpout, PSTR("\n%d \"trust parameter(s)\" changed.\n"), changed);
        !           471:        if (status < -1)        /* -1 is OK, EOF */
        !           472:                return(status);
        !           473:        return(changed);
        !           474: }      /* maint_cmpfiles */
        !           475: 
        !           476: 
        !           477: /*
        !           478:  * translate the messages in the arrays trust_lst and legit_lst.
        !           479:  * trustlst_len and legitlst_len will be set to the length of
        !           480:  * the longest translated string.
        !           481:  */
        !           482: void
        !           483: init_trust_lst()
        !           484: {
        !           485:        static int initialized = 0;
        !           486:        int i, len;
        !           487:        char *s;
        !           488: 
        !           489:        if (initialized)
        !           490:                return;
        !           491:        for (i = 0; i < 8; ++i)
        !           492:        {       if (trust_lst[i][0])
        !           493:                {       s = PSTR (trust_lst[i]);
        !           494:                        if (s != trust_lst[i])
        !           495:                                strncpy(trust_lst[i], s, sizeof(trust_lst[0]) - 1);
        !           496:                        len = strlen(s);
        !           497:                        if (len > trustlst_len)
        !           498:                                trustlst_len = len;
        !           499:                }
        !           500:        }
        !           501:        for (i = 0; i < 4; ++i)
        !           502:        {       s = PSTR (legit_lst[i]);
        !           503:                if (s != legit_lst[i])
        !           504:                        strncpy(legit_lst[i], s, sizeof(legit_lst[0]) - 1);
        !           505:                len = strlen(s);
        !           506:                if (len > legitlst_len)
        !           507:                        legitlst_len = len;
        !           508:        }
        !           509:        ++trustlst_len;
        !           510:        ++legitlst_len;
        !           511:        initialized = 1;
        !           512: }      /* init_trust_lst */
        !           513: 
        !           514: /*
        !           515:  * show the trust level of trust byte kc_new.  If it is
        !           516:  * different from the old level (kc_orig) the print a '!' before
        !           517:  * the level string
        !           518:  */
        !           519: int
        !           520: show_trust(byte kc_new, byte kc_orig)
        !           521: {
        !           522: #ifdef DEBUG
        !           523:        fprintf(pgpout, " %02x", kc_new);
        !           524:        if (kc_new != kc_orig)
        !           525:        {
        !           526:                fprintf(pgpout, " (%02x)    ", kc_orig);
        !           527:                return(1);
        !           528:        }
        !           529:        fprintf(pgpout, "        ");
        !           530:        return(0);
        !           531: #else
        !           532:        init_trust_lst();
        !           533:        fprintf(pgpout, "%c%-*s", (kc_new == kc_orig ? ' ' : '!'),
        !           534:                        trustlst_len, trust_lst[TRUST_LEV(kc_new)]);
        !           535:        return(kc_new != kc_orig);
        !           536: #endif
        !           537: }      /* show_trust */
        !           538: 
        !           539: /*
        !           540:  * show_legit is the same as show_trust, only it uses legit_lst
        !           541:  * for messages
        !           542:  */
        !           543: int
        !           544: show_legit(byte kc_new, byte kc_orig)
        !           545: {
        !           546: #ifdef DEBUG
        !           547:        return(show_trust(kc_new, kc_orig));
        !           548: #else
        !           549:        init_trust_lst();
        !           550:        kc_new &= KC_LEGIT_MASK;
        !           551:        kc_orig &= KC_LEGIT_MASK;
        !           552:        fprintf(pgpout, "%c%-*s", (kc_new == kc_orig ? ' ' : '!'),
        !           553:                        legitlst_len, legit_lst[kc_new]);
        !           554:        return(kc_new != kc_orig);
        !           555: #endif
        !           556: }      /* show_legit */
        !           557: 
        !           558: 
        !           559: /*
        !           560:  * Find all signatures made with a key, fromID is the keyID of this key
        !           561:  * owner_trust is the trust level of this key.
        !           562:  * If a trusted signature makes a key fully legit then signatures made
        !           563:  * with this key are also recursively traced on down the tree.
        !           564:  *
        !           565:  * The file f is the public keyring, it must be open for update.
        !           566:  * depth is the level of recursion, it is used to indent the userIDs
        !           567:  * and to check if we don't exceed the limit "max_cert_depth"
        !           568:  *
        !           569:  * fromID should be the keyID of a fully validated key.
        !           570:  */
        !           571: int
        !           572: trace_sig_chain(FILE *f, byte *fromID, int owner_trust, int depth)
        !           573: {
        !           574:        long filepos;
        !           575:        int status;
        !           576:        int trust_count = 0;
        !           577:        byte keyID[KEYFRAGSIZE];
        !           578:        byte sigkeyID[KEYFRAGSIZE];
        !           579:        byte ctb;
        !           580:        byte own_trust, sig_trust;
        !           581:        char userid[256];
        !           582:        int sig_count = 0;
        !           583:        int compromised = 0;
        !           584:        long usertrustpos = 0;
        !           585:        long ownt_pos = 0;
        !           586:        boolean fromsig = FALSE;
        !           587: 
        !           588: #ifdef DEBUG
        !           589:        if (mverbose)
        !           590:                fprintf(pgpout, "%*s--- %s\n", 2*depth, "", keyIDstring(fromID));
        !           591: #endif
        !           592:        filepos = ftell(f);
        !           593:        rewind(f);
        !           594:        userid[0] = '\0';
        !           595:        while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) != -1)
        !           596:        {
        !           597:                if (status == -3)
        !           598:                        return(status);
        !           599:                if (status < 0)
        !           600:                        continue;
        !           601: 
        !           602:                if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
        !           603:                {
        !           604:                        compromised = is_compromised(f);
        !           605:                        ownt_pos = ftell(f);
        !           606:                        if (read_trust(f, &own_trust))
        !           607:                                return(ERR_NOTRUST);
        !           608:                        userid[0] = '\0';
        !           609:                }
        !           610:                else if (ctb == CTB_USERID)
        !           611:                {
        !           612:                        usertrustpos = ftell(f);
        !           613:                        trust_count = 0;
        !           614:                        fromsig = FALSE;
        !           615:                }
        !           616:                else if (is_ctb_type(ctb, CTB_SKE_TYPE))
        !           617:                {       /* signature packet */
        !           618:                        if (compromised)
        !           619:                                continue;
        !           620:                        read_trust(f, &sig_trust);
        !           621:                        /* we're looking for signatures made by "fromID" */
        !           622:                        if (memcmp(sigkeyID, fromID, sizeof(sigkeyID)) == 0)
        !           623:                        {
        !           624:                                ++sig_count;
        !           625:                                if (mverbose)
        !           626:                                        fprintf(pgpout, "%*s  > %s\n", 2*depth, "", 
        !           627:                                                LOCAL_CHARSET(userid));
        !           628:                                if (TRUST_LEV(sig_trust) != owner_trust)
        !           629:                                {
        !           630:                                        SET_TRUST(&sig_trust, owner_trust);
        !           631:                                }
        !           632:                                sig_trust |= KC_CONTIG;
        !           633:                                fseek(f, -1L, SEEK_CUR);
        !           634:                                fwrite(&sig_trust, 1, 1, f);
        !           635:                                fseek(f, 0L, SEEK_CUR);
        !           636:                                fromsig = TRUE;
        !           637:                        }
        !           638: 
        !           639:                        if (sig_trust & KC_CONTIG)
        !           640:                        {
        !           641:                                trust_count += TRUST_FAC(sig_trust);
        !           642: 
        !           643:                                if (fromsig)    /* fromID has signed this key */
        !           644:                                {
        !           645:                                        switch (set_legit(f, usertrustpos, trust_count))
        !           646:                                        {
        !           647:                                        case -1: return(-1);
        !           648:                                        case  1:        /* this signature made the key fully valid */
        !           649:                                                if ((own_trust & (KC_BUCKSTOP|KC_VISITED)) == 0)
        !           650:                                                {
        !           651:                                                        if (TRUST_LEV(own_trust) == KC_OWNERTRUST_UNDEFINED)
        !           652:                                                                SET_TRUST(&own_trust, ask_owntrust(userid, own_trust));
        !           653:                                                        if (depth < max_cert_depth)
        !           654:                                                                own_trust |= KC_VISITED;
        !           655:                                                        write_trust_pos(f, own_trust, ownt_pos);
        !           656:                                                        if (depth < max_cert_depth)
        !           657:                                                                trace_sig_chain(f, keyID, TRUST_LEV(own_trust), depth+1);
        !           658:                                                }
        !           659:                                        }
        !           660:                                }
        !           661:                        }
        !           662:                }
        !           663:        }
        !           664: #ifdef DEBUG
        !           665:        if (mverbose && sig_count == 0) /* no signatures from this user */
        !           666:                fprintf(pgpout, PSTR("%*s  (No signatures)\n"), 2*depth, "");
        !           667:        if (mverbose)
        !           668:                fprintf(pgpout, "%*s--- %s\n", 2*depth, "", keyIDstring(fromID));
        !           669: #endif
        !           670:        fseek(f, filepos, SEEK_SET);
        !           671:        return(0);
        !           672: }      /* trace_sig_chain */
        !           673: 
        !           674: 
        !           675: /*
        !           676:  * compare the key in file f at keypos with the matching key in the
        !           677:  * secret keyring, the global variable sec_fp must contain the file pointer
        !           678:  * for of the secret keyring.
        !           679:  *
        !           680:  * returns 1 if the key was not found, -2 if the keys were different
        !           681:  * and 0 if the keys compared OK
        !           682:  */
        !           683: int
        !           684: check_secretkey(FILE *f, long keypos)
        !           685: {
        !           686:        int status = -1;
        !           687:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
        !           688:        unit nsec[MAX_UNIT_PRECISION], esec[MAX_UNIT_PRECISION];
        !           689:        char userid[256];
        !           690:        byte keyID[KEYFRAGSIZE];
        !           691:        long savepos, pktlen;
        !           692:        byte ctb;
        !           693: 
        !           694:        if (sec_fp == NULL)
        !           695:                return(-1);
        !           696: 
        !           697:        savepos = ftell(f);
        !           698:        fseek(f, keypos, SEEK_SET);
        !           699:        if (readkeypacket(f, FALSE, &ctb, NULL, NULL, n, e,
        !           700:                                        NULL, NULL, NULL, NULL, NULL, NULL) < 0)
        !           701:                goto ex;
        !           702:        extract_keyID(keyID, n);
        !           703: 
        !           704:        do      /* get userid */
        !           705:        {       status = readkpacket(f, &ctb, userid, NULL, NULL);
        !           706:                if (status == -1 || status == -3)
        !           707:                        goto ex;
        !           708:        } while (ctb != CTB_USERID);
        !           709: 
        !           710:        if (lookup_by_keyID(sec_fp, keyID) < 0)
        !           711:        {
        !           712: #if 0
        !           713:                if (!check_only)
        !           714:                {
        !           715:                        fprintf(pgpout, PSTR (
        !           716: "\nAn \"axiomatic\" key is one which does not need certifying by\n\
        !           717: anyone else.  Usually this special status is reserved only for your\n\
        !           718: own keys, which should also appear on your secret keyring.  The owner\n\
        !           719: of an axiomatic key (who is typically yourself) is \"ultimately trusted\"\n\
        !           720: by you to certify any or all other keys.\n"));
        !           721:                        fprintf(pgpout, PSTR ("\nKey for user ID: \"%s\"\n\
        !           722: is designated as an \"ultimately-trusted\" introducer, but the key\n\
        !           723: does not appear in the secret keyring.\n\
        !           724: Use this key as an ultimately-trusted introducer (y/N)? "), 
        !           725:                                LOCAL_CHARSET(userid));
        !           726:                        status = (getyesno('n') ? 0 : 1);
        !           727:                }
        !           728: #else
        !           729:                status = 1;
        !           730: #endif
        !           731:        }
        !           732:        else
        !           733:        {
        !           734:                long kpos = ftell(sec_fp);
        !           735:                if (readkeypacket(sec_fp, FALSE, &ctb, NULL, NULL, nsec, esec,
        !           736:                                                NULL, NULL, NULL, NULL, NULL, NULL) < 0)
        !           737:                {
        !           738:                        fprintf(pgpout, PSTR("\n\007Cannot read from secret keyring.\n"));
        !           739:                        status = -3;
        !           740:                        goto ex;
        !           741:                }
        !           742:                if (mp_compare(n, nsec) || mp_compare(e, esec))
        !           743:                {       /* Red Alert! */
        !           744:                        fprintf(pgpout, PSTR("\n\007WARNING: Public key for user ID: \"%s\"\n\
        !           745: does not match the corresponding key in the secret keyring.\n"), 
        !           746:                                LOCAL_CHARSET(userid));
        !           747:                        fprintf(pgpout, PSTR("This is a serious condition, indicating possible keyring tampering.\n"));
        !           748:                        status = -2;
        !           749:                }
        !           750:                else
        !           751:                        status = 0;
        !           752: 
        !           753:                if (floppy_fp)
        !           754:                {
        !           755:                        if (lookup_by_keyID(floppy_fp, keyID) < 0)
        !           756:                        {
        !           757:                                fprintf(pgpout, PSTR("Public key for: \"%s\"\n\
        !           758: is not present in the backup keyring '%s'.\n"),
        !           759:                                        LOCAL_CHARSET(userid), floppyring);
        !           760:                        }
        !           761:                        else
        !           762:                        {
        !           763:                                pktlen = ftell(sec_fp) - kpos;
        !           764:                                fseek(sec_fp, kpos, SEEK_SET);
        !           765:                                while (--pktlen >= 0 && getc(sec_fp) == getc(floppy_fp)) ;
        !           766:                                if (pktlen != -1)
        !           767:                                {
        !           768:                                        fprintf(pgpout, PSTR("\n\007WARNING: Secret key for: \"%s\"\n\
        !           769: does not match the key in the backup keyring '%s'.\n"),
        !           770:                                                LOCAL_CHARSET(userid), floppyring);
        !           771:                                        fprintf(pgpout, PSTR("This is a serious condition, indicating possible keyring tampering.\n"));
        !           772:                                        status = -2;
        !           773:                                }
        !           774:                        }
        !           775:                }
        !           776:        }
        !           777: ex:
        !           778:        fseek(f, savepos, SEEK_SET);
        !           779:        return(status);
        !           780: }      /* check_secretkey */
        !           781: 
        !           782: 
        !           783: /*
        !           784:  * setup tables for trust scoring.
        !           785:  */
        !           786: void
        !           787: setup_trust()
        !           788: {      /* initialize trust table */
        !           789:        if (marg_min == 0)      /* marginally trusted signatures are ignored */
        !           790:        {
        !           791:                trust_tbl[5] = 0;
        !           792:                trust_tbl[6] = 1;
        !           793:                complete_min = compl_min;
        !           794:        }
        !           795:        else
        !           796:        {
        !           797:                if (marg_min < compl_min)
        !           798:                        marg_min = compl_min;
        !           799:                trust_tbl[5] = compl_min;
        !           800:                trust_tbl[6] = marg_min;
        !           801:                complete_min = compl_min * marg_min;
        !           802:        }
        !           803:        trust_tbl[7] = complete_min;    /* ultimate trust */
        !           804:        marginal_min = complete_min / 2;
        !           805: }      /* setup_trust */
        !           806: 
        !           807: 
        !           808: /*
        !           809:  * set valid level of a userid, computed from trust_count.
        !           810:  * returns 1 if the key/userid pair is fully legit.
        !           811:  */
        !           812: int
        !           813: set_legit(FILE *f, long trustpos, int trust_count)
        !           814: {
        !           815:        long filepos;
        !           816:        byte keyctrl;
        !           817: 
        !           818:        filepos = ftell(f);
        !           819:        fseek(f, trustpos, SEEK_SET);   /* user id trust byte */
        !           820:        if (read_trust(f, &keyctrl) < 0)
        !           821:                return(-1);
        !           822:        
        !           823:        keyctrl &= ~KC_LEGIT_MASK;
        !           824:        if (trust_count < marginal_min)
        !           825:                keyctrl |= KC_LEGIT_UNTRUSTED;
        !           826:        else if (trust_count < complete_min)
        !           827:                keyctrl |= KC_LEGIT_MARGINAL;
        !           828:        else
        !           829:                keyctrl |= KC_LEGIT_COMPLETE;
        !           830:        
        !           831:        fseek(f, trustpos, SEEK_SET);
        !           832:        write_trust(f, keyctrl);
        !           833: 
        !           834:        fseek(f, filepos, SEEK_SET);
        !           835: 
        !           836:        if ((keyctrl & KC_LEGIT_MASK) == KC_LEGIT_COMPLETE)
        !           837:                return(1);
        !           838:        else
        !           839:                return(0);
        !           840: }      /* set_legit */
        !           841: 
        !           842: 
        !           843: int ask_owntrust(char *userid, byte cur_trust)
        !           844: /* Ask for a wetware decision from the human on how much to trust 
        !           845: this key's owner to certify other keys.  Returns trust value. */
        !           846: {
        !           847:        char buf[8];
        !           848: 
        !           849:        if (check_only)
        !           850:        {       ++undefined_trust;
        !           851:                return(KC_OWNERTRUST_UNDEFINED);
        !           852:        }
        !           853: 
        !           854:        fprintf(pgpout, 
        !           855: PSTR("\nMake a determination in your own mind whether this key actually\n\
        !           856: belongs to the person whom you think it belongs to, based on available\n\
        !           857: evidence.  If you think it does, then based on your estimate of\n\
        !           858: that person's integrity and competence in key management, answer\n\
        !           859: the following question:\n"));  
        !           860:        fprintf(pgpout, PSTR("\nWould you trust \"%s\"\n\
        !           861: to act as an introducer and certify other people's public keys to you?\n\
        !           862: (1=I don't know. 2=No. 3=Usually. 4=Yes, always.) ? "), 
        !           863:                LOCAL_CHARSET(userid));
        !           864:        fflush(pgpout);
        !           865:        getstring(buf, sizeof(buf)-1, TRUE);
        !           866:        switch (buf[0])
        !           867:        {       case '1': return KC_OWNERTRUST_UNKNOWN;
        !           868:                case '2': return KC_OWNERTRUST_NEVER;
        !           869:                case '3': return KC_OWNERTRUST_USUALLY;
        !           870:                case '4': return KC_OWNERTRUST_ALWAYS;
        !           871:                default: return(TRUST_LEV(cur_trust));
        !           872:        }
        !           873: }      /* ask_owntrust */
        !           874: 
        !           875: 
        !           876: /* 
        !           877:  * compare all key packets in keyring file f with file g
        !           878:  * XXX: untested
        !           879:  */
        !           880: int
        !           881: keyring_cmp(FILE *f, FILE *g)
        !           882: {
        !           883:        int status, error = 0, badkeys = 0;
        !           884:        byte ctb;
        !           885:        byte keyID[KEYFRAGSIZE];
        !           886:        char userid[256];
        !           887:        long pktlen, keypos = 0;
        !           888: 
        !           889:        rewind(f);
        !           890:        while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1)
        !           891:        {
        !           892:                if (status == -3)
        !           893:                        return(status);
        !           894:                if (status < 0)
        !           895:                        continue;
        !           896:                if (is_key_ctb(ctb))
        !           897:                {
        !           898:                        pktlen = ftell(f) - keypos;
        !           899:                        fseek(f, keypos, SEEK_SET);
        !           900:                        if (lookup_by_keyID(g, keyID) < 0)
        !           901:                        {
        !           902:                                error = 1;
        !           903:                                continue;
        !           904:                        }
        !           905:                        while (--pktlen >= 0 && getc(f) == getc(g)) ;
        !           906:                        if (pktlen != -1)
        !           907:                        {
        !           908:                                error = 2;
        !           909:                                ++badkeys;
        !           910:                        }
        !           911: 
        !           912:                }
        !           913:                if (error && ctb == CTB_USERID)
        !           914:                {
        !           915:                        switch (error) {
        !           916:                                case 1: fprintf(pgpout, PSTR("\n\007Key for user ID \"%s\"\n\
        !           917: is not present in backup keyring\n"), LOCAL_CHARSET(userid));
        !           918:                                case 2: fprintf(pgpout, PSTR("\n\007Key for user ID \"%s\"\n\
        !           919: does not match key in backup keyring\n"), LOCAL_CHARSET(userid));
        !           920:                        }
        !           921:                        error = 0;
        !           922:                }
        !           923:                keypos = ftell(f);
        !           924:        }
        !           925:        if (error)
        !           926:                status = -5;
        !           927:        return(status < 0 ? status : badkeys);
        !           928: }      /* keyring_cmp */
        !           929: 
        !           930: 
        !           931: /*
        !           932:  * stripped down version of readkeypacket(), the output userid
        !           933:  * is a null terminated string.
        !           934:  */
        !           935: int
        !           936: readkpacket(FILE *f, byte *ctb, char *userid, byte *keyID, byte *sigkeyID)
        !           937: {
        !           938:        int status;
        !           939:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
        !           940: 
        !           941:        status = readkeypacket(f, FALSE, ctb, NULL, userid, n, e,
        !           942:                                        NULL, NULL, NULL, NULL, sigkeyID, NULL);
        !           943: 
        !           944:        if (status < 0)
        !           945:        {
        !           946: #ifdef DEBUG
        !           947:                if (status < -1)
        !           948:                        fprintf(stderr, "readkeypacket returned %d\n", status);
        !           949: #endif
        !           950:                return(status);
        !           951:        }
        !           952: 
        !           953:        if (keyID && is_key_ctb(*ctb))
        !           954:                extract_keyID(keyID, n);
        !           955: 
        !           956:        if (userid && *ctb == CTB_USERID)
        !           957:                PascalToC(userid);
        !           958: 
        !           959:        return(0);
        !           960: }      /* readkpacket */
        !           961: 
        !           962: 
        !           963: /*
        !           964:  * scan keyfile f for keyID srch_keyID.
        !           965:  * returns the file position of the key if it is found, and sets the
        !           966:  * file pointer to the start of the key packet.
        !           967:  * returns -1 if the key was not found or < -1 if there was an error
        !           968:  */
        !           969: long
        !           970: lookup_by_keyID(FILE *f, byte *srch_keyID)
        !           971: {
        !           972:        int status;
        !           973:        long keypos = 0;
        !           974:        byte keyID[KEYFRAGSIZE];
        !           975:        byte ctb;
        !           976: 
        !           977:        rewind(f);
        !           978:        while ((status = readkpacket(f, &ctb, NULL, keyID, NULL)) != -1)
        !           979:        {
        !           980:                if (status == -3)
        !           981:                        break;
        !           982:                if (status < 0)
        !           983:                        continue;
        !           984:                if (is_key_ctb(ctb) && memcmp(keyID, srch_keyID, KEYFRAGSIZE) == 0)
        !           985:                {
        !           986:                        fseek(f, keypos, SEEK_SET);
        !           987:                        return(keypos);
        !           988:                }
        !           989:                keypos = ftell(f);
        !           990:        }
        !           991:        return(status);
        !           992: }      /* lookup_by_keyID */
        !           993: 
        !           994: 
        !           995: /*
        !           996:  * look up the key matching "keyID" and print the first userID
        !           997:  * of this key.  File position of f is saved.
        !           998:  */
        !           999: void
        !          1000: show_userid(FILE *f, byte *keyID)
        !          1001: {
        !          1002:        int status;
        !          1003:        long filepos;
        !          1004:        char userid[256];
        !          1005:        byte ctb;
        !          1006: 
        !          1007:        filepos = ftell(f);
        !          1008:        if (lookup_by_keyID(f, keyID) >= 0)
        !          1009:                while ((status = readkpacket(f, &ctb, userid, NULL, NULL)) != -1 && status != -3)
        !          1010:                        if (ctb == CTB_USERID)
        !          1011:                        {
        !          1012:                                fprintf(pgpout, "%s\n", LOCAL_CHARSET(userid));
        !          1013:                                fseek(f, filepos, SEEK_SET);
        !          1014:                                return;
        !          1015:                        }
        !          1016: 
        !          1017:        fprintf(pgpout, "(KeyID: %s)\n",keyIDstring(keyID));
        !          1018:        fseek(f, filepos, SEEK_SET);
        !          1019: }      /* show_userid */
        !          1020: 
        !          1021: /*
        !          1022:  * show the key in file f at file position keypos.
        !          1023:  * 'what' controls the info that will be shown:
        !          1024:  *   SHOW_TRUST: show trust byte info
        !          1025:  *   SHOW_SIGS:  show signatures
        !          1026:  * these constants can be or'ed to get both
        !          1027:  */
        !          1028: int
        !          1029: show_key(FILE *f, long keypos, int what)
        !          1030: {
        !          1031:        int status;
        !          1032:        long filepos;
        !          1033:        char userid[256];
        !          1034:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
        !          1035:        byte sigkeyID[KEYFRAGSIZE];
        !          1036:        word32 timestamp;
        !          1037:        byte ctb, keyctrl;
        !          1038:        int userids = 0;
        !          1039:        boolean print_trust = FALSE;
        !          1040:        int precision = global_precision;
        !          1041: 
        !          1042:        filepos = ftell(f);
        !          1043:        fseek(f, keypos, SEEK_SET);
        !          1044:        while ((status = readkeypacket(f, FALSE, &ctb, (byte *)&timestamp, userid,
        !          1045:                                        n, e, NULL, NULL, NULL, NULL, sigkeyID, &keyctrl)) == 0)
        !          1046:        {
        !          1047:                if (is_key_ctb(ctb))
        !          1048:                {       if (userids)
        !          1049:                                break;
        !          1050:                }
        !          1051:                else if (ctb == CTB_KEYCTRL)  /* trust bytes only in public keyrings */
        !          1052:                {
        !          1053:                        if (what & SHOW_TRUST)
        !          1054:                                print_trust = TRUE;
        !          1055:                }
        !          1056:                else if (ctb == CTB_USERID)
        !          1057:                {       if (userids == 0)
        !          1058:                        {       PascalToC(userid);      /* for display */
        !          1059:                                fprintf(pgpout,PSTR("\nKey for user ID: %s\n"),
        !          1060:                                        LOCAL_CHARSET(userid));
        !          1061:                                fprintf(pgpout,PSTR("%d-bit key, Key ID %s, created %s\n"),
        !          1062:                                        countbits(n), key2IDstring(n), cdate(&timestamp) );
        !          1063:                                if (print_trust)
        !          1064:                                {
        !          1065:                                        switch (TRUST_LEV(keyctrl))
        !          1066:                                        {
        !          1067:                                                case KC_OWNERTRUST_UNDEFINED:
        !          1068:                                                case KC_OWNERTRUST_UNKNOWN:
        !          1069:                                                        /* Just don't say anything in this case */
        !          1070:                                                        break;
        !          1071:                                                case KC_OWNERTRUST_NEVER:       /* untrusted */
        !          1072:                                                        fprintf(pgpout, PSTR("This user is untrusted to certify other keys.\n"));
        !          1073:                                                        break;
        !          1074:                                                case KC_OWNERTRUST_USUALLY:     /* marginal trust */
        !          1075:                                                        fprintf(pgpout, PSTR("This user is generally trusted to certify other keys.\n"));
        !          1076:                                                        break;
        !          1077:                                                case KC_OWNERTRUST_ALWAYS:      /* complete trust */
        !          1078:                                                        fprintf(pgpout, PSTR("This user is completely trusted to certify other keys.\n"));
        !          1079:                                                        break;
        !          1080:                                                case KC_OWNERTRUST_ULTIMATE:    /* axiomatic, ultimate trust */
        !          1081:                                                        fprintf(pgpout, PSTR("This axiomatic key is ultimately trusted to certify other keys.\n"));
        !          1082:                                                        break;
        !          1083:                                                default:
        !          1084:                                                        break;
        !          1085:                                        }       /* switch */
        !          1086:                                }
        !          1087:                                ++userids;
        !          1088:                        }
        !          1089:                        else
        !          1090:                        {       PascalToC(userid);
        !          1091:                                if (what != 0)
        !          1092:                                        fprintf(pgpout, "\n");
        !          1093:                                fprintf(pgpout,PSTR("Also known as: %s\n"), 
        !          1094:                                        LOCAL_CHARSET(userid));
        !          1095:                        }
        !          1096:                        if (print_trust)
        !          1097:                        {
        !          1098:                                read_trust(f, &keyctrl);
        !          1099:                                switch (keyctrl & KC_LEGIT_MASK)
        !          1100:                                {
        !          1101:                                        case 0:         /* undefined certification level */
        !          1102:                                        case 1:         /* uncertified */
        !          1103:                                                fprintf(pgpout, PSTR("This key/userID association is not certified.\n"));
        !          1104:                                                break;
        !          1105:                                        case 2:         /* marginal certification */
        !          1106:                                                fprintf(pgpout, PSTR("This key/userID association is marginally certified.\n"));
        !          1107:                                                break;
        !          1108:                                        case 3:         /* complete certification */
        !          1109:                                                fprintf(pgpout, PSTR("This key/userID association is fully certified.\n"));
        !          1110:                                                break;
        !          1111:                                        default:        /* can't get here, right? */
        !          1112:                                                break;
        !          1113:                                }       /* switch */
        !          1114:                        }       /* print_trust */
        !          1115:                }
        !          1116:                else if ((what & SHOW_SIGS) && is_ctb_type(ctb, CTB_SKE_TYPE))
        !          1117:                {
        !          1118:                        if (print_trust)
        !          1119:                        {
        !          1120:                                read_trust(f, &keyctrl);
        !          1121:                                switch (TRUST_LEV(keyctrl))
        !          1122:                                {
        !          1123:                                        case KC_SIGTRUST_UNDEFINED:     /* undefined trust level */
        !          1124:                                        case KC_SIGTRUST_UNKNOWN:
        !          1125:                                                /* Just don't say anything in this case */
        !          1126:                                                fprintf(pgpout, PSTR("  Questionable certification from:\n  "));
        !          1127:                                                break;
        !          1128:                                        case KC_SIGTRUST_UNTRUSTED:     /* untrusted */
        !          1129:                                                fprintf(pgpout, PSTR("  Untrusted certification from:\n  "));
        !          1130:                                                break;
        !          1131:                                        case KC_SIGTRUST_MARGINAL:      /* marginal trust */
        !          1132:                                                fprintf(pgpout, PSTR("  Generally trusted certification from:\n  "));
        !          1133:                                                break;
        !          1134:                                        case KC_SIGTRUST_COMPLETE:      /* complete trust */
        !          1135:                                                fprintf(pgpout, PSTR("  Completely trusted certification from:\n  "));
        !          1136:                                                break;
        !          1137:                                        case KC_SIGTRUST_ULTIMATE:      /* axiomatic, ultimate trust */
        !          1138:                                                fprintf(pgpout, PSTR("  Axiomatically trusted certification from:\n  "));
        !          1139:                                                break;
        !          1140:                                        default:        /* can't get here, right? */
        !          1141:                                                break;
        !          1142:                                }       /* switch */
        !          1143:                        }
        !          1144:                        else
        !          1145:                                fprintf(pgpout, PSTR("  Certified by: "));
        !          1146:                        show_userid(f, sigkeyID);
        !          1147:                }
        !          1148:        }
        !          1149:        if (status == -1 && userids)
        !          1150:                status = 0;
        !          1151:        set_precision(precision);
        !          1152:        fseek(f, filepos, SEEK_SET);
        !          1153:        return(status);
        !          1154: }      /* show_key */
        !          1155: 
        !          1156: 
        !          1157: /*
        !          1158:  * write trust byte "keyctrl" to file f at file position "pos"
        !          1159:  */
        !          1160: void
        !          1161: write_trust_pos(FILE *f, byte keyctrl, long pos)
        !          1162: {
        !          1163:        long fpos;
        !          1164: 
        !          1165:        fpos = ftell(f);
        !          1166:        fseek(f, pos, SEEK_SET);
        !          1167:        write_trust(f, keyctrl);
        !          1168:        fseek(f, fpos, SEEK_SET);
        !          1169: }      /* write_trust_pos */
        !          1170: 
        !          1171: 
        !          1172: /*
        !          1173:  * read a trust byte packet from file f, the trust byte will be
        !          1174:  * stored in "keyctrl".
        !          1175:  * returns -1 on EOF, -3 on corrupt input, and ERR_NOTRUST if
        !          1176:  * the packet was not a trust byte (this can be used to check if
        !          1177:  * a file is a keyring (with trust bytes) or a keyfile).
        !          1178:  */
        !          1179: int
        !          1180: read_trust(FILE *f, byte *keyctrl)
        !          1181: {
        !          1182:        unsigned char buf[3];
        !          1183: 
        !          1184:        if (fread(buf, 1, 3, f) != 3)
        !          1185:                return -1;
        !          1186:        if (buf[0] != CTB_KEYCTRL)
        !          1187:        {
        !          1188:                if (is_ctb(buf[0]))
        !          1189:                        return(ERR_NOTRUST);
        !          1190:                 else
        !          1191:                        return(-3);             /* bad data */
        !          1192:        }
        !          1193:        if (buf[1] != 1)                /* length must be 1 */
        !          1194:                return(-3);
        !          1195:        if (keyctrl)
        !          1196:                *keyctrl = buf[2];
        !          1197:        return(0);
        !          1198: }      /* read_trust */

unix.superglobalmegacorp.com

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