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