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