|
|
1.1 root 1: /* keymaint.c - Keyring maintenance pass 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: keymaint.c implemented by Branko Lankester.
21: */
22:
23: #include <stdio.h>
24: #include <time.h>
25: #include "mpilib.h"
26: #include "random.h"
27: #include "crypto.h"
28: #include "fileio.h"
29: #include "keymgmt.h"
30: #include "mpiio.h"
31: #include "language.h"
32: #include "pgp.h"
33:
34:
35: void setup_trust();
36: int maint_pass1(FILE *f);
37: int maint_trace_chain(FILE *f);
38: int maint_cmpfiles(FILE *f, FILE *g);
39: int trace_sig_chain(FILE *f, byte *fromID, int owner_trust, int depth);
40: int check_secretkey(FILE *f, long keypos);
41: int set_legit(FILE *f, long trustpos, int trust_count);
42: long lookup_by_keyID(FILE *f, byte *srch_keyID);
43: void show_userid(FILE *f, byte *keyID);
44: int show_trust(byte, byte);
45: int show_legit(byte, byte);
46: void write_trust_pos(FILE *f, byte keyctrl, long pos);
47:
48: /* returned when trying to do a maintenance pass on a secret keyring or keyfile */
49: #define ERR_NOTRUST -7
50:
51: #define TRUST_MASK 7 /* mask for userid/signature trust bytes */
52: #define SET_TRUST(b,v) (*(b) = (*(b) & ~TRUST_MASK) | (v))
53: #define TRUST_LEV(b) ((b) & TRUST_MASK)
54:
55: #define TRUST_FAC(x) (trust_tbl[TRUST_LEV(x)])
56:
57: /*
58: * table for tuning user paranoia index.
59: * values represent contribution of one signature indexed by the
60: * SIGTRUST of a signature
61: */
62: int trust_tbl[8];
63:
64: static int marginal_min;
65: static int complete_min; /* total count needed for a fully legit key */
66:
67: int marg_min = 2; /* number of marginally trusted signatures needed for
68: a fully legit key (can be set in config.pgp). */
69: int compl_min = 1; /* number of fully trusted signatures needed */
70:
71: char trust_lst[8][16] = {
72: "undefined", /* PSTR("undefined") */
73: "unknown", /* PSTR("unknown") */
74: "untrusted", /* PSTR("untrusted") */
75: "<3>", /* unused */
76: "<4>", /* unused */
77: "marginal", /* PSTR("marginal") */
78: "complete", /* PSTR("complete") */
79: "ultimate", /* PSTR("ultimate") */
80: };
81:
82: char legit_lst[4][16] = {
83: "undefined",
84: "untrusted",
85: "marginal",
86: "complete"
87: };
88:
89: int trustlst_len = 9; /* length of longest trust word */
90: int legitlst_len = 9; /* length of longest legit word */
91:
92: char floppyring[MAX_PATH] = "";
93: int max_cert_depth = 4; /* maximum nesting of signatures */
94:
95: static boolean check_only = FALSE;
96: static boolean mverbose;
97: static FILE *sec_fp;
98: static FILE *floppy_fp = NULL;
99: static int undefined_trust; /* number of legit keys with undef. trust */
100:
101: int
102: maintenance(char *ringfile, int options)
103: {
104: FILE *f, *g;
105: int status;
106: char *tmpring;
107: char secretkeyring[MAX_PATH];
108:
109: check_only = (options & MAINT_CHECK) != 0;
110: mverbose = (options & MAINT_VERBOSE) != 0;
111: undefined_trust = 0;
112:
113: if ((tmpring = tempfile(TMP_TMPDIR)) == NULL)
114: return(-1);
115: if ((g = fopenbin(tmpring, "w+")) == NULL)
116: return(-1);
117:
118: if ((f = fopenbin(ringfile,"r")) == NULL)
119: { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
120: fclose(g);
121: return(-1);
122: }
123:
124: buildfilename(secretkeyring, SECRET_KEYRING_FILENAME);
125: if ((sec_fp = fopenbin(secretkeyring, "r")) == NULL)
126: fprintf(pgpout,PSTR("\nCan't open secret key ring file '%s'\n"),
127: secretkeyring);
128:
129: if (!(options & MAINT_SILENT) && *floppyring != '\0' &&
130: (floppy_fp = fopenbin(floppyring, "r")) == NULL)
131: fprintf(pgpout,PSTR("\nCan't open backup key ring file '%s'\n"),
132: floppyring);
133:
134: if ((status = copyfile(f, g, -1L)) < 0)
135: { fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"), ringfile);
136: goto failed;
137: }
138:
139: setup_trust();
140: if (mverbose)
141: fprintf(pgpout, PSTR("\nPass 1: Looking for the \"ultimately-trusted\" keys...\n"));
142: rewind(g);
143: if ((status = maint_pass1(g)) < 0)
144: goto failed;
145:
146: if (mverbose)
147: fprintf(pgpout, PSTR("\nPass 2: Tracing signature chains...\n"));
148: rewind(g);
149: if ((status = maint_trace_chain(g)) < 0)
150: goto failed;
151:
152: if (!(options & MAINT_SILENT))
153: { if (mverbose)
154: fprintf(pgpout, PSTR("\nPass 3: Comparing with original keyring...\n"));
155: rewind(f);
156: rewind(g);
157: if ((status = maint_cmpfiles(f, g)) < 0)
158: goto failed;
159: } else
160: status = 1;
161:
162: fflush(g);
163: if (ferror(g))
164: { status = -1;
165: goto failed;
166: }
167: fclose(f);
168: fclose(g);
169: if (sec_fp)
170: fclose(sec_fp);
171: if (floppy_fp)
172: { fclose(floppy_fp);
173: floppy_fp = NULL;
174: }
175:
176: #ifdef DEBUG
177: if (check_only)
178: {
179: if (undefined_trust)
180: fprintf(pgpout, "\nKeyring contains %d fully validated key(s) with undefined trust.\n", undefined_trust);
181: else
182: if (status == 0)
183: fprintf(pgpout, "\nMaintenance check OK.\n");
184: rmtemp(tmpring);
185: return(0);
186: }
187: #endif
188:
189: if (status > 0) /* keyring is changed */
190: {
191: if (options & MAINT_SILENT)
192: { /* implicit maintenance pass (after pgp -ka, -kr, -ks) */
193: remove(ringfile);
194: if (savetemp(tmpring, ringfile) == NULL)
195: return(-1);
196: }
197: else
198: { /* explicit maintenance pass */
199: fprintf(pgpout, PSTR("Update public keyring '%s' (Y/n)? "), ringfile);
200: if (!getyesno('y'))
201: {
202: rmtemp(tmpring);
203: return(0);
204: }
205: if (savetempbak(tmpring, ringfile))
206: return(-1);
207: }
208: }
209: else
210: rmtemp(tmpring);
211:
212: return(0);
213:
214: failed:
215: if (sec_fp)
216: fclose(sec_fp);
217: if (floppy_fp)
218: { fclose(floppy_fp);
219: floppy_fp = NULL;
220: }
221: fclose(f);
222: fclose(g);
223: #ifdef DEBUG
224: savetempbak(tmpring, "tmpring.pub");
225: #else
226: rmtemp(tmpring);
227: #endif
228: return(status);
229: }
230:
231:
232: /*
233: * check if axiomatic keys are present in the secret keyring and
234: * clear userid and signature trust bytes
235: */
236: int
237: maint_pass1(FILE *f)
238: {
239: int status;
240: char userid[256];
241: byte keyID[KEYFRAGSIZE];
242: byte ctb;
243: byte keyctrl;
244: boolean buckstop = FALSE, show_user = FALSE;
245: boolean compromised = FALSE;
246: int buckstopcount = 0;
247: int usercount = 0;
248: long keypos = 0;
249:
250: while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1)
251: {
252: if (status < 0)
253: return(status);
254:
255: if (is_ctb_type(ctb, CTB_COMMENT_TYPE))
256: continue;
257: if (compromised && is_ctb_type(ctb, CTB_SKE_TYPE) && !usercount)
258: continue; /* compromise certificate */
259:
260: /* other packets should have trust byte */
261: if (read_trust(f, &keyctrl) < 0)
262: return(ERR_NOTRUST); /* not a public keyring */
263:
264: if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
265: {
266: if (compromised = is_compromised(f))
267: keyctrl = KC_OWNERTRUST_NEVER;
268: if ((keyctrl & KC_BUCKSTOP))
269: {
270: if (check_secretkey(f, keypos) == 0)
271: {
272: ++buckstopcount;
273: buckstop = TRUE;
274: if (mverbose)
275: fprintf(pgpout, "* %s",keyIDstring(keyID));
276: }
277: else
278: { /* not in secret keyring */
279: keyctrl &= ~KC_BUCKSTOP;
280: if (TRUST_LEV(keyctrl) == KC_OWNERTRUST_ULTIMATE)
281: keyctrl = KC_OWNERTRUST_ALWAYS;
282: if (mverbose)
283: fprintf(pgpout, ". %s",keyIDstring(keyID));
284: }
285: show_user = mverbose;
286: }
287: else
288: {
289: buckstop = FALSE;
290: show_user = FALSE;
291: }
292: usercount = 0;
293: keyctrl &= ~KC_VISITED;
294:
295: }
296: else if (ctb == CTB_USERID)
297: {
298: if (show_user)
299: {
300: if (usercount) /* more than one user ID */
301: fprintf(pgpout, " ");
302: fprintf(pgpout, " %s\n", EXTERNAL(userid));
303: }
304: if (buckstop)
305: keyctrl = KC_LEGIT_COMPLETE;
306: else
307: keyctrl = KC_LEGIT_UNKNOWN;
308: ++usercount;
309: }
310: else if (is_ctb_type(ctb, CTB_SKE_TYPE))
311: {
312: keyctrl = KC_SIGTRUST_UNDEFINED;
313: }
314: fseek(f, -1L, SEEK_CUR);
315: fwrite(&keyctrl, 1, 1, f);
316: fseek(f, 0L, SEEK_CUR);
317: keypos = ftell(f);
318: }
319: if (buckstopcount == 0 && mverbose)
320: {
321: fprintf(pgpout, PSTR("No ultimately-trusted keys.\n"));
322: }
323: return(0);
324: }
325:
326:
327: /*
328: * scan keyring for buckstop keys and start the recursive trace_sig_chain()
329: * on them
330: */
331: int
332: maint_trace_chain(FILE *f)
333: {
334: int status;
335: char userid[256];
336: byte keyID[KEYFRAGSIZE];
337: long trustpos = 0;
338: byte ctb;
339: byte own_trust;
340: boolean buckstop = FALSE;
341:
342: while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1)
343: {
344: if (status < 0)
345: return status;
346:
347: if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
348: {
349: trustpos = ftell(f);
350: if ((status = read_trust(f, &own_trust)) < 0)
351: return(status);
352: buckstop = (own_trust & KC_BUCKSTOP) != 0;
353: userid[0] = '\0';
354: }
355: else if (ctb == CTB_USERID)
356: {
357: if (buckstop)
358: {
359: buckstop = FALSE; /* only for first user id */
360: if (mverbose)
361: fprintf(pgpout, "* %s\n", EXTERNAL(userid));
362:
363: if (TRUST_LEV(own_trust) == KC_OWNERTRUST_UNDEFINED)
364: { SET_TRUST(&own_trust, ask_owntrust(userid, own_trust));
365: write_trust_pos(f, own_trust, trustpos);
366: }
367: if (trace_sig_chain(f, keyID, TRUST_LEV(own_trust), 0) < 0)
368: return(-1);
369: }
370: }
371: }
372: return(0);
373: }
374:
375:
376: /*
377: * check if the maintenance pass changed anything
378: * returns 0 if files f and g are equal.
379: */
380: int
381: maint_cmpfiles(FILE *f, FILE *g)
382: {
383: int status;
384: char userid[256];
385: byte keyID[KEYFRAGSIZE];
386: byte sigkeyID[KEYFRAGSIZE];
387: byte ctb;
388: byte kc_orig, kc_new;
389: int usercount = 0;
390: int changed = 0;
391:
392: fprintf(pgpout, PSTR(" KeyID Trust Validity User ID\n"));
393: while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) == 0)
394: {
395: if (is_ctb_type(ctb, CTB_COMMENT_TYPE))
396: continue;
397: /* other packets should have trust byte */
398:
399: fseek(g, ftell(f), SEEK_SET);
400: if (read_trust(f, &kc_orig) < 0 || read_trust(g, &kc_new) < 0)
401: { status = ERR_NOTRUST;
402: break;
403: }
404:
405: if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
406: {
407: if (is_compromised(f))
408: {
409: fprintf(pgpout, "# ");
410: nextkeypacket(f, &ctb); /* skip compromise certificate */
411: nextkeypacket(g, &ctb);
412: }
413: else if ((kc_new & KC_BUCKSTOP))
414: fprintf(pgpout, "* ");
415: else
416: fprintf(pgpout, " ");
417:
418: fprintf(pgpout, "%s ",keyIDstring(keyID));
419: changed += show_trust(kc_new, kc_orig);
420: usercount = 0;
421: userid[0] = '\0';
422: }
423: else if (ctb == CTB_USERID)
424: {
425: if (usercount) /* more than one user ID */
426: fprintf(pgpout, " %*s", trustlst_len, "");
427: ++usercount;
428: changed += show_legit(kc_new, kc_orig);
429: fprintf(pgpout, "%s\n", EXTERNAL(userid));
430: }
431: else if (is_ctb_type(ctb, CTB_SKE_TYPE))
432: {
433: if (kc_new & KC_CONTIG)
434: fprintf(pgpout, "c ");
435: else
436: fprintf(pgpout, " ");
437: changed += show_trust(kc_new, kc_orig);
438: fprintf(pgpout, " %*s", legitlst_len, "");
439: show_userid(f, sigkeyID);
440: }
441: }
442: if (status >= -1 && changed)
443: fprintf(pgpout, PSTR("\n%d \"trust byte(s)\" changed.\n"), changed);
444: if (status < -1) /* -1 is OK, EOF */
445: return(status);
446: return(changed);
447: }
448:
449:
450: void
451: init_trust_lst()
452: {
453: static int initialized = 0;
454: int i, len;
455: char *s;
456:
457: if (initialized)
458: return;
459: for (i = 0; i < 8; ++i)
460: { if (trust_lst[i][0])
461: { s = PSTR (trust_lst[i]);
462: if (s != trust_lst[i])
463: strncpy(trust_lst[i], s, sizeof(trust_lst[0]) - 1);
464: len = strlen(s);
465: if (len > trustlst_len)
466: trustlst_len = len;
467: }
468: }
469: for (i = 0; i < 4; ++i)
470: { s = PSTR (legit_lst[i]);
471: if (s != legit_lst[i])
472: strncpy(legit_lst[i], s, sizeof(legit_lst[0]) - 1);
473: len = strlen(s);
474: if (len > legitlst_len)
475: legitlst_len = len;
476: }
477: ++trustlst_len;
478: ++legitlst_len;
479: initialized = 1;
480: }
481:
482: int
483: show_trust(byte kc_new, byte kc_orig)
484: {
485: #ifdef DEBUG
486: fprintf(pgpout, " %02x", kc_new);
487: if (kc_new != kc_orig)
488: {
489: fprintf(pgpout, " (%02x) ", kc_orig);
490: return(1);
491: }
492: fprintf(pgpout, " ");
493: return(0);
494: #else
495: init_trust_lst();
496: fprintf(pgpout, "%c%-*s", (kc_new == kc_orig ? ' ' : '!'),
497: trustlst_len, trust_lst[TRUST_LEV(kc_new)]);
498: return(kc_new != kc_orig);
499: #endif
500: }
501:
502: int
503: show_legit(byte kc_new, byte kc_orig)
504: {
505: #ifdef DEBUG
506: return(show_trust(kc_new, kc_orig));
507: #else
508: init_trust_lst();
509: kc_new &= KC_LEGIT_MASK;
510: kc_orig &= KC_LEGIT_MASK;
511: fprintf(pgpout, "%c%-*s", (kc_new == kc_orig ? ' ' : '!'),
512: legitlst_len, legit_lst[kc_new]);
513: return(kc_new != kc_orig);
514: #endif
515: }
516:
517:
518: /*
519: * Find all signatures made with a key, fromID is the keyID of this key
520: * owner_trust is the trust level of this key.
521: * If a trusted signature makes a key fully legit then signatures made
522: * with this key are also recursively traced on down the tree.
523: */
524: int
525: trace_sig_chain(FILE *f, byte *fromID, int owner_trust, int depth)
526: {
527: long filepos;
528: int status;
529: int trust_count = 0;
530: byte keyID[KEYFRAGSIZE];
531: byte sigkeyID[KEYFRAGSIZE];
532: byte ctb;
533: byte own_trust, sig_trust;
534: char userid[256];
535: int sig_count = 0;
536: int compromised = 0;
537: long usertrustpos = 0;
538: long ownt_pos = 0;
539:
540: if (max_cert_depth > 8)
541: max_cert_depth = 8;
542: if (depth > max_cert_depth)
543: return(0);
544: filepos = ftell(f);
545: rewind(f);
546: userid[0] = '\0';
547: while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) != -1)
548: {
549: if (status < 0)
550: return status;
551:
552: if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
553: {
554: compromised = is_compromised(f);
555: ownt_pos = ftell(f);
556: if (read_trust(f, &own_trust))
557: return(ERR_NOTRUST);
558: userid[0] = '\0';
559: }
560: else if (ctb == CTB_USERID)
561: {
562: usertrustpos = ftell(f);
563: trust_count = 0;
564: }
565: else if (is_ctb_type(ctb, CTB_SKE_TYPE))
566: {
567: if (compromised)
568: continue;
569: read_trust(f, &sig_trust);
570: if (memcmp(sigkeyID, fromID, sizeof(sigkeyID)) == 0)
571: {
572: ++sig_count;
573: if (mverbose)
574: fprintf(pgpout, "%*s > %s\n", 2*depth, "", EXTERNAL(userid));
575: if (TRUST_LEV(sig_trust) != owner_trust)
576: {
577: SET_TRUST(&sig_trust, owner_trust);
578: }
579: sig_trust |= KC_CONTIG;
580: fseek(f, -1L, SEEK_CUR);
581: fwrite(&sig_trust, 1, 1, f);
582: fseek(f, 0L, SEEK_CUR);
583: }
584:
585: if (sig_trust & KC_CONTIG)
586: {
587: trust_count += TRUST_FAC(sig_trust);
588:
589: switch (set_legit(f, usertrustpos, trust_count))
590: {
591: case -1: return(-1);
592: case 1:
593: if ((own_trust & (KC_BUCKSTOP|KC_VISITED)) == 0)
594: {
595: if (TRUST_LEV(own_trust) == KC_OWNERTRUST_UNDEFINED)
596: SET_TRUST(&own_trust, ask_owntrust(userid, own_trust));
597: own_trust |= KC_VISITED;
598: write_trust_pos(f, own_trust, ownt_pos);
599: trace_sig_chain(f, keyID, TRUST_LEV(own_trust), depth+1);
600: }
601: }
602: }
603: }
604: }
605: if (mverbose && sig_count == 0) /* no signatures from this user */
606: fprintf(pgpout, PSTR("%*s (No signatures)\n"), 2*depth, "");
607: fseek(f, filepos, SEEK_SET);
608: return(0);
609: }
610:
611:
612: int
613: check_secretkey(FILE *f, long keypos)
614: {
615: int status = -1;
616: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
617: unit nsec[MAX_UNIT_PRECISION], esec[MAX_UNIT_PRECISION];
618: char userid[256];
619: byte keyID[KEYFRAGSIZE];
620: long savepos, pktlen;
621: byte ctb;
622:
623: if (sec_fp == NULL)
624: return(-1);
625:
626: savepos = ftell(f);
627: fseek(f, keypos, SEEK_SET);
628: if (readkeypacket(f, FALSE, &ctb, NULL, NULL, n, e,
629: NULL, NULL, NULL, NULL, NULL, NULL) < 0)
630: goto ex;
631: extract_keyID(keyID, n);
632:
633: do /* get userid */
634: { if (readkpacket(f, &ctb, userid, NULL, NULL) < 0)
635: goto ex;
636: } while (ctb != CTB_USERID);
637:
638: if (lookup_by_keyID(sec_fp, keyID) < 0)
639: {
640: #if 0
641: if (!check_only)
642: {
643: fprintf(pgpout, PSTR (
644: "\nAn \"axiomatic\" key is one which does not need certifying by\n\
645: anyone else. Usually this special status is reserved only for your\n\
646: own keys, which should also appear on your secret keyring. The owner\n\
647: of an axiomatic key (who is typically yourself) is \"ultimately trusted\"\n\
648: by you to certify any or all other keys.\n"));
649: fprintf(pgpout, PSTR ("\nKey for user ID: \"%s\"\n\
650: is designated as an \"ultimately-trusted\" introducer, but the key\n\
651: does not appear in the secret keyring.\n\
652: Use this key as an ultimately-trusted introducer (y/N)? "), EXTERNAL(userid));
653: status = (getyesno('n') ? 0 : 1);
654: }
655: #else
656: status = 1;
657: #endif
658: }
659: else
660: {
661: long kpos = ftell(sec_fp);
662: if (readkeypacket(sec_fp, FALSE, &ctb, NULL, NULL, nsec, esec,
663: NULL, NULL, NULL, NULL, NULL, NULL) < 0)
664: {
665: fprintf(pgpout, PSTR("\n\007Cannot read from secret keyring.\n"));
666: goto ex;
667: }
668: if (mp_compare(n, nsec) || mp_compare(e, esec))
669: { /* Red Alert! */
670: fprintf(pgpout, PSTR("\n\007WARNING: Public key for user ID: \"%s\"\n\
671: does not match the corresponding key in the secret keyring.\n"), EXTERNAL(userid));
672: fprintf(pgpout, PSTR("This is a serious condition, indicating possible keyring tampering.\n"));
673: status = -2;
674: }
675: else
676: status = 0;
677:
678: if (floppy_fp)
679: {
680: if (lookup_by_keyID(floppy_fp, keyID) < 0)
681: {
682: fprintf(pgpout, PSTR("Public key for: \"%s\"\n\
683: is not present in the backup keyring '%s'.\n"),
684: EXTERNAL(userid), floppyring);
685: }
686: else
687: {
688: pktlen = ftell(sec_fp) - kpos;
689: fseek(sec_fp, kpos, SEEK_SET);
690: while (--pktlen >= 0 && getc(sec_fp) == getc(floppy_fp)) ;
691: if (pktlen != -1)
692: {
693: fprintf(pgpout, PSTR("\n\007WARNING: Secret key for: \"%s\"\n\
694: does not match the key in the backup keyring '%s'.\n"),
695: EXTERNAL(userid), floppyring);
696: fprintf(pgpout, PSTR("This is a serious condition, indicating possible keyring tampering.\n"));
697: status = -2;
698: }
699: }
700: }
701: }
702: ex:
703: fseek(f, savepos, SEEK_SET);
704: return(status);
705: }
706:
707:
708: void
709: setup_trust()
710: { /* initialize trust table */
711: if (marg_min == 0) /* marginally trusted signatures are ignored */
712: {
713: trust_tbl[5] = 0;
714: trust_tbl[6] = 1;
715: complete_min = compl_min;
716: }
717: else
718: {
719: if (marg_min < compl_min)
720: marg_min = compl_min;
721: trust_tbl[5] = compl_min;
722: trust_tbl[6] = marg_min;
723: complete_min = compl_min * marg_min;
724: }
725: trust_tbl[7] = complete_min; /* ultimate trust */
726: marginal_min = complete_min / 2;
727: }
728:
729:
730: /*
731: * set legit level of a userid
732: * returns 1 if the key/userid pair is fully legit.
733: */
734: int
735: set_legit(FILE *f, long trustpos, int trust_count)
736: {
737: long filepos;
738: byte keyctrl;
739:
740: filepos = ftell(f);
741: fseek(f, trustpos, SEEK_SET); /* user id trust byte */
742: if (read_trust(f, &keyctrl) < 0)
743: return(-1);
744:
745: if (trust_count < marginal_min)
746: keyctrl = KC_LEGIT_UNTRUSTED;
747: else if (trust_count < complete_min)
748: keyctrl = KC_LEGIT_MARGINAL;
749: else
750: keyctrl = KC_LEGIT_COMPLETE;
751:
752: fseek(f, trustpos, SEEK_SET);
753: write_trust(f, keyctrl);
754:
755: fseek(f, filepos, SEEK_SET);
756:
757: if ((keyctrl & KC_LEGIT_MASK) == KC_LEGIT_COMPLETE)
758: return(1);
759: else
760: return(0);
761: }
762:
763:
764: int ask_owntrust(char *userid, byte cur_trust)
765: /* Ask for a wetware decision from the human on how much to trust
766: this key's owner to certify other keys. Returns trust value. */
767: {
768: char buf[8];
769:
770: if (check_only)
771: { ++undefined_trust;
772: return(KC_OWNERTRUST_UNDEFINED);
773: }
774:
775: fprintf(pgpout,
776: PSTR("\nMake a determination in your own mind whether this key actually\n\
777: belongs to the person whom you think it belongs to, based on available\n\
778: evidence. If you think it does, then based on your estimate of\n\
779: that person's integrity and competence in key management, answer\n\
780: the following question:\n"));
781: fprintf(pgpout, PSTR("\nWould you trust \"%s\"\n\
782: to act as an introducer and certify other people's public keys to you?\n\
783: (1=I don't know. 2=No. 3=Usually. 4=Yes, always.) ? "), EXTERNAL(userid));
784: fflush(pgpout);
785: getstring(buf, sizeof(buf)-1, TRUE);
786: switch (buf[0])
787: { case '1': return KC_OWNERTRUST_UNKNOWN;
788: case '2': return KC_OWNERTRUST_NEVER;
789: case '3': return KC_OWNERTRUST_USUALLY;
790: case '4': return KC_OWNERTRUST_ALWAYS;
791: default: return(TRUST_LEV(cur_trust));
792: }
793: } /* ask_owntrust */
794:
795:
796: /*
797: * compare all key packets in keyring file f with file g
798: * XXX: untested
799: */
800: int
801: keyring_cmp(FILE *f, FILE *g)
802: {
803: int status, error = 0, badkeys = 0;
804: byte ctb;
805: byte keyID[KEYFRAGSIZE];
806: char userid[256];
807: long pktlen, keypos = 0;
808:
809: rewind(f);
810: while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) == 0)
811: {
812: if (is_key_ctb(ctb))
813: {
814: pktlen = ftell(f) - keypos;
815: fseek(f, keypos, SEEK_SET);
816: if (lookup_by_keyID(g, keyID) < 0)
817: {
818: error = 1;
819: continue;
820: }
821: while (--pktlen >= 0 && getc(f) == getc(g)) ;
822: if (pktlen != -1)
823: {
824: error = 2;
825: ++badkeys;
826: }
827:
828: }
829: if (error && ctb == CTB_USERID)
830: {
831: switch (error) {
832: case 1: fprintf(pgpout, PSTR("\n\007Key for user ID \"%s\"\n\
833: is not present in backup keyring\n"), EXTERNAL(userid));
834: case 2: fprintf(pgpout, PSTR("\n\007Key for user ID \"%s\"\n\
835: does not match key in backup keyring\n"), EXTERNAL(userid));
836: }
837: error = 0;
838: }
839: keypos = ftell(f);
840: }
841: if (error)
842: status = -5;
843: return(status < 0 ? status : badkeys);
844: }
845:
846:
847: int
848: readkpacket(FILE *f, byte *ctb, char *userid, byte *keyID, byte *sigkeyID)
849: {
850: int status;
851: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
852:
853: status = readkeypacket(f, FALSE, ctb, NULL, userid, n, e,
854: NULL, NULL, NULL, NULL, sigkeyID, NULL);
855:
856: if (status < 0)
857: {
858: #ifdef DEBUG
859: if (status < -1)
860: fprintf(stderr, "readkeypacket returned %d\n", status);
861: #endif
862: return(status);
863: }
864:
865: if (keyID && is_key_ctb(*ctb))
866: extract_keyID(keyID, n);
867:
868: if (userid && *ctb == CTB_USERID)
869: PascalToC(userid);
870:
871: return(0);
872: }
873:
874: long
875: lookup_by_keyID(FILE *f, byte *srch_keyID)
876: {
877: int status;
878: long keypos = 0;
879: byte keyID[KEYFRAGSIZE];
880: byte ctb;
881:
882: rewind(f);
883: while ((status = readkpacket(f, &ctb, NULL, keyID, NULL)) == 0)
884: {
885: if (is_key_ctb(ctb) && memcmp(keyID, srch_keyID, KEYFRAGSIZE) == 0)
886: {
887: fseek(f, keypos, SEEK_SET);
888: return(keypos);
889: }
890: keypos = ftell(f);
891: }
892: return(status);
893: }
894:
895:
896: void
897: show_userid(FILE *f, byte *keyID)
898: {
899: long filepos;
900: char userid[256];
901: byte ctb;
902:
903: filepos = ftell(f);
904: if (lookup_by_keyID(f, keyID) >= 0)
905: while (readkpacket(f, &ctb, userid, NULL, NULL) == 0)
906: if (ctb == CTB_USERID)
907: {
908: fprintf(pgpout, "%s\n", EXTERNAL(userid));
909: fseek(f, filepos, SEEK_SET);
910: return;
911: }
912:
913: fprintf(pgpout, "(KeyID: %s)\n",keyIDstring(keyID));
914: fseek(f, filepos, SEEK_SET);
915: }
916:
917: /*
918: * show the key in file f at file position keypos.
919: * 'what' controls the info that will be shown:
920: * SHOW_TRUST: show trust byte info
921: * SHOW_SIGS: show signatures
922: * these constants can be or'ed to get both
923: */
924: int
925: show_key(FILE *f, long keypos, int what)
926: {
927: int status;
928: long filepos;
929: char userid[256];
930: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
931: byte sigkeyID[KEYFRAGSIZE];
932: word32 timestamp;
933: byte ctb, keyctrl;
934: int userids = 0;
935: boolean print_trust = FALSE;
936: int precision = global_precision;
937:
938: filepos = ftell(f);
939: fseek(f, keypos, SEEK_SET);
940: while ((status = readkeypacket(f, FALSE, &ctb, (byte *)×tamp, userid,
941: n, e, NULL, NULL, NULL, NULL, sigkeyID, &keyctrl)) == 0)
942: {
943: if (is_key_ctb(ctb))
944: { if (userids)
945: break;
946: }
947: else if (ctb == CTB_KEYCTRL) /* trust bytes only in public keyrings */
948: {
949: if (what & SHOW_TRUST)
950: print_trust = TRUE;
951: }
952: else if (ctb == CTB_USERID)
953: { if (userids == 0)
954: { PascalToC(userid); /* for display */
955: fprintf(pgpout,PSTR("\nKey for user ID: %s\n"),EXTERNAL(userid));
956: fprintf(pgpout,PSTR("%d-bit key, Key ID %s, created %s\n"),
957: countbits(n), key2IDstring(n), cdate(×tamp) );
958: if (print_trust)
959: {
960: switch (TRUST_LEV(keyctrl))
961: {
962: case KC_OWNERTRUST_UNDEFINED:
963: case KC_OWNERTRUST_UNKNOWN:
964: /* Just don't say anything in this case */
965: break;
966: case KC_OWNERTRUST_NEVER: /* untrusted */
967: fprintf(pgpout, PSTR("This user is untrusted to certify other keys.\n"));
968: break;
969: case KC_OWNERTRUST_USUALLY: /* marginal trust */
970: fprintf(pgpout, PSTR("This user is generally trusted to certify other keys.\n"));
971: break;
972: case KC_OWNERTRUST_ALWAYS: /* complete trust */
973: fprintf(pgpout, PSTR("This user is completely trusted to certify other keys.\n"));
974: break;
975: case KC_OWNERTRUST_ULTIMATE: /* axiomatic, ultimate trust */
976: fprintf(pgpout, PSTR("This axiomatic key is ultimately trusted to certify other keys.\n"));
977: break;
978: default:
979: break;
980: } /* switch */
981: }
982: ++userids;
983: }
984: else
985: { PascalToC(userid);
986: if (what != 0)
987: fprintf(pgpout, "\n");
988: fprintf(pgpout,PSTR("Also known as: %s\n"), EXTERNAL(userid));
989: }
990: if (print_trust)
991: {
992: read_trust(f, &keyctrl);
993: switch (keyctrl & KC_LEGIT_MASK)
994: {
995: case 0: /* undefined certification level */
996: case 1: /* uncertified */
997: fprintf(pgpout, PSTR("This key/userID association is not certified.\n"));
998: break;
999: case 2: /* marginal certification */
1000: fprintf(pgpout, PSTR("This key/userID association is marginally certified.\n"));
1001: break;
1002: case 3: /* complete certification */
1003: fprintf(pgpout, PSTR("This key/userID association is fully certified.\n"));
1004: break;
1005: default: /* can't get here, right? */
1006: break;
1007: } /* switch */
1008: } /* print_trust */
1009: }
1010: else if ((what & SHOW_SIGS) && is_ctb_type(ctb, CTB_SKE_TYPE))
1011: {
1012: if (print_trust)
1013: {
1014: read_trust(f, &keyctrl);
1015: switch (TRUST_LEV(keyctrl))
1016: {
1017: case KC_SIGTRUST_UNDEFINED: /* undefined trust level */
1018: case KC_SIGTRUST_UNKNOWN:
1019: /* Just don't say anything in this case */
1020: fprintf(pgpout, PSTR(" Questionable certification from:\n "));
1021: break;
1022: case KC_SIGTRUST_UNTRUSTED: /* untrusted */
1023: fprintf(pgpout, PSTR(" Untrusted certification from:\n "));
1024: break;
1025: case KC_SIGTRUST_MARGINAL: /* marginal trust */
1026: fprintf(pgpout, PSTR(" Generally trusted certification from:\n "));
1027: break;
1028: case KC_SIGTRUST_COMPLETE: /* complete trust */
1029: fprintf(pgpout, PSTR(" Completely trusted certification from:\n "));
1030: break;
1031: case KC_SIGTRUST_ULTIMATE: /* axiomatic, ultimate trust */
1032: fprintf(pgpout, PSTR(" Axiomatically trusted certification from:\n "));
1033: break;
1034: default: /* can't get here, right? */
1035: break;
1036: } /* switch */
1037: }
1038: else
1039: fprintf(pgpout, PSTR(" Certified by: "));
1040: show_userid(f, sigkeyID);
1041: }
1042: }
1043: if (status == -1 && userids)
1044: status = 0;
1045: set_precision(precision);
1046: fseek(f, filepos, SEEK_SET);
1047: return(status);
1048: }
1049:
1050:
1051: void
1052: write_trust_pos(FILE *f, byte keyctrl, long pos)
1053: {
1054: long fpos;
1055:
1056: fpos = ftell(f);
1057: fseek(f, pos, SEEK_SET);
1058: write_trust(f, keyctrl);
1059: fseek(f, fpos, SEEK_SET);
1060: }
1061:
1062: int
1063: read_trust(FILE *f, byte *keyctrl)
1064: {
1065: unsigned char buf[3];
1066:
1067: if (fread(buf, 1, 3, f) != 3)
1068: return -1;
1069: if (buf[0] != CTB_KEYCTRL)
1070: {
1071: if (is_ctb(buf[0]))
1072: return(ERR_NOTRUST);
1073: else
1074: return(-3); /* bad data */
1075: }
1076: if (buf[1] != 1) /* length must be 1 */
1077: return(-3);
1078: if (keyctrl)
1079: *keyctrl = buf[2];
1080: return(0);
1081: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.