Annotation of pgp/src/keyadd.c, revision 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.