|
|
1.1 ! root 1: /* keyadd.c - Keyring merging 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: ! 21: #include <stdio.h> ! 22: #include <stdlib.h> ! 23: #ifdef UNIX ! 24: #include <sys/types.h> ! 25: #endif ! 26: #include <time.h> ! 27: #include "mpilib.h" ! 28: #include "idea.h" ! 29: #include "random.h" ! 30: #include "crypto.h" ! 31: #include "fileio.h" ! 32: #include "keymgmt.h" ! 33: #include "genprime.h" ! 34: #include "rsagen.h" ! 35: #include "mpiio.h" ! 36: #include "language.h" ! 37: #include "pgp.h" ! 38: ! 39: static int ask_to_sign(byte *keyID, char *ringfile); ! 40: ! 41: static int newkeys, newsigs, newids, newrvks; ! 42: ! 43: void mergesigs (FILE *fkey, char *keyfile, long keypos, FILE *fring, ! 44: char *ringfile, long *pringpos, FILE *out) ! 45: /* Merge signatures from userid in fkey (which is keyfile) at keypos with ! 46: * userid from fring (which is ringfile) at ringpos, appending result to out. ! 47: */ ! 48: { ! 49: long ringuseridpos, ringpos; ! 50: int ringpktlen, keypktlen; ! 51: int status; ! 52: byte ctb; ! 53: int copying; ! 54: byte keyID[KEYFRAGSIZE]; ! 55: char userid[256]; ! 56: ! 57: /* First, copy the userid packet itself, plus any comments or ctrls */ ! 58: ringuseridpos = ringpos = *pringpos; ! 59: fseek (fring, ringpos, SEEK_SET); ! 60: (void) readkeypacket(fring,FALSE,&ctb,NULL,userid,NULL,NULL, ! 61: NULL,NULL,NULL,NULL,NULL,NULL); ! 62: PascalToC(userid); ! 63: ringpktlen = ftell(fring) - ringpos; ! 64: copyfilepos (fring, out, ringpktlen, ringpos); ! 65: for ( ; ; ) ! 66: { ringpos = ftell(fring); ! 67: status = nextkeypacket (fring, &ctb); ! 68: if (status < 0 || is_key_ctb(ctb) || ctb==CTB_USERID || ! 69: is_ctb_type(ctb,CTB_SKE_TYPE)) ! 70: break; ! 71: ringpktlen = ftell(fring) - ringpos; ! 72: copyfilepos (fring, out, ringpktlen, ringpos); ! 73: } ! 74: fseek (fring, ringpos, SEEK_SET); ! 75: ! 76: /* Now, ringpos points just past userid packet and ctrl packet. */ ! 77: /* Advance keypos to the analogous location. */ ! 78: fseek (fkey, keypos, SEEK_SET); ! 79: (void) nextkeypacket (fkey, &ctb); ! 80: for ( ; ; ) ! 81: { keypos = ftell(fkey); ! 82: status = nextkeypacket (fkey, &ctb); ! 83: if (status < 0 || is_key_ctb(ctb) || ctb==CTB_USERID || ! 84: is_ctb_type(ctb,CTB_SKE_TYPE)) ! 85: break; ! 86: } ! 87: fseek (fkey, keypos, SEEK_SET); ! 88: ! 89: /* Second, copy all keyfile signatures that aren't in ringfile. ! 90: */ ! 91: ! 92: copying = FALSE; ! 93: for ( ; ; ) ! 94: { /* Read next sig from keyfile; see if it is in ringfile; ! 95: * set copying true/false accordingly. If copying is true ! 96: * and it is a signature, copy it. Loop till hit ! 97: * a new key or userid in keyfile, or EOF. ! 98: */ ! 99: keypos = ftell(fkey); ! 100: status = readkeypacket(fkey,FALSE,&ctb,NULL,NULL,NULL,NULL, ! 101: NULL,NULL,NULL,NULL,keyID,NULL); ! 102: keypktlen = ftell(fkey) - keypos; ! 103: if (status < 0 || is_key_ctb (ctb) || ctb==CTB_USERID) ! 104: break; ! 105: if (is_ctb_type(ctb,CTB_SKE_TYPE)) ! 106: { long sig_pos; ! 107: int sig_len; ! 108: /* Set copying true if signature is not in the ringfile */ ! 109: copying = (getpubusersig (ringfile, ringuseridpos, keyID, &sig_pos, ! 110: &sig_len) < 0); ! 111: if (copying) ! 112: { fprintf (pgpout, PSTR("New signature from keyID %s on userid \"%s\"\n"), ! 113: keyIDstring(keyID),EXTERNAL(userid)); ! 114: ++newsigs; ! 115: } ! 116: } ! 117: if (copying && is_ctb_type(ctb,CTB_SKE_TYPE)) ! 118: { copyfilepos (fkey, out, keypktlen, keypos); ! 119: write_trust (out, KC_SIGTRUST_UNDEFINED); ! 120: } ! 121: } ! 122: ! 123: /* Third, for all ring sig's, copy to output */ ! 124: fseek (fring, ringpos, SEEK_SET); ! 125: for ( ; ; ) ! 126: { ringpos = ftell(fring); ! 127: status = nextkeypacket (fring, &ctb); ! 128: ringpktlen = ftell(fring) - ringpos; ! 129: if (status < 0 || is_key_ctb (ctb) || ctb==CTB_USERID) ! 130: break; ! 131: copyfilepos (fring, out, ringpktlen, ringpos); ! 132: } /* End of loop for each sig in ringfile */ ! 133: fseek (fring, ringpos, SEEK_SET); ! 134: *pringpos = ringpos; ! 135: } /* mergesigs */ ! 136: ! 137: ! 138: void mergekeys (FILE *fkey, char *keyfile, long keypos, FILE *fring, ! 139: char *ringfile, long *pringpos, FILE *out) ! 140: /* Merge key from fkey (which is keyfile) at keypos with key from ! 141: * fring (which is ringfile) at ringpos, appending result to out. ! 142: */ ! 143: { ! 144: long ringkeypos, keykeypos, ringpos; ! 145: int ringpktlen, keypktlen; ! 146: int status; ! 147: byte ctb; ! 148: int copying; ! 149: boolean ring_compromise = FALSE; ! 150: byte userid[256]; ! 151: ! 152: /* First, copy the key packet itself, plus any comments or ctrls */ ! 153: ringkeypos = ringpos = *pringpos; ! 154: fseek (fring, ringpos, SEEK_SET); ! 155: (void) nextkeypacket(fring, &ctb); ! 156: ringpktlen = ftell(fring) - ringpos; ! 157: copyfilepos (fring, out, ringpktlen, ringpos); ! 158: for ( ; ; ) ! 159: { ringpos = ftell(fring); ! 160: status = nextkeypacket (fring, &ctb); ! 161: if (status < 0 || is_key_ctb(ctb) || ctb==CTB_USERID) ! 162: break; ! 163: if (is_ctb_type(ctb, CTB_SKE_TYPE)) ! 164: ring_compromise = TRUE; /* compromise cert on keyring */ ! 165: ringpktlen = ftell(fring) - ringpos; ! 166: copyfilepos (fring, out, ringpktlen, ringpos); ! 167: } ! 168: fseek (fring, ringpos, SEEK_SET); ! 169: ! 170: /* Now, ringpos points just past key packet and ctrl packet. */ ! 171: /* Advance keypos to the analogous location. */ ! 172: fseek (fkey, keypos, SEEK_SET); ! 173: keykeypos = keypos; ! 174: (void) nextkeypacket (fkey, &ctb); ! 175: keypktlen = ftell(fkey) - keypos; /* for check_key_sig() */ ! 176: for ( ; ; ) ! 177: { keypos = ftell(fkey); ! 178: status = nextkeypacket (fkey, &ctb); ! 179: if (status < 0 || ctb == CTB_USERID || is_ctb_type(ctb, CTB_SKE_TYPE)) ! 180: break; ! 181: } ! 182: if (!ring_compromise && is_ctb_type(ctb, CTB_SKE_TYPE)) ! 183: { /* found a compromise cert on keyfile that is not in ringfile */ ! 184: word32 timestamp; ! 185: byte sig_class; ! 186: int cert_pktlen; ! 187: ! 188: cert_pktlen = ftell(fkey) - keypos; ! 189: if (check_key_sig(fkey, keykeypos, keypktlen, (char *)userid, fkey, keypos, ! 190: ringfile, (char *)userid, (byte *)×tamp, &sig_class) == 0 && ! 191: sig_class == KC_SIGNATURE_BYTE) ! 192: { ! 193: fprintf(pgpout, PSTR("Key revocation certificate from \"%s\".\n"), ! 194: EXTERNAL((char *)userid)); ! 195: copyfilepos (fkey, out, cert_pktlen, keypos); ! 196: ++newrvks; ! 197: } ! 198: else ! 199: fprintf(pgpout, PSTR("\n\007WARNING: File '%s' contains bad revocation certificate.\n")); ! 200: } ! 201: fseek (fkey, keypos, SEEK_SET); ! 202: ! 203: /* Second, copy all keyfile userid's plus signatures that aren't ! 204: * in ringfile. ! 205: */ ! 206: ! 207: copying = FALSE; ! 208: for ( ; ; ) ! 209: { /* Read next userid from keyfile; see if it is in ringfile; ! 210: * set copying true/false accordingly. If copying is true ! 211: * and it is a userid or a signature, copy it. Loop till hit ! 212: * a new key in keyfile, or EOF. ! 213: */ ! 214: keypos = ftell(fkey); ! 215: status = readkeypacket(fkey,FALSE,&ctb,NULL,(char *)userid,NULL,NULL, ! 216: NULL,NULL,NULL,NULL,NULL,NULL); ! 217: keypktlen = ftell(fkey) - keypos; ! 218: if (status < 0 || is_key_ctb (ctb)) ! 219: break; ! 220: if (ctb == CTB_USERID) ! 221: { long userid_pos; ! 222: int userid_len; ! 223: PascalToC ((char *)userid); ! 224: /* Set copying true if userid is not in the ringfile */ ! 225: copying = (getpubuserid (ringfile, ringkeypos, userid, &userid_pos, ! 226: &userid_len) < 0); ! 227: if (copying) ! 228: { fprintf (pgpout, PSTR("New userid: \"%s\".\n"), EXTERNAL((char *)userid)); ! 229: ++newids; ! 230: } ! 231: } ! 232: if (copying) ! 233: { if (ctb==CTB_USERID || is_ctb_type(ctb,CTB_SKE_TYPE)) ! 234: { copyfilepos (fkey, out, keypktlen, keypos); ! 235: if (is_ctb_type(ctb,CTB_SKE_TYPE)) ! 236: write_trust (out, KC_SIGTRUST_UNDEFINED); ! 237: else ! 238: write_trust (out, KC_LEGIT_UNKNOWN); ! 239: } ! 240: } ! 241: } ! 242: ! 243: /* Third, for all ring userid's, if not in keyfile, copy the userid ! 244: * plus its dependant signatures. ! 245: */ ! 246: fseek (fring, ringpos, SEEK_SET); ! 247: for ( ; ; ) ! 248: { ringpos = ftell(fring); ! 249: status = readkeypacket(fring,FALSE,&ctb,NULL,(char *)userid,NULL,NULL, ! 250: NULL,NULL,NULL,NULL,NULL,NULL); ! 251: ringpktlen = ftell(fring) - ringpos; ! 252: if (status < 0 || is_key_ctb (ctb)) ! 253: break; ! 254: if (ctb == CTB_USERID) ! 255: { long userid_pos; ! 256: int userid_len; ! 257: /* See if there is a match in keyfile */ ! 258: PascalToC ((char *) userid); ! 259: if (getpubuserid (keyfile, keykeypos, userid, &userid_pos, ! 260: &userid_len) >= 0) ! 261: { mergesigs (fkey,keyfile,userid_pos,fring,ringfile,&ringpos,out); ! 262: copying = FALSE; ! 263: } ! 264: else ! 265: copying = TRUE; ! 266: } ! 267: if (copying) ! 268: { /* Copy ringfile userid and sigs to out */ ! 269: copyfilepos (fring, out, ringpktlen, ringpos); ! 270: } ! 271: } /* End of loop for each key in ringfile */ ! 272: fseek (fring, ringpos, SEEK_SET); ! 273: *pringpos = ringpos; ! 274: } /* mergekeys */ ! 275: ! 276: ! 277: int addto_keyring(char *keyfile, char *ringfile, boolean query) ! 278: /* Adds (prepends) key file to key ring file. If query is TRUE, ask ! 279: before doing any actual changes. */ ! 280: { FILE *f, *g, *h; ! 281: long file_position,fp; ! 282: int pktlen; /* unused, just to satisfy getpublickey */ ! 283: byte ctb; ! 284: int status; ! 285: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION]; ! 286: unit n1[MAX_UNIT_PRECISION]; ! 287: byte keyID[KEYFRAGSIZE]; ! 288: byte userid[256]; /* key certificate userid */ ! 289: byte userid1[256]; ! 290: word32 tstamp; byte *timestamp = (byte *) &tstamp; /* key certificate timestamp */ ! 291: char trans_keyfile[MAX_PATH]; ! 292: boolean is_armored = FALSE; ! 293: boolean userid_seen = FALSE; ! 294: int commonkeys = 0; ! 295: int copying; ! 296: struct nkey { ! 297: byte keyID[KEYFRAGSIZE]; ! 298: struct nkey *next; ! 299: } *nkey, *nkeys = NULL; ! 300: ! 301: if (build_path(SCRATCH_KEYRING_PATH,SCRATCH_KEYRING_FILENAME,ringfile)<0) ! 302: return(-1); /* File path too long */ ! 303: ! 304: /* check if the keyfile to be added is armored */ ! 305: if ((is_armored = is_armor_file(keyfile)) == TRUE) ! 306: { /* decode it into the actual keyfile */ ! 307: boolean changed_name; ! 308: strcpy(trans_keyfile,keyfile); ! 309: keyfile = tempfile(TMP_TMPDIR|TMP_WIPE); ! 310: if (de_armor_file(trans_keyfile,keyfile,&changed_name) < 0) ! 311: return(-1); ! 312: } ! 313: ! 314: userid[0] = '\0'; ! 315: if (dokeycheck((char *) userid, keyfile, NULL) < 0) ! 316: { fprintf(pgpout, PSTR("\007Keyring check error. ") ); ! 317: fprintf(pgpout, PSTR("\nKey(s) will not be added to keyring.\n")); ! 318: goto err; ! 319: } ! 320: ! 321: /* open file f for read, in binary (not text) mode...*/ ! 322: #ifdef VMS ! 323: if ((f = fopen(keyfile,"rb","ctx=stm")) == NULL) ! 324: #else ! 325: if ((f = fopen(keyfile,"rb")) == NULL) ! 326: #endif ! 327: { fprintf(pgpout,PSTR("\n\007Can't open key file '%s'\n"),keyfile); ! 328: goto err; ! 329: } ! 330: if (!file_exists(ringfile)) ! 331: { /* ringfile does not exist. Can it be created? */ ! 332: /* open file g for writing, in binary (not text) mode...*/ ! 333: g = fopen(ringfile,"wb"); ! 334: if (g==NULL) ! 335: { fprintf(pgpout,PSTR("\nKey ring file '%s' cannot be created.\n"),ringfile); ! 336: fclose(f); ! 337: goto err; ! 338: } ! 339: fclose(g); ! 340: } ! 341: ! 342: /* Create working output file */ ! 343: remove(SCRATCH_KEYRING_PATH); ! 344: /* open file g for writing, in binary (not text) mode...*/ ! 345: if ((g = fopen(SCRATCH_KEYRING_PATH,"wb")) == NULL) ! 346: { fclose(f); ! 347: goto err; ! 348: } ! 349: newkeys = newsigs = newids = newrvks = 0; ! 350: ! 351: /* Pass 1 - copy all keys from f which aren't in ring file */ ! 352: /* Also copy userid and signature packets. */ ! 353: copying = FALSE; ! 354: for ( ; ; ) ! 355: { file_position = ftell(f); ! 356: ! 357: status = readkeypacket(f,FALSE,&ctb,timestamp,(char *)userid,n,e, ! 358: NULL,NULL,NULL,NULL,NULL,NULL); ! 359: /* Note that readkeypacket has called set_precision */ ! 360: if (status == -1) /* EOF */ ! 361: break; ! 362: if (status < 0) ! 363: { fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"), ! 364: keyfile); ! 365: fclose(f); /* close key file */ ! 366: goto err; ! 367: } ! 368: ! 369: /* Check to see if key is already on key ring */ ! 370: if (is_key_ctb(ctb)) ! 371: { ! 372: extract_keyID(keyID, n); /* from keyfile, not ringfile */ ! 373: ! 374: /* Check for duplicate key in key ring: */ ! 375: if (getpublickey(TRUE, FALSE, ringfile, &fp, &pktlen, keyID, timestamp, userid, n1, e) >= 0) ! 376: { if (mp_compare (n, n1) != 0) ! 377: { fprintf(pgpout, PSTR("\n\007Warning: Key ID %s matches key ID of key already on \n\ ! 378: key ring '%s', but the keys themselves differ.\n\ ! 379: This is highly suspicious. This key will not be added to ring.\n\ ! 380: Acknowledge by pressing return: "), keyIDstring(keyID), ringfile); ! 381: getyesno('n'); ! 382: fclose(f); /* close key file */ ! 383: goto err; ! 384: } ! 385: else ! 386: { if (verbose) ! 387: fprintf(pgpout,PSTR("Key ID %s is already included in key ring '%s'.\n"), ! 388: keyIDstring(keyID), ringfile); ! 389: ++commonkeys; ! 390: } ! 391: copying = FALSE; ! 392: } ! 393: else ! 394: { ! 395: ++newkeys; ! 396: #if 0 ! 397: if (query) ! 398: { if (is_ctb_type(ctb, CTB_CERT_SECKEY_TYPE)) ! 399: fprintf (pgpout, PSTR ("\nAdd secret key to key ring '%s' (y/N)? "), ! 400: ringfile); ! 401: else ! 402: fprintf (pgpout, PSTR ("\nAdd public key to key ring '%s' (y/N)? "), ! 403: ringfile); ! 404: ! 405: if (! getyesno( 'n' )) ! 406: { fclose(f); ! 407: remove(SCRATCH_KEYRING_PATH); ! 408: return(0); /* user chose to abort */ ! 409: } ! 410: query = FALSE; /* Don't ask subsequently */ ! 411: } ! 412: #endif ! 413: ! 414: if ((nkey = (struct nkey *) malloc(sizeof(struct nkey))) == NULL) ! 415: { ! 416: fprintf(stderr, PSTR("\n\007Out of memory.\n")); ! 417: exitPGP(7); ! 418: } ! 419: memcpy(nkey->keyID, keyID, KEYFRAGSIZE); ! 420: nkey->next = nkeys; ! 421: nkeys = nkey; ! 422: ! 423: fprintf(pgpout, PSTR("New key ID: %s\n"), keyIDstring(keyID)); ! 424: copying = TRUE; ! 425: } ! 426: } ! 427: /* Now, we copy according to the copying flag */ ! 428: /* The key is prepended to the ring to give it search precedence ! 429: over other keys with that same userid. */ ! 430: ! 431: if (copying && (is_key_ctb(ctb) || ctb==CTB_USERID || ! 432: is_ctb_type(ctb,CTB_SKE_TYPE))) ! 433: { pktlen = (int) (ftell(f) - file_position); ! 434: copyfilepos(f,g,pktlen,file_position); /* copy packet from f */ ! 435: /* Initialize trust packets after keys and signatures */ ! 436: if (is_key_ctb(ctb)) ! 437: { ! 438: write_trust (g, KC_OWNERTRUST_UNDEFINED); ! 439: userid_seen = FALSE; ! 440: } ! 441: else if (is_ctb_type(ctb,CTB_SKE_TYPE)) ! 442: { ! 443: if (userid_seen) ! 444: write_trust (g, KC_SIGTRUST_UNDEFINED); ! 445: else ! 446: /* signature certificate before userid must be compromise cert. */ ! 447: fprintf(pgpout, PSTR("Key has been revoked.\n")); ! 448: } ! 449: else if (is_ctb_type(ctb,CTB_USERID_TYPE)) ! 450: { ! 451: write_trust (g, KC_LEGIT_UNKNOWN); ! 452: userid_seen = TRUE; ! 453: } ! 454: } ! 455: } ! 456: ! 457: /* Now copy the remainder of the ringfile, h, to g. commonkeys tells ! 458: how many keys are common to keyfile and ringfile. As long as that is ! 459: nonzero we will check each key in ringfile to see if it has a match ! 460: in keyfile. ! 461: */ ! 462: #ifdef VMS ! 463: if ((h = fopen(ringfile,"rb","ctx=stm")) != NULL) ! 464: #else ! 465: if ((h = fopen(ringfile,"rb")) != NULL) ! 466: #endif ! 467: { while (commonkeys) /* Loop for each key in ringfile */ ! 468: { file_position = ftell(h); ! 469: status = readkeypacket(h,FALSE,&ctb,NULL,(char *)userid,n,e, ! 470: NULL,NULL,NULL,NULL,NULL,NULL); ! 471: if (status < 0) ! 472: { if (status == -1) ! 473: fprintf(pgpout, PSTR("\n\007Key file contains duplicate keys: cannot be added to keyring\n")); ! 474: else ! 475: fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"), ! 476: ringfile); ! 477: fclose(f); ! 478: fclose(g); ! 479: fclose(h); ! 480: goto err; ! 481: } ! 482: PascalToC ((char *) userid); ! 483: pktlen = ftell(h) - file_position; ! 484: if (is_key_ctb(ctb)) ! 485: { long tfp; ! 486: int tpktlen; ! 487: /* See if there is a match in keyfile */ ! 488: extract_keyID(keyID, n); /* from ringfile, not keyfile */ ! 489: if ((getpublickey(TRUE, FALSE, keyfile, &tfp, &tpktlen, ! 490: keyID, timestamp, userid1, n1, e) >= 0) && ! 491: (mp_compare(n, n1) == 0)) ! 492: { ! 493: if (verbose) ! 494: fprintf (pgpout, PSTR("Merging key ID: %s\n"),keyIDstring(keyID)); ! 495: mergekeys (f,keyfile,tfp, h,ringfile,&file_position, g); ! 496: copying = FALSE; ! 497: --commonkeys; ! 498: } ! 499: else ! 500: copying = TRUE; ! 501: } ! 502: if (copying) ! 503: { /* Copy ringfile key to g, without its sigs */ ! 504: copyfilepos (h,g,pktlen,file_position); ! 505: file_position += pktlen; ! 506: } ! 507: } /* End of loop for each key in ringfile */ ! 508: copyfile(h,g,-1L); /* copy rest of file from file h to g */ ! 509: fclose(h); ! 510: } ! 511: fclose(f); ! 512: fclose(g); ! 513: if (newsigs == 0 && newkeys == 0 && newids == 0 && newrvks == 0) ! 514: { ! 515: fprintf(pgpout, PSTR("No new keys or signatures in keyfile.\n")); ! 516: remove(SCRATCH_KEYRING_PATH); ! 517: return(0); ! 518: } ! 519: ! 520: for (nkey = nkeys; nkey; nkey = nkey->next) ! 521: { ! 522: if (dokeycheck(NULL, SCRATCH_KEYRING_PATH, nkey->keyID)) ! 523: goto err; ! 524: } ! 525: fprintf(pgpout, PSTR("\nKeyfile contains:\n")); ! 526: if (newkeys) ! 527: fprintf(pgpout, PSTR("%4d new key(s)\n"), newkeys); ! 528: if (newsigs) ! 529: fprintf(pgpout, PSTR("%4d new signatures(s)\n"), newsigs); ! 530: if (newids) ! 531: fprintf(pgpout, PSTR("%4d new user ID(s)\n"), newids); ! 532: if (newrvks) ! 533: fprintf(pgpout, PSTR("%4d new revocation(s)\n"), newrvks); ! 534: if (query) ! 535: { ! 536: fprintf(pgpout, PSTR("\nDo you want to add this keyfile to keyring '%s' (y/N)? "), ringfile); ! 537: if (!getyesno('n')) ! 538: { remove(SCRATCH_KEYRING_PATH); ! 539: return(1); ! 540: } ! 541: } ! 542: if ((status = maintenance(SCRATCH_KEYRING_PATH, MAINT_SILENT)) == 0) ! 543: for (nkey = nkeys; nkey; nkey = nkey->next) ! 544: { fprintf(pgpout,PSTR("Adding key ID %s from file '%s' to key ring '%s'.\n"), ! 545: keyIDstring(nkey->keyID),(is_armored?trans_keyfile:keyfile),ringfile); ! 546: ask_to_sign(nkey->keyID, SCRATCH_KEYRING_PATH); ! 547: } ! 548: ! 549: backup_rename(SCRATCH_KEYRING_PATH,ringfile); ! 550: ! 551: if (is_armored) ! 552: rmtemp(keyfile); /* zap decoded keyfile */ ! 553: return(0); /* normal return */ ! 554: ! 555: err: ! 556: /* make sure we remove any garbage files we may have created */ ! 557: if (is_armored) ! 558: rmtemp(keyfile); /* zap decoded keyfile */ ! 559: remove(SCRATCH_KEYRING_PATH); ! 560: return(-1); ! 561: } /* addto_keyring */ ! 562: ! 563: ! 564: static int ask_to_sign(byte *keyID, char *ringfile) ! 565: { ! 566: FILE *f; ! 567: word32 timestamp; ! 568: byte ctb, trust; ! 569: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION]; ! 570: byte userid[256]; ! 571: long fpos; ! 572: int pktlen; /* unused, just to satisfy getpublickey */ ! 573: int status; ! 574: extern char my_name[]; ! 575: ! 576: if (getpublickey(TRUE, FALSE, ringfile, &fpos, &pktlen, ! 577: keyID, (byte *)×tamp, userid, n, e) < 0) ! 578: return(-1); ! 579: ! 580: if ((f = fopenbin(ringfile, "r")) == NULL) ! 581: return(-1); ! 582: ! 583: fseek(f, fpos, SEEK_SET); ! 584: if (is_compromised(f)) ! 585: { fclose(f); ! 586: return(0); ! 587: } ! 588: if (nextkeypacket(f, &ctb) < 0) ! 589: { fclose(f); ! 590: return(-1); ! 591: } ! 592: if (ctb != CTB_CERT_PUBKEY) ! 593: { fclose(f); ! 594: return(0); /* don't ask to sign secret key */ ! 595: } ! 596: while (nextkeypacket(f, &ctb) == 0 && !is_key_ctb(ctb)) ! 597: if (ctb == CTB_USERID) /* check first userid */ ! 598: break; ! 599: if (ctb != CTB_USERID) ! 600: { ! 601: fclose(f); ! 602: return(-1); ! 603: } ! 604: ! 605: if ((status = read_trust(f, &trust)) < 0) ! 606: { ! 607: fclose(f); ! 608: return(status); ! 609: } ! 610: if ((trust & KC_LEGIT_MASK) == KC_LEGIT_COMPLETE) ! 611: { ! 612: fclose(f); ! 613: return(0); ! 614: } ! 615: show_key(f, fpos, SHOW_ALL); ! 616: fclose(f); ! 617: PascalToC((char *)userid); ! 618: fprintf(pgpout, PSTR("\nDo you want to certify this key yourself (y/N)? ")); ! 619: if (getyesno('n')) ! 620: { ! 621: if (signkey((char *)userid, my_name, ringfile) == 0) ! 622: maintenance(ringfile, MAINT_SILENT); ! 623: } ! 624: return(0); ! 625: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.