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

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>
1.1.1.3 ! root       25: #include <stdlib.h>
1.1.1.2   root       26: #include "mpilib.h"
                     27: #include "random.h"
                     28: #include "crypto.h"
                     29: #include "fileio.h"
                     30: #include "keymgmt.h"
1.1.1.3 ! root       31: #include "keymaint.h"
1.1.1.2   root       32: #include "mpiio.h"
1.1.1.3 ! root       33: #include "charset.h"
1.1.1.2   root       34: #include "language.h"
                     35: #include "pgp.h"
                     36: 
1.1.1.3 ! root       37: #if 1 /* def DEBUG */
        !            38: #include <assert.h>
        !            39: #else
        !            40: #define assert(x)
        !            41: #endif
        !            42: 
        !            43: struct userid;
        !            44: struct signature;
        !            45: 
        !            46: struct pubkey {
        !            47:        struct pubkey *pk_next;
        !            48:        struct pubkey *pk_hash;                 /* hash list for keyID */
        !            49:        struct userid *pk_userids;
        !            50:        struct signature *pk_signed;    /* signatures this key made */
        !            51:        byte pk_keyid[KEYFRAGSIZE];
        !            52:        byte pk_owntrust;
        !            53:        byte pk_depth;          /* shortest cert. path to buckstop key */
        !            54: };
        !            55: 
        !            56: struct userid {
        !            57:        struct userid *uid_next;
        !            58:        struct pubkey *uid_key;         /* backlink to key */
        !            59:        struct signature *uid_signatures;
        !            60:        char *uid_userid;
        !            61:        byte uid_legit;
        !            62: };
        !            63: 
        !            64: struct signature {
        !            65:        struct signature *sig_next;             /* list of signatures on a userid */
        !            66:        struct userid *sig_uid;                 /* the userid it signs */
        !            67:        struct pubkey *sig_from;                /* key that made this signature */
        !            68:        struct signature *sig_nextfrom; /* list of sigs made by the same key (sig_from) */
        !            69:        byte sig_trust;
        !            70: };
1.1.1.2   root       71: 
1.1.1.3 ! root       72: 
        !            73: int maint_list(char *ringfile);
        !            74: void init_trust_lst(void);
1.1.1.2   root       75: long lookup_by_keyID(FILE *f, byte *srch_keyID);
                     76: void show_userid(FILE *f, byte *keyID);
1.1.1.3 ! root       77: 
        !            78: static int maintenance(char *ringfile);
        !            79: static int maint_read_data(char *ringfile);
        !            80: static int maint_trace_chain(void);
        !            81: static int trace_sig_chain(struct pubkey *pk, int depth);
        !            82: static int maint_final(char *ringfile);
        !            83: static struct pubkey * getpubkey(byte *keyID);
        !            84: static void setup_trust(void);
        !            85: static int check_secretkey(FILE *f, long keypos);
        !            86: static void maint_init_mem(void);
        !            87: static void maint_release_mem(void);
        !            88: static VOID * allocn(int size);
        !            89: static char * store_str(char *str);
        !            90: static VOID * allocbuf(int size);
        !            91: static void freebufpool(void);
        !            92: 
        !            93: 
        !            94: #define        ALLOC_UNIT      4000    /* memory will be allocated in chunks of this size */
        !            95: 
        !            96: #define        MAX_DEPTH       8       /* max. value of max_cert_depth */
1.1.1.2   root       97: 
                     98: /* returned when trying to do a maintenance pass on a secret keyring or keyfile */
                     99: #define        ERR_NOTRUST             -7
                    100: 
                    101: #define TRUST_MASK             7       /* mask for userid/signature trust bytes */
                    102: #define SET_TRUST(b,v) (*(b) = (*(b) & ~TRUST_MASK) | (v))
                    103: #define TRUST_LEV(b)   ((b) & TRUST_MASK)
                    104: 
                    105: #define        TRUST_FAC(x)    (trust_tbl[TRUST_LEV(x)])
                    106: 
1.1.1.3 ! root      107: #define ctb_type(c)            ((c&CTB_TYPE_MASK)>>2)
1.1.1.2   root      108: /*
                    109:  * table for tuning user paranoia index.
                    110:  * values represent contribution of one signature indexed by the
                    111:  * SIGTRUST of a signature
                    112:  */
1.1.1.3 ! root      113: static int trust_tbl[8];
1.1.1.2   root      114: 
                    115: static int marginal_min;
                    116: static int complete_min;       /* total count needed for a fully legit key */
                    117: 
                    118: int marg_min = 2;              /* number of marginally trusted signatures needed for
                    119:                                                   a fully legit key (can be set in config.pgp). */
                    120: int compl_min = 1;             /* number of fully trusted signatures needed */
                    121: 
                    122: char trust_lst[8][16] = {
                    123:        "undefined",            /* PSTR("undefined") */
                    124:        "unknown",                      /* PSTR("unknown") */
                    125:        "untrusted",            /* PSTR("untrusted") */
                    126:        "<3>",                          /* unused */
                    127:        "<4>",                          /* unused */
                    128:        "marginal",                     /* PSTR("marginal") */
                    129:        "complete",                     /* PSTR("complete") */
                    130:        "ultimate",                     /* PSTR("ultimate") */
                    131: };
                    132: 
                    133: char legit_lst[4][16] = {
                    134:        "undefined",
                    135:        "untrusted",
                    136:        "marginal",
                    137:        "complete"
                    138: };
                    139: 
1.1.1.3 ! root      140: static int trustlst_len = 9;   /* length of longest trust word */
        !           141: static int legitlst_len = 9;   /* length of longest legit word */
1.1.1.2   root      142: 
                    143: char floppyring[MAX_PATH] = "";
                    144: int max_cert_depth = 4;                /* maximum nesting of signatures */
                    145: 
                    146: static boolean check_only = FALSE;
                    147: static boolean mverbose;
                    148: static FILE *sec_fp;
                    149: static FILE *floppy_fp = NULL;
1.1.1.3 ! root      150: 
        !           151: 
        !           152: /*
        !           153:  * Update trust parameters in a keyring, should be called after all
        !           154:  * key management functions which can affect the trust parameters.
        !           155:  * Changes are done "inplace", the file must be writable.
        !           156:  */
        !           157: int
        !           158: maint_update(char *ringfile)
        !           159: {
        !           160:        check_only = mverbose = FALSE;
        !           161:        return maintenance(ringfile);
        !           162: }
1.1.1.2   root      163: 
                    164: /*
1.1.1.3 ! root      165:  * Check trust parameters in ringfile
1.1.1.2   root      166:  * options can be:
1.1.1.3 ! root      167:  *     MAINT_CHECK             check only, don't ask if keyring should be updated
1.1.1.2   root      168:  *     MAINT_VERBOSE   verbose output, shows signature chains
                    169:  */
                    170: int
1.1.1.3 ! root      171: maint_check(char *ringfile, int options)
1.1.1.2   root      172: {
                    173:        int status;
1.1.1.3 ! root      174:        char *fixfile;
1.1.1.2   root      175: 
1.1.1.3 ! root      176:        mverbose = ((options & MAINT_VERBOSE) != 0);
        !           177:        if (moreflag)
        !           178:                open_more();
        !           179:        if (*floppyring != '\0' && (floppy_fp = fopen(floppyring, FOPRBIN)) == NULL)
        !           180:                fprintf(pgpout,PSTR("\nCan't open backup key ring file '%s'\n"),
        !           181:                                floppyring);
        !           182:        check_only = TRUE;
        !           183:        status = maintenance(ringfile);
        !           184:        if (floppy_fp) {
        !           185:                fclose(floppy_fp);
        !           186:                floppy_fp = NULL;
        !           187:        }
        !           188:        if (status <= 0) {
        !           189:                if (status == 0)
        !           190:                        maint_list(ringfile);
        !           191:                close_more();
        !           192:                return status;
        !           193:        }
        !           194: #ifdef xDEBUG
        !           195:        if (status > 0 && (options & MAINT_CHECK)) {
        !           196:                FILE *sav = pgpout;
        !           197:                if (pgpout = fopen("before.lst", "w")) {
        !           198:                        maint_list(ringfile);
        !           199:                        fclose(pgpout);
        !           200:                }
        !           201:                pgpout = sav;
        !           202:        }
        !           203: #endif
        !           204:        /* do the fixes in a scratch file */
        !           205:        fixfile = tempfile(0);
        !           206:        if (copyfiles_by_name(ringfile, fixfile) < 0) {
        !           207:                close_more();
        !           208:                return -1;
        !           209:        }
        !           210:        check_only = mverbose = FALSE;
        !           211:        if ((status = maintenance(fixfile)) >= 0) {
        !           212:                maint_list(fixfile);
        !           213:                fprintf(pgpout, PSTR("\n%d \"trust parameter(s)\" changed.\n"), status);
        !           214:        }
        !           215:        close_more();
        !           216:        if (status > 0 && !(options & MAINT_CHECK)) {
        !           217:                fprintf(pgpout, PSTR("Update public keyring '%s' (Y/n)? "), ringfile);
        !           218:                if (getyesno('y'))
        !           219:                        return savetempbak(fixfile, ringfile);
        !           220:        }
        !           221:        rmtemp(fixfile);
        !           222:        return status;
        !           223: }
1.1.1.2   root      224: 
                    225: 
1.1.1.3 ! root      226: static int
        !           227: maintenance(char *ringfile)
        !           228: {
        !           229:        int status;
        !           230:        char secretkeyring[MAX_PATH];
        !           231: 
        !           232:        if (max_cert_depth > MAX_DEPTH)
        !           233:                max_cert_depth = MAX_DEPTH;
1.1.1.2   root      234: 
                    235:        buildfilename(secretkeyring, SECRET_KEYRING_FILENAME);
                    236:        if ((sec_fp = fopen(secretkeyring, FOPRBIN)) == NULL)
                    237:                fprintf(pgpout,PSTR("\nCan't open secret key ring file '%s'\n"),
                    238:                                secretkeyring);
                    239: 
1.1.1.3 ! root      240:        setkrent(ringfile);
1.1.1.2   root      241:        setup_trust();
1.1.1.3 ! root      242:        maint_init_mem();
        !           243:        if (mverbose || verbose)
1.1.1.2   root      244:                fprintf(pgpout, PSTR("\nPass 1: Looking for the \"ultimately-trusted\" keys...\n"));
1.1.1.3 ! root      245:        status = maint_read_data(ringfile);
        !           246:        if (sec_fp) {
        !           247:                fclose(sec_fp);
        !           248:                sec_fp = NULL;
        !           249:        }
        !           250:        if (status < 0)
1.1.1.2   root      251:                goto failed;
                    252: 
1.1.1.3 ! root      253:        if (mverbose || verbose)
1.1.1.2   root      254:                fprintf(pgpout, PSTR("\nPass 2: Tracing signature chains...\n"));
1.1.1.3 ! root      255:        if ((status = maint_trace_chain()) < 0)
1.1.1.2   root      256:                goto failed;
                    257: 
1.1.1.3 ! root      258:        if (verbose)
        !           259:                fprintf(pgpout, "\nPass 3: %s keyring...\n",
        !           260:                        (check_only ? "Checking with" : "Updating"));
        !           261:        if ((status = maint_final(ringfile)) < 0)
1.1.1.2   root      262:                goto failed;
                    263: 
1.1.1.3 ! root      264:        endkrent();
        !           265:        maint_release_mem();
        !           266:        return(status);
1.1.1.2   root      267: 
                    268: failed:
1.1.1.3 ! root      269:        if (verbose)
        !           270:                fprintf(pgpout, "maintenance pass: error exit = %d\n", status);
        !           271:        endkrent();
        !           272:        maint_release_mem();
1.1.1.2   root      273:        return(status);
                    274: }      /* maintenance */
                    275: 
                    276: 
1.1.1.3 ! root      277: static struct pubkey *pklist, **pkhash = NULL;
        !           278: 
        !           279: #define        PK_HASHSIZE     256             /* must be power of 2 */
        !           280: #define        PK_HASH(x)              (*(byte *) (x) & (PK_HASHSIZE - 1))
        !           281: 
1.1.1.2   root      282: /*
1.1.1.3 ! root      283:  * get the pubkey struct for keyID from hash table, allocate a new
        !           284:  * node and insert in hash table if necessary.
1.1.1.2   root      285:  */
1.1.1.3 ! root      286: static struct pubkey *
        !           287: getpubkey(byte *keyID)
        !           288: {
        !           289:        struct pubkey *pk;
        !           290:        for (pk = pkhash[PK_HASH(keyID)]; pk; pk = pk->pk_hash)
        !           291:                if (memcmp(pk->pk_keyid, keyID, KEYFRAGSIZE) == 0)
        !           292:                        return pk;
        !           293:        pk = allocn(sizeof(struct pubkey));
        !           294:        memset(pk, 0, sizeof(struct pubkey));
        !           295:        memcpy(pk->pk_keyid, keyID, KEYFRAGSIZE);
        !           296:        pk->pk_hash = pkhash[PK_HASH(keyID)];
        !           297:        pkhash[PK_HASH(keyID)] = pk;
        !           298:        return pk;
        !           299: }
        !           300: 
        !           301: /*
        !           302:  * Read in keyring, a graph of keys, userids and signatures is built.
        !           303:  * Also check if axiomatic keys are present in the secret keyring and
        !           304:  * compare them with the floppy ring if this is requested.
        !           305:  */
        !           306: static int
        !           307: maint_read_data(char *ringfile)
1.1.1.2   root      308: {
1.1.1.3 ! root      309:        FILE *f;
1.1.1.2   root      310:        int status;
                    311:        char userid[256];
                    312:        byte keyID[KEYFRAGSIZE];
1.1.1.3 ! root      313:        byte sigkeyID[KEYFRAGSIZE];
1.1.1.2   root      314:        byte ctb;
                    315:        byte keyctrl;
                    316:        boolean buckstop = FALSE, show_user = FALSE;
                    317:        int buckstopcount = 0;
                    318:        long keypos = 0;
1.1.1.3 ! root      319:        int skip = 0;
        !           320:        struct pubkey *pk = NULL;
        !           321:        struct userid *id = NULL;
        !           322:        struct signature *sig = NULL;
1.1.1.2   root      323: 
1.1.1.3 ! root      324:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
        !           325:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
        !           326:                return(-1);
        !           327:        }
        !           328: 
        !           329:        while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) != -1) {
        !           330:                if (status == -3 || status == -2) {
        !           331:                        fclose(f);
1.1.1.2   root      332:                        return(status);
1.1.1.3 ! root      333:                }
        !           334:                if (status < 0 || is_ctb_type(ctb, CTB_CERT_SECKEY_TYPE)) {
        !           335:                        skip = 1;       /* version error or bad key */
1.1.1.2   root      336:                        continue;
1.1.1.3 ! root      337:                }
        !           338:                if (skip) {
        !           339:                        if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
        !           340:                                skip = 0;
        !           341:                        else
        !           342:                                continue;
        !           343:                }
1.1.1.2   root      344: 
                    345:                if (is_ctb_type(ctb, CTB_COMMENT_TYPE) || ctb == CTB_KEYCTRL)
                    346:                        continue;
1.1.1.3 ! root      347: 
        !           348:                if (pk && is_ctb_type(ctb, CTB_SKE_TYPE) && !pk->pk_userids) {
        !           349:                        /* sig. cert before userids can only be compromise cert. */
        !           350:                        pk->pk_owntrust = KC_OWNERTRUST_NEVER;
        !           351:                        continue;
        !           352:                }
1.1.1.2   root      353: 
                    354:                /* other packets should have trust byte */
1.1.1.3 ! root      355:                if (read_trust(f, &keyctrl) < 0) {
        !           356:                        fclose(f);
1.1.1.2   root      357:                        return(ERR_NOTRUST);            /* not a public keyring */
1.1.1.3 ! root      358:                }
1.1.1.2   root      359: 
1.1.1.3 ! root      360:                switch (ctb_type(ctb)) {
        !           361:                case CTB_CERT_PUBKEY_TYPE:
        !           362:                        if (pk)
        !           363:                                pk = pk->pk_next = getpubkey(keyID);
        !           364:                        else
        !           365:                                pk = pklist = getpubkey(keyID);
        !           366: 
        !           367:                        if (pk->pk_next) {
        !           368:                                fprintf(pgpout, PSTR("Keyring contains duplicate key: %s\n"), keyIDstring(keyID));
        !           369:                                fclose(f);
        !           370:                                return -1;
        !           371:                        }
        !           372: 
        !           373:                        if ((keyctrl & KC_BUCKSTOP)) {
        !           374:                                if (check_secretkey(f, keypos) == 0) {
1.1.1.2   root      375:                                        ++buckstopcount;
                    376:                                        buckstop = TRUE;
                    377:                                        if (mverbose)
                    378:                                                fprintf(pgpout, "* %s",keyIDstring(keyID));
1.1.1.3 ! root      379:                                } else {        /* not in secret keyring */
1.1.1.2   root      380:                                        keyctrl &= ~KC_BUCKSTOP;
                    381:                                        if (TRUST_LEV(keyctrl) == KC_OWNERTRUST_ULTIMATE)
                    382:                                                keyctrl = KC_OWNERTRUST_ALWAYS;
                    383:                                        if (mverbose)
                    384:                                                fprintf(pgpout, ". %s",keyIDstring(keyID));
                    385:                                }
                    386:                                show_user = mverbose;
1.1.1.3 ! root      387:                        } else {
1.1.1.2   root      388:                                buckstop = FALSE;
                    389:                                show_user = FALSE;
                    390:                        }
                    391:                        keyctrl &= ~KC_VISITED;
1.1.1.3 ! root      392:                        pk->pk_owntrust = keyctrl;
        !           393:                        pk->pk_userids = id = NULL;
        !           394:                        break;
        !           395:                case CTB_USERID_TYPE:
        !           396:                        if (!pk)
        !           397:                                break;
        !           398:                        if (show_user) {
        !           399:                                if (pk->pk_userids)             /* more than one user ID */
1.1.1.2   root      400:                                        fprintf(pgpout, "        ");
                    401:                                fprintf(pgpout, "  %s\n", LOCAL_CHARSET(userid));
                    402:                        }
1.1.1.3 ! root      403:                        if (id)
        !           404:                                id = id->uid_next = allocn(sizeof(struct userid));
        !           405:                        else
        !           406:                                id = pk->pk_userids = allocn(sizeof(struct userid));
        !           407: 
        !           408:                        if (mverbose)
        !           409:                                id->uid_userid = store_str(userid);
1.1.1.2   root      410:                        keyctrl &= ~KC_LEGIT_MASK;
                    411:                        if (buckstop)
                    412:                                keyctrl |= KC_LEGIT_COMPLETE;
                    413:                        else
                    414:                                keyctrl |= KC_LEGIT_UNKNOWN;
1.1.1.3 ! root      415:                        id->uid_next = NULL;
        !           416:                        id->uid_key = pk;
        !           417:                        id->uid_legit = keyctrl;
        !           418:                        id->uid_signatures = sig = NULL;
        !           419:                        break;
        !           420:                case CTB_SKE_TYPE:
        !           421:                        if (!pk || !id)
        !           422:                                break;
        !           423:                        if (sig)
        !           424:                                sig = sig->sig_next = allocn(sizeof(struct signature));
        !           425:                        else
        !           426:                                sig = id->uid_signatures = allocn(sizeof(struct signature));
        !           427:                        sig->sig_next = NULL;
        !           428:                        sig->sig_uid = id;
        !           429:                        sig->sig_from = getpubkey(sigkeyID);
        !           430:                        sig->sig_nextfrom = sig->sig_from->pk_signed;
        !           431:                        sig->sig_from->pk_signed = sig;
        !           432:                        sig->sig_trust = keyctrl&KC_SIG_CHECKED;
        !           433:                        break;
        !           434:                } /* switch ctb_type */
1.1.1.2   root      435:                keypos = ftell(f);
                    436:        }
                    437:        if (buckstopcount == 0 && mverbose)
                    438:                fprintf(pgpout, PSTR("No ultimately-trusted keys.\n"));
1.1.1.3 ! root      439:        fclose(f);
1.1.1.2   root      440:        return(0);
                    441: }
                    442: 
                    443: 
                    444: /*
                    445:  * scan keyring for buckstop keys and start the recursive trace_sig_chain()
                    446:  * on them
                    447:  */
1.1.1.3 ! root      448: static int
        !           449: maint_trace_chain(void)
1.1.1.2   root      450: {
1.1.1.3 ! root      451:        char *userid;
        !           452:        struct pubkey *pk;
1.1.1.2   root      453: 
1.1.1.3 ! root      454:        for (pk = pklist; pk; pk = pk->pk_next) {
        !           455:                if (!(pk->pk_owntrust&KC_BUCKSTOP))
1.1.1.2   root      456:                        continue;
1.1.1.3 ! root      457:                if (mverbose)
        !           458:                        fprintf(pgpout, "* %s\n", LOCAL_CHARSET(pk->pk_userids->uid_userid));
        !           459:                if (TRUST_LEV(pk->pk_owntrust) == KC_OWNERTRUST_UNDEFINED) {
        !           460:                        userid = user_from_keyID(pk->pk_keyid);
        !           461:                        SET_TRUST(&pk->pk_owntrust, ask_owntrust(userid, pk->pk_owntrust));
1.1.1.2   root      462:                }
1.1.1.3 ! root      463:                trace_sig_chain(pk, 0);
        !           464:        }
        !           465:        return 0;
        !           466: }
1.1.1.2   root      467: 
1.1.1.3 ! root      468: 
        !           469: /*
        !           470:  * Find all signatures made with the key pk.
        !           471:  * If a trusted signature makes a key fully legit then signatures made
        !           472:  * with this key are also recursively traced on down the tree.
        !           473:  *
        !           474:  * depth is the level of recursion, it is used to indent the userIDs
        !           475:  * and to check if we don't exceed the limit "max_cert_depth"
        !           476:  *
        !           477:  * NOTE: a signature made with a key with pk_depth == max_cert_depth will
        !           478:  * not be counted here to limit the maximum chain length, but will be
        !           479:  * counted when the validity of a key is computed in maint_final()
        !           480:  */
        !           481: static int
        !           482: trace_sig_chain(struct pubkey *pk, int depth)
        !           483: {
        !           484:        int d, trust_count = 0;
        !           485:        int counts[MAX_DEPTH];
        !           486:        struct signature *sig, *s;
        !           487:        struct pubkey *p;
        !           488: 
        !           489:        assert(depth <= max_cert_depth);
        !           490:        if (pk->pk_depth && pk->pk_depth <= depth)
        !           491:                return 0;
        !           492:        pk->pk_depth = depth;
        !           493: 
        !           494: #ifdef DEBUG
        !           495:        if (mverbose)
        !           496:                fprintf(pgpout, "%*s%d-v  %s\n", 2*depth, "", depth, pk->pk_userids->uid_userid);
        !           497: #endif
        !           498: 
        !           499:        if (pk->pk_signed && TRUST_LEV(pk->pk_owntrust) == KC_OWNERTRUST_UNDEFINED)
        !           500:                SET_TRUST(&pk->pk_owntrust,
        !           501:                        ask_owntrust(user_from_keyID(pk->pk_keyid), pk->pk_owntrust));
        !           502: 
        !           503:        /* all keys signed by pk */
        !           504:        for (sig = pk->pk_signed; sig; sig = sig->sig_nextfrom) {
        !           505:                if (mverbose)
        !           506:                        fprintf(pgpout, "%*s  > %s\n", 2*depth, "", LOCAL_CHARSET(sig->sig_uid->uid_userid));
        !           507: 
        !           508:                /* copy trust from signator */
        !           509:                SET_TRUST(&sig->sig_trust, TRUST_LEV(pk->pk_owntrust));
        !           510:                sig->sig_trust |= KC_CONTIG;    /* CONTIG bit currently unused */
        !           511: 
        !           512:                p = sig->sig_uid->uid_key;      /* this key signed by pk */
        !           513:                if (!p->pk_signed)
        !           514:                        continue;       /* didn't sign anything */
        !           515:                if (p->pk_owntrust & KC_BUCKSTOP)
        !           516:                        continue;       /* will be handled from main loop */
        !           517:                if (p->pk_depth && p->pk_depth <= depth+1)
        !           518:                        continue;       /* already handled this key at a lower level */
        !           519: 
        !           520:                for (d = 0; d < max_cert_depth; ++d)
        !           521:                        counts[d] = 0;
        !           522:                for (s = sig->sig_uid->uid_signatures; s; s = s->sig_next) {
        !           523:                        d = s->sig_from->pk_depth;
        !           524:                        if (d < max_cert_depth)
        !           525:                                counts[d] += TRUST_FAC(s->sig_trust);
        !           526:                }
        !           527:                /*
        !           528:                 * find a combination of signatures that will make the key
        !           529:                 * valid through the shortest cert. path.
        !           530:                 */
        !           531:                trust_count = 0;
        !           532:                for (d = 0; d < max_cert_depth; ++d) {
        !           533:                        trust_count += counts[d];
        !           534:                        if (trust_count >= complete_min) {
        !           535:                                trace_sig_chain(p, d+1);
        !           536:                                break;
1.1.1.2   root      537:                        }
                    538:                }
                    539:        }
1.1.1.3 ! root      540: 
        !           541: #ifdef DEBUG
        !           542:        if (mverbose)
        !           543:                fprintf(pgpout, "%*s%d-^  %s\n", 2*depth, "", depth, pk->pk_userids->uid_userid);
        !           544: #endif
        !           545:        return 0;
1.1.1.2   root      546: }
                    547: 
1.1.1.3 ! root      548: /*
        !           549:  * compute validity of userid/key pair, the number of signatures and the
        !           550:  * trust level of these signatures determines the validity.
        !           551:  */
        !           552: void
        !           553: compute_legit(struct userid *id)
        !           554: {
        !           555:        struct signature *s;
        !           556:        int trust_count, legit;
        !           557: 
        !           558:        if (id->uid_key->pk_owntrust & KC_BUCKSTOP)
        !           559:                legit = KC_LEGIT_COMPLETE;
        !           560:        else {
        !           561:                trust_count = 0;
        !           562:                for (s = id->uid_signatures; s; s = s->sig_next)
        !           563:                        trust_count += TRUST_FAC(s->sig_trust);
        !           564: 
        !           565:                if (trust_count == 0)
        !           566:                        legit = KC_LEGIT_UNKNOWN;
        !           567:                else if (trust_count < marginal_min)
        !           568:                        legit = KC_LEGIT_UNTRUSTED;
        !           569:                else if (trust_count < complete_min)
        !           570:                        legit = KC_LEGIT_MARGINAL;
        !           571:                else
        !           572:                        legit = KC_LEGIT_COMPLETE;
        !           573:        }
        !           574:        id->uid_legit = (id->uid_legit & ~KC_LEGIT_MASK) | legit;
        !           575: }
1.1.1.2   root      576: 
                    577: /* 
                    578:  * check if the maintenance pass changed anything
                    579:  * returns 0 if files f and g are equal and the number of changed
                    580:  * trust bytes if the files are different or a negative value on error
                    581:  */
1.1.1.3 ! root      582: static int
        !           583: maint_final(char *ringfile)
1.1.1.2   root      584: {
                    585:        int status;
1.1.1.3 ! root      586:        FILE *f;
        !           587:        long trust_pos = 0;
1.1.1.2   root      588:        char userid[256];
                    589:        byte keyID[KEYFRAGSIZE];
                    590:        byte sigkeyID[KEYFRAGSIZE];
                    591:        byte ctb;
1.1.1.3 ! root      592:        byte kc_orig, kc_new = 0, mask;
1.1.1.2   root      593:        int changed = 0;
1.1.1.3 ! root      594:        int skip = 0;
        !           595:        struct pubkey *pk;
        !           596:        struct userid *id = NULL;
        !           597:        struct signature *sig = NULL;
1.1.1.2   root      598: 
1.1.1.3 ! root      599:        if (check_only)
        !           600:                f = fopen(ringfile,FOPRBIN);
        !           601:        else
        !           602:                f = fopen(ringfile,FOPRWBIN);
        !           603:        if (f == NULL)
        !           604:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
        !           605:                return(-1);
        !           606:        }
        !           607: 
        !           608:        pk = pklist;
        !           609:        while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) != -1) {
        !           610:                if (status == -3 || status == -2)
1.1.1.2   root      611:                        break;
1.1.1.3 ! root      612:                if (status < 0 || is_ctb_type(ctb, CTB_CERT_SECKEY_TYPE)) {
        !           613:                        skip = 1;
1.1.1.2   root      614:                        continue;
1.1.1.3 ! root      615:                }
        !           616:                if (skip) {
        !           617:                        if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
        !           618:                                skip = 0;
        !           619:                        else
        !           620:                                continue;
        !           621:                }
        !           622:                if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE) || 
        !           623:                                is_ctb_type(ctb, CTB_SKE_TYPE) || ctb == CTB_USERID) {
        !           624:                        trust_pos = ftell(f);
        !           625:                        if (read_trust(f, &kc_orig) < 0) {
        !           626:                                status = ERR_NOTRUST;
        !           627:                                if (is_ctb_type(ctb, CTB_SKE_TYPE))
        !           628:                                        continue;       /* skip compr. cert. */
        !           629:                                else
        !           630:                                        break;
        !           631:                        }
        !           632:                }
        !           633:                switch (ctb_type(ctb)) {
        !           634:                        case CTB_CERT_PUBKEY_TYPE:
        !           635:                                assert(pk && !memcmp(pk->pk_keyid, keyID, KEYFRAGSIZE));
        !           636:                                assert(!sig && !id);
        !           637:                                id = pk->pk_userids;
        !           638:                                kc_new = pk->pk_owntrust;
        !           639: #ifdef DEBUG
        !           640:                                if (mverbose)
        !           641:                                        fprintf(pgpout, "  ------ %d\n", pk->pk_depth);
        !           642: #endif
        !           643:                                pk = pk->pk_next;
        !           644:                                mask = KC_OWNERTRUST_MASK|KC_BUCKSTOP;
        !           645:                                break;
        !           646:                        case CTB_USERID_TYPE:
        !           647:                                assert(id && !sig);
        !           648:                                sig = id->uid_signatures;
        !           649:                                compute_legit(id);
        !           650:                                kc_new = id->uid_legit;
        !           651: #ifdef DEBUG
        !           652:                                if (mverbose)
        !           653:                                        fprintf(pgpout, "%c %02x  %02x  %s\n", ' ' + (kc_new != kc_orig),
        !           654:                                                kc_orig, kc_new, id->uid_userid);
        !           655: #endif
        !           656:                                id = id->uid_next;
        !           657:                                mask = KC_LEGIT_MASK;
        !           658:                                break;
        !           659:                        case CTB_SKE_TYPE:
        !           660:                                assert(sig);
        !           661:                                assert(!memcmp(sig->sig_from->pk_keyid, sigkeyID, KEYFRAGSIZE));
        !           662:                                kc_new = sig->sig_trust;
        !           663: #ifdef DEBUG
        !           664:                                if (mverbose && sig->sig_from->pk_userids)
        !           665:                                        fprintf(pgpout, "%c %02x  %02x    %s\n", ' ' + (kc_new != kc_orig),
        !           666:                                                kc_orig, kc_new, sig->sig_from->pk_userids->uid_userid);
        !           667: #endif
        !           668:                                sig = sig->sig_next;
        !           669:                                mask = KC_SIGTRUST_MASK|KC_CONTIG;
        !           670:                                break;
        !           671:                        default:
        !           672:                                mask = 0;
        !           673:                }
        !           674:                if ((kc_new&mask) != (kc_orig&mask)) {
        !           675:                        if (!check_only)
        !           676:                                write_trust_pos(f, kc_new, trust_pos);
        !           677:                        ++changed;
        !           678:                }
        !           679:        }
        !           680:        fclose(f);
        !           681:        if (status < -1)        /* -1 is OK, EOF */
        !           682:                return(status);
        !           683:        if (pk || sig || id) {
        !           684:                fprintf(pgpout, "maint_final: internal error\n");
        !           685:                return -1;
        !           686:        }
        !           687:        return(changed);
        !           688: }      /* maint_final */
1.1.1.2   root      689: 
1.1.1.3 ! root      690: 
        !           691: int
        !           692: maint_list(char *ringfile)
        !           693: {
        !           694:        int status;
        !           695:        FILE *f;
        !           696:        char userid[256];
        !           697:        byte keyID[KEYFRAGSIZE];
        !           698:        byte sigkeyID[KEYFRAGSIZE];
        !           699:        char *signator;
        !           700:        char tchar = 0;
        !           701:        byte ctb, kc;
        !           702:        int owntrust = 0;
        !           703:        int usercount = 0;
        !           704: 
        !           705:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
        !           706:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
        !           707:                return(-1);
        !           708:        }
        !           709:        init_trust_lst();
        !           710:        setkrent(ringfile);
        !           711:        init_userhash();
        !           712: 
        !           713:        fprintf(pgpout, PSTR("  KeyID   Trust      Validity  User ID\n"));
        !           714:        while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) != -1) {
        !           715:                if (status == -3 || status == -2)
1.1.1.2   root      716:                        break;
1.1.1.3 ! root      717:                if (status < 0)
        !           718:                        continue;
1.1.1.2   root      719: 
1.1.1.3 ! root      720:                if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE) || 
        !           721:                                is_ctb_type(ctb, CTB_SKE_TYPE) || ctb == CTB_USERID) {
        !           722:                        if (read_trust(f, &kc) < 0) {
        !           723:                                status = ERR_NOTRUST;
        !           724:                                /* compromise cert. don't have trust byte */
        !           725:                                if (!is_ctb_type(ctb, CTB_SKE_TYPE))
        !           726:                                        break;
1.1.1.2   root      727:                        }
1.1.1.3 ! root      728:                }
1.1.1.2   root      729: 
1.1.1.3 ! root      730:                switch (ctb_type(ctb)) {
        !           731:                case CTB_CERT_PUBKEY_TYPE:
        !           732:                        tchar = (kc & KC_BUCKSTOP ? '*' : ' ');
        !           733:                        owntrust = TRUST_LEV(kc);
1.1.1.2   root      734:                        usercount = 0;
                    735:                        userid[0] = '\0';
1.1.1.3 ! root      736:                        break;
        !           737:                case CTB_USERID_TYPE:
        !           738:                        if (!usercount) {       /* first userid */
        !           739:                                fprintf(pgpout, "%c %s ", tchar, keyIDstring(keyID));
        !           740:                                fprintf(pgpout, " %-*s", trustlst_len, trust_lst[owntrust]);
        !           741:                        } else
1.1.1.2   root      742:                                fprintf(pgpout, "         %*s ", trustlst_len, "");
1.1.1.3 ! root      743:                        fprintf(pgpout, " %-*s", legitlst_len, legit_lst[kc&KC_LEGIT_MASK]);
        !           744:                        if (usercount)
        !           745:                                putc(' ', pgpout);
1.1.1.2   root      746:                        ++usercount;
                    747:                        fprintf(pgpout, "%s\n", LOCAL_CHARSET(userid));
1.1.1.3 ! root      748:                        break;
        !           749:                case CTB_SKE_TYPE:
        !           750:                        if (!usercount) {       /* sig before userid: compromise cert. */
        !           751:                                tchar = '#';
        !           752:                                break;
        !           753:                        }
        !           754:                        fprintf(pgpout, "%c        ", (kc & KC_CONTIG) ? 'c' : ' ');
        !           755:                        fprintf(pgpout, " %-*s", trustlst_len, trust_lst[TRUST_LEV(kc)]);
1.1.1.2   root      756:                        fprintf(pgpout, "%*s   ", legitlst_len, "");
1.1.1.3 ! root      757:                        if ((signator = user_from_keyID(sigkeyID)) == NULL)
        !           758:                                fprintf(pgpout, "(KeyID: %s)\n",keyIDstring(sigkeyID));
        !           759:                        else
        !           760:                                fprintf(pgpout, "%s\n", LOCAL_CHARSET(signator));
        !           761:                        break;
1.1.1.2   root      762:                }
                    763:        }
1.1.1.3 ! root      764:        endkrent();
        !           765:        fclose(f);
1.1.1.2   root      766:        if (status < -1)        /* -1 is OK, EOF */
                    767:                return(status);
1.1.1.3 ! root      768:        return(0);
        !           769: }      /* maint_list */
1.1.1.2   root      770: 
                    771: 
                    772: /*
                    773:  * translate the messages in the arrays trust_lst and legit_lst.
                    774:  * trustlst_len and legitlst_len will be set to the length of
                    775:  * the longest translated string.
                    776:  */
                    777: void
1.1.1.3 ! root      778: init_trust_lst(void)
1.1.1.2   root      779: {
                    780:        static int initialized = 0;
                    781:        int i, len;
                    782:        char *s;
                    783: 
                    784:        if (initialized)
                    785:                return;
                    786:        for (i = 0; i < 8; ++i)
1.1.1.3 ! root      787:        {       if (trust_lst[i][0])
        !           788:                {       s = PSTR (trust_lst[i]);
        !           789:                        if (s != trust_lst[i])
        !           790:                                strncpy(trust_lst[i], s, sizeof(trust_lst[0]) - 1);
        !           791:                        len = strlen(s);
        !           792:                        if (len > trustlst_len)
        !           793:                                trustlst_len = len;
1.1.1.2   root      794:                }
                    795:        }
1.1.1.3 ! root      796:        for (i = 0; i < 4; ++i)
        !           797:        {       s = PSTR (legit_lst[i]);
        !           798:                if (s != legit_lst[i])
        !           799:                        strncpy(legit_lst[i], s, sizeof(legit_lst[0]) - 1);
        !           800:                len = strlen(s);
        !           801:                if (len > legitlst_len)
        !           802:                        legitlst_len = len;
        !           803:        }
        !           804:        ++trustlst_len;
        !           805:        ++legitlst_len;
        !           806:        initialized = 1;
        !           807: }      /* init_trust_lst */
        !           808: 
1.1.1.2   root      809: 
                    810: 
                    811: /*
                    812:  * compare the key in file f at keypos with the matching key in the
                    813:  * secret keyring, the global variable sec_fp must contain the file pointer
                    814:  * for of the secret keyring.
                    815:  *
                    816:  * returns 1 if the key was not found, -2 if the keys were different
                    817:  * and 0 if the keys compared OK
                    818:  */
1.1.1.3 ! root      819: static int
1.1.1.2   root      820: check_secretkey(FILE *f, long keypos)
                    821: {
                    822:        int status = -1;
                    823:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
                    824:        unit nsec[MAX_UNIT_PRECISION], esec[MAX_UNIT_PRECISION];
                    825:        char userid[256];
                    826:        byte keyID[KEYFRAGSIZE];
                    827:        long savepos, pktlen;
                    828:        byte ctb;
                    829: 
                    830:        if (sec_fp == NULL)
                    831:                return(-1);
                    832: 
                    833:        savepos = ftell(f);
                    834:        fseek(f, keypos, SEEK_SET);
                    835:        if (readkeypacket(f, FALSE, &ctb, NULL, NULL, n, e,
                    836:                                        NULL, NULL, NULL, NULL, NULL, NULL) < 0)
                    837:                goto ex;
                    838:        extract_keyID(keyID, n);
                    839: 
                    840:        do      /* get userid */
                    841:        {       status = readkpacket(f, &ctb, userid, NULL, NULL);
                    842:                if (status == -1 || status == -3)
                    843:                        goto ex;
                    844:        } while (ctb != CTB_USERID);
                    845: 
                    846:        if (lookup_by_keyID(sec_fp, keyID) < 0)
                    847:        {
                    848: #if 0
                    849:                if (!check_only)
                    850:                {
                    851:                        fprintf(pgpout, PSTR (
                    852: "\nAn \"axiomatic\" key is one which does not need certifying by\n\
                    853: anyone else.  Usually this special status is reserved only for your\n\
                    854: own keys, which should also appear on your secret keyring.  The owner\n\
                    855: of an axiomatic key (who is typically yourself) is \"ultimately trusted\"\n\
                    856: by you to certify any or all other keys.\n"));
                    857:                        fprintf(pgpout, PSTR ("\nKey for user ID: \"%s\"\n\
                    858: is designated as an \"ultimately-trusted\" introducer, but the key\n\
                    859: does not appear in the secret keyring.\n\
                    860: Use this key as an ultimately-trusted introducer (y/N)? "), 
                    861:                                LOCAL_CHARSET(userid));
                    862:                        status = (getyesno('n') ? 0 : 1);
                    863:                }
                    864: #else
                    865:                status = 1;
                    866: #endif
                    867:        }
                    868:        else
                    869:        {
                    870:                long kpos = ftell(sec_fp);
                    871:                if (readkeypacket(sec_fp, FALSE, &ctb, NULL, NULL, nsec, esec,
                    872:                                                NULL, NULL, NULL, NULL, NULL, NULL) < 0)
                    873:                {
                    874:                        fprintf(pgpout, PSTR("\n\007Cannot read from secret keyring.\n"));
                    875:                        status = -3;
                    876:                        goto ex;
                    877:                }
                    878:                if (mp_compare(n, nsec) || mp_compare(e, esec))
                    879:                {       /* Red Alert! */
                    880:                        fprintf(pgpout, PSTR("\n\007WARNING: Public key for user ID: \"%s\"\n\
                    881: does not match the corresponding key in the secret keyring.\n"), 
                    882:                                LOCAL_CHARSET(userid));
                    883:                        fprintf(pgpout, PSTR("This is a serious condition, indicating possible keyring tampering.\n"));
                    884:                        status = -2;
                    885:                }
                    886:                else
                    887:                        status = 0;
                    888: 
                    889:                if (floppy_fp)
                    890:                {
                    891:                        if (lookup_by_keyID(floppy_fp, keyID) < 0)
                    892:                        {
                    893:                                fprintf(pgpout, PSTR("Public key for: \"%s\"\n\
                    894: is not present in the backup keyring '%s'.\n"),
                    895:                                        LOCAL_CHARSET(userid), floppyring);
                    896:                        }
                    897:                        else
                    898:                        {
                    899:                                pktlen = ftell(sec_fp) - kpos;
                    900:                                fseek(sec_fp, kpos, SEEK_SET);
                    901:                                while (--pktlen >= 0 && getc(sec_fp) == getc(floppy_fp)) ;
                    902:                                if (pktlen != -1)
                    903:                                {
                    904:                                        fprintf(pgpout, PSTR("\n\007WARNING: Secret key for: \"%s\"\n\
                    905: does not match the key in the backup keyring '%s'.\n"),
                    906:                                                LOCAL_CHARSET(userid), floppyring);
                    907:                                        fprintf(pgpout, PSTR("This is a serious condition, indicating possible keyring tampering.\n"));
                    908:                                        status = -2;
                    909:                                }
                    910:                        }
                    911:                }
                    912:        }
                    913: ex:
                    914:        fseek(f, savepos, SEEK_SET);
                    915:        return(status);
                    916: }      /* check_secretkey */
                    917: 
                    918: 
                    919: /*
                    920:  * setup tables for trust scoring.
                    921:  */
1.1.1.3 ! root      922: static void
        !           923: setup_trust(void)
1.1.1.2   root      924: {      /* initialize trust table */
                    925:        if (marg_min == 0)      /* marginally trusted signatures are ignored */
                    926:        {
                    927:                trust_tbl[5] = 0;
                    928:                trust_tbl[6] = 1;
                    929:                complete_min = compl_min;
                    930:        }
                    931:        else
                    932:        {
                    933:                if (marg_min < compl_min)
                    934:                        marg_min = compl_min;
                    935:                trust_tbl[5] = compl_min;
                    936:                trust_tbl[6] = marg_min;
                    937:                complete_min = compl_min * marg_min;
                    938:        }
                    939:        trust_tbl[7] = complete_min;    /* ultimate trust */
                    940:        marginal_min = complete_min / 2;
                    941: }      /* setup_trust */
                    942: 
                    943: 
                    944: int ask_owntrust(char *userid, byte cur_trust)
                    945: /* Ask for a wetware decision from the human on how much to trust 
                    946: this key's owner to certify other keys.  Returns trust value. */
                    947: {
                    948:        char buf[8];
                    949: 
1.1.1.3 ! root      950:        if (check_only || filter_mode || batchmode)
        !           951:        {       /* not interactive */
1.1.1.2   root      952:                return(KC_OWNERTRUST_UNDEFINED);
                    953:        }
                    954: 
                    955:        fprintf(pgpout, 
                    956: PSTR("\nMake a determination in your own mind whether this key actually\n\
                    957: belongs to the person whom you think it belongs to, based on available\n\
                    958: evidence.  If you think it does, then based on your estimate of\n\
                    959: that person's integrity and competence in key management, answer\n\
                    960: the following question:\n"));  
                    961:        fprintf(pgpout, PSTR("\nWould you trust \"%s\"\n\
                    962: to act as an introducer and certify other people's public keys to you?\n\
                    963: (1=I don't know. 2=No. 3=Usually. 4=Yes, always.) ? "), 
                    964:                LOCAL_CHARSET(userid));
                    965:        fflush(pgpout);
                    966:        getstring(buf, sizeof(buf)-1, TRUE);
                    967:        switch (buf[0])
                    968:        {       case '1': return KC_OWNERTRUST_UNKNOWN;
                    969:                case '2': return KC_OWNERTRUST_NEVER;
                    970:                case '3': return KC_OWNERTRUST_USUALLY;
                    971:                case '4': return KC_OWNERTRUST_ALWAYS;
                    972:                default: return(TRUST_LEV(cur_trust));
                    973:        }
                    974: }      /* ask_owntrust */
                    975: 
                    976: 
                    977: /*
                    978:  * scan keyfile f for keyID srch_keyID.
                    979:  * returns the file position of the key if it is found, and sets the
                    980:  * file pointer to the start of the key packet.
                    981:  * returns -1 if the key was not found or < -1 if there was an error
                    982:  */
                    983: long
                    984: lookup_by_keyID(FILE *f, byte *srch_keyID)
                    985: {
                    986:        int status;
                    987:        long keypos = 0;
                    988:        byte keyID[KEYFRAGSIZE];
                    989:        byte ctb;
                    990: 
                    991:        rewind(f);
                    992:        while ((status = readkpacket(f, &ctb, NULL, keyID, NULL)) != -1)
                    993:        {
1.1.1.3 ! root      994:                if (status == -3 || status == -2)
1.1.1.2   root      995:                        break;
                    996:                if (status < 0)
                    997:                        continue;
                    998:                if (is_key_ctb(ctb) && memcmp(keyID, srch_keyID, KEYFRAGSIZE) == 0)
                    999:                {
                   1000:                        fseek(f, keypos, SEEK_SET);
                   1001:                        return(keypos);
                   1002:                }
                   1003:                keypos = ftell(f);
                   1004:        }
                   1005:        return(status);
                   1006: }      /* lookup_by_keyID */
                   1007: 
                   1008: /*
                   1009:  * look up the key matching "keyID" and print the first userID
                   1010:  * of this key.  File position of f is saved.
                   1011:  */
                   1012: void
                   1013: show_userid(FILE *f, byte *keyID)
                   1014: {
                   1015:        int status;
                   1016:        long filepos;
                   1017:        char userid[256];
                   1018:        byte ctb;
                   1019: 
                   1020:        filepos = ftell(f);
                   1021:        if (lookup_by_keyID(f, keyID) >= 0)
                   1022:                while ((status = readkpacket(f, &ctb, userid, NULL, NULL)) != -1 && status != -3)
                   1023:                        if (ctb == CTB_USERID)
                   1024:                        {
                   1025:                                fprintf(pgpout, "%s\n", LOCAL_CHARSET(userid));
                   1026:                                fseek(f, filepos, SEEK_SET);
                   1027:                                return;
                   1028:                        }
                   1029: 
                   1030:        fprintf(pgpout, "(KeyID: %s)\n",keyIDstring(keyID));
                   1031:        fseek(f, filepos, SEEK_SET);
                   1032: }      /* show_userid */
                   1033: 
1.1.1.3 ! root     1034: 
        !          1035: /*
        !          1036:  * messages printed by show_key()
        !          1037:  */
        !          1038: static char *owntrust_msg[] = {
        !          1039:        "", /* Just don't say anything in this case */
        !          1040:        "",
        !          1041:        _PSTR("This user is untrusted to certify other keys.\n"),
        !          1042:        "", /* reserved */
        !          1043:        "", /* reserved */
        !          1044:        _PSTR("This user is generally trusted to certify other keys.\n"),
        !          1045:        _PSTR("This user is completely trusted to certify other keys.\n"),
        !          1046:        _PSTR("This axiomatic key is ultimately trusted to certify other keys.\n"),
        !          1047: };
        !          1048: static char *keylegit_msg[] = {
        !          1049:        _PSTR("This key/userID association is not certified.\n"),
        !          1050:        _PSTR("This key/userID association is not certified.\n"),
        !          1051:        _PSTR("This key/userID association is marginally certified.\n"),
        !          1052:        _PSTR("This key/userID association is fully certified.\n"),
        !          1053: };
        !          1054: static char *sigtrust_msg[] = {
        !          1055:        _PSTR("  Questionable certification from:\n  "),
        !          1056:        _PSTR("  Questionable certification from:\n  "),
        !          1057:        _PSTR("  Untrusted certification from:\n  "),
        !          1058:        "", /* reserved */
        !          1059:        "", /* reserved */
        !          1060:        _PSTR("  Generally trusted certification from:\n  "),
        !          1061:        _PSTR("  Completely trusted certification from:\n  "),
        !          1062:        _PSTR("  Axiomatically trusted certification from:\n  "),
        !          1063: };
        !          1064: 
1.1.1.2   root     1065: /*
                   1066:  * show the key in file f at file position keypos.
                   1067:  * 'what' controls the info that will be shown:
                   1068:  *   SHOW_TRUST: show trust byte info
                   1069:  *   SHOW_SIGS:  show signatures
1.1.1.3 ! root     1070:  *   SHOW_HASH:  show key fingerprint
        !          1071:  * these constants can be or'ed
        !          1072:  *
        !          1073:  * 'what' can also be SHOW_LISTFMT to get the same format as for pgp -kv
        !          1074:  * no signatures or extra userids will be printed in this case.
1.1.1.2   root     1075:  */
                   1076: int
                   1077: show_key(FILE *f, long keypos, int what)
                   1078: {
1.1.1.3 ! root     1079:        int status, keystatus = -1;
1.1.1.2   root     1080:        long filepos;
                   1081:        char userid[256];
                   1082:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
                   1083:        byte sigkeyID[KEYFRAGSIZE];
                   1084:        word32 timestamp;
1.1.1.3 ! root     1085:        byte ctb, keyctb = 0, keyctrl;
1.1.1.2   root     1086:        int userids = 0;
                   1087:        boolean print_trust = FALSE;
1.1.1.3 ! root     1088:        byte hash[16];
1.1.1.2   root     1089:        int precision = global_precision;
1.1.1.3 ! root     1090:        int compromised = 0;
        !          1091:        int disabled = 0;
1.1.1.2   root     1092: 
                   1093:        filepos = ftell(f);
                   1094:        fseek(f, keypos, SEEK_SET);
                   1095:        while ((status = readkeypacket(f, FALSE, &ctb, (byte *)&timestamp, userid,
1.1.1.3 ! root     1096:                                        n, e, NULL, NULL, NULL, NULL, sigkeyID, &keyctrl)) != -1)
1.1.1.2   root     1097:        {
1.1.1.3 ! root     1098:                if (status == -2 || status == -3)
        !          1099:                        break;
1.1.1.2   root     1100:                if (is_key_ctb(ctb))
                   1101:                {       if (userids)
                   1102:                                break;
1.1.1.3 ! root     1103:                        if (what & SHOW_HASH)
        !          1104:                                getKeyHash(hash, n, e);
        !          1105:                        keyctb = ctb;
        !          1106:                        keystatus = status;     /* remember status, could be version error */
1.1.1.2   root     1107:                }
                   1108:                else if (ctb == CTB_KEYCTRL)  /* trust bytes only in public keyrings */
                   1109:                {
1.1.1.3 ! root     1110:                        if (keystatus >= 0 && !userids) /* key packet trust byte */
        !          1111:                                if (keyctrl & KC_DISABLED)
        !          1112:                                        disabled = 1;
1.1.1.2   root     1113:                        if (what & SHOW_TRUST)
                   1114:                                print_trust = TRUE;
                   1115:                }
                   1116:                else if (ctb == CTB_USERID)
                   1117:                {       if (userids == 0)
                   1118:                        {       PascalToC(userid);      /* for display */
1.1.1.3 ! root     1119:                                ++userids;
        !          1120:                                if (what & SHOW_LISTFMT) {
        !          1121:                                        if (is_ctb_type(keyctb,CTB_CERT_PUBKEY_TYPE))
        !          1122:                                                fprintf(pgpout,"pub");
        !          1123:                                        else if (is_ctb_type(keyctb,CTB_CERT_SECKEY_TYPE))
        !          1124:                                                fprintf(pgpout,"sec");
        !          1125:                                        else
        !          1126:                                                fprintf(pgpout,"???");
        !          1127:                                        if (keystatus < 0)
        !          1128:                                                fprintf(pgpout,"? ");
        !          1129:                                        else if (compromised)
        !          1130:                                                fprintf(pgpout,"# ");
        !          1131:                                        else if (disabled)
        !          1132:                                                fprintf(pgpout,"- ");
        !          1133:                                        else
        !          1134:                                                fprintf(pgpout,"  ");
        !          1135:                                        fprintf(pgpout,"%4d/%s %s  ",
        !          1136:                                                countbits(n),key2IDstring(n),cdate(&timestamp));
        !          1137:                                        fprintf(pgpout,"%s\n",LOCAL_CHARSET(userid));
        !          1138:                                        break;  /* only print default userid */
        !          1139:                                }
1.1.1.2   root     1140:                                fprintf(pgpout,PSTR("\nKey for user ID: %s\n"),
                   1141:                                        LOCAL_CHARSET(userid));
                   1142:                                fprintf(pgpout,PSTR("%d-bit key, Key ID %s, created %s\n"),
                   1143:                                        countbits(n), key2IDstring(n), cdate(&timestamp) );
1.1.1.3 ! root     1144:                                if (keystatus == -4)
        !          1145:                                        fprintf(pgpout,PSTR("Bad key format.\n"));
        !          1146:                                else if (keystatus == -6)
        !          1147:                                        fprintf(pgpout,PSTR("Unrecognized version.\n"));
        !          1148:                                else if (what & SHOW_HASH)
        !          1149:                                        printKeyHash(hash, FALSE);
        !          1150:                                if (compromised)
        !          1151:                                        fprintf(pgpout, PSTR("Key has been revoked.\n"));
        !          1152:                                if (disabled)
        !          1153:                                        fprintf(pgpout, PSTR("Key is disabled.\n"));
        !          1154:                                if (print_trust && *owntrust_msg[TRUST_LEV(keyctrl)] != '\0')
        !          1155:                                        fprintf(pgpout, PSTR (owntrust_msg[TRUST_LEV(keyctrl)]));
1.1.1.2   root     1156:                        }
                   1157:                        else
                   1158:                        {       PascalToC(userid);
                   1159:                                if (what != 0)
                   1160:                                        fprintf(pgpout, "\n");
                   1161:                                fprintf(pgpout,PSTR("Also known as: %s\n"), 
                   1162:                                        LOCAL_CHARSET(userid));
                   1163:                        }
1.1.1.3 ! root     1164:                        if (print_trust) {
1.1.1.2   root     1165:                                read_trust(f, &keyctrl);
1.1.1.3 ! root     1166:                                fprintf(pgpout, PSTR (keylegit_msg[keyctrl&KC_LEGIT_MASK]));
1.1.1.2   root     1167:                        }       /* print_trust */
                   1168:                }
1.1.1.3 ! root     1169:                else if (is_ctb_type(ctb, CTB_SKE_TYPE))
1.1.1.2   root     1170:                {
1.1.1.3 ! root     1171:                        if (userids == 0)
        !          1172:                                compromised = 1;
        !          1173:                        if (what & SHOW_SIGS) {
        !          1174:                                if (print_trust) {
        !          1175:                                        read_trust(f, &keyctrl);
        !          1176:                                        fprintf(pgpout, PSTR (sigtrust_msg[TRUST_LEV(keyctrl)]));
        !          1177:                                }
        !          1178:                                else
        !          1179:                                        fprintf(pgpout, PSTR("  Certified by: "));
        !          1180:                                show_userid(f, sigkeyID);
1.1.1.2   root     1181:                        }
                   1182:                }
                   1183:        }
                   1184:        if (status == -1 && userids)
                   1185:                status = 0;
                   1186:        set_precision(precision);
                   1187:        fseek(f, filepos, SEEK_SET);
                   1188:        return(status);
                   1189: }      /* show_key */
                   1190: 
                   1191: 
1.1.1.3 ! root     1192: 
        !          1193: /*
        !          1194:  * stripped down version of readkeypacket(), the output userid
        !          1195:  * is a null terminated string.
        !          1196:  */
        !          1197: int
        !          1198: readkpacket(FILE *f, byte *ctb, char *userid, byte *keyID, byte *sigkeyID)
        !          1199: {
        !          1200:        int status;
        !          1201:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
        !          1202: 
        !          1203:        status = readkeypacket(f, FALSE, ctb, NULL, userid, n, e,
        !          1204:                                        NULL, NULL, NULL, NULL, sigkeyID, NULL);
        !          1205: 
        !          1206:        if (status < 0)
        !          1207:        {
        !          1208: #ifdef DEBUG
        !          1209:                if (status < -1)
        !          1210:                        fprintf(stderr, "readkeypacket returned %d\n", status);
        !          1211: #endif
        !          1212:                return(status);
        !          1213:        }
        !          1214: 
        !          1215:        if (keyID && is_key_ctb(*ctb))
        !          1216:                extract_keyID(keyID, n);
        !          1217: 
        !          1218:        if (userid && *ctb == CTB_USERID)
        !          1219:                PascalToC(userid);
        !          1220: 
        !          1221:        return(0);
        !          1222: }      /* readkpacket */
        !          1223: 
        !          1224: 
1.1.1.2   root     1225: /*
                   1226:  * write trust byte "keyctrl" to file f at file position "pos"
                   1227:  */
                   1228: void
                   1229: write_trust_pos(FILE *f, byte keyctrl, long pos)
                   1230: {
                   1231:        long fpos;
                   1232: 
                   1233:        fpos = ftell(f);
                   1234:        fseek(f, pos, SEEK_SET);
                   1235:        write_trust(f, keyctrl);
                   1236:        fseek(f, fpos, SEEK_SET);
                   1237: }      /* write_trust_pos */
                   1238: 
                   1239: 
                   1240: /*
                   1241:  * read a trust byte packet from file f, the trust byte will be
                   1242:  * stored in "keyctrl".
                   1243:  * returns -1 on EOF, -3 on corrupt input, and ERR_NOTRUST if
                   1244:  * the packet was not a trust byte (this can be used to check if
                   1245:  * a file is a keyring (with trust bytes) or a keyfile).
1.1.1.3 ! root     1246:  * The current file position is left unchanged in this case.
1.1.1.2   root     1247:  */
                   1248: int
                   1249: read_trust(FILE *f, byte *keyctrl)
                   1250: {
                   1251:        unsigned char buf[3];
                   1252: 
                   1253:        if (fread(buf, 1, 3, f) != 3)
                   1254:                return -1;
1.1.1.3 ! root     1255:        if (buf[0] != CTB_KEYCTRL) {
        !          1256:                if (is_ctb(buf[0])) {
        !          1257:                        fseek(f, -3L, SEEK_CUR);
1.1.1.2   root     1258:                        return(ERR_NOTRUST);
1.1.1.3 ! root     1259:                } else
1.1.1.2   root     1260:                        return(-3);             /* bad data */
                   1261:        }
                   1262:        if (buf[1] != 1)                /* length must be 1 */
                   1263:                return(-3);
                   1264:        if (keyctrl)
                   1265:                *keyctrl = buf[2];
                   1266:        return(0);
                   1267: }      /* read_trust */
1.1.1.3 ! root     1268: 
        !          1269: 
        !          1270: 
        !          1271: /****** userid lookup ******/
        !          1272: 
        !          1273: #define        HASH_ALLOC      (ALLOC_UNIT / sizeof(struct hashent))
        !          1274: 
        !          1275: static char * store_str(char *str);
        !          1276: static VOID * allocbuf(int size);
        !          1277: static void freebufpool();
        !          1278: 
        !          1279: static struct hashent {
        !          1280:        struct hashent *next;
        !          1281:        byte keyID[KEYFRAGSIZE];
        !          1282:        char *userid;
        !          1283: } **hashtbl = NULL, *hashptr;
        !          1284: 
        !          1285: static char *strptr;
        !          1286: static int strleft = 0;
        !          1287: static int hashleft = 0;
        !          1288: static int nleft = 0;
        !          1289: 
        !          1290: #define MAXKR  8       /* max. number of keyrings for user_from_keyID() */
        !          1291: static char *krnames[MAXKR];
        !          1292: static int nkr = 0;
        !          1293: /*
        !          1294:  * Lookup userid by keyID without using the in-memory hash table.
        !          1295:  */
        !          1296: static char *
        !          1297: _user_from_keyID(byte *srch_keyID)
        !          1298: {
        !          1299:        FILE *f;
        !          1300:        int i, status, found = 0;
        !          1301:        byte keyID[KEYFRAGSIZE];
        !          1302:        static char userid[256];
        !          1303:        byte ctb;
        !          1304: 
        !          1305:        /* search all keyfiles set with setkrent() */
        !          1306:        for (i = 0; !found && i < nkr; ++i) {
        !          1307:                if ((f = fopen(krnames[i], FOPRBIN)) == NULL)
        !          1308:                        continue;
        !          1309:                while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1) {
        !          1310:                        if (status == -2 || status == -3)
        !          1311:                                break;
        !          1312:                        if (is_key_ctb(ctb) && memcmp(keyID, srch_keyID, KEYFRAGSIZE) == 0)
        !          1313:                                found = 1;
        !          1314:                        if (found && ctb == CTB_USERID)
        !          1315:                                break;
        !          1316:                }
        !          1317:                fclose(f);
        !          1318:        }
        !          1319:        return(found ? userid : NULL);
        !          1320: }
        !          1321: 
        !          1322: /*
        !          1323:  * Lookup userid by keyID, use hash table if initialized.
        !          1324:  */
        !          1325: char *
        !          1326: user_from_keyID(byte *keyID)
        !          1327: {
        !          1328:        struct hashent *p;
        !          1329: 
        !          1330:        if (!hashtbl)
        !          1331:                return _user_from_keyID(keyID);
        !          1332:        for (p = hashtbl[PK_HASH(keyID)]; p; p = p->next)
        !          1333:                if (memcmp(keyID, p->keyID, KEYFRAGSIZE) == 0)
        !          1334:                        return p->userid;
        !          1335:        return NULL;
        !          1336: }
        !          1337: 
        !          1338: /*
        !          1339:  * add keyfile to userid hash table, userids are added, endkrent() clears
        !          1340:  * the hash table.
        !          1341:  */
        !          1342: int
        !          1343: setkrent(char *keyring)
        !          1344: {
        !          1345:        int i;
        !          1346:        char pubring[MAX_PATH];
        !          1347: 
        !          1348:        assert(nkr < MAXKR);
        !          1349:        if (keyring == NULL) {
        !          1350:                buildfilename(pubring, PUBLIC_KEYRING_FILENAME);
        !          1351:                keyring = pubring;
        !          1352:        }
        !          1353:        for (i = 0; i < nkr; ++i)
        !          1354:                if (strcmp(keyring, krnames[i]) == 0)
        !          1355:                        return 0;       /* duplicate name */
        !          1356:        krnames[nkr++] = store_str(keyring);
        !          1357:        return 0;
        !          1358: }
        !          1359: 
        !          1360: void
        !          1361: endkrent(void)
        !          1362: {
        !          1363:        hashleft = strleft = 0;
        !          1364:        hashtbl = NULL;
        !          1365:        nkr = 0;
        !          1366:        freebufpool();
        !          1367: }
        !          1368: 
        !          1369: /*
        !          1370:  * create userid hash table, read all files set with setkrent()
        !          1371:  */
        !          1372: int
        !          1373: init_userhash(void)
        !          1374: {
        !          1375:        FILE *f;
        !          1376:        int status, i;
        !          1377:        byte keyID[KEYFRAGSIZE];
        !          1378:        char userid[256];
        !          1379:        byte ctb;
        !          1380:        int keyflag;
        !          1381: 
        !          1382:        if (!hashtbl) {
        !          1383:                hashtbl = allocbuf(PK_HASHSIZE * sizeof(struct hashent *));
        !          1384:                memset(hashtbl, 0, PK_HASHSIZE * sizeof(struct hashent *));
        !          1385:        }
        !          1386:        for (i = 0; i < nkr; ++i) {
        !          1387:                if ((f = fopen(krnames[i], FOPRBIN)) == NULL)
        !          1388:                        continue;
        !          1389:                keyflag = 0;
        !          1390:                while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1) {
        !          1391:                        if (is_key_ctb(ctb) && user_from_keyID(keyID) == NULL)
        !          1392:                                keyflag = 1;
        !          1393:                        if (keyflag && ctb == CTB_USERID) {
        !          1394:                                if (!hashleft) {
        !          1395:                                        hashptr = allocbuf(HASH_ALLOC * sizeof(struct hashent));
        !          1396:                                        hashleft = HASH_ALLOC;
        !          1397:                                }
        !          1398:                                memcpy(hashptr->keyID, keyID, KEYFRAGSIZE);
        !          1399:                                hashptr->userid = store_str(userid);
        !          1400:                                hashptr->next = hashtbl[PK_HASH(keyID)];
        !          1401:                                hashtbl[PK_HASH(keyID)] = hashptr;
        !          1402:                                ++hashptr;
        !          1403:                                --hashleft;
        !          1404:                                keyflag = 0;
        !          1405:                        }
        !          1406:                }
        !          1407:                fclose(f);
        !          1408:        }
        !          1409:        return 0;
        !          1410: }
        !          1411: 
        !          1412: /*
        !          1413:  * memory management routines
        !          1414:  */
        !          1415: 
        !          1416: static void
        !          1417: maint_init_mem(void)
        !          1418: {
        !          1419:        pkhash = allocbuf(PK_HASHSIZE * sizeof(struct pubkey *));
        !          1420:        memset(pkhash, 0, PK_HASHSIZE * sizeof(struct pubkey *));
        !          1421: }
        !          1422: 
        !          1423: static void
        !          1424: maint_release_mem(void)
        !          1425: {
        !          1426:        nleft = 0;
        !          1427:        strleft = 0;
        !          1428:        pkhash = NULL;
        !          1429:        freebufpool();
        !          1430: }
        !          1431: 
        !          1432: /*
        !          1433:  * allocn() does the same as malloc().  Memory is allocated in chunks
        !          1434:  * of ALLOC_UNIT bytes, all memory can be freed by calling freebufpool().
        !          1435:  */
        !          1436: static VOID *
        !          1437: allocn(int size)
        !          1438: {
        !          1439:        static char *ptr;
        !          1440: #ifndef MSDOS  /* don't align on MSDOS to save memory */
        !          1441:        size = (size + 3) & ~3;
        !          1442: #endif
        !          1443:        assert(size < ALLOC_UNIT);
        !          1444:        if (size > nleft) {
        !          1445:                ptr = allocbuf(ALLOC_UNIT);
        !          1446:                nleft = ALLOC_UNIT;
        !          1447:        }
        !          1448:        nleft -= size;
        !          1449:        ptr += size;
        !          1450:        return ptr - size;
        !          1451: }
        !          1452: 
        !          1453: /*
        !          1454:  * store_str does the same as strdup(), but allocates memory with allocbuf()
        !          1455:  */
        !          1456: static char *
        !          1457: store_str(char *str)
        !          1458: {
        !          1459:        int size = strlen(str) + 1;
        !          1460:        if (size > ALLOC_UNIT) {
        !          1461:                fprintf(stderr, "store_str: string too long\n");
        !          1462:                return NULL;
        !          1463:        }
        !          1464:        if (size > strleft) {
        !          1465:                strptr = allocbuf(ALLOC_UNIT);
        !          1466:                strleft = ALLOC_UNIT;
        !          1467:        }
        !          1468:        strcpy(strptr, str);
        !          1469:        strptr += size;
        !          1470:        strleft -= size;
        !          1471:        return strptr - size;
        !          1472: }
        !          1473: 
        !          1474: 
        !          1475: static struct bufpool {
        !          1476:        struct bufpool *next;
        !          1477:        char buf[1];            /* variable size */
        !          1478: } *bufpool = NULL;
        !          1479: 
        !          1480: long totalsize = 0;
        !          1481: 
        !          1482: /*
        !          1483:  * allocate buffer, all buffers allocated with this function can be
        !          1484:  * freed with one call to freebufpool()
        !          1485:  */
        !          1486: static VOID *
        !          1487: allocbuf(int size)
        !          1488: {
        !          1489:        struct bufpool *p;
        !          1490: 
        !          1491:        p = xmalloc(size + sizeof(struct bufpool *));
        !          1492:        totalsize += size;
        !          1493:        p->next = bufpool;
        !          1494:        bufpool = p;
        !          1495:        return p->buf;
        !          1496: }
        !          1497: 
        !          1498: /*
        !          1499:  * free all memory obtained with allocbuf()
        !          1500:  */
        !          1501: static void
        !          1502: freebufpool(void)
        !          1503: {
        !          1504:        struct bufpool *p;
        !          1505: 
        !          1506:        if (verbose)
        !          1507:                fprintf(pgpout, "\nMemory used: %ldk\n", totalsize / 1024);
        !          1508:        totalsize = 0;
        !          1509:        while (bufpool) {
        !          1510:                p = bufpool;
        !          1511:                bufpool = bufpool->next;
        !          1512:                free(p);
        !          1513:        }
        !          1514: }

unix.superglobalmegacorp.com

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