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

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

unix.superglobalmegacorp.com

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