|
|
1.1.1.2 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>
1.1.1.3 root 25: #include <stdlib.h>
1.1.1.2 root 26: #include "mpilib.h"
27: #include "random.h"
28: #include "crypto.h"
29: #include "fileio.h"
30: #include "keymgmt.h"
1.1.1.3 root 31: #include "keymaint.h"
1.1.1.2 root 32: #include "mpiio.h"
1.1.1.3 root 33: #include "charset.h"
1.1.1.2 root 34: #include "language.h"
35: #include "pgp.h"
36:
1.1.1.3 root 37: #if 1 /* def DEBUG */
38: #include <assert.h>
39: #else
40: #define assert(x)
41: #endif
42:
43: struct userid;
44: struct signature;
45:
46: struct pubkey {
47: struct pubkey *pk_next;
48: struct pubkey *pk_hash; /* hash list for keyID */
49: struct userid *pk_userids;
50: struct signature *pk_signed; /* signatures this key made */
51: byte pk_keyid[KEYFRAGSIZE];
52: byte pk_owntrust;
53: byte pk_depth; /* shortest cert. path to buckstop key */
54: };
55:
56: struct userid {
57: struct userid *uid_next;
58: struct pubkey *uid_key; /* backlink to key */
59: struct signature *uid_signatures;
60: char *uid_userid;
61: byte uid_legit;
62: };
63:
64: struct signature {
65: struct signature *sig_next; /* list of signatures on a userid */
66: struct userid *sig_uid; /* the userid it signs */
67: struct pubkey *sig_from; /* key that made this signature */
68: struct signature *sig_nextfrom; /* list of sigs made by the same key (sig_from) */
69: byte sig_trust;
70: };
1.1.1.2 root 71:
1.1.1.3 root 72:
73: int maint_list(char *ringfile);
74: void init_trust_lst(void);
1.1.1.2 root 75: long lookup_by_keyID(FILE *f, byte *srch_keyID);
76: void show_userid(FILE *f, byte *keyID);
1.1.1.3 root 77:
78: static int maintenance(char *ringfile);
79: static int maint_read_data(char *ringfile);
80: static int maint_trace_chain(void);
81: static int trace_sig_chain(struct pubkey *pk, int depth);
82: static int maint_final(char *ringfile);
83: static struct pubkey * getpubkey(byte *keyID);
84: static void setup_trust(void);
85: static int check_secretkey(FILE *f, long keypos);
86: static void maint_init_mem(void);
87: static void maint_release_mem(void);
88: static VOID * allocn(int size);
89: static char * store_str(char *str);
90: static VOID * allocbuf(int size);
91: static void freebufpool(void);
1.1.1.4 ! root 92: static void compute_legit(struct userid *id);
1.1.1.3 root 93:
94:
95: #define ALLOC_UNIT 4000 /* memory will be allocated in chunks of this size */
96:
97: #define MAX_DEPTH 8 /* max. value of max_cert_depth */
1.1.1.2 root 98:
99: /* returned when trying to do a maintenance pass on a secret keyring or keyfile */
100: #define ERR_NOTRUST -7
101:
102: #define TRUST_MASK 7 /* mask for userid/signature trust bytes */
103: #define SET_TRUST(b,v) (*(b) = (*(b) & ~TRUST_MASK) | (v))
104: #define TRUST_LEV(b) ((b) & TRUST_MASK)
105:
106: #define TRUST_FAC(x) (trust_tbl[TRUST_LEV(x)])
107:
1.1.1.3 root 108: #define ctb_type(c) ((c&CTB_TYPE_MASK)>>2)
1.1.1.2 root 109: /*
110: * table for tuning user paranoia index.
111: * values represent contribution of one signature indexed by the
112: * SIGTRUST of a signature
113: */
1.1.1.3 root 114: static int trust_tbl[8];
1.1.1.2 root 115:
116: static int marginal_min;
117: static int complete_min; /* total count needed for a fully legit key */
118:
119: int marg_min = 2; /* number of marginally trusted signatures needed for
120: a fully legit key (can be set in config.pgp). */
121: int compl_min = 1; /* number of fully trusted signatures needed */
122:
123: char trust_lst[8][16] = {
124: "undefined", /* PSTR("undefined") */
125: "unknown", /* PSTR("unknown") */
126: "untrusted", /* PSTR("untrusted") */
127: "<3>", /* unused */
128: "<4>", /* unused */
129: "marginal", /* PSTR("marginal") */
130: "complete", /* PSTR("complete") */
131: "ultimate", /* PSTR("ultimate") */
132: };
133:
134: char legit_lst[4][16] = {
135: "undefined",
136: "untrusted",
137: "marginal",
138: "complete"
139: };
140:
1.1.1.3 root 141: static int trustlst_len = 9; /* length of longest trust word */
142: static int legitlst_len = 9; /* length of longest legit word */
1.1.1.2 root 143:
144: char floppyring[MAX_PATH] = "";
145: int max_cert_depth = 4; /* maximum nesting of signatures */
146:
147: static boolean check_only = FALSE;
148: static boolean mverbose;
149: static FILE *sec_fp;
150: static FILE *floppy_fp = NULL;
1.1.1.4 ! root 151: static int undefined_trust; /* number of complete keys with undef. trust */
1.1.1.3 root 152:
153: /*
154: * Update trust parameters in a keyring, should be called after all
155: * key management functions which can affect the trust parameters.
156: * Changes are done "inplace", the file must be writable.
157: */
158: int
159: maint_update(char *ringfile)
160: {
161: check_only = mverbose = FALSE;
162: return maintenance(ringfile);
163: }
1.1.1.2 root 164:
165: /*
1.1.1.3 root 166: * Check trust parameters in ringfile
1.1.1.2 root 167: * options can be:
1.1.1.3 root 168: * MAINT_CHECK check only, don't ask if keyring should be updated
1.1.1.2 root 169: * MAINT_VERBOSE verbose output, shows signature chains
170: */
171: int
1.1.1.3 root 172: maint_check(char *ringfile, int options)
1.1.1.2 root 173: {
174: int status;
1.1.1.3 root 175: char *fixfile;
1.1.1.2 root 176:
1.1.1.3 root 177: mverbose = ((options & MAINT_VERBOSE) != 0);
1.1.1.4 ! root 178:
1.1.1.3 root 179: if (moreflag)
180: open_more();
181: if (*floppyring != '\0' && (floppy_fp = fopen(floppyring, FOPRBIN)) == NULL)
182: fprintf(pgpout,PSTR("\nCan't open backup key ring file '%s'\n"),
183: floppyring);
184: check_only = TRUE;
185: status = maintenance(ringfile);
186: if (floppy_fp) {
187: fclose(floppy_fp);
188: floppy_fp = NULL;
189: }
190: if (status <= 0) {
191: if (status == 0)
192: maint_list(ringfile);
193: close_more();
194: return status;
195: }
196: #ifdef xDEBUG
197: if (status > 0 && (options & MAINT_CHECK)) {
198: FILE *sav = pgpout;
199: if (pgpout = fopen("before.lst", "w")) {
200: maint_list(ringfile);
201: fclose(pgpout);
202: }
203: pgpout = sav;
204: }
205: #endif
1.1.1.4 ! root 206: /* Inform user of trust parameters to be changed... */
! 207: if (undefined_trust) {
! 208:
! 209: /* If we are just going to check, then exit now... */
! 210: if (options & MAINT_CHECK){
! 211: maint_list(ringfile);
! 212: }
! 213:
! 214: fprintf(pgpout, PSTR("\n%d \"trust parameter(s)\" need to be changed.\n"),
! 215: undefined_trust);
! 216:
! 217: if (options & MAINT_CHECK) {
! 218: close_more();
! 219: return status;
! 220: }
! 221:
! 222: fprintf(pgpout, PSTR("Continue with '%s' (Y/n)? "),
! 223: ringfile);
! 224: if (!getyesno('y')) {
! 225: close_more();
! 226: return status;
! 227: }
! 228: }
! 229:
1.1.1.3 root 230: /* do the fixes in a scratch file */
231: fixfile = tempfile(0);
232: if (copyfiles_by_name(ringfile, fixfile) < 0) {
233: close_more();
234: return -1;
235: }
236: check_only = mverbose = FALSE;
237: if ((status = maintenance(fixfile)) >= 0) {
238: maint_list(fixfile);
239: fprintf(pgpout, PSTR("\n%d \"trust parameter(s)\" changed.\n"), status);
240: }
241: close_more();
242: if (status > 0 && !(options & MAINT_CHECK)) {
243: fprintf(pgpout, PSTR("Update public keyring '%s' (Y/n)? "), ringfile);
244: if (getyesno('y'))
245: return savetempbak(fixfile, ringfile);
246: }
247: rmtemp(fixfile);
248: return status;
249: }
1.1.1.2 root 250:
251:
1.1.1.3 root 252: static int
253: maintenance(char *ringfile)
254: {
255: int status;
256: char secretkeyring[MAX_PATH];
1.1.1.4 ! root 257: undefined_trust = 0; /* None so far... */
1.1.1.3 root 258:
259: if (max_cert_depth > MAX_DEPTH)
260: max_cert_depth = MAX_DEPTH;
1.1.1.2 root 261: buildfilename(secretkeyring, SECRET_KEYRING_FILENAME);
262: if ((sec_fp = fopen(secretkeyring, FOPRBIN)) == NULL)
263: fprintf(pgpout,PSTR("\nCan't open secret key ring file '%s'\n"),
264: secretkeyring);
265:
1.1.1.3 root 266: setkrent(ringfile);
1.1.1.2 root 267: setup_trust();
1.1.1.3 root 268: maint_init_mem();
269: if (mverbose || verbose)
1.1.1.2 root 270: fprintf(pgpout, PSTR("\nPass 1: Looking for the \"ultimately-trusted\" keys...\n"));
1.1.1.3 root 271: status = maint_read_data(ringfile);
272: if (sec_fp) {
273: fclose(sec_fp);
274: sec_fp = NULL;
275: }
276: if (status < 0)
1.1.1.2 root 277: goto failed;
278:
1.1.1.3 root 279: if (mverbose || verbose)
1.1.1.2 root 280: fprintf(pgpout, PSTR("\nPass 2: Tracing signature chains...\n"));
1.1.1.3 root 281: if ((status = maint_trace_chain()) < 0)
1.1.1.2 root 282: goto failed;
283:
1.1.1.3 root 284: if (verbose)
285: fprintf(pgpout, "\nPass 3: %s keyring...\n",
286: (check_only ? "Checking with" : "Updating"));
287: if ((status = maint_final(ringfile)) < 0)
1.1.1.2 root 288: goto failed;
289:
1.1.1.3 root 290: endkrent();
291: maint_release_mem();
1.1.1.4 ! root 292: return(status+undefined_trust);
1.1.1.2 root 293:
294: failed:
1.1.1.3 root 295: if (verbose)
296: fprintf(pgpout, "maintenance pass: error exit = %d\n", status);
297: endkrent();
298: maint_release_mem();
1.1.1.2 root 299: return(status);
300: } /* maintenance */
301:
302:
1.1.1.3 root 303: static struct pubkey *pklist, **pkhash = NULL;
304:
305: #define PK_HASHSIZE 256 /* must be power of 2 */
306: #define PK_HASH(x) (*(byte *) (x) & (PK_HASHSIZE - 1))
307:
1.1.1.2 root 308: /*
1.1.1.3 root 309: * get the pubkey struct for keyID from hash table, allocate a new
310: * node and insert in hash table if necessary.
1.1.1.2 root 311: */
1.1.1.3 root 312: static struct pubkey *
313: getpubkey(byte *keyID)
314: {
315: struct pubkey *pk;
316: for (pk = pkhash[PK_HASH(keyID)]; pk; pk = pk->pk_hash)
317: if (memcmp(pk->pk_keyid, keyID, KEYFRAGSIZE) == 0)
318: return pk;
319: pk = allocn(sizeof(struct pubkey));
320: memset(pk, 0, sizeof(struct pubkey));
321: memcpy(pk->pk_keyid, keyID, KEYFRAGSIZE);
322: pk->pk_hash = pkhash[PK_HASH(keyID)];
323: pkhash[PK_HASH(keyID)] = pk;
324: return pk;
325: }
326:
327: /*
328: * Read in keyring, a graph of keys, userids and signatures is built.
329: * Also check if axiomatic keys are present in the secret keyring and
330: * compare them with the floppy ring if this is requested.
331: */
332: static int
333: maint_read_data(char *ringfile)
1.1.1.2 root 334: {
1.1.1.3 root 335: FILE *f;
1.1.1.2 root 336: int status;
337: char userid[256];
338: byte keyID[KEYFRAGSIZE];
1.1.1.3 root 339: byte sigkeyID[KEYFRAGSIZE];
1.1.1.2 root 340: byte ctb;
341: byte keyctrl;
342: boolean buckstop = FALSE, show_user = FALSE;
343: int buckstopcount = 0;
344: long keypos = 0;
1.1.1.3 root 345: int skip = 0;
346: struct pubkey *pk = NULL;
347: struct userid *id = NULL;
348: struct signature *sig = NULL;
1.1.1.2 root 349:
1.1.1.3 root 350: if ((f = fopen(ringfile,FOPRBIN)) == NULL)
351: { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
352: return(-1);
353: }
354:
355: while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) != -1) {
356: if (status == -3 || status == -2) {
357: fclose(f);
1.1.1.2 root 358: return(status);
1.1.1.3 root 359: }
360: if (status < 0 || is_ctb_type(ctb, CTB_CERT_SECKEY_TYPE)) {
361: skip = 1; /* version error or bad key */
1.1.1.2 root 362: continue;
1.1.1.3 root 363: }
364: if (skip) {
365: if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
366: skip = 0;
367: else
368: continue;
369: }
1.1.1.2 root 370:
371: if (is_ctb_type(ctb, CTB_COMMENT_TYPE) || ctb == CTB_KEYCTRL)
372: continue;
1.1.1.3 root 373:
374: if (pk && is_ctb_type(ctb, CTB_SKE_TYPE) && !pk->pk_userids) {
375: /* sig. cert before userids can only be compromise cert. */
376: pk->pk_owntrust = KC_OWNERTRUST_NEVER;
377: continue;
378: }
1.1.1.2 root 379:
380: /* other packets should have trust byte */
1.1.1.3 root 381: if (read_trust(f, &keyctrl) < 0) {
382: fclose(f);
1.1.1.2 root 383: return(ERR_NOTRUST); /* not a public keyring */
1.1.1.3 root 384: }
1.1.1.2 root 385:
1.1.1.3 root 386: switch (ctb_type(ctb)) {
387: case CTB_CERT_PUBKEY_TYPE:
388: if (pk)
389: pk = pk->pk_next = getpubkey(keyID);
390: else
391: pk = pklist = getpubkey(keyID);
392:
393: if (pk->pk_next) {
394: fprintf(pgpout, PSTR("Keyring contains duplicate key: %s\n"), keyIDstring(keyID));
395: fclose(f);
396: return -1;
397: }
398:
399: if ((keyctrl & KC_BUCKSTOP)) {
400: if (check_secretkey(f, keypos) == 0) {
1.1.1.2 root 401: ++buckstopcount;
402: buckstop = TRUE;
403: if (mverbose)
404: fprintf(pgpout, "* %s",keyIDstring(keyID));
1.1.1.3 root 405: } else { /* not in secret keyring */
1.1.1.2 root 406: keyctrl &= ~KC_BUCKSTOP;
407: if (TRUST_LEV(keyctrl) == KC_OWNERTRUST_ULTIMATE)
408: keyctrl = KC_OWNERTRUST_ALWAYS;
409: if (mverbose)
410: fprintf(pgpout, ". %s",keyIDstring(keyID));
411: }
412: show_user = mverbose;
1.1.1.3 root 413: } else {
1.1.1.2 root 414: buckstop = FALSE;
415: show_user = FALSE;
416: }
417: keyctrl &= ~KC_VISITED;
1.1.1.3 root 418: pk->pk_owntrust = keyctrl;
419: pk->pk_userids = id = NULL;
420: break;
421: case CTB_USERID_TYPE:
422: if (!pk)
423: break;
424: if (show_user) {
425: if (pk->pk_userids) /* more than one user ID */
1.1.1.2 root 426: fprintf(pgpout, " ");
427: fprintf(pgpout, " %s\n", LOCAL_CHARSET(userid));
428: }
1.1.1.3 root 429: if (id)
430: id = id->uid_next = allocn(sizeof(struct userid));
431: else
432: id = pk->pk_userids = allocn(sizeof(struct userid));
433:
434: if (mverbose)
435: id->uid_userid = store_str(userid);
1.1.1.2 root 436: keyctrl &= ~KC_LEGIT_MASK;
437: if (buckstop)
438: keyctrl |= KC_LEGIT_COMPLETE;
439: else
440: keyctrl |= KC_LEGIT_UNKNOWN;
1.1.1.3 root 441: id->uid_next = NULL;
442: id->uid_key = pk;
443: id->uid_legit = keyctrl;
444: id->uid_signatures = sig = NULL;
445: break;
446: case CTB_SKE_TYPE:
447: if (!pk || !id)
448: break;
449: if (sig)
450: sig = sig->sig_next = allocn(sizeof(struct signature));
451: else
452: sig = id->uid_signatures = allocn(sizeof(struct signature));
453: sig->sig_next = NULL;
454: sig->sig_uid = id;
455: sig->sig_from = getpubkey(sigkeyID);
456: sig->sig_nextfrom = sig->sig_from->pk_signed;
457: sig->sig_from->pk_signed = sig;
458: sig->sig_trust = keyctrl&KC_SIG_CHECKED;
459: break;
460: } /* switch ctb_type */
1.1.1.2 root 461: keypos = ftell(f);
462: }
463: if (buckstopcount == 0 && mverbose)
464: fprintf(pgpout, PSTR("No ultimately-trusted keys.\n"));
1.1.1.3 root 465: fclose(f);
1.1.1.2 root 466: return(0);
467: }
468:
469:
470: /*
471: * scan keyring for buckstop keys and start the recursive trace_sig_chain()
472: * on them
473: */
1.1.1.3 root 474: static int
475: maint_trace_chain(void)
1.1.1.2 root 476: {
1.1.1.3 root 477: char *userid;
478: struct pubkey *pk;
1.1.1.2 root 479:
1.1.1.3 root 480: for (pk = pklist; pk; pk = pk->pk_next) {
481: if (!(pk->pk_owntrust&KC_BUCKSTOP))
1.1.1.2 root 482: continue;
1.1.1.3 root 483: if (mverbose)
484: fprintf(pgpout, "* %s\n", LOCAL_CHARSET(pk->pk_userids->uid_userid));
485: if (TRUST_LEV(pk->pk_owntrust) == KC_OWNERTRUST_UNDEFINED) {
486: userid = user_from_keyID(pk->pk_keyid);
487: SET_TRUST(&pk->pk_owntrust, ask_owntrust(userid, pk->pk_owntrust));
1.1.1.2 root 488: }
1.1.1.3 root 489: trace_sig_chain(pk, 0);
490: }
491: return 0;
492: }
1.1.1.2 root 493:
1.1.1.3 root 494:
495: /*
496: * Find all signatures made with the key pk.
497: * If a trusted signature makes a key fully legit then signatures made
498: * with this key are also recursively traced on down the tree.
499: *
500: * depth is the level of recursion, it is used to indent the userIDs
501: * and to check if we don't exceed the limit "max_cert_depth"
502: *
503: * NOTE: a signature made with a key with pk_depth == max_cert_depth will
504: * not be counted here to limit the maximum chain length, but will be
505: * counted when the validity of a key is computed in maint_final()
506: */
507: static int
508: trace_sig_chain(struct pubkey *pk, int depth)
509: {
510: int d, trust_count = 0;
511: int counts[MAX_DEPTH];
512: struct signature *sig, *s;
513: struct pubkey *p;
1.1.1.4 ! root 514: struct userid *id;
1.1.1.3 root 515:
516: assert(depth <= max_cert_depth);
517: if (pk->pk_depth && pk->pk_depth <= depth)
518: return 0;
519: pk->pk_depth = depth;
520:
1.1.1.4 ! root 521: /* Should we ask for trust. If this key is legit, then go for
! 522: * it! Ask the user....
! 523: */
! 524: if (TRUST_LEV(pk->pk_owntrust) == KC_OWNERTRUST_UNDEFINED)
! 525: for (id = pk->pk_userids; id; id = id->uid_next) {
! 526: compute_legit(id);
! 527: if ((id->uid_legit & KC_LEGIT_MASK) ==
! 528: KC_LEGIT_COMPLETE) {
! 529: SET_TRUST(&pk->pk_owntrust,
! 530: ask_owntrust(user_from_keyID(pk->pk_keyid),
! 531: pk->pk_owntrust));
! 532: break;
! 533: }
! 534: }
! 535:
! 536: /* Return if I haven't signed anyone's keys, since I
! 537: * don't need to check any further.. -warlord 93-04-11
! 538: */
! 539: if (!pk->pk_signed)
! 540: return 0;
! 541:
1.1.1.3 root 542: #ifdef DEBUG
543: if (mverbose)
544: fprintf(pgpout, "%*s%d-v %s\n", 2*depth, "", depth, pk->pk_userids->uid_userid);
545: #endif
546:
547: /* all keys signed by pk */
548: for (sig = pk->pk_signed; sig; sig = sig->sig_nextfrom) {
549: if (mverbose)
550: fprintf(pgpout, "%*s > %s\n", 2*depth, "", LOCAL_CHARSET(sig->sig_uid->uid_userid));
551:
552: /* copy trust from signator */
553: SET_TRUST(&sig->sig_trust, TRUST_LEV(pk->pk_owntrust));
554: sig->sig_trust |= KC_CONTIG; /* CONTIG bit currently unused */
555:
556: p = sig->sig_uid->uid_key; /* this key signed by pk */
557: if (p->pk_owntrust & KC_BUCKSTOP)
558: continue; /* will be handled from main loop */
559: if (p->pk_depth && p->pk_depth <= depth+1)
560: continue; /* already handled this key at a lower level */
561:
562: for (d = 0; d < max_cert_depth; ++d)
563: counts[d] = 0;
564: for (s = sig->sig_uid->uid_signatures; s; s = s->sig_next) {
565: d = s->sig_from->pk_depth;
566: if (d < max_cert_depth)
567: counts[d] += TRUST_FAC(s->sig_trust);
568: }
569: /*
570: * find a combination of signatures that will make the key
571: * valid through the shortest cert. path.
572: */
573: trust_count = 0;
574: for (d = 0; d < max_cert_depth; ++d) {
575: trust_count += counts[d];
576: if (trust_count >= complete_min) {
577: trace_sig_chain(p, d+1);
578: break;
1.1.1.2 root 579: }
580: }
581: }
1.1.1.3 root 582:
583: #ifdef DEBUG
584: if (mverbose)
585: fprintf(pgpout, "%*s%d-^ %s\n", 2*depth, "", depth, pk->pk_userids->uid_userid);
586: #endif
587: return 0;
1.1.1.2 root 588: }
589:
1.1.1.3 root 590: /*
591: * compute validity of userid/key pair, the number of signatures and the
592: * trust level of these signatures determines the validity.
593: */
1.1.1.4 ! root 594: static void
1.1.1.3 root 595: compute_legit(struct userid *id)
596: {
597: struct signature *s;
598: int trust_count, legit;
599:
600: if (id->uid_key->pk_owntrust & KC_BUCKSTOP)
601: legit = KC_LEGIT_COMPLETE;
602: else {
603: trust_count = 0;
604: for (s = id->uid_signatures; s; s = s->sig_next)
605: trust_count += TRUST_FAC(s->sig_trust);
606:
607: if (trust_count == 0)
608: legit = KC_LEGIT_UNKNOWN;
609: else if (trust_count < marginal_min)
610: legit = KC_LEGIT_UNTRUSTED;
611: else if (trust_count < complete_min)
612: legit = KC_LEGIT_MARGINAL;
613: else
614: legit = KC_LEGIT_COMPLETE;
615: }
616: id->uid_legit = (id->uid_legit & ~KC_LEGIT_MASK) | legit;
617: }
1.1.1.2 root 618:
619: /*
620: * check if the maintenance pass changed anything
621: * returns 0 if files f and g are equal and the number of changed
622: * trust bytes if the files are different or a negative value on error
623: */
1.1.1.3 root 624: static int
625: maint_final(char *ringfile)
1.1.1.2 root 626: {
627: int status;
1.1.1.3 root 628: FILE *f;
629: long trust_pos = 0;
1.1.1.2 root 630: char userid[256];
631: byte keyID[KEYFRAGSIZE];
632: byte sigkeyID[KEYFRAGSIZE];
633: byte ctb;
1.1.1.3 root 634: byte kc_orig, kc_new = 0, mask;
1.1.1.2 root 635: int changed = 0;
1.1.1.3 root 636: int skip = 0;
637: struct pubkey *pk;
638: struct userid *id = NULL;
639: struct signature *sig = NULL;
1.1.1.2 root 640:
1.1.1.3 root 641: if (check_only)
642: f = fopen(ringfile,FOPRBIN);
643: else
644: f = fopen(ringfile,FOPRWBIN);
645: if (f == NULL)
646: { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
647: return(-1);
648: }
649:
650: pk = pklist;
651: while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) != -1) {
652: if (status == -3 || status == -2)
1.1.1.2 root 653: break;
1.1.1.3 root 654: if (status < 0 || is_ctb_type(ctb, CTB_CERT_SECKEY_TYPE)) {
655: skip = 1;
1.1.1.2 root 656: continue;
1.1.1.3 root 657: }
658: if (skip) {
659: if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
660: skip = 0;
661: else
662: continue;
663: }
664: if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE) ||
665: is_ctb_type(ctb, CTB_SKE_TYPE) || ctb == CTB_USERID) {
666: trust_pos = ftell(f);
667: if (read_trust(f, &kc_orig) < 0) {
668: status = ERR_NOTRUST;
669: if (is_ctb_type(ctb, CTB_SKE_TYPE))
670: continue; /* skip compr. cert. */
671: else
672: break;
673: }
674: }
675: switch (ctb_type(ctb)) {
676: case CTB_CERT_PUBKEY_TYPE:
677: assert(pk && !memcmp(pk->pk_keyid, keyID, KEYFRAGSIZE));
678: assert(!sig && !id);
679: id = pk->pk_userids;
680: kc_new = pk->pk_owntrust;
681: #ifdef DEBUG
682: if (mverbose)
683: fprintf(pgpout, " ------ %d\n", pk->pk_depth);
684: #endif
685: pk = pk->pk_next;
686: mask = KC_OWNERTRUST_MASK|KC_BUCKSTOP;
687: break;
688: case CTB_USERID_TYPE:
689: assert(id && !sig);
690: sig = id->uid_signatures;
691: compute_legit(id);
692: kc_new = id->uid_legit;
693: #ifdef DEBUG
694: if (mverbose)
695: fprintf(pgpout, "%c %02x %02x %s\n", ' ' + (kc_new != kc_orig),
696: kc_orig, kc_new, id->uid_userid);
697: #endif
698: id = id->uid_next;
699: mask = KC_LEGIT_MASK;
700: break;
701: case CTB_SKE_TYPE:
702: assert(sig);
703: assert(!memcmp(sig->sig_from->pk_keyid, sigkeyID, KEYFRAGSIZE));
704: kc_new = sig->sig_trust;
705: #ifdef DEBUG
706: if (mverbose && sig->sig_from->pk_userids)
707: fprintf(pgpout, "%c %02x %02x %s\n", ' ' + (kc_new != kc_orig),
708: kc_orig, kc_new, sig->sig_from->pk_userids->uid_userid);
709: #endif
710: sig = sig->sig_next;
711: mask = KC_SIGTRUST_MASK|KC_CONTIG;
712: break;
713: default:
714: mask = 0;
715: }
716: if ((kc_new&mask) != (kc_orig&mask)) {
717: if (!check_only)
718: write_trust_pos(f, kc_new, trust_pos);
719: ++changed;
720: }
721: }
722: fclose(f);
723: if (status < -1) /* -1 is OK, EOF */
724: return(status);
725: if (pk || sig || id) {
726: fprintf(pgpout, "maint_final: internal error\n");
727: return -1;
728: }
729: return(changed);
730: } /* maint_final */
1.1.1.2 root 731:
1.1.1.3 root 732:
733: int
734: maint_list(char *ringfile)
735: {
736: int status;
737: FILE *f;
738: char userid[256];
739: byte keyID[KEYFRAGSIZE];
740: byte sigkeyID[KEYFRAGSIZE];
741: char *signator;
742: char tchar = 0;
743: byte ctb, kc;
744: int owntrust = 0;
745: int usercount = 0;
746:
747: if ((f = fopen(ringfile,FOPRBIN)) == NULL)
748: { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
749: return(-1);
750: }
751: init_trust_lst();
752: setkrent(ringfile);
753: init_userhash();
754:
755: fprintf(pgpout, PSTR(" KeyID Trust Validity User ID\n"));
756: while ((status = readkpacket(f, &ctb, userid, keyID, sigkeyID)) != -1) {
757: if (status == -3 || status == -2)
1.1.1.2 root 758: break;
1.1.1.3 root 759: if (status < 0)
760: continue;
1.1.1.2 root 761:
1.1.1.3 root 762: if (is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE) ||
763: is_ctb_type(ctb, CTB_SKE_TYPE) || ctb == CTB_USERID) {
764: if (read_trust(f, &kc) < 0) {
765: status = ERR_NOTRUST;
766: /* compromise cert. don't have trust byte */
767: if (!is_ctb_type(ctb, CTB_SKE_TYPE))
768: break;
1.1.1.2 root 769: }
1.1.1.3 root 770: }
1.1.1.2 root 771:
1.1.1.3 root 772: switch (ctb_type(ctb)) {
773: case CTB_CERT_PUBKEY_TYPE:
774: tchar = (kc & KC_BUCKSTOP ? '*' : ' ');
775: owntrust = TRUST_LEV(kc);
1.1.1.2 root 776: usercount = 0;
777: userid[0] = '\0';
1.1.1.3 root 778: break;
779: case CTB_USERID_TYPE:
1.1.1.4 ! root 780: if (!usercount) { /* first userid */
1.1.1.3 root 781: fprintf(pgpout, "%c %s ", tchar, keyIDstring(keyID));
782: fprintf(pgpout, " %-*s", trustlst_len, trust_lst[owntrust]);
783: } else
1.1.1.2 root 784: fprintf(pgpout, " %*s ", trustlst_len, "");
1.1.1.3 root 785: fprintf(pgpout, " %-*s", legitlst_len, legit_lst[kc&KC_LEGIT_MASK]);
786: if (usercount)
787: putc(' ', pgpout);
1.1.1.2 root 788: ++usercount;
789: fprintf(pgpout, "%s\n", LOCAL_CHARSET(userid));
1.1.1.3 root 790: break;
791: case CTB_SKE_TYPE:
792: if (!usercount) { /* sig before userid: compromise cert. */
793: tchar = '#';
794: break;
795: }
796: fprintf(pgpout, "%c ", (kc & KC_CONTIG) ? 'c' : ' ');
797: fprintf(pgpout, " %-*s", trustlst_len, trust_lst[TRUST_LEV(kc)]);
1.1.1.2 root 798: fprintf(pgpout, "%*s ", legitlst_len, "");
1.1.1.3 root 799: if ((signator = user_from_keyID(sigkeyID)) == NULL)
800: fprintf(pgpout, "(KeyID: %s)\n",keyIDstring(sigkeyID));
801: else
802: fprintf(pgpout, "%s\n", LOCAL_CHARSET(signator));
803: break;
1.1.1.2 root 804: }
805: }
1.1.1.3 root 806: endkrent();
807: fclose(f);
1.1.1.2 root 808: if (status < -1) /* -1 is OK, EOF */
809: return(status);
1.1.1.3 root 810: return(0);
811: } /* maint_list */
1.1.1.2 root 812:
813:
814: /*
815: * translate the messages in the arrays trust_lst and legit_lst.
816: * trustlst_len and legitlst_len will be set to the length of
817: * the longest translated string.
818: */
819: void
1.1.1.3 root 820: init_trust_lst(void)
1.1.1.2 root 821: {
822: static int initialized = 0;
823: int i, len;
824: char *s;
825:
826: if (initialized)
827: return;
828: for (i = 0; i < 8; ++i)
1.1.1.3 root 829: { if (trust_lst[i][0])
830: { s = PSTR (trust_lst[i]);
831: if (s != trust_lst[i])
832: strncpy(trust_lst[i], s, sizeof(trust_lst[0]) - 1);
833: len = strlen(s);
834: if (len > trustlst_len)
835: trustlst_len = len;
1.1.1.2 root 836: }
837: }
1.1.1.3 root 838: for (i = 0; i < 4; ++i)
839: { s = PSTR (legit_lst[i]);
840: if (s != legit_lst[i])
841: strncpy(legit_lst[i], s, sizeof(legit_lst[0]) - 1);
842: len = strlen(s);
843: if (len > legitlst_len)
844: legitlst_len = len;
845: }
846: ++trustlst_len;
847: ++legitlst_len;
848: initialized = 1;
849: } /* init_trust_lst */
850:
1.1.1.2 root 851:
852:
853: /*
854: * compare the key in file f at keypos with the matching key in the
855: * secret keyring, the global variable sec_fp must contain the file pointer
856: * for of the secret keyring.
857: *
858: * returns 1 if the key was not found, -2 if the keys were different
859: * and 0 if the keys compared OK
860: */
1.1.1.3 root 861: static int
1.1.1.2 root 862: check_secretkey(FILE *f, long keypos)
863: {
864: int status = -1;
865: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
866: unit nsec[MAX_UNIT_PRECISION], esec[MAX_UNIT_PRECISION];
867: char userid[256];
868: byte keyID[KEYFRAGSIZE];
869: long savepos, pktlen;
870: byte ctb;
871:
872: if (sec_fp == NULL)
873: return(-1);
874:
875: savepos = ftell(f);
876: fseek(f, keypos, SEEK_SET);
877: if (readkeypacket(f, FALSE, &ctb, NULL, NULL, n, e,
878: NULL, NULL, NULL, NULL, NULL, NULL) < 0)
879: goto ex;
880: extract_keyID(keyID, n);
881:
882: do /* get userid */
883: { status = readkpacket(f, &ctb, userid, NULL, NULL);
884: if (status == -1 || status == -3)
885: goto ex;
886: } while (ctb != CTB_USERID);
887:
888: if (lookup_by_keyID(sec_fp, keyID) < 0)
889: {
890: #if 0
891: if (!check_only)
892: {
893: fprintf(pgpout, PSTR (
894: "\nAn \"axiomatic\" key is one which does not need certifying by\n\
895: anyone else. Usually this special status is reserved only for your\n\
896: own keys, which should also appear on your secret keyring. The owner\n\
897: of an axiomatic key (who is typically yourself) is \"ultimately trusted\"\n\
898: by you to certify any or all other keys.\n"));
899: fprintf(pgpout, PSTR ("\nKey for user ID: \"%s\"\n\
900: is designated as an \"ultimately-trusted\" introducer, but the key\n\
901: does not appear in the secret keyring.\n\
902: Use this key as an ultimately-trusted introducer (y/N)? "),
903: LOCAL_CHARSET(userid));
904: status = (getyesno('n') ? 0 : 1);
905: }
906: #else
907: status = 1;
908: #endif
909: }
910: else
911: {
912: long kpos = ftell(sec_fp);
913: if (readkeypacket(sec_fp, FALSE, &ctb, NULL, NULL, nsec, esec,
914: NULL, NULL, NULL, NULL, NULL, NULL) < 0)
915: {
916: fprintf(pgpout, PSTR("\n\007Cannot read from secret keyring.\n"));
917: status = -3;
918: goto ex;
919: }
920: if (mp_compare(n, nsec) || mp_compare(e, esec))
921: { /* Red Alert! */
922: fprintf(pgpout, PSTR("\n\007WARNING: Public key for user ID: \"%s\"\n\
923: does not match the corresponding key in the secret keyring.\n"),
924: LOCAL_CHARSET(userid));
925: fprintf(pgpout, PSTR("This is a serious condition, indicating possible keyring tampering.\n"));
926: status = -2;
927: }
928: else
929: status = 0;
930:
931: if (floppy_fp)
932: {
933: if (lookup_by_keyID(floppy_fp, keyID) < 0)
934: {
935: fprintf(pgpout, PSTR("Public key for: \"%s\"\n\
936: is not present in the backup keyring '%s'.\n"),
937: LOCAL_CHARSET(userid), floppyring);
938: }
939: else
940: {
941: pktlen = ftell(sec_fp) - kpos;
942: fseek(sec_fp, kpos, SEEK_SET);
943: while (--pktlen >= 0 && getc(sec_fp) == getc(floppy_fp)) ;
944: if (pktlen != -1)
945: {
946: fprintf(pgpout, PSTR("\n\007WARNING: Secret key for: \"%s\"\n\
947: does not match the key in the backup keyring '%s'.\n"),
948: LOCAL_CHARSET(userid), floppyring);
949: fprintf(pgpout, PSTR("This is a serious condition, indicating possible keyring tampering.\n"));
950: status = -2;
951: }
952: }
953: }
954: }
955: ex:
956: fseek(f, savepos, SEEK_SET);
957: return(status);
958: } /* check_secretkey */
959:
960:
961: /*
962: * setup tables for trust scoring.
963: */
1.1.1.3 root 964: static void
965: setup_trust(void)
1.1.1.2 root 966: { /* initialize trust table */
967: if (marg_min == 0) /* marginally trusted signatures are ignored */
968: {
969: trust_tbl[5] = 0;
970: trust_tbl[6] = 1;
971: complete_min = compl_min;
972: }
973: else
974: {
975: if (marg_min < compl_min)
976: marg_min = compl_min;
977: trust_tbl[5] = compl_min;
978: trust_tbl[6] = marg_min;
979: complete_min = compl_min * marg_min;
980: }
981: trust_tbl[7] = complete_min; /* ultimate trust */
982: marginal_min = complete_min / 2;
983: } /* setup_trust */
984:
985:
986: int ask_owntrust(char *userid, byte cur_trust)
987: /* Ask for a wetware decision from the human on how much to trust
988: this key's owner to certify other keys. Returns trust value. */
989: {
990: char buf[8];
991:
1.1.1.3 root 992: if (check_only || filter_mode || batchmode)
993: { /* not interactive */
1.1.1.4 ! root 994: ++undefined_trust; /* We complete/undefined. Why? */
1.1.1.2 root 995: return(KC_OWNERTRUST_UNDEFINED);
996: }
997:
998: fprintf(pgpout,
999: PSTR("\nMake a determination in your own mind whether this key actually\n\
1000: belongs to the person whom you think it belongs to, based on available\n\
1001: evidence. If you think it does, then based on your estimate of\n\
1002: that person's integrity and competence in key management, answer\n\
1003: the following question:\n"));
1004: fprintf(pgpout, PSTR("\nWould you trust \"%s\"\n\
1005: to act as an introducer and certify other people's public keys to you?\n\
1006: (1=I don't know. 2=No. 3=Usually. 4=Yes, always.) ? "),
1007: LOCAL_CHARSET(userid));
1008: fflush(pgpout);
1009: getstring(buf, sizeof(buf)-1, TRUE);
1010: switch (buf[0])
1011: { case '1': return KC_OWNERTRUST_UNKNOWN;
1012: case '2': return KC_OWNERTRUST_NEVER;
1013: case '3': return KC_OWNERTRUST_USUALLY;
1014: case '4': return KC_OWNERTRUST_ALWAYS;
1015: default: return(TRUST_LEV(cur_trust));
1016: }
1017: } /* ask_owntrust */
1018:
1019:
1020: /*
1021: * scan keyfile f for keyID srch_keyID.
1022: * returns the file position of the key if it is found, and sets the
1023: * file pointer to the start of the key packet.
1024: * returns -1 if the key was not found or < -1 if there was an error
1025: */
1026: long
1027: lookup_by_keyID(FILE *f, byte *srch_keyID)
1028: {
1029: int status;
1030: long keypos = 0;
1031: byte keyID[KEYFRAGSIZE];
1032: byte ctb;
1033:
1034: rewind(f);
1035: while ((status = readkpacket(f, &ctb, NULL, keyID, NULL)) != -1)
1036: {
1.1.1.3 root 1037: if (status == -3 || status == -2)
1.1.1.2 root 1038: break;
1039: if (status < 0)
1040: continue;
1041: if (is_key_ctb(ctb) && memcmp(keyID, srch_keyID, KEYFRAGSIZE) == 0)
1042: {
1043: fseek(f, keypos, SEEK_SET);
1044: return(keypos);
1045: }
1046: keypos = ftell(f);
1047: }
1048: return(status);
1049: } /* lookup_by_keyID */
1050:
1051: /*
1052: * look up the key matching "keyID" and print the first userID
1053: * of this key. File position of f is saved.
1054: */
1055: void
1056: show_userid(FILE *f, byte *keyID)
1057: {
1058: int status;
1059: long filepos;
1060: char userid[256];
1061: byte ctb;
1062:
1063: filepos = ftell(f);
1064: if (lookup_by_keyID(f, keyID) >= 0)
1065: while ((status = readkpacket(f, &ctb, userid, NULL, NULL)) != -1 && status != -3)
1066: if (ctb == CTB_USERID)
1067: {
1068: fprintf(pgpout, "%s\n", LOCAL_CHARSET(userid));
1069: fseek(f, filepos, SEEK_SET);
1070: return;
1071: }
1072:
1073: fprintf(pgpout, "(KeyID: %s)\n",keyIDstring(keyID));
1074: fseek(f, filepos, SEEK_SET);
1075: } /* show_userid */
1076:
1.1.1.3 root 1077:
1078: /*
1079: * messages printed by show_key()
1080: */
1081: static char *owntrust_msg[] = {
1082: "", /* Just don't say anything in this case */
1083: "",
1084: _PSTR("This user is untrusted to certify other keys.\n"),
1085: "", /* reserved */
1086: "", /* reserved */
1087: _PSTR("This user is generally trusted to certify other keys.\n"),
1088: _PSTR("This user is completely trusted to certify other keys.\n"),
1089: _PSTR("This axiomatic key is ultimately trusted to certify other keys.\n"),
1090: };
1091: static char *keylegit_msg[] = {
1092: _PSTR("This key/userID association is not certified.\n"),
1093: _PSTR("This key/userID association is not certified.\n"),
1094: _PSTR("This key/userID association is marginally certified.\n"),
1095: _PSTR("This key/userID association is fully certified.\n"),
1096: };
1097: static char *sigtrust_msg[] = {
1098: _PSTR(" Questionable certification from:\n "),
1099: _PSTR(" Questionable certification from:\n "),
1100: _PSTR(" Untrusted certification from:\n "),
1101: "", /* reserved */
1102: "", /* reserved */
1103: _PSTR(" Generally trusted certification from:\n "),
1104: _PSTR(" Completely trusted certification from:\n "),
1105: _PSTR(" Axiomatically trusted certification from:\n "),
1106: };
1107:
1.1.1.2 root 1108: /*
1109: * show the key in file f at file position keypos.
1110: * 'what' controls the info that will be shown:
1111: * SHOW_TRUST: show trust byte info
1112: * SHOW_SIGS: show signatures
1.1.1.3 root 1113: * SHOW_HASH: show key fingerprint
1114: * these constants can be or'ed
1115: *
1116: * 'what' can also be SHOW_LISTFMT to get the same format as for pgp -kv
1117: * no signatures or extra userids will be printed in this case.
1.1.1.4 ! root 1118: *
! 1119: * 'what' can be SHOW_CHANGE, in which case it will take the keyID and
! 1120: * call show_update();
1.1.1.2 root 1121: */
1122: int
1123: show_key(FILE *f, long keypos, int what)
1124: {
1.1.1.3 root 1125: int status, keystatus = -1;
1.1.1.2 root 1126: long filepos;
1127: char userid[256];
1128: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
1129: byte sigkeyID[KEYFRAGSIZE];
1130: word32 timestamp;
1.1.1.3 root 1131: byte ctb, keyctb = 0, keyctrl;
1.1.1.2 root 1132: int userids = 0;
1133: boolean print_trust = FALSE;
1.1.1.3 root 1134: byte hash[16];
1.1.1.2 root 1135: int precision = global_precision;
1.1.1.3 root 1136: int compromised = 0;
1137: int disabled = 0;
1.1.1.2 root 1138:
1139: filepos = ftell(f);
1140: fseek(f, keypos, SEEK_SET);
1141: while ((status = readkeypacket(f, FALSE, &ctb, (byte *)×tamp, userid,
1.1.1.3 root 1142: n, e, NULL, NULL, NULL, NULL, sigkeyID, &keyctrl)) != -1)
1.1.1.2 root 1143: {
1.1.1.3 root 1144: if (status == -2 || status == -3)
1145: break;
1.1.1.2 root 1146: if (is_key_ctb(ctb))
1147: { if (userids)
1148: break;
1.1.1.3 root 1149: if (what & SHOW_HASH)
1150: getKeyHash(hash, n, e);
1151: keyctb = ctb;
1152: keystatus = status; /* remember status, could be version error */
1.1.1.2 root 1153: }
1154: else if (ctb == CTB_KEYCTRL) /* trust bytes only in public keyrings */
1155: {
1.1.1.3 root 1156: if (keystatus >= 0 && !userids) /* key packet trust byte */
1157: if (keyctrl & KC_DISABLED)
1158: disabled = 1;
1.1.1.2 root 1159: if (what & SHOW_TRUST)
1160: print_trust = TRUE;
1161: }
1162: else if (ctb == CTB_USERID)
1163: { if (userids == 0)
1164: { PascalToC(userid); /* for display */
1.1.1.3 root 1165: ++userids;
1.1.1.4 ! root 1166: if (what & SHOW_CHANGE) {
! 1167: show_update(key2IDstring(n));
! 1168: break;
! 1169: }
1.1.1.3 root 1170: if (what & SHOW_LISTFMT) {
1171: if (is_ctb_type(keyctb,CTB_CERT_PUBKEY_TYPE))
1172: fprintf(pgpout,"pub");
1173: else if (is_ctb_type(keyctb,CTB_CERT_SECKEY_TYPE))
1174: fprintf(pgpout,"sec");
1175: else
1176: fprintf(pgpout,"???");
1177: if (keystatus < 0)
1178: fprintf(pgpout,"? ");
1179: else if (compromised)
1180: fprintf(pgpout,"# ");
1181: else if (disabled)
1182: fprintf(pgpout,"- ");
1183: else
1184: fprintf(pgpout," ");
1185: fprintf(pgpout,"%4d/%s %s ",
1186: countbits(n),key2IDstring(n),cdate(×tamp));
1187: fprintf(pgpout,"%s\n",LOCAL_CHARSET(userid));
1188: break; /* only print default userid */
1189: }
1.1.1.2 root 1190: fprintf(pgpout,PSTR("\nKey for user ID: %s\n"),
1191: LOCAL_CHARSET(userid));
1192: fprintf(pgpout,PSTR("%d-bit key, Key ID %s, created %s\n"),
1193: countbits(n), key2IDstring(n), cdate(×tamp) );
1.1.1.3 root 1194: if (keystatus == -4)
1195: fprintf(pgpout,PSTR("Bad key format.\n"));
1196: else if (keystatus == -6)
1197: fprintf(pgpout,PSTR("Unrecognized version.\n"));
1198: else if (what & SHOW_HASH)
1199: printKeyHash(hash, FALSE);
1200: if (compromised)
1201: fprintf(pgpout, PSTR("Key has been revoked.\n"));
1202: if (disabled)
1203: fprintf(pgpout, PSTR("Key is disabled.\n"));
1204: if (print_trust && *owntrust_msg[TRUST_LEV(keyctrl)] != '\0')
1205: fprintf(pgpout, PSTR (owntrust_msg[TRUST_LEV(keyctrl)]));
1.1.1.2 root 1206: }
1207: else
1208: { PascalToC(userid);
1209: if (what != 0)
1210: fprintf(pgpout, "\n");
1211: fprintf(pgpout,PSTR("Also known as: %s\n"),
1212: LOCAL_CHARSET(userid));
1213: }
1.1.1.3 root 1214: if (print_trust) {
1.1.1.2 root 1215: read_trust(f, &keyctrl);
1.1.1.3 root 1216: fprintf(pgpout, PSTR (keylegit_msg[keyctrl&KC_LEGIT_MASK]));
1.1.1.2 root 1217: } /* print_trust */
1218: }
1.1.1.3 root 1219: else if (is_ctb_type(ctb, CTB_SKE_TYPE))
1.1.1.2 root 1220: {
1.1.1.3 root 1221: if (userids == 0)
1222: compromised = 1;
1.1.1.4 ! root 1223: if (what & SHOW_CHANGE) {
! 1224: show_update(key2IDstring(n));
! 1225: break;
! 1226: }
1.1.1.3 root 1227: if (what & SHOW_SIGS) {
1228: if (print_trust) {
1229: read_trust(f, &keyctrl);
1230: fprintf(pgpout, PSTR (sigtrust_msg[TRUST_LEV(keyctrl)]));
1231: }
1232: else
1233: fprintf(pgpout, PSTR(" Certified by: "));
1234: show_userid(f, sigkeyID);
1.1.1.2 root 1235: }
1236: }
1237: }
1238: if (status == -1 && userids)
1239: status = 0;
1240: set_precision(precision);
1241: fseek(f, filepos, SEEK_SET);
1242: return(status);
1243: } /* show_key */
1244:
1.1.1.4 ! root 1245: /* show_update -- this function just prints an update message to
! 1246: * pgpout to inform the user that an update happened.
! 1247: */
! 1248: void
! 1249: show_update(char *s)
! 1250: {
! 1251: fprintf(pgpout, "Updated keyID: 0x%s\n", s);
! 1252: }
1.1.1.2 root 1253:
1.1.1.3 root 1254:
1255: /*
1256: * stripped down version of readkeypacket(), the output userid
1257: * is a null terminated string.
1258: */
1259: int
1260: readkpacket(FILE *f, byte *ctb, char *userid, byte *keyID, byte *sigkeyID)
1261: {
1262: int status;
1263: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
1264:
1265: status = readkeypacket(f, FALSE, ctb, NULL, userid, n, e,
1266: NULL, NULL, NULL, NULL, sigkeyID, NULL);
1267:
1268: if (status < 0)
1269: {
1270: #ifdef DEBUG
1271: if (status < -1)
1272: fprintf(stderr, "readkeypacket returned %d\n", status);
1273: #endif
1274: return(status);
1275: }
1276:
1277: if (keyID && is_key_ctb(*ctb))
1278: extract_keyID(keyID, n);
1279:
1280: if (userid && *ctb == CTB_USERID)
1281: PascalToC(userid);
1282:
1283: return(0);
1284: } /* readkpacket */
1285:
1286:
1.1.1.2 root 1287: /*
1288: * write trust byte "keyctrl" to file f at file position "pos"
1289: */
1290: void
1291: write_trust_pos(FILE *f, byte keyctrl, long pos)
1292: {
1293: long fpos;
1294:
1295: fpos = ftell(f);
1296: fseek(f, pos, SEEK_SET);
1297: write_trust(f, keyctrl);
1298: fseek(f, fpos, SEEK_SET);
1299: } /* write_trust_pos */
1300:
1301:
1302: /*
1303: * read a trust byte packet from file f, the trust byte will be
1304: * stored in "keyctrl".
1305: * returns -1 on EOF, -3 on corrupt input, and ERR_NOTRUST if
1306: * the packet was not a trust byte (this can be used to check if
1307: * a file is a keyring (with trust bytes) or a keyfile).
1.1.1.3 root 1308: * The current file position is left unchanged in this case.
1.1.1.2 root 1309: */
1310: int
1311: read_trust(FILE *f, byte *keyctrl)
1312: {
1313: unsigned char buf[3];
1314:
1315: if (fread(buf, 1, 3, f) != 3)
1316: return -1;
1.1.1.3 root 1317: if (buf[0] != CTB_KEYCTRL) {
1318: if (is_ctb(buf[0])) {
1319: fseek(f, -3L, SEEK_CUR);
1.1.1.2 root 1320: return(ERR_NOTRUST);
1.1.1.3 root 1321: } else
1.1.1.2 root 1322: return(-3); /* bad data */
1323: }
1324: if (buf[1] != 1) /* length must be 1 */
1325: return(-3);
1326: if (keyctrl)
1327: *keyctrl = buf[2];
1328: return(0);
1329: } /* read_trust */
1.1.1.3 root 1330:
1331:
1332:
1333: /****** userid lookup ******/
1334:
1335: #define HASH_ALLOC (ALLOC_UNIT / sizeof(struct hashent))
1336:
1337: static char * store_str(char *str);
1338: static VOID * allocbuf(int size);
1339: static void freebufpool();
1340:
1341: static struct hashent {
1342: struct hashent *next;
1343: byte keyID[KEYFRAGSIZE];
1344: char *userid;
1345: } **hashtbl = NULL, *hashptr;
1346:
1347: static char *strptr;
1348: static int strleft = 0;
1349: static int hashleft = 0;
1350: static int nleft = 0;
1351:
1352: #define MAXKR 8 /* max. number of keyrings for user_from_keyID() */
1353: static char *krnames[MAXKR];
1354: static int nkr = 0;
1355: /*
1356: * Lookup userid by keyID without using the in-memory hash table.
1357: */
1358: static char *
1359: _user_from_keyID(byte *srch_keyID)
1360: {
1361: FILE *f;
1362: int i, status, found = 0;
1363: byte keyID[KEYFRAGSIZE];
1364: static char userid[256];
1365: byte ctb;
1366:
1367: /* search all keyfiles set with setkrent() */
1368: for (i = 0; !found && i < nkr; ++i) {
1369: if ((f = fopen(krnames[i], FOPRBIN)) == NULL)
1370: continue;
1371: while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1) {
1372: if (status == -2 || status == -3)
1373: break;
1374: if (is_key_ctb(ctb) && memcmp(keyID, srch_keyID, KEYFRAGSIZE) == 0)
1375: found = 1;
1376: if (found && ctb == CTB_USERID)
1377: break;
1378: }
1379: fclose(f);
1380: }
1381: return(found ? userid : NULL);
1382: }
1383:
1384: /*
1385: * Lookup userid by keyID, use hash table if initialized.
1386: */
1387: char *
1388: user_from_keyID(byte *keyID)
1389: {
1390: struct hashent *p;
1391:
1392: if (!hashtbl)
1393: return _user_from_keyID(keyID);
1394: for (p = hashtbl[PK_HASH(keyID)]; p; p = p->next)
1395: if (memcmp(keyID, p->keyID, KEYFRAGSIZE) == 0)
1396: return p->userid;
1397: return NULL;
1398: }
1399:
1400: /*
1401: * add keyfile to userid hash table, userids are added, endkrent() clears
1402: * the hash table.
1403: */
1404: int
1405: setkrent(char *keyring)
1406: {
1407: int i;
1408: char pubring[MAX_PATH];
1409:
1410: assert(nkr < MAXKR);
1411: if (keyring == NULL) {
1412: buildfilename(pubring, PUBLIC_KEYRING_FILENAME);
1413: keyring = pubring;
1414: }
1415: for (i = 0; i < nkr; ++i)
1416: if (strcmp(keyring, krnames[i]) == 0)
1417: return 0; /* duplicate name */
1418: krnames[nkr++] = store_str(keyring);
1419: return 0;
1420: }
1421:
1422: void
1423: endkrent(void)
1424: {
1425: hashleft = strleft = 0;
1426: hashtbl = NULL;
1427: nkr = 0;
1428: freebufpool();
1429: }
1430:
1431: /*
1432: * create userid hash table, read all files set with setkrent()
1433: */
1434: int
1435: init_userhash(void)
1436: {
1437: FILE *f;
1438: int status, i;
1439: byte keyID[KEYFRAGSIZE];
1440: char userid[256];
1441: byte ctb;
1442: int keyflag;
1443:
1444: if (!hashtbl) {
1445: hashtbl = allocbuf(PK_HASHSIZE * sizeof(struct hashent *));
1446: memset(hashtbl, 0, PK_HASHSIZE * sizeof(struct hashent *));
1447: }
1448: for (i = 0; i < nkr; ++i) {
1449: if ((f = fopen(krnames[i], FOPRBIN)) == NULL)
1450: continue;
1451: keyflag = 0;
1452: while ((status = readkpacket(f, &ctb, userid, keyID, NULL)) != -1) {
1453: if (is_key_ctb(ctb) && user_from_keyID(keyID) == NULL)
1454: keyflag = 1;
1455: if (keyflag && ctb == CTB_USERID) {
1456: if (!hashleft) {
1457: hashptr = allocbuf(HASH_ALLOC * sizeof(struct hashent));
1458: hashleft = HASH_ALLOC;
1459: }
1460: memcpy(hashptr->keyID, keyID, KEYFRAGSIZE);
1461: hashptr->userid = store_str(userid);
1462: hashptr->next = hashtbl[PK_HASH(keyID)];
1463: hashtbl[PK_HASH(keyID)] = hashptr;
1464: ++hashptr;
1465: --hashleft;
1466: keyflag = 0;
1467: }
1468: }
1469: fclose(f);
1470: }
1471: return 0;
1472: }
1473:
1474: /*
1475: * memory management routines
1476: */
1477:
1478: static void
1479: maint_init_mem(void)
1480: {
1481: pkhash = allocbuf(PK_HASHSIZE * sizeof(struct pubkey *));
1482: memset(pkhash, 0, PK_HASHSIZE * sizeof(struct pubkey *));
1483: }
1484:
1485: static void
1486: maint_release_mem(void)
1487: {
1488: nleft = 0;
1489: strleft = 0;
1490: pkhash = NULL;
1491: freebufpool();
1492: }
1493:
1494: /*
1495: * allocn() does the same as malloc(). Memory is allocated in chunks
1496: * of ALLOC_UNIT bytes, all memory can be freed by calling freebufpool().
1497: */
1498: static VOID *
1499: allocn(int size)
1500: {
1501: static char *ptr;
1502: #ifndef MSDOS /* don't align on MSDOS to save memory */
1503: size = (size + 3) & ~3;
1504: #endif
1505: assert(size < ALLOC_UNIT);
1506: if (size > nleft) {
1507: ptr = allocbuf(ALLOC_UNIT);
1508: nleft = ALLOC_UNIT;
1509: }
1510: nleft -= size;
1511: ptr += size;
1512: return ptr - size;
1513: }
1514:
1515: /*
1516: * store_str does the same as strdup(), but allocates memory with allocbuf()
1517: */
1518: static char *
1519: store_str(char *str)
1520: {
1521: int size = strlen(str) + 1;
1522: if (size > ALLOC_UNIT) {
1523: fprintf(stderr, "store_str: string too long\n");
1524: return NULL;
1525: }
1526: if (size > strleft) {
1527: strptr = allocbuf(ALLOC_UNIT);
1528: strleft = ALLOC_UNIT;
1529: }
1530: strcpy(strptr, str);
1531: strptr += size;
1532: strleft -= size;
1533: return strptr - size;
1534: }
1535:
1536:
1537: static struct bufpool {
1538: struct bufpool *next;
1539: char buf[1]; /* variable size */
1540: } *bufpool = NULL;
1541:
1542: long totalsize = 0;
1543:
1544: /*
1545: * allocate buffer, all buffers allocated with this function can be
1546: * freed with one call to freebufpool()
1547: */
1548: static VOID *
1549: allocbuf(int size)
1550: {
1551: struct bufpool *p;
1552:
1553: p = xmalloc(size + sizeof(struct bufpool *));
1554: totalsize += size;
1555: p->next = bufpool;
1556: bufpool = p;
1557: return p->buf;
1558: }
1559:
1560: /*
1561: * free all memory obtained with allocbuf()
1562: */
1563: static void
1564: freebufpool(void)
1565: {
1566: struct bufpool *p;
1567:
1568: if (verbose)
1569: fprintf(pgpout, "\nMemory used: %ldk\n", totalsize / 1024);
1570: totalsize = 0;
1571: while (bufpool) {
1572: p = bufpool;
1573: bufpool = bufpool->next;
1574: free(p);
1575: }
1576: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.