|
|
1.1 ! 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> ! 25: #include "mpilib.h" ! 26: #include "random.h" ! 27: #include "crypto.h" ! 28: #include "fileio.h" ! 29: #include "keymgmt.h" ! 30: #include "mpiio.h" ! 31: #include "language.h" ! 32: #include "pgp.h" ! 33: ! 34: ! 35: void setup_trust(); ! 36: int maint_pass1(FILE *f); ! 37: int maint_trace_chain(FILE *f); ! 38: int maint_cmpfiles(FILE *f, FILE *g); ! 39: int trace_sig_chain(FILE *f, byte *fromID, int owner_trust, int depth); ! 40: int check_secretkey(FILE *f, long keypos); ! 41: int set_legit(FILE *f, long trustpos, int trust_count); ! 42: long lookup_by_keyID(FILE *f, byte *srch_keyID); ! 43: void show_userid(FILE *f, byte *keyID); ! 44: int show_trust(byte, byte); ! 45: int show_legit(byte, byte); ! 46: void write_trust_pos(FILE *f, byte keyctrl, long pos); ! 47: ! 48: /* returned when trying to do a maintenance pass on a secret keyring or keyfile */ ! 49: #define ERR_NOTRUST -7 ! 50: ! 51: #define TRUST_MASK 7 /* mask for userid/signature trust bytes */ ! 52: #define SET_TRUST(b,v) (*(b) = (*(b) & ~TRUST_MASK) | (v)) ! 53: #define TRUST_LEV(b) ((b) & TRUST_MASK) ! 54: ! 55: #define TRUST_FAC(x) (trust_tbl[TRUST_LEV(x)]) ! 56: ! 57: /* ! 58: * table for tuning user paranoia index. ! 59: * values represent contribution of one signature indexed by the ! 60: * SIGTRUST of a signature ! 61: */ ! 62: int trust_tbl[8]; ! 63: ! 64: static int marginal_min; ! 65: static int complete_min; /* total count needed for a fully legit key */ ! 66: ! 67: int marg_min = 2; /* number of marginally trusted signatures needed for ! 68: a fully legit key (can be set in config.pgp). */ ! 69: int compl_min = 1; /* number of fully trusted signatures needed */ ! 70: ! 71: char trust_lst[8][16] = { ! 72: "undefined", /* PSTR("undefined") */ ! 73: "unknown", /* PSTR("unknown") */ ! 74: "untrusted", /* PSTR("untrusted") */ ! 75: "<3>", /* unused */ ! 76: "<4>", /* unused */ ! 77: "marginal", /* PSTR("marginal") */ ! 78: "complete", /* PSTR("complete") */ ! 79: "ultimate", /* PSTR("ultimate") */ ! 80: }; ! 81: ! 82: char legit_lst[4][16] = { ! 83: "undefined", ! 84: "untrusted", ! 85: "marginal", ! 86: "complete" ! 87: }; ! 88: ! 89: int trustlst_len = 9; /* length of longest trust word */ ! 90: int legitlst_len = 9; /* length of longest legit word */ ! 91: ! 92: char floppyring[MAX_PATH] = ""; ! 93: int max_cert_depth = 4; /* maximum nesting of signatures */ ! 94: ! 95: static boolean check_only = FALSE; ! 96: static boolean mverbose; ! 97: static FILE *sec_fp; ! 98: static FILE *floppy_fp = NULL; ! 99: static int undefined_trust; /* number of legit keys with undef. trust */ ! 100: ! 101: int ! 102: maintenance(char *ringfile, int options) ! 103: { ! 104: FILE *f, *g; ! 105: int status; ! 106: char *tmpring; ! 107: char secretkeyring[MAX_PATH]; ! 108: ! 109: check_only = (options & MAINT_CHECK) != 0; ! 110: mverbose = (options & MAINT_VERBOSE) != 0; ! 111: undefined_trust = 0; ! 112: ! 113: if ((tmpring = tempfile(TMP_TMPDIR)) == NULL) ! 114: return(-1); ! 115: if ((g = fopenbin(tmpring, "w+")) == NULL) ! 116: return(-1); ! 117: ! 118: if ((f = fopenbin(ringfile,"r")) == NULL) ! 119: { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile); ! 120: fclose(g); ! 121: return(-1); ! 122: } ! 123: ! 124: buildfilename(secretkeyring, SECRET_KEYRING_FILENAME); ! 125: if ((sec_fp = fopenbin(secretkeyring, "r")) == NULL) ! 126: fprintf(pgpout,PSTR("\nCan't open secret key ring file '%s'\n"), ! 127: secretkeyring); ! 128: ! 129: if (!(options & MAINT_SILENT) && *floppyring != '\0' && ! 130: (floppy_fp = fopenbin(floppyring, "r")) == NULL) ! 131: fprintf(pgpout,PSTR("\nCan't open backup key ring file '%s'\n"), ! 132: floppyring); ! 133: ! 134: if ((status = copyfile(f, g, -1L)) < 0) ! 135: { fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"), ringfile); ! 136: goto failed; ! 137: } ! 138: ! 139: setup_trust(); ! 140: if (mverbose) ! 141: fprintf(pgpout, PSTR("\nPass 1: Looking for the \"ultimately-trusted\" keys...\n")); ! 142: rewind(g); ! 143: if ((status = maint_pass1(g)) < 0) ! 144: goto failed; ! 145: ! 146: if (mverbose) ! 147: fprintf(pgpout, PSTR("\nPass 2: Tracing signature chains...\n")); ! 148: rewind(g); ! 149: if ((status = maint_trace_chain(g)) < 0) ! 150: goto failed; ! 151: ! 152: if (!(options & MAINT_SILENT)) ! 153: { if (mverbose) ! 154: fprintf(pgpout, PSTR("\nPass 3: Comparing with original keyring...\n")); ! 155: rewind(f); ! 156: rewind(g); ! 157: if ((status = maint_cmpfiles(f, g)) < 0) ! 158: goto failed; ! 159: } else ! 160: status = 1; ! 161: ! 162: fflush(g); ! 163: if (ferror(g)) ! 164: { status = -1; ! 165: goto failed; ! 166: } ! 167: fclose(f); ! 168: fclose(g); ! 169: if (sec_fp) ! 170: fclose(sec_fp); ! 171: if (floppy_fp) ! 172: { fclose(floppy_fp); ! 173: floppy_fp = NULL; ! 174: } ! 175: ! 176: #ifdef DEBUG ! 177: if (check_only) ! 178: { ! 179: if (undefined_trust) ! 180: fprintf(pgpout, "\nKeyring contains %d fully validated key(s) with undefined trust.\n", undefined_trust); ! 181: else ! 182: if (status == 0) ! 183: fprintf(pgpout, "\nMaintenance check OK.\n"); ! 184: rmtemp(tmpring); ! 185: return(0); ! 186: } ! 187: #endif ! 188: ! 189: if (status > 0) /* keyring is changed */ ! 190: { ! 191: if (options & MAINT_SILENT) ! 192: { /* implicit maintenance pass (after pgp -ka, -kr, -ks) */ ! 193: remove(ringfile); ! 194: if (savetemp(tmpring, ringfile) == NULL) ! 195: return(-1); ! 196: } ! 197: else ! 198: { /* explicit maintenance pass */ ! 199: fprintf(pgpout, PSTR("Update public keyring '%s' (Y/n)? "), ringfile); ! 200: if (!getyesno('y')) ! 201: { ! 202: rmtemp(tmpring); ! 203: return(0); ! 204: } ! 205: if (savetempbak(tmpring, ringfile)) ! 206: return(-1); ! 207: } ! 208: } ! 209: else ! 210: rmtemp(tmpring); ! 211: ! 212: return(0); ! 213: ! 214: failed: ! 215: if (sec_fp) ! 216: fclose(sec_fp); ! 217: if (floppy_fp) ! 218: { fclose(floppy_fp); ! 219: floppy_fp = NULL; ! 220: } ! 221: fclose(f); ! 222: fclose(g); ! 223: #ifdef DEBUG ! 224: savetempbak(tmpring, "tmpring.pub"); ! 225: #else ! 226: rmtemp(tmpring); ! 227: #endif ! 228: return(status); ! 229: } ! 230: ! 231: ! 232: /* ! 233: * check if axiomatic keys are present in the secret keyring and ! 234: * clear userid and signature trust bytes ! 235: */ ! 236: int ! 237: maint_pass1(FILE *f) ! 238: { ! 239: int status; ! 240: char userid[256]; ! 241: byte keyID[KEYFRAGSIZE]; ! 242: byte ctb; ! 243: byte keyctrl; ! 244: boolean buckstop = FALSE, show_user = FALSE; ! 245: boolean compromised = FALSE; ! 246: int buckstopcount = 0; ! 247: int usercount = 0; ! 248: long keypos = 0; ! 249: ! 250: while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1) ! 251: { ! 252: if (status < 0) ! 253: return(status); ! 254: ! 255: if (is_ctb_type(ctb, CTB_COMMENT_TYPE)) ! 256: continue; ! 257: if (compromised && is_ctb_type(ctb, CTB_SKE_TYPE) && !usercount) ! 258: continue; /* compromise certificate */ ! 259: ! 260: /* other packets should have trust byte */ ! 261: if (read_trust(f, &keyctrl) < 0) ! 262: return(ERR_NOTRUST); /* not a public keyring */ ! 263: ! 264: if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE)) ! 265: { ! 266: if (compromised = is_compromised(f)) ! 267: keyctrl = KC_OWNERTRUST_NEVER; ! 268: if ((keyctrl & KC_BUCKSTOP)) ! 269: { ! 270: if (check_secretkey(f, keypos) == 0) ! 271: { ! 272: ++buckstopcount; ! 273: buckstop = TRUE; ! 274: if (mverbose) ! 275: fprintf(pgpout, "* %s",keyIDstring(keyID)); ! 276: } ! 277: else ! 278: { /* not in secret keyring */ ! 279: keyctrl &= ~KC_BUCKSTOP; ! 280: if (TRUST_LEV(keyctrl) == KC_OWNERTRUST_ULTIMATE) ! 281: keyctrl = KC_OWNERTRUST_ALWAYS; ! 282: if (mverbose) ! 283: fprintf(pgpout, ". %s",keyIDstring(keyID)); ! 284: } ! 285: show_user = mverbose; ! 286: } ! 287: else ! 288: { ! 289: buckstop = FALSE; ! 290: show_user = FALSE; ! 291: } ! 292: usercount = 0; ! 293: keyctrl &= ~KC_VISITED; ! 294: ! 295: } ! 296: else if (ctb == CTB_USERID) ! 297: { ! 298: if (show_user) ! 299: { ! 300: if (usercount) /* more than one user ID */ ! 301: fprintf(pgpout, " "); ! 302: fprintf(pgpout, " %s\n", EXTERNAL(userid)); ! 303: } ! 304: if (buckstop) ! 305: keyctrl = KC_LEGIT_COMPLETE; ! 306: else ! 307: keyctrl = KC_LEGIT_UNKNOWN; ! 308: ++usercount; ! 309: } ! 310: else if (is_ctb_type(ctb, CTB_SKE_TYPE)) ! 311: { ! 312: keyctrl = KC_SIGTRUST_UNDEFINED; ! 313: } ! 314: fseek(f, -1L, SEEK_CUR); ! 315: fwrite(&keyctrl, 1, 1, f); ! 316: fseek(f, 0L, SEEK_CUR); ! 317: keypos = ftell(f); ! 318: } ! 319: if (buckstopcount == 0 && mverbose) ! 320: { ! 321: fprintf(pgpout, PSTR("No ultimately-trusted keys.\n")); ! 322: } ! 323: return(0); ! 324: } ! 325: ! 326: ! 327: /* ! 328: * scan keyring for buckstop keys and start the recursive trace_sig_chain() ! 329: * on them ! 330: */ ! 331: int ! 332: maint_trace_chain(FILE *f) ! 333: { ! 334: int status; ! 335: char userid[256]; ! 336: byte keyID[KEYFRAGSIZE]; ! 337: long trustpos = 0; ! 338: byte ctb; ! 339: byte own_trust; ! 340: boolean buckstop = FALSE; ! 341: ! 342: while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1) ! 343: { ! 344: if (status < 0) ! 345: return status; ! 346: ! 347: if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE)) ! 348: { ! 349: trustpos = ftell(f); ! 350: if ((status = read_trust(f, &own_trust)) < 0) ! 351: return(status); ! 352: buckstop = (own_trust & KC_BUCKSTOP) != 0; ! 353: userid[0] = '\0'; ! 354: } ! 355: else if (ctb == CTB_USERID) ! 356: { ! 357: if (buckstop) ! 358: { ! 359: buckstop = FALSE; /* only for first user id */ ! 360: if (mverbose) ! 361: fprintf(pgpout, "* %s\n", EXTERNAL(userid)); ! 362: ! 363: if (TRUST_LEV(own_trust) == KC_OWNERTRUST_UNDEFINED) ! 364: { SET_TRUST(&own_trust, ask_owntrust(userid, own_trust)); ! 365: write_trust_pos(f, own_trust, trustpos); ! 366: } ! 367: if (trace_sig_chain(f, keyID, TRUST_LEV(own_trust), 0) < 0) ! 368: return(-1); ! 369: } ! 370: } ! 371: } ! 372: return(0); ! 373: } ! 374: ! 375: ! 376: /* ! 377: * check if the maintenance pass changed anything ! 378: * returns 0 if files f and g are equal. ! 379: */ ! 380: int ! 381: maint_cmpfiles(FILE *f, FILE *g) ! 382: { ! 383: int status; ! 384: char userid[256]; ! 385: byte keyID[KEYFRAGSIZE]; ! 386: byte sigkeyID[KEYFRAGSIZE]; ! 387: byte ctb; ! 388: byte kc_orig, kc_new; ! 389: int usercount = 0; ! 390: int changed = 0; ! 391: ! 392: fprintf(pgpout, PSTR(" KeyID Trust Validity User ID\n")); ! 393: while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) == 0) ! 394: { ! 395: if (is_ctb_type(ctb, CTB_COMMENT_TYPE)) ! 396: continue; ! 397: /* other packets should have trust byte */ ! 398: ! 399: fseek(g, ftell(f), SEEK_SET); ! 400: if (read_trust(f, &kc_orig) < 0 || read_trust(g, &kc_new) < 0) ! 401: { status = ERR_NOTRUST; ! 402: break; ! 403: } ! 404: ! 405: if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE)) ! 406: { ! 407: if (is_compromised(f)) ! 408: { ! 409: fprintf(pgpout, "# "); ! 410: nextkeypacket(f, &ctb); /* skip compromise certificate */ ! 411: nextkeypacket(g, &ctb); ! 412: } ! 413: else if ((kc_new & KC_BUCKSTOP)) ! 414: fprintf(pgpout, "* "); ! 415: else ! 416: fprintf(pgpout, " "); ! 417: ! 418: fprintf(pgpout, "%s ",keyIDstring(keyID)); ! 419: changed += show_trust(kc_new, kc_orig); ! 420: usercount = 0; ! 421: userid[0] = '\0'; ! 422: } ! 423: else if (ctb == CTB_USERID) ! 424: { ! 425: if (usercount) /* more than one user ID */ ! 426: fprintf(pgpout, " %*s", trustlst_len, ""); ! 427: ++usercount; ! 428: changed += show_legit(kc_new, kc_orig); ! 429: fprintf(pgpout, "%s\n", EXTERNAL(userid)); ! 430: } ! 431: else if (is_ctb_type(ctb, CTB_SKE_TYPE)) ! 432: { ! 433: if (kc_new & KC_CONTIG) ! 434: fprintf(pgpout, "c "); ! 435: else ! 436: fprintf(pgpout, " "); ! 437: changed += show_trust(kc_new, kc_orig); ! 438: fprintf(pgpout, " %*s", legitlst_len, ""); ! 439: show_userid(f, sigkeyID); ! 440: } ! 441: } ! 442: if (status >= -1 && changed) ! 443: fprintf(pgpout, PSTR("\n%d \"trust byte(s)\" changed.\n"), changed); ! 444: if (status < -1) /* -1 is OK, EOF */ ! 445: return(status); ! 446: return(changed); ! 447: } ! 448: ! 449: ! 450: void ! 451: init_trust_lst() ! 452: { ! 453: static int initialized = 0; ! 454: int i, len; ! 455: char *s; ! 456: ! 457: if (initialized) ! 458: return; ! 459: for (i = 0; i < 8; ++i) ! 460: { if (trust_lst[i][0]) ! 461: { s = PSTR (trust_lst[i]); ! 462: if (s != trust_lst[i]) ! 463: strncpy(trust_lst[i], s, sizeof(trust_lst[0]) - 1); ! 464: len = strlen(s); ! 465: if (len > trustlst_len) ! 466: trustlst_len = len; ! 467: } ! 468: } ! 469: for (i = 0; i < 4; ++i) ! 470: { s = PSTR (legit_lst[i]); ! 471: if (s != legit_lst[i]) ! 472: strncpy(legit_lst[i], s, sizeof(legit_lst[0]) - 1); ! 473: len = strlen(s); ! 474: if (len > legitlst_len) ! 475: legitlst_len = len; ! 476: } ! 477: ++trustlst_len; ! 478: ++legitlst_len; ! 479: initialized = 1; ! 480: } ! 481: ! 482: int ! 483: show_trust(byte kc_new, byte kc_orig) ! 484: { ! 485: #ifdef DEBUG ! 486: fprintf(pgpout, " %02x", kc_new); ! 487: if (kc_new != kc_orig) ! 488: { ! 489: fprintf(pgpout, " (%02x) ", kc_orig); ! 490: return(1); ! 491: } ! 492: fprintf(pgpout, " "); ! 493: return(0); ! 494: #else ! 495: init_trust_lst(); ! 496: fprintf(pgpout, "%c%-*s", (kc_new == kc_orig ? ' ' : '!'), ! 497: trustlst_len, trust_lst[TRUST_LEV(kc_new)]); ! 498: return(kc_new != kc_orig); ! 499: #endif ! 500: } ! 501: ! 502: int ! 503: show_legit(byte kc_new, byte kc_orig) ! 504: { ! 505: #ifdef DEBUG ! 506: return(show_trust(kc_new, kc_orig)); ! 507: #else ! 508: init_trust_lst(); ! 509: kc_new &= KC_LEGIT_MASK; ! 510: kc_orig &= KC_LEGIT_MASK; ! 511: fprintf(pgpout, "%c%-*s", (kc_new == kc_orig ? ' ' : '!'), ! 512: legitlst_len, legit_lst[kc_new]); ! 513: return(kc_new != kc_orig); ! 514: #endif ! 515: } ! 516: ! 517: ! 518: /* ! 519: * Find all signatures made with a key, fromID is the keyID of this key ! 520: * owner_trust is the trust level of this key. ! 521: * If a trusted signature makes a key fully legit then signatures made ! 522: * with this key are also recursively traced on down the tree. ! 523: */ ! 524: int ! 525: trace_sig_chain(FILE *f, byte *fromID, int owner_trust, int depth) ! 526: { ! 527: long filepos; ! 528: int status; ! 529: int trust_count = 0; ! 530: byte keyID[KEYFRAGSIZE]; ! 531: byte sigkeyID[KEYFRAGSIZE]; ! 532: byte ctb; ! 533: byte own_trust, sig_trust; ! 534: char userid[256]; ! 535: int sig_count = 0; ! 536: int compromised = 0; ! 537: long usertrustpos = 0; ! 538: long ownt_pos = 0; ! 539: ! 540: if (max_cert_depth > 8) ! 541: max_cert_depth = 8; ! 542: if (depth > max_cert_depth) ! 543: return(0); ! 544: filepos = ftell(f); ! 545: rewind(f); ! 546: userid[0] = '\0'; ! 547: while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) != -1) ! 548: { ! 549: if (status < 0) ! 550: return status; ! 551: ! 552: if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE)) ! 553: { ! 554: compromised = is_compromised(f); ! 555: ownt_pos = ftell(f); ! 556: if (read_trust(f, &own_trust)) ! 557: return(ERR_NOTRUST); ! 558: userid[0] = '\0'; ! 559: } ! 560: else if (ctb == CTB_USERID) ! 561: { ! 562: usertrustpos = ftell(f); ! 563: trust_count = 0; ! 564: } ! 565: else if (is_ctb_type(ctb, CTB_SKE_TYPE)) ! 566: { ! 567: if (compromised) ! 568: continue; ! 569: read_trust(f, &sig_trust); ! 570: if (memcmp(sigkeyID, fromID, sizeof(sigkeyID)) == 0) ! 571: { ! 572: ++sig_count; ! 573: if (mverbose) ! 574: fprintf(pgpout, "%*s > %s\n", 2*depth, "", EXTERNAL(userid)); ! 575: if (TRUST_LEV(sig_trust) != owner_trust) ! 576: { ! 577: SET_TRUST(&sig_trust, owner_trust); ! 578: } ! 579: sig_trust |= KC_CONTIG; ! 580: fseek(f, -1L, SEEK_CUR); ! 581: fwrite(&sig_trust, 1, 1, f); ! 582: fseek(f, 0L, SEEK_CUR); ! 583: } ! 584: ! 585: if (sig_trust & KC_CONTIG) ! 586: { ! 587: trust_count += TRUST_FAC(sig_trust); ! 588: ! 589: switch (set_legit(f, usertrustpos, trust_count)) ! 590: { ! 591: case -1: return(-1); ! 592: case 1: ! 593: if ((own_trust & (KC_BUCKSTOP|KC_VISITED)) == 0) ! 594: { ! 595: if (TRUST_LEV(own_trust) == KC_OWNERTRUST_UNDEFINED) ! 596: SET_TRUST(&own_trust, ask_owntrust(userid, own_trust)); ! 597: own_trust |= KC_VISITED; ! 598: write_trust_pos(f, own_trust, ownt_pos); ! 599: trace_sig_chain(f, keyID, TRUST_LEV(own_trust), depth+1); ! 600: } ! 601: } ! 602: } ! 603: } ! 604: } ! 605: if (mverbose && sig_count == 0) /* no signatures from this user */ ! 606: fprintf(pgpout, PSTR("%*s (No signatures)\n"), 2*depth, ""); ! 607: fseek(f, filepos, SEEK_SET); ! 608: return(0); ! 609: } ! 610: ! 611: ! 612: int ! 613: check_secretkey(FILE *f, long keypos) ! 614: { ! 615: int status = -1; ! 616: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION]; ! 617: unit nsec[MAX_UNIT_PRECISION], esec[MAX_UNIT_PRECISION]; ! 618: char userid[256]; ! 619: byte keyID[KEYFRAGSIZE]; ! 620: long savepos, pktlen; ! 621: byte ctb; ! 622: ! 623: if (sec_fp == NULL) ! 624: return(-1); ! 625: ! 626: savepos = ftell(f); ! 627: fseek(f, keypos, SEEK_SET); ! 628: if (readkeypacket(f, FALSE, &ctb, NULL, NULL, n, e, ! 629: NULL, NULL, NULL, NULL, NULL, NULL) < 0) ! 630: goto ex; ! 631: extract_keyID(keyID, n); ! 632: ! 633: do /* get userid */ ! 634: { if (readkpacket(f, &ctb, userid, NULL, NULL) < 0) ! 635: goto ex; ! 636: } while (ctb != CTB_USERID); ! 637: ! 638: if (lookup_by_keyID(sec_fp, keyID) < 0) ! 639: { ! 640: #if 0 ! 641: if (!check_only) ! 642: { ! 643: fprintf(pgpout, PSTR ( ! 644: "\nAn \"axiomatic\" key is one which does not need certifying by\n\ ! 645: anyone else. Usually this special status is reserved only for your\n\ ! 646: own keys, which should also appear on your secret keyring. The owner\n\ ! 647: of an axiomatic key (who is typically yourself) is \"ultimately trusted\"\n\ ! 648: by you to certify any or all other keys.\n")); ! 649: fprintf(pgpout, PSTR ("\nKey for user ID: \"%s\"\n\ ! 650: is designated as an \"ultimately-trusted\" introducer, but the key\n\ ! 651: does not appear in the secret keyring.\n\ ! 652: Use this key as an ultimately-trusted introducer (y/N)? "), EXTERNAL(userid)); ! 653: status = (getyesno('n') ? 0 : 1); ! 654: } ! 655: #else ! 656: status = 1; ! 657: #endif ! 658: } ! 659: else ! 660: { ! 661: long kpos = ftell(sec_fp); ! 662: if (readkeypacket(sec_fp, FALSE, &ctb, NULL, NULL, nsec, esec, ! 663: NULL, NULL, NULL, NULL, NULL, NULL) < 0) ! 664: { ! 665: fprintf(pgpout, PSTR("\n\007Cannot read from secret keyring.\n")); ! 666: goto ex; ! 667: } ! 668: if (mp_compare(n, nsec) || mp_compare(e, esec)) ! 669: { /* Red Alert! */ ! 670: fprintf(pgpout, PSTR("\n\007WARNING: Public key for user ID: \"%s\"\n\ ! 671: does not match the corresponding key in the secret keyring.\n"), EXTERNAL(userid)); ! 672: fprintf(pgpout, PSTR("This is a serious condition, indicating possible keyring tampering.\n")); ! 673: status = -2; ! 674: } ! 675: else ! 676: status = 0; ! 677: ! 678: if (floppy_fp) ! 679: { ! 680: if (lookup_by_keyID(floppy_fp, keyID) < 0) ! 681: { ! 682: fprintf(pgpout, PSTR("Public key for: \"%s\"\n\ ! 683: is not present in the backup keyring '%s'.\n"), ! 684: EXTERNAL(userid), floppyring); ! 685: } ! 686: else ! 687: { ! 688: pktlen = ftell(sec_fp) - kpos; ! 689: fseek(sec_fp, kpos, SEEK_SET); ! 690: while (--pktlen >= 0 && getc(sec_fp) == getc(floppy_fp)) ; ! 691: if (pktlen != -1) ! 692: { ! 693: fprintf(pgpout, PSTR("\n\007WARNING: Secret key for: \"%s\"\n\ ! 694: does not match the key in the backup keyring '%s'.\n"), ! 695: EXTERNAL(userid), floppyring); ! 696: fprintf(pgpout, PSTR("This is a serious condition, indicating possible keyring tampering.\n")); ! 697: status = -2; ! 698: } ! 699: } ! 700: } ! 701: } ! 702: ex: ! 703: fseek(f, savepos, SEEK_SET); ! 704: return(status); ! 705: } ! 706: ! 707: ! 708: void ! 709: setup_trust() ! 710: { /* initialize trust table */ ! 711: if (marg_min == 0) /* marginally trusted signatures are ignored */ ! 712: { ! 713: trust_tbl[5] = 0; ! 714: trust_tbl[6] = 1; ! 715: complete_min = compl_min; ! 716: } ! 717: else ! 718: { ! 719: if (marg_min < compl_min) ! 720: marg_min = compl_min; ! 721: trust_tbl[5] = compl_min; ! 722: trust_tbl[6] = marg_min; ! 723: complete_min = compl_min * marg_min; ! 724: } ! 725: trust_tbl[7] = complete_min; /* ultimate trust */ ! 726: marginal_min = complete_min / 2; ! 727: } ! 728: ! 729: ! 730: /* ! 731: * set legit level of a userid ! 732: * returns 1 if the key/userid pair is fully legit. ! 733: */ ! 734: int ! 735: set_legit(FILE *f, long trustpos, int trust_count) ! 736: { ! 737: long filepos; ! 738: byte keyctrl; ! 739: ! 740: filepos = ftell(f); ! 741: fseek(f, trustpos, SEEK_SET); /* user id trust byte */ ! 742: if (read_trust(f, &keyctrl) < 0) ! 743: return(-1); ! 744: ! 745: if (trust_count < marginal_min) ! 746: keyctrl = KC_LEGIT_UNTRUSTED; ! 747: else if (trust_count < complete_min) ! 748: keyctrl = KC_LEGIT_MARGINAL; ! 749: else ! 750: keyctrl = KC_LEGIT_COMPLETE; ! 751: ! 752: fseek(f, trustpos, SEEK_SET); ! 753: write_trust(f, keyctrl); ! 754: ! 755: fseek(f, filepos, SEEK_SET); ! 756: ! 757: if ((keyctrl & KC_LEGIT_MASK) == KC_LEGIT_COMPLETE) ! 758: return(1); ! 759: else ! 760: return(0); ! 761: } ! 762: ! 763: ! 764: int ask_owntrust(char *userid, byte cur_trust) ! 765: /* Ask for a wetware decision from the human on how much to trust ! 766: this key's owner to certify other keys. Returns trust value. */ ! 767: { ! 768: char buf[8]; ! 769: ! 770: if (check_only) ! 771: { ++undefined_trust; ! 772: return(KC_OWNERTRUST_UNDEFINED); ! 773: } ! 774: ! 775: fprintf(pgpout, ! 776: PSTR("\nMake a determination in your own mind whether this key actually\n\ ! 777: belongs to the person whom you think it belongs to, based on available\n\ ! 778: evidence. If you think it does, then based on your estimate of\n\ ! 779: that person's integrity and competence in key management, answer\n\ ! 780: the following question:\n")); ! 781: fprintf(pgpout, PSTR("\nWould you trust \"%s\"\n\ ! 782: to act as an introducer and certify other people's public keys to you?\n\ ! 783: (1=I don't know. 2=No. 3=Usually. 4=Yes, always.) ? "), EXTERNAL(userid)); ! 784: fflush(pgpout); ! 785: getstring(buf, sizeof(buf)-1, TRUE); ! 786: switch (buf[0]) ! 787: { case '1': return KC_OWNERTRUST_UNKNOWN; ! 788: case '2': return KC_OWNERTRUST_NEVER; ! 789: case '3': return KC_OWNERTRUST_USUALLY; ! 790: case '4': return KC_OWNERTRUST_ALWAYS; ! 791: default: return(TRUST_LEV(cur_trust)); ! 792: } ! 793: } /* ask_owntrust */ ! 794: ! 795: ! 796: /* ! 797: * compare all key packets in keyring file f with file g ! 798: * XXX: untested ! 799: */ ! 800: int ! 801: keyring_cmp(FILE *f, FILE *g) ! 802: { ! 803: int status, error = 0, badkeys = 0; ! 804: byte ctb; ! 805: byte keyID[KEYFRAGSIZE]; ! 806: char userid[256]; ! 807: long pktlen, keypos = 0; ! 808: ! 809: rewind(f); ! 810: while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) == 0) ! 811: { ! 812: if (is_key_ctb(ctb)) ! 813: { ! 814: pktlen = ftell(f) - keypos; ! 815: fseek(f, keypos, SEEK_SET); ! 816: if (lookup_by_keyID(g, keyID) < 0) ! 817: { ! 818: error = 1; ! 819: continue; ! 820: } ! 821: while (--pktlen >= 0 && getc(f) == getc(g)) ; ! 822: if (pktlen != -1) ! 823: { ! 824: error = 2; ! 825: ++badkeys; ! 826: } ! 827: ! 828: } ! 829: if (error && ctb == CTB_USERID) ! 830: { ! 831: switch (error) { ! 832: case 1: fprintf(pgpout, PSTR("\n\007Key for user ID \"%s\"\n\ ! 833: is not present in backup keyring\n"), EXTERNAL(userid)); ! 834: case 2: fprintf(pgpout, PSTR("\n\007Key for user ID \"%s\"\n\ ! 835: does not match key in backup keyring\n"), EXTERNAL(userid)); ! 836: } ! 837: error = 0; ! 838: } ! 839: keypos = ftell(f); ! 840: } ! 841: if (error) ! 842: status = -5; ! 843: return(status < 0 ? status : badkeys); ! 844: } ! 845: ! 846: ! 847: int ! 848: readkpacket(FILE *f, byte *ctb, char *userid, byte *keyID, byte *sigkeyID) ! 849: { ! 850: int status; ! 851: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION]; ! 852: ! 853: status = readkeypacket(f, FALSE, ctb, NULL, userid, n, e, ! 854: NULL, NULL, NULL, NULL, sigkeyID, NULL); ! 855: ! 856: if (status < 0) ! 857: { ! 858: #ifdef DEBUG ! 859: if (status < -1) ! 860: fprintf(stderr, "readkeypacket returned %d\n", status); ! 861: #endif ! 862: return(status); ! 863: } ! 864: ! 865: if (keyID && is_key_ctb(*ctb)) ! 866: extract_keyID(keyID, n); ! 867: ! 868: if (userid && *ctb == CTB_USERID) ! 869: PascalToC(userid); ! 870: ! 871: return(0); ! 872: } ! 873: ! 874: long ! 875: lookup_by_keyID(FILE *f, byte *srch_keyID) ! 876: { ! 877: int status; ! 878: long keypos = 0; ! 879: byte keyID[KEYFRAGSIZE]; ! 880: byte ctb; ! 881: ! 882: rewind(f); ! 883: while ((status = readkpacket(f, &ctb, NULL, keyID, NULL)) == 0) ! 884: { ! 885: if (is_key_ctb(ctb) && memcmp(keyID, srch_keyID, KEYFRAGSIZE) == 0) ! 886: { ! 887: fseek(f, keypos, SEEK_SET); ! 888: return(keypos); ! 889: } ! 890: keypos = ftell(f); ! 891: } ! 892: return(status); ! 893: } ! 894: ! 895: ! 896: void ! 897: show_userid(FILE *f, byte *keyID) ! 898: { ! 899: long filepos; ! 900: char userid[256]; ! 901: byte ctb; ! 902: ! 903: filepos = ftell(f); ! 904: if (lookup_by_keyID(f, keyID) >= 0) ! 905: while (readkpacket(f, &ctb, userid, NULL, NULL) == 0) ! 906: if (ctb == CTB_USERID) ! 907: { ! 908: fprintf(pgpout, "%s\n", EXTERNAL(userid)); ! 909: fseek(f, filepos, SEEK_SET); ! 910: return; ! 911: } ! 912: ! 913: fprintf(pgpout, "(KeyID: %s)\n",keyIDstring(keyID)); ! 914: fseek(f, filepos, SEEK_SET); ! 915: } ! 916: ! 917: /* ! 918: * show the key in file f at file position keypos. ! 919: * 'what' controls the info that will be shown: ! 920: * SHOW_TRUST: show trust byte info ! 921: * SHOW_SIGS: show signatures ! 922: * these constants can be or'ed to get both ! 923: */ ! 924: int ! 925: show_key(FILE *f, long keypos, int what) ! 926: { ! 927: int status; ! 928: long filepos; ! 929: char userid[256]; ! 930: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION]; ! 931: byte sigkeyID[KEYFRAGSIZE]; ! 932: word32 timestamp; ! 933: byte ctb, keyctrl; ! 934: int userids = 0; ! 935: boolean print_trust = FALSE; ! 936: int precision = global_precision; ! 937: ! 938: filepos = ftell(f); ! 939: fseek(f, keypos, SEEK_SET); ! 940: while ((status = readkeypacket(f, FALSE, &ctb, (byte *)×tamp, userid, ! 941: n, e, NULL, NULL, NULL, NULL, sigkeyID, &keyctrl)) == 0) ! 942: { ! 943: if (is_key_ctb(ctb)) ! 944: { if (userids) ! 945: break; ! 946: } ! 947: else if (ctb == CTB_KEYCTRL) /* trust bytes only in public keyrings */ ! 948: { ! 949: if (what & SHOW_TRUST) ! 950: print_trust = TRUE; ! 951: } ! 952: else if (ctb == CTB_USERID) ! 953: { if (userids == 0) ! 954: { PascalToC(userid); /* for display */ ! 955: fprintf(pgpout,PSTR("\nKey for user ID: %s\n"),EXTERNAL(userid)); ! 956: fprintf(pgpout,PSTR("%d-bit key, Key ID %s, created %s\n"), ! 957: countbits(n), key2IDstring(n), cdate(×tamp) ); ! 958: if (print_trust) ! 959: { ! 960: switch (TRUST_LEV(keyctrl)) ! 961: { ! 962: case KC_OWNERTRUST_UNDEFINED: ! 963: case KC_OWNERTRUST_UNKNOWN: ! 964: /* Just don't say anything in this case */ ! 965: break; ! 966: case KC_OWNERTRUST_NEVER: /* untrusted */ ! 967: fprintf(pgpout, PSTR("This user is untrusted to certify other keys.\n")); ! 968: break; ! 969: case KC_OWNERTRUST_USUALLY: /* marginal trust */ ! 970: fprintf(pgpout, PSTR("This user is generally trusted to certify other keys.\n")); ! 971: break; ! 972: case KC_OWNERTRUST_ALWAYS: /* complete trust */ ! 973: fprintf(pgpout, PSTR("This user is completely trusted to certify other keys.\n")); ! 974: break; ! 975: case KC_OWNERTRUST_ULTIMATE: /* axiomatic, ultimate trust */ ! 976: fprintf(pgpout, PSTR("This axiomatic key is ultimately trusted to certify other keys.\n")); ! 977: break; ! 978: default: ! 979: break; ! 980: } /* switch */ ! 981: } ! 982: ++userids; ! 983: } ! 984: else ! 985: { PascalToC(userid); ! 986: if (what != 0) ! 987: fprintf(pgpout, "\n"); ! 988: fprintf(pgpout,PSTR("Also known as: %s\n"), EXTERNAL(userid)); ! 989: } ! 990: if (print_trust) ! 991: { ! 992: read_trust(f, &keyctrl); ! 993: switch (keyctrl & KC_LEGIT_MASK) ! 994: { ! 995: case 0: /* undefined certification level */ ! 996: case 1: /* uncertified */ ! 997: fprintf(pgpout, PSTR("This key/userID association is not certified.\n")); ! 998: break; ! 999: case 2: /* marginal certification */ ! 1000: fprintf(pgpout, PSTR("This key/userID association is marginally certified.\n")); ! 1001: break; ! 1002: case 3: /* complete certification */ ! 1003: fprintf(pgpout, PSTR("This key/userID association is fully certified.\n")); ! 1004: break; ! 1005: default: /* can't get here, right? */ ! 1006: break; ! 1007: } /* switch */ ! 1008: } /* print_trust */ ! 1009: } ! 1010: else if ((what & SHOW_SIGS) && is_ctb_type(ctb, CTB_SKE_TYPE)) ! 1011: { ! 1012: if (print_trust) ! 1013: { ! 1014: read_trust(f, &keyctrl); ! 1015: switch (TRUST_LEV(keyctrl)) ! 1016: { ! 1017: case KC_SIGTRUST_UNDEFINED: /* undefined trust level */ ! 1018: case KC_SIGTRUST_UNKNOWN: ! 1019: /* Just don't say anything in this case */ ! 1020: fprintf(pgpout, PSTR(" Questionable certification from:\n ")); ! 1021: break; ! 1022: case KC_SIGTRUST_UNTRUSTED: /* untrusted */ ! 1023: fprintf(pgpout, PSTR(" Untrusted certification from:\n ")); ! 1024: break; ! 1025: case KC_SIGTRUST_MARGINAL: /* marginal trust */ ! 1026: fprintf(pgpout, PSTR(" Generally trusted certification from:\n ")); ! 1027: break; ! 1028: case KC_SIGTRUST_COMPLETE: /* complete trust */ ! 1029: fprintf(pgpout, PSTR(" Completely trusted certification from:\n ")); ! 1030: break; ! 1031: case KC_SIGTRUST_ULTIMATE: /* axiomatic, ultimate trust */ ! 1032: fprintf(pgpout, PSTR(" Axiomatically trusted certification from:\n ")); ! 1033: break; ! 1034: default: /* can't get here, right? */ ! 1035: break; ! 1036: } /* switch */ ! 1037: } ! 1038: else ! 1039: fprintf(pgpout, PSTR(" Certified by: ")); ! 1040: show_userid(f, sigkeyID); ! 1041: } ! 1042: } ! 1043: if (status == -1 && userids) ! 1044: status = 0; ! 1045: set_precision(precision); ! 1046: fseek(f, filepos, SEEK_SET); ! 1047: return(status); ! 1048: } ! 1049: ! 1050: ! 1051: void ! 1052: write_trust_pos(FILE *f, byte keyctrl, long pos) ! 1053: { ! 1054: long fpos; ! 1055: ! 1056: fpos = ftell(f); ! 1057: fseek(f, pos, SEEK_SET); ! 1058: write_trust(f, keyctrl); ! 1059: fseek(f, fpos, SEEK_SET); ! 1060: } ! 1061: ! 1062: int ! 1063: read_trust(FILE *f, byte *keyctrl) ! 1064: { ! 1065: unsigned char buf[3]; ! 1066: ! 1067: if (fread(buf, 1, 3, f) != 3) ! 1068: return -1; ! 1069: if (buf[0] != CTB_KEYCTRL) ! 1070: { ! 1071: if (is_ctb(buf[0])) ! 1072: return(ERR_NOTRUST); ! 1073: else ! 1074: return(-3); /* bad data */ ! 1075: } ! 1076: if (buf[1] != 1) /* length must be 1 */ ! 1077: return(-3); ! 1078: if (keyctrl) ! 1079: *keyctrl = buf[2]; ! 1080: return(0); ! 1081: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.