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