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