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