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

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

unix.superglobalmegacorp.com

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