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

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

unix.superglobalmegacorp.com

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