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

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

unix.superglobalmegacorp.com

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