|
|
1.1.1.7 root 1: /* keyadd.c - Keyring merging 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.
20: */
1.1.1.6 root 21:
22: #include <stdio.h>
23: #include <stdlib.h>
24: #ifdef UNIX
25: #include <sys/types.h>
26: #endif
27: #include <time.h>
28: #include "mpilib.h"
29: #include "crypto.h"
30: #include "fileio.h"
31: #include "keymgmt.h"
32: #include "charset.h"
33: #include "mpiio.h"
34: #include "language.h"
35: #include "pgp.h"
36: #include "exitpgp.h"
37: #include "keyadd.h"
38: #include "keymaint.h"
39:
40: void gpk_close(void);
41: int gpk_open(char *keyfile);
1.1.1.7 root 42: int get_publickey(long *file_position, int *pktlen,
43: byte * keyID, byte * timestamp,
44: byte * userid, unitptr n, unitptr e);
1.1.1.6 root 45:
1.1.1.7 root 46: static int ask_to_sign(byte * keyID, char *ringfile);
1.1.1.6 root 47: static boolean ask_first;
48:
49: static boolean publickey; /* if TRUE, add trust packets */
50:
51: static int newkeys, newsigs, newids, newrvks;
52: static byte mykeyID[KEYFRAGSIZE];
53:
54: static struct sig_list {
1.1.1.7 root 55: struct sig_list *next;
56: long pos;
1.1.1.6 root 57: } *siglist;
1.1.1.7 root 58: static void sig_list_add(long pos)
1.1.1.6 root 59: {
1.1.1.7 root 60: struct sig_list *p;
61: p = xmalloc(sizeof *p);
62: p->pos = pos;
63: p->next = siglist;
64: siglist = p;
65: }
66: static int sig_list_find(long pos)
67: {
68: struct sig_list *p;
69: for (p = siglist; p; p = p->next)
70: if (p->pos == pos)
71: return 1;
72: return 0;
73: }
74: static void sig_list_clear(void)
75: {
76: struct sig_list *p, *n;
77: for (p = siglist; p; p = n) {
78: n = p->next;
79: free(p);
80: }
81: siglist = NULL;
1.1.1.6 root 82: }
1.1.1.7 root 83:
1.1.1.6 root 84: /* Merge signatures from userid in fkey (which is keyfile) at keypos with
85: * userid from fring (which is ringfile) at ringpos, appending result to out.
86: */
1.1.1.7 root 87: static int mergesigs(FILE * fkey, char *keyfile, long keypos, FILE * fring,
88: char *ringfile, long *pringpos, FILE * out)
1.1.1.6 root 89: {
1.1.1.7 root 90: long ringuseridpos, ringpos;
91: int ringpktlen, keypktlen;
92: int status;
93: byte ctb;
94: int copying;
95: word32 rstamp, kstamp, xstamp;
96: byte keyID[KEYFRAGSIZE];
97: char userid[256];
98:
99: /* First, copy the userid packet itself, plus any comments or ctrls */
100: ringuseridpos = ringpos = *pringpos;
101: fseek(fring, ringpos, SEEK_SET);
102: (void) readkeypacket(fring, FALSE, &ctb, NULL, userid, NULL, NULL,
103: NULL, NULL, NULL, NULL, NULL, NULL);
104: PascalToC(userid);
105: ringpktlen = ftell(fring) - ringpos;
106: copyfilepos(fring, out, ringpktlen, ringpos);
107: for (;;) {
108: ringpos = ftell(fring);
109: status = nextkeypacket(fring, &ctb);
110: if (status < 0 || is_key_ctb(ctb) || ctb == CTB_USERID ||
111: is_ctb_type(ctb, CTB_SKE_TYPE))
112: break;
1.1.1.6 root 113: ringpktlen = ftell(fring) - ringpos;
1.1.1.7 root 114: copyfilepos(fring, out, ringpktlen, ringpos);
115: }
116: fseek(fring, ringpos, SEEK_SET);
117:
118: /* Now, ringpos points just past userid packet and ctrl packet. */
119: /* Advance keypos to the analogous location. */
120: fseek(fkey, keypos, SEEK_SET);
121: (void) nextkeypacket(fkey, &ctb);
122: for (;;) {
123: keypos = ftell(fkey);
124: status = nextkeypacket(fkey, &ctb);
125: if (status < 0 || is_key_ctb(ctb) || ctb == CTB_USERID ||
126: is_ctb_type(ctb, CTB_SKE_TYPE))
127: break;
128: }
129: fseek(fkey, keypos, SEEK_SET);
130:
131: /* Second, copy all keyfile signatures that aren't in ringfile.
132: */
133:
134: copying = FALSE;
135: for (;;) {
136: /* Read next sig from keyfile; see if it is in ringfile;
137: * if it is not a signature, ignore it,
138: * if it is absent from ringfile, copy it,
139: * if it is present, and the timestamp is not newer, ignore it,
140: * if present and newer, replace old with new.
141: * Loop till hit a new key or userid in keyfile, or EOF.
1.1.1.6 root 142: */
1.1.1.7 root 143: keypos = ftell(fkey);
144: status = readkeypacket(fkey, FALSE, &ctb, (byte *) & kstamp,
145: NULL, NULL, NULL,
146: NULL, NULL, NULL, NULL, keyID, NULL);
147: if (status == -3) /* unrecoverable error: bad packet
148: length etc. */
149: return status;
150: keypktlen = ftell(fkey) - keypos;
151: if (status == -1 || is_key_ctb(ctb) || ctb == CTB_USERID)
152: break; /* EOF or next key/userid */
153: if (status < 0)
154: continue; /* bad packet, skip it */
155: if (is_ctb_type(ctb, CTB_SKE_TYPE)) {
156: long sig_pos;
157: int sig_len;
158: /* Set copying true if signature is not in the ringfile */
159: copying = (getpubusersig(ringfile, ringuseridpos,
160: keyID, (byte *) & rstamp,
161: &sig_pos,
162: &sig_len) < 0);
163: if (!copying) {
164: long save_pos = ftell(fkey);
165: fseek(fkey, keypos + 6, SEEK_SET);
166: fread(&kstamp, 1, SIZEOF_TIMESTAMP, fkey);
167: fseek(fkey, save_pos, SEEK_SET);
168: convert_byteorder((byte *) & kstamp, SIZEOF_TIMESTAMP);
169: if (verbose)
170: fprintf(pgpout, "ring: %lx key: %lx\n", rstamp, kstamp);
171: if (kstamp > rstamp) { /* Update, Maybe */
172: char *signator;
173: if ((signator = user_from_keyID(keyID)) == NULL) {
174: fprintf(pgpout,
175: LANG("Replacing signature from keyID %s on userid \"%s\"\n"),
176: keyIDstring(keyID), LOCAL_CHARSET(userid));
177: /* No pubkey for KeyID, no update! */
178: } else {
179: long save_keypos;
180: long save_ringpos;
181: long KeyIDpos;
182: int KeyIDlen;
183: byte sigClass;
184: fprintf(pgpout,
185: LANG("Verifying signature from %s\n"),
186: LOCAL_CHARSET(signator));
187: fprintf(pgpout, LANG("on userid \"%s\"\n"),
188: LOCAL_CHARSET(userid));
189: save_keypos = ftell(fkey);
190: save_ringpos = ftell(fring);
191: status = getpublickey(GPK_GIVEUP, ringfile,
192: &KeyIDpos, &KeyIDlen, NULL,
193: NULL, (byte *) userid, NULL,
194: NULL);
195: if (!status)
196: status = check_key_sig(fring,
197: KeyIDpos, KeyIDlen,
198: userid, fkey, keypos,
199: ringfile, signator,
200: (byte *) & xstamp,
201: &sigClass);
202: PascalToC(userid);
203: PascalToC(signator);
204: if (!status) {
205: fprintf(pgpout,
206: LANG("Replacing signature from %s\n"),
207: LOCAL_CHARSET(signator));
208: fprintf(pgpout,
209: LANG("on userid \"%s\"\n"),
210: LOCAL_CHARSET(userid));
211: sig_list_add(sig_pos);
212: ++newsigs;
213: copying = 1;
214: } else
215: fprintf(pgpout, LANG("Verification Failed\n"));
216: fseek(fring, save_ringpos, SEEK_SET);
217: fseek(fkey, save_keypos, SEEK_SET);
218: }
219: }
220: } else {
221: char *signator;
222: if ((signator = user_from_keyID(keyID)) == NULL)
223: fprintf(pgpout,
224: LANG("New signature from keyID %s on userid \"%s\"\n"),
225: keyIDstring(keyID), LOCAL_CHARSET(userid));
226: else {
227: fprintf(pgpout,
228: LANG("New signature from %s\n"),
229: LOCAL_CHARSET(signator));
230: fprintf(pgpout,
231: LANG("on userid \"%s\"\n"), LOCAL_CHARSET(userid));
232: }
233: ++newsigs;
234: if (batchmode)
235: show_update(keyIDstring(mykeyID));
236: }
237: }
238: if (copying && is_ctb_type(ctb, CTB_SKE_TYPE)) {
239: copyfilepos(fkey, out, keypktlen, keypos);
240: if (publickey)
241: write_trust(out, KC_SIGTRUST_UNDEFINED);
242: }
243: }
244:
245: /* Third, for all ring sig's which are not replaced, copy to output */
246: fseek(fring, ringpos, SEEK_SET);
247: for (;;) {
248: ringpos = ftell(fring);
249: if (sig_list_find(ringpos)) {
250: /* skip signature packet */
251: nextkeypacket(fring, &ctb);
252: ringpos = ftell(fring);
253: /* skip trust packet, if present */
254: if (nextkeypacket(fring, &ctb) < 0 || ctb != CTB_KEYCTRL)
255: fseek(fring, ringpos, SEEK_SET);
256: continue;
1.1.1.6 root 257: }
1.1.1.7 root 258: status = nextkeypacket(fring, &ctb);
259: ringpktlen = ftell(fring) - ringpos;
260: if (status < 0 || is_key_ctb(ctb) || ctb == CTB_USERID)
261: break;
262: copyfilepos(fring, out, ringpktlen, ringpos);
263: } /* End of loop for each sig in ringfile */
264: sig_list_clear();
265: fseek(fring, ringpos, SEEK_SET);
266: *pringpos = ringpos;
267: return 0;
268: } /* mergesigs */
1.1.1.6 root 269:
270: /* Merge key from fkey (which is keyfile) at keypos with key from
271: * fring (which is ringfile) at ringpos, appending result to out.
272: */
1.1.1.7 root 273: static int mergekeys(FILE * fkey, char *keyfile, long keypos, FILE * fring,
274: char *ringfile, long *pringpos, FILE * out)
1.1.1.6 root 275: {
1.1.1.7 root 276: long ringkeypos, keykeypos, ringpos;
277: int ringpktlen, keypktlen;
278: int status;
279: byte ctb;
280: int copying;
281: boolean ring_compromise = FALSE;
282: byte userid[256];
283:
284: /* First, copy the key packet itself, plus any comments or ctrls */
285: ringkeypos = ringpos = *pringpos;
286: fseek(fring, ringpos, SEEK_SET);
287: (void) nextkeypacket(fring, &ctb);
288: ringpktlen = ftell(fring) - ringpos;
289: copyfilepos(fring, out, ringpktlen, ringpos);
290: for (;;) {
291: ringpos = ftell(fring);
292: status = nextkeypacket(fring, &ctb);
293: if (status < 0 || is_key_ctb(ctb) || ctb == CTB_USERID)
294: break;
295: if (is_ctb_type(ctb, CTB_SKE_TYPE))
296: ring_compromise = TRUE; /* compromise cert on keyring */
1.1.1.6 root 297: ringpktlen = ftell(fring) - ringpos;
1.1.1.7 root 298: copyfilepos(fring, out, ringpktlen, ringpos);
299: }
300: fseek(fring, ringpos, SEEK_SET);
301:
302: /* Now, ringpos points just past key packet and ctrl packet. */
303: /* Advance keypos to the analogous location. */
304: fseek(fkey, keypos, SEEK_SET);
305: keykeypos = keypos;
306: (void) nextkeypacket(fkey, &ctb);
307: keypktlen = ftell(fkey) - keypos; /* for check_key_sig() */
308: for (;;) {
309: keypos = ftell(fkey);
310: status = nextkeypacket(fkey, &ctb);
311: if (status < 0 || ctb == CTB_USERID || is_ctb_type(ctb, CTB_SKE_TYPE))
312: break;
313: }
314: if (!ring_compromise && is_ctb_type(ctb, CTB_SKE_TYPE)) {
315: /* found a compromise cert on keyfile that is not in ringfile */
316: word32 timestamp;
317: byte sig_class;
318: int cert_pktlen;
1.1.1.6 root 319:
1.1.1.7 root 320: cert_pktlen = ftell(fkey) - keypos;
321: if (check_key_sig(fkey, keykeypos, keypktlen,
322: (char *) userid, fkey, keypos,
323: ringfile, (char *) userid, (byte *) & timestamp,
324: &sig_class) == 0 &&
325: sig_class == KC_SIGNATURE_BYTE) {
326: PascalToC((char *) userid);
327: fprintf(pgpout, LANG("Key revocation certificate from \"%s\".\n"),
328: LOCAL_CHARSET((char *) userid));
329: copyfilepos(fkey, out, cert_pktlen, keypos);
330: /* Show updates */
331: if (batchmode)
332: show_key(fring, *pringpos, SHOW_CHANGE);
333: ++newrvks;
334: } else
335: fprintf(pgpout,
336: LANG("\n\007WARNING: File '%s' contains bad revocation certificate.\n"),
337: keyfile);
338: }
339: fseek(fkey, keypos, SEEK_SET);
340:
341: /* Second, copy all keyfile userid's plus signatures that aren't
342: * in ringfile.
343: */
344:
345: copying = FALSE;
346: for (;;) {
347: /* Read next userid from keyfile; see if it is in ringfile;
348: * set copying true/false accordingly. If copying is true
349: * and it is a userid or a signature, copy it. Loop till hit
350: * a new key in keyfile, or EOF.
1.1.1.6 root 351: */
1.1.1.7 root 352: keypos = ftell(fkey);
353: status = readkeypacket(fkey, FALSE, &ctb, NULL, (char *) userid, NULL,
354: NULL, NULL, NULL, NULL, NULL, NULL, NULL);
355: if (status == -3) /* unrecoverable error: bad packet length etc. */
356: return status;
357: keypktlen = ftell(fkey) - keypos;
358: if (status == -1 || is_key_ctb(ctb))
359: break; /* EOF or next key */
360: if (status < 0)
361: continue; /* bad packet, skip it */
362: if (ctb == CTB_USERID) {
363: long userid_pos;
364: int userid_len;
365: PascalToC((char *) userid);
366: /* Set copying true if userid is not in the ringfile */
367: copying = (getpubuserid(ringfile, ringkeypos, userid, &userid_pos,
368: &userid_len, TRUE) < 0);
369: if (copying) {
370: putc('\n', pgpout);
371: fprintf(pgpout, LANG("New userid: \"%s\".\n"),
372: LOCAL_CHARSET((char *) userid));
373: fprintf(pgpout,
374: LANG("\nWill be added to the following key:\n"));
375: show_key(fring, *pringpos, 0);
376: fprintf(pgpout, LANG("\nAdd this userid (y/N)? "));
377: if (batchmode || getyesno('n')) {
378: ++newids;
379: /* Show an update string */
380: if (batchmode) {
381: fprintf(pgpout, "\n");
382: show_key(fring, *pringpos, SHOW_CHANGE);
383: }
384: } else {
385: copying = FALSE;
386: }
387: }
388: }
389: if (copying) {
390: if (ctb == CTB_USERID || is_ctb_type(ctb, CTB_SKE_TYPE)) {
391: copyfilepos(fkey, out, keypktlen, keypos);
392: if (publickey) {
393: if (is_ctb_type(ctb, CTB_SKE_TYPE))
394: write_trust(out, KC_SIGTRUST_UNDEFINED);
395: else
396: write_trust(out, KC_LEGIT_UNKNOWN);
397: }
398: }
399: }
400: }
401:
402: /* Third, for all ring userid's, if not in keyfile, copy the userid
403: * plus its dependant signatures.
404: */
405: fseek(fring, ringpos, SEEK_SET);
406: /* Grab the keyID here */
407: readkeypacket(fring, FALSE, &ctb, NULL, (char *) userid, NULL, NULL,
408: NULL, NULL, NULL, NULL, NULL, NULL);
409: fseek(fring, ringpos, SEEK_SET);
410: for (;;) {
411: ringpos = ftell(fring);
412: status = readkeypacket(fring, FALSE, &ctb, NULL,
413: (char *) userid, NULL, NULL,
414: NULL, NULL, NULL, NULL, NULL, NULL);
415: ringpktlen = ftell(fring) - ringpos;
416: if (status == -3)
417: return status;
418: if (status == -1 || is_key_ctb(ctb))
419: break;
420: if (ctb == CTB_USERID) {
421: long userid_pos;
422: int userid_len;
423: /* See if there is a match in keyfile */
424: PascalToC((char *) userid);
425: /* don't use substring match (exact_match = TRUE) */
426: if (getpubuserid(keyfile, keykeypos, userid,
427: &userid_pos, &userid_len, TRUE) >= 0) {
428: if ((status = mergesigs(fkey, keyfile, userid_pos,
429: fring, ringfile, &ringpos, out)) < 0)
430: return status;
431: copying = FALSE;
432: } else {
433: copying = TRUE;
434: }
435: }
436: if (copying) {
437: /* Copy ringfile userid and sigs to out */
438: copyfilepos(fring, out, ringpktlen, ringpos);
439: }
440: } /* End of loop for each key in ringfile */
441: fseek(fring, ringpos, SEEK_SET);
442: *pringpos = ringpos;
443: return 0;
444: } /* mergekeys */
1.1.1.6 root 445:
446: /* Adds (prepends) key file to key ring file. */
1.1.1.7 root 447: int _addto_keyring(char *keyfile, char *ringfile)
1.1.1.6 root 448: {
1.1.1.7 root 449: FILE *f, *g, *h;
450: long file_position, fp;
451: int pktlen;
452: byte ctb;
453: int status;
454: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
455: unit n1[MAX_UNIT_PRECISION];
456: byte keyID[KEYFRAGSIZE];
457: byte userid[256]; /* key certificate userid */
458: byte userid1[256];
459: word32 tstamp;
460: byte *timestamp = (byte *) & tstamp; /* key certificate timestamp */
461: boolean userid_seen = FALSE;
462: int commonkeys = 0;
463: int copying;
464: struct newkey *nkey, *nkeys = NULL;
465: char *scratchf;
466:
467: /* open file f for read, in binary (not text) mode... */
468: if ((f = fopen(keyfile, FOPRBIN)) == NULL) {
469: fprintf(pgpout, LANG("\n\007Can't open key file '%s'\n"), keyfile);
470: return -1;
471: }
472: ctb = 0;
473: if (fread(&ctb, 1, 1, f) != 1 || !is_key_ctb(ctb)) {
474: fclose(f);
475: return -1;
476: }
477: rewind(f);
1.1.1.6 root 478:
1.1.1.7 root 479: setoutdir(ringfile);
480: scratchf = tempfile(0);
1.1.1.6 root 481:
1.1.1.7 root 482: /*
483: * get userids from both files, maybe should also use the default public
484: * keyring if ringfile is not the default ring.
485: */
486: setkrent(ringfile);
487: setkrent(keyfile);
488: init_userhash();
489:
490: if (!file_exists(ringfile)) {
491: /* ringfile does not exist. Can it be created? */
492: /* open file g for writing, in binary (not text) mode... */
493: g = fopen(ringfile, FOPWBIN);
494: if (g == NULL) {
495: fprintf(pgpout,
496: LANG("\nKey ring file '%s' cannot be created.\n"),
497: ringfile);
498: fclose(f);
499: goto err;
1.1.1.6 root 500: }
1.1.1.7 root 501: fclose(g);
502: }
503: /* Create working output file */
504: /* open file g for writing, in binary (not text) mode... */
505: if ((g = fopen(scratchf, FOPWBIN)) == NULL) {
506: fclose(f);
507: goto err;
508: }
509: newkeys = newsigs = newids = newrvks = 0;
510:
511: /* Pass 1 - copy all keys from f which aren't in ring file */
512: /* Also copy userid and signature packets. */
513: fprintf(pgpout, LANG("\nLooking for new keys...\n"));
514: copying = FALSE;
515: if (gpk_open(ringfile) < 0) {
516: fclose(f); /* close key file */
517: fclose(g);
518: goto err;
519: }
520: for (;;) {
521: file_position = ftell(f);
522:
523: status = readkeypacket(f, FALSE, &ctb,
524: timestamp, (char *) userid, n, e,
525: NULL, NULL, NULL, NULL, NULL, NULL);
526: /* Note that readkeypacket has called set_precision */
527: if (status == -1) /* EOF */
528: break;
529: if (status == -2 || status == -3) {
530: fprintf(pgpout,
531: LANG("\n\007Could not read key from file '%s'.\n"),
532: keyfile);
533: fclose(f); /* close key file */
534: fclose(g);
535: goto err;
536: }
537: if (status < 0) {
538: copying = FALSE;
539: continue; /* don't merge keys from unrecognized version */
540: }
541: /* Check to see if key is already on key ring */
542: if (is_key_ctb(ctb)) {
543: extract_keyID(keyID, n); /* from keyfile, not ringfile */
544: publickey = is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE);
545:
546: /* Check for duplicate key in key ring: */
547: status = get_publickey(&fp, NULL, keyID, timestamp, userid, n1, e);
548: if (status == 0) {
549: /* key in both keyring and keyfile */
550: if (mp_compare(n, n1) != 0) {
551: fprintf(pgpout,
552: LANG("\n\007Warning: Key ID %s matches key ID of key already on \n\
1.1.1.6 root 553: key ring '%s', but the keys themselves differ.\n\
554: This is highly suspicious. This key will not be added to ring.\n\
555: Acknowledge by pressing return: "), keyIDstring(keyID), ringfile);
1.1.1.7 root 556: getyesno('n');
557: } else {
558: ++commonkeys;
559: }
560: copying = FALSE;
561: } else if (status == -1) { /* key NOT in keyring */
562: ++newkeys;
563: if (interactive_add) {
564: if (!show_key(f, file_position, SHOW_ALL)) {
565: fprintf(pgpout,
566: LANG("\nDo you want to add this key to keyring '%s' (y/N)? "),
567: ringfile);
568: copying = getyesno('n');
569: } else
570: copying = FALSE;
571: } else {
572: if (!show_key(f, file_position, SHOW_LISTFMT))
573: copying = TRUE;
574: else
575: copying = FALSE;
576: }
577:
578: /* If batchmode, output an update message */
579: if (batchmode)
580: show_key(f, file_position, SHOW_CHANGE);
581: if (copying) {
582: nkey = xmalloc(sizeof(*nkey));
583: memcpy(nkey->keyID, keyID, KEYFRAGSIZE);
584: nkey->next = nkeys;
585: nkeys = nkey;
586: }
587: } else {
588: /* unknown version or bad key */
589: copying = FALSE;
590: }
1.1.1.6 root 591: }
592: /*
1.1.1.7 root 593: * Now, we copy according to the copying flag
594: * The key is prepended to the ring to give it search
595: * precedence over other keys with that same userid.
1.1.1.6 root 596: */
1.1.1.7 root 597: if (copying && (is_key_ctb(ctb) || ctb == CTB_USERID ||
598: is_ctb_type(ctb, CTB_SKE_TYPE))) {
599: pktlen = (int) (ftell(f) - file_position);
600: copyfilepos(f, g, pktlen, file_position); /* copy packet from f */
601: if (publickey) {
602: /* Initialize trust packets after keys and signatures */
603: if (is_key_ctb(ctb)) {
604: write_trust(g, KC_OWNERTRUST_UNDEFINED);
605: userid_seen = FALSE;
606: } else if (is_ctb_type(ctb, CTB_SKE_TYPE)) {
607: if (userid_seen) {
608: write_trust(g, KC_SIGTRUST_UNDEFINED);
609: } else {
610: /* signature certificate before userid must be compromise cert. */
611: fprintf(pgpout, LANG("Key has been revoked.\n"));
612: }
613: } else if (is_ctb_type(ctb, CTB_USERID_TYPE)) {
614: write_trust(g, KC_LEGIT_UNKNOWN);
615: userid_seen = TRUE;
616: }
617: }
618: }
619: }
620: gpk_close();
621:
622: /*
623: * Now copy the remainder of the ringfile, h, to g. commonkeys tells
624: * how many keys are common to keyfile and ringfile. As long as that
625: * is nonzero we will check each key in ringfile to see if it has a
626: * match in keyfile.
627: */
628: if ((h = fopen(ringfile, FOPRBIN)) != NULL) {
629: if (gpk_open(keyfile) < 0) {
630: fclose(f);
631: fclose(g);
632: fclose(h);
633: goto err;
634: }
635: while (commonkeys) {
636: /* Loop for each key in ringfile */
637: file_position = ftell(h);
638: status = readkeypacket(h, FALSE, &ctb, NULL, (char *) userid, n, e,
639: NULL, NULL, NULL, NULL, NULL, NULL);
640: if (status == -1 || status == -3) {
641: if (status == -1) /* hit EOF */
642: fprintf(pgpout,
643: LANG("\n\007Key file contains duplicate keys: cannot be added to keyring\n"));
644: else
645: fprintf(pgpout,
646: LANG("\n\007Could not read key from file '%s'.\n"),
647: ringfile);
648: fclose(f);
1.1.1.6 root 649: fclose(g);
1.1.1.7 root 650: fclose(h);
1.1.1.6 root 651: goto err;
1.1.1.7 root 652: }
653: PascalToC((char *) userid);
654: pktlen = ftell(h) - file_position;
655: if (is_key_ctb(ctb)) {
656: long tfp;
657: /* unknown version or bad data: copy (don't remove packets from ringfile) */
658: copying = TRUE;
659: if (status == 0) {
660: /* See if there is a match in keyfile */
661: extract_keyID(keyID, n); /* from ringfile,
662: not keyfile */
663: extract_keyID(mykeyID, n); /* save this */
664: publickey = is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE);
1.1.1.8 ! root 665: if ((status = get_publickey(&tfp, NULL, keyID,
! 666: timestamp, userid1, n1, e)) >= 0) {
1.1.1.7 root 667: if (verbose)
668: fprintf(pgpout,
669: "Merging key ID: %s\n",
670: keyIDstring(keyID));
671: if (mergekeys(f, keyfile, tfp, h,
672: ringfile, &file_position, g) < 0) {
673: fclose(f);
674: fclose(g);
675: fclose(h);
676: goto err;
677: }
678: copying = FALSE;
679: --commonkeys;
1.1.1.8 ! root 680: } else {
! 681: if (status == -3)
! 682: --commonkeys; /* missing userid packet? */
1.1.1.7 root 683: }
684: }
685: }
686: if (copying) {
687: /* Copy ringfile key to g, without its sigs */
688: copyfilepos(h, g, pktlen, file_position);
689: file_position += pktlen;
690: }
691: } /* End of loop for each key in ringfile */
692: gpk_close();
693: copyfile(h, g, -1L); /* copy rest of file from file h to g */
694: fclose(h);
695: }
696: fclose(f);
697: if (write_error(g)) {
1.1.1.6 root 698: fclose(g);
1.1.1.7 root 699: goto err;
700: }
701: fclose(g);
702: if (newsigs == 0 && newkeys == 0 && newids == 0 && newrvks == 0) {
703: fprintf(pgpout, LANG("No new keys or signatures in keyfile.\n"));
1.1.1.6 root 704: rmtemp(scratchf);
1.1.1.7 root 705: endkrent();
706: return 0;
707: }
708: if (status = dokeycheck(NULL, scratchf, CHECK_NEW)) {
709: if (verbose)
710: fprintf(pgpout, "addto_keyring: dokeycheck returned %d\n", status);
711: goto err;
712: }
713: endkrent();
714:
715: fprintf(pgpout, LANG("\nKeyfile contains:\n"));
716: if (newkeys)
717: fprintf(pgpout, LANG("%4d new key(s)\n"), newkeys);
718: if (newsigs)
719: fprintf(pgpout, LANG("%4d new signatures(s)\n"), newsigs);
720: if (newids)
721: fprintf(pgpout, LANG("%4d new user ID(s)\n"), newids);
722: if (newrvks)
723: fprintf(pgpout, LANG("%4d new revocation(s)\n"), newrvks);
724:
725: ask_first = TRUE;
726: status = maint_update(scratchf, nkeys);
727: if (status >= 0 && !filter_mode && !batchmode)
728: for (nkey = nkeys; nkey; nkey = nkey->next)
729: if (ask_to_sign(nkey->keyID, scratchf) != 0)
730: break;
731: if (status && verbose)
732: fprintf(pgpout, "addto_keyring: maint_update returned %d\n", status);
733:
734: free_newkeys(nkeys);
735:
736: savetempbak(scratchf, ringfile);
737:
738: return 0; /* normal return */
739:
740: err:
741: gpk_close(); /* save to call if not opened */
742: endkrent();
743: /* make sure we remove any garbage files we may have created */
744: rmtemp(scratchf);
745: return -1;
746: } /* _addto_keyring */
1.1.1.6 root 747:
748: int addto_keyring(char *keyfile, char *ringfile)
749: {
1.1.1.7 root 750: long armorline = 0;
751: char *tempf;
752: int addflag = 0;
1.1.1.6 root 753:
1.1.1.7 root 754: if (_addto_keyring(keyfile, ringfile) == 0)
755: return 0;
756: /* check if the keyfile to be added is armored */
757: while (is_armor_file(keyfile, armorline)) {
758: tempf = tempfile(TMP_TMPDIR | TMP_WIPE);
759: if (de_armor_file(keyfile, tempf, &armorline)) {
760: rmtemp(tempf);
761: return -1;
762: }
763: if (_addto_keyring(tempf, ringfile) == 0)
764: addflag = 1;
765: rmtemp(tempf);
766: }
767: if (!addflag) {
768: fprintf(pgpout, LANG("\nNo keys found in '%s'.\n"), keyfile);
769: return -1;
770: } else {
771: return 0;
772: }
773: }
1.1.1.6 root 774:
1.1.1.7 root 775: static int ask_to_sign(byte * keyID, char *ringfile)
1.1.1.6 root 776: {
1.1.1.7 root 777: FILE *f;
778: word32 timestamp;
779: byte ctb, trust;
780: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
781: byte userid[256];
782: long fpos;
783: int status;
784: extern char my_name[];
1.1.1.6 root 785:
1.1.1.7 root 786: if (getpublickey(GPK_GIVEUP, ringfile, &fpos, NULL, keyID,
787: (byte *) & timestamp, userid, n, e) < 0)
788: return -1;
1.1.1.6 root 789:
1.1.1.7 root 790: if ((f = fopen(ringfile, FOPRBIN)) == NULL)
791: return -1;
1.1.1.6 root 792:
1.1.1.7 root 793: fseek(f, fpos, SEEK_SET);
794: if (is_compromised(f)) {
1.1.1.6 root 795: fclose(f);
796: return 0;
1.1.1.7 root 797: }
798: if (nextkeypacket(f, &ctb) < 0) {
799: fclose(f);
800: return -1;
801: }
802: if (ctb != CTB_CERT_PUBKEY) {
803: fclose(f);
804: return 0; /* don't ask to sign secret key */
805: }
806: while (nextkeypacket(f, &ctb) == 0 && !is_key_ctb(ctb))
807: if (ctb == CTB_USERID) /* check first userid */
808: break;
809: if (ctb != CTB_USERID) {
810: fclose(f);
811: return -1;
812: }
813: if ((status = read_trust(f, &trust)) < 0) {
814: fclose(f);
815: return status;
816: }
817: if ((trust & KC_LEGIT_MASK) == KC_LEGIT_COMPLETE) {
818: fclose(f);
819: return 0;
820: }
821: if (ask_first) {
822: /* shortcut for adding big keyfile */
823: fprintf(pgpout,
824: LANG("\nOne or more of the new keys are not fully certified.\n\
825: Do you want to certify any of these keys yourself (y/N)? "));
826: if (!getyesno('n')) {
827: fclose(f);
828: return 1;
829: }
830: }
831: ask_first = FALSE;
832: show_key(f, fpos, SHOW_ALL | SHOW_HASH);
833: fclose(f);
834: PascalToC((char *) userid);
835: fprintf(pgpout,
836: LANG("\nDo you want to certify this key yourself (y/N)? "));
837: if (getyesno('n')) {
838: if (signkey((char *) userid, my_name, ringfile) == 0)
839: maint_update(ringfile, 0);
840: }
841: return 0;
1.1.1.6 root 842: }
843:
844: /**** faster version of getpublickey() ****/
845:
1.1.1.7 root 846: static long find_keyID(byte * keyID);
1.1.1.6 root 847:
848: static FILE *gpkf = NULL;
849:
850: /*
851: * speedup replacement for getpublickey(), does not have the arguments
852: * giveup, showkey and keyfile (giveup = TRUE, showkey = FALSE, keyfile
853: * is set with gpk_open().
854: * only searches on keyID
855: */
1.1.1.7 root 856: int get_publickey(long *file_position, int *pktlen, byte * keyID,
857: byte * timestamp, byte * userid, unitptr n, unitptr e)
1.1.1.6 root 858: {
1.1.1.7 root 859: byte ctb; /* returned by readkeypacket */
860: int status, keystatus = -1;
861: long fpos;
1.1.1.6 root 862:
1.1.1.7 root 863: if ((fpos = find_keyID(keyID)) == -1)
864: return -1;
865: fseek(gpkf, fpos, SEEK_SET);
1.1.1.6 root 866:
1.1.1.7 root 867: for (;;) {
868: fpos = ftell(gpkf);
869: status = readkeypacket(gpkf, FALSE, &ctb, timestamp,
870: (char *) userid, n, e,
871: NULL, NULL, NULL, NULL, NULL, NULL);
872: /* Note that readkeypacket has called set_precision */
873:
874: if (status < 0 && status != -4 && status != -6)
875: return status;
876:
877: /* Remember packet position and size for last key packet */
878: if (is_key_ctb(ctb)) {
879: if (file_position)
880: *file_position = fpos;
881: if (pktlen)
882: *pktlen = (int) (ftell(gpkf) - fpos);
883: if (keystatus != -1)
884: return -3; /* should not happen, probably missing userid pkt */
885: keystatus = status;
886: }
887: if (ctb == CTB_USERID)
888: return keystatus;
889: }
1.1.1.6 root 890: }
891:
1.1.1.7 root 892: #define PK_HASHSIZE 256 /* must be power of 2 */
1.1.1.6 root 893: #define PK_HASH(x) (*(byte *) (x) & (PK_HASHSIZE - 1))
894: #define HASH_ALLOC 400
895:
1.1.1.7 root 896: static VOID *allocbuf(int size);
1.1.1.6 root 897: static void freebufpool(void);
898:
899: static struct hashent {
1.1.1.7 root 900: struct hashent *next;
901: byte keyID[KEYFRAGSIZE];
902: long offset;
1.1.1.6 root 903: } **hashtbl = NULL, *hashptr;
904:
905: static int hashleft = 0;
906:
1.1.1.7 root 907: int gpk_open(char *keyfile)
1.1.1.6 root 908: {
1.1.1.7 root 909: int status;
910: long fpos = 0;
911: byte keyID[KEYFRAGSIZE];
912: byte ctb;
1.1.1.6 root 913:
1.1.1.7 root 914: if (gpkf) {
915: fprintf(pgpout, "gpk_open: already open\n");
916: return -1;
917: }
918: default_extension(keyfile, PGP_EXTENSION);
919: if ((gpkf = fopen(keyfile, FOPRBIN)) == NULL)
920: return -1; /* error return */
921: hashtbl = allocbuf(PK_HASHSIZE * sizeof(struct hashent *));
922: memset(hashtbl, 0, PK_HASHSIZE * sizeof(struct hashent *));
923: while ((status = readkpacket(gpkf, &ctb, NULL, keyID, NULL)) != -1) {
924: if (status == -2 || status == -3) {
925: fprintf(pgpout, LANG("\n\007Could not read key from file '%s'.\n"),
926: keyfile);
927: fclose(gpkf); /* close key file */
928: return -1;
929: }
930: if (is_key_ctb(ctb)) {
931: if (status != -4) {
932: if (find_keyID(keyID) != -1)
933: fprintf(pgpout,
934: "Warning: duplicate key in keyring '%s'\n", keyfile);
935: if (!hashleft) {
936: hashptr = allocbuf(HASH_ALLOC * sizeof(struct hashent));
937: hashleft = HASH_ALLOC;
938: }
939: memcpy(hashptr->keyID, keyID, KEYFRAGSIZE);
940: hashptr->offset = fpos;
941: hashptr->next = hashtbl[PK_HASH(keyID)];
942: hashtbl[PK_HASH(keyID)] = hashptr;
943: ++hashptr;
944: --hashleft;
945: }
946: }
947: fpos = ftell(gpkf);
948: }
949: return 0;
950: }
951:
952: void gpk_close(void)
953: {
954: if (!gpkf)
955: return;
956: hashleft = 0;
957: hashtbl = NULL;
958: freebufpool();
959: fclose(gpkf); /* close key file */
960: gpkf = NULL;
1.1.1.6 root 961: }
962:
963: /*
964: * Lookup file position in hash table by keyID, returns -1 if not found
965: */
1.1.1.7 root 966: static long find_keyID(byte * keyID)
1.1.1.6 root 967: {
1.1.1.7 root 968: struct hashent *p;
1.1.1.6 root 969:
1.1.1.7 root 970: for (p = hashtbl[PK_HASH(keyID)]; p; p = p->next)
971: if (memcmp(keyID, p->keyID, KEYFRAGSIZE) == 0)
972: return p->offset;
973: return -1;
1.1.1.6 root 974: }
975:
976:
977: static struct bufpool {
1.1.1.7 root 978: struct bufpool *next;
979: char buf[1]; /* variable size */
1.1.1.6 root 980: } *bufpool = NULL;
981:
982: /*
983: * allocate buffer, all buffers allocated with this function can be
984: * freed with one call to freebufpool()
985: */
986: static VOID *
1.1.1.7 root 987: allocbuf(int size)
1.1.1.6 root 988: {
1.1.1.7 root 989: struct bufpool *p;
1.1.1.6 root 990:
1.1.1.7 root 991: p = xmalloc(size + sizeof(struct bufpool *));
992: p->next = bufpool;
993: bufpool = p;
994: return p->buf;
1.1.1.6 root 995: }
996:
997: /*
998: * free all memory obtained with allocbuf()
999: */
1.1.1.7 root 1000: static void freebufpool(void)
1.1.1.6 root 1001: {
1.1.1.7 root 1002: struct bufpool *p;
1.1.1.6 root 1003:
1.1.1.7 root 1004: while (bufpool) {
1005: p = bufpool;
1006: bufpool = bufpool->next;
1007: free(p);
1008: }
1.1.1.6 root 1009: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.