|
|
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(×tamp)); ! 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(×tamp)); ! 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(×tamp)); ! 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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.