Annotation of pgp/src/keyadd.c, revision 1.1.1.8

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.