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

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 "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: int 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:                if (status == -3)       /* unrecoverable error: bad packet length etc. */
        !           103:                        return(status);
        !           104:                keypktlen = ftell(fkey) - keypos;
        !           105:                if (status == -1  ||  is_key_ctb (ctb)  ||  ctb==CTB_USERID)
        !           106:                        break;  /* EOF or next key/userid */
        !           107:                if (status < 0)
        !           108:                        continue;       /* bad packet, skip it */
        !           109:                if (is_ctb_type(ctb,CTB_SKE_TYPE))
        !           110:                {       long sig_pos;
        !           111:                        int sig_len;
        !           112:                        /* Set copying true if signature is not in the ringfile */
        !           113:                        copying = (getpubusersig (ringfile, ringuseridpos, keyID, &sig_pos,
        !           114:                                                &sig_len) < 0);
        !           115:                        if (copying)
        !           116:                        {       fprintf (pgpout, PSTR("New signature from keyID %s on userid \"%s\"\n"), 
        !           117:                                        keyIDstring(keyID),LOCAL_CHARSET(userid));
        !           118:                                ++newsigs;
        !           119:                        }
        !           120:                }
        !           121:                if (copying  &&  is_ctb_type(ctb,CTB_SKE_TYPE))
        !           122:                {       copyfilepos (fkey, out, keypktlen, keypos);
        !           123:                        write_trust (out, KC_SIGTRUST_UNDEFINED);
        !           124:                }
        !           125:        }
        !           126: 
        !           127:        /* Third, for all ring sig's, copy to output */
        !           128:        fseek (fring, ringpos, SEEK_SET);
        !           129:        for ( ; ; )
        !           130:        {       ringpos = ftell(fring);
        !           131:                status = nextkeypacket (fring, &ctb);
        !           132:                ringpktlen = ftell(fring) - ringpos;
        !           133:                if (status < 0  ||  is_key_ctb (ctb)  ||  ctb==CTB_USERID)
        !           134:                        break;
        !           135:                copyfilepos (fring, out, ringpktlen, ringpos);
        !           136:        }       /* End of loop for each sig in ringfile */
        !           137:        fseek (fring, ringpos, SEEK_SET);
        !           138:        *pringpos = ringpos;
        !           139:        return(0);
        !           140: } /* mergesigs */
        !           141: 
        !           142: 
        !           143: int mergekeys (FILE *fkey, char *keyfile, long keypos, FILE *fring,
        !           144:                char *ringfile, long *pringpos, FILE *out)
        !           145: /* Merge key from fkey (which is keyfile) at keypos with key from
        !           146:  * fring (which is ringfile) at ringpos, appending result to out.
        !           147:  */
        !           148: {
        !           149:        long ringkeypos, keykeypos, ringpos;
        !           150:        int ringpktlen, keypktlen;
        !           151:        int status;
        !           152:        byte ctb;
        !           153:        int copying;
        !           154:        boolean ring_compromise = FALSE;
        !           155:        byte userid[256];
        !           156: 
        !           157:        /* First, copy the key packet itself, plus any comments or ctrls */
        !           158:        ringkeypos = ringpos = *pringpos;
        !           159:        fseek (fring, ringpos, SEEK_SET);
        !           160:        (void) nextkeypacket(fring, &ctb);
        !           161:        ringpktlen = ftell(fring) - ringpos;
        !           162:        copyfilepos (fring, out, ringpktlen, ringpos);
        !           163:        for ( ; ; )
        !           164:        {       ringpos = ftell(fring);
        !           165:                status = nextkeypacket (fring, &ctb);
        !           166:                if (status < 0  ||  is_key_ctb(ctb)  ||  ctb==CTB_USERID)
        !           167:                        break;
        !           168:                if (is_ctb_type(ctb, CTB_SKE_TYPE))
        !           169:                        ring_compromise = TRUE; /* compromise cert on keyring */
        !           170:                ringpktlen = ftell(fring) - ringpos;
        !           171:                copyfilepos (fring, out, ringpktlen, ringpos);
        !           172:        }
        !           173:        fseek (fring, ringpos, SEEK_SET);
        !           174: 
        !           175:        /* Now, ringpos points just past key packet and ctrl packet. */
        !           176:        /* Advance keypos to the analogous location. */
        !           177:        fseek (fkey, keypos, SEEK_SET);
        !           178:        keykeypos = keypos;
        !           179:        (void) nextkeypacket (fkey, &ctb);
        !           180:        keypktlen = ftell(fkey) - keypos;       /* for check_key_sig() */
        !           181:        for ( ; ; )
        !           182:        {       keypos = ftell(fkey);
        !           183:                status = nextkeypacket (fkey, &ctb);
        !           184:                if (status < 0 || ctb == CTB_USERID || is_ctb_type(ctb, CTB_SKE_TYPE))
        !           185:                        break;
        !           186:        }
        !           187:        if (!ring_compromise && is_ctb_type(ctb, CTB_SKE_TYPE))
        !           188:        {       /* found a compromise cert on keyfile that is not in ringfile */
        !           189:                word32 timestamp;
        !           190:                byte sig_class;
        !           191:                int cert_pktlen;
        !           192: 
        !           193:                cert_pktlen = ftell(fkey) - keypos;
        !           194:                if (check_key_sig(fkey, keykeypos, keypktlen, (char *)userid, fkey, keypos,
        !           195:                                ringfile, (char *)userid, (byte *)&timestamp, &sig_class) == 0 &&
        !           196:                                sig_class == KC_SIGNATURE_BYTE)
        !           197:                {
        !           198:                        fprintf(pgpout, PSTR("Key revocation certificate from \"%s\".\n"),
        !           199:                                        LOCAL_CHARSET((char *)userid));
        !           200:                        copyfilepos (fkey, out, cert_pktlen, keypos);
        !           201:                        ++newrvks;
        !           202:                }
        !           203:                else
        !           204:                        fprintf(pgpout, PSTR("\n\007WARNING:  File '%s' contains bad revocation certificate.\n"));
        !           205:        }
        !           206:        fseek (fkey, keypos, SEEK_SET);
        !           207: 
        !           208:        /* Second, copy all keyfile userid's plus signatures that aren't
        !           209:         * in ringfile.
        !           210:         */
        !           211: 
        !           212:        copying = FALSE;
        !           213:        for ( ; ; )
        !           214:        {       /* Read next userid from keyfile; see if it is in ringfile;
        !           215:                 * set copying true/false accordingly.  If copying is true
        !           216:                 * and it is a userid or a signature, copy it.  Loop till hit
        !           217:                 * a new key in keyfile, or EOF.
        !           218:                 */
        !           219:                keypos = ftell(fkey);
        !           220:                status = readkeypacket(fkey,FALSE,&ctb,NULL,(char *)userid,NULL,NULL,
        !           221:                                NULL,NULL,NULL,NULL,NULL,NULL);
        !           222:                if (status == -3)       /* unrecoverable error: bad packet length etc. */
        !           223:                        return(status);
        !           224:                keypktlen = ftell(fkey) - keypos;
        !           225:                if (status == -1  ||  is_key_ctb (ctb))
        !           226:                        break;  /* EOF or next key */
        !           227:                if (status < 0)
        !           228:                        continue;       /* bad packet, skip it */
        !           229:                if (ctb == CTB_USERID)
        !           230:                {       long userid_pos;
        !           231:                        int userid_len;
        !           232:                        PascalToC ((char *)userid);
        !           233:                        /* Set copying true if userid is not in the ringfile */
        !           234:                        copying =  (getpubuserid (ringfile, ringkeypos, userid, &userid_pos,
        !           235:                                                &userid_len, TRUE) < 0);
        !           236:                        if (copying)
        !           237:                        {       fprintf (pgpout, PSTR("New userid: \"%s\".\n"), 
        !           238:                                        LOCAL_CHARSET((char *)userid));
        !           239:                                fprintf(pgpout, PSTR("\nWill be added to the following key:\n"));
        !           240:                                show_key(fring, *pringpos, 0);
        !           241:                                fprintf(pgpout, PSTR("\nAdd this userid (y/N)? "));
        !           242:                                if (getyesno('n'))
        !           243:                                        ++newids;
        !           244:                                else
        !           245:                                        copying = FALSE;
        !           246:                        }
        !           247:                }
        !           248:                if (copying)
        !           249:                {       if (ctb==CTB_USERID  ||  is_ctb_type(ctb,CTB_SKE_TYPE))
        !           250:                        {       copyfilepos (fkey, out, keypktlen, keypos);
        !           251:                                if (is_ctb_type(ctb,CTB_SKE_TYPE))
        !           252:                                        write_trust (out, KC_SIGTRUST_UNDEFINED);
        !           253:                                else
        !           254:                                        write_trust (out, KC_LEGIT_UNKNOWN);
        !           255:                        }
        !           256:                }
        !           257:        }
        !           258: 
        !           259:        /* Third, for all ring userid's, if not in keyfile, copy the userid
        !           260:         * plus its dependant signatures.
        !           261:         */
        !           262:        fseek (fring, ringpos, SEEK_SET);
        !           263:        for ( ; ; )
        !           264:        {       ringpos = ftell(fring);
        !           265:                status = readkeypacket(fring,FALSE,&ctb,NULL,(char *)userid,NULL,NULL,
        !           266:                                        NULL,NULL,NULL,NULL,NULL,NULL);
        !           267:                ringpktlen = ftell(fring) - ringpos;
        !           268:                if (status == -3)
        !           269:                        return(status);
        !           270:                if (status == -1  ||  is_key_ctb (ctb))
        !           271:                        break;
        !           272:                if (ctb == CTB_USERID)
        !           273:                {       long userid_pos;
        !           274:                        int userid_len;
        !           275:                        /* See if there is a match in keyfile */
        !           276:                        PascalToC ((char *) userid);
        !           277:                        /* don't use substring match (exact_match = TRUE) */
        !           278:                        if (getpubuserid (keyfile, keykeypos, userid, &userid_pos,
        !           279:                                                &userid_len, TRUE) >= 0)
        !           280:                        {       if ((status = mergesigs (fkey,keyfile,userid_pos,fring,ringfile,&ringpos,out)) < 0)
        !           281:                                        return(status);
        !           282:                                copying = FALSE;
        !           283:                        }
        !           284:                        else
        !           285:                                copying = TRUE;
        !           286:                }
        !           287:                if (copying)
        !           288:                {       /* Copy ringfile userid and sigs to out */
        !           289:                        copyfilepos (fring, out, ringpktlen, ringpos);
        !           290:                }
        !           291:        }       /* End of loop for each key in ringfile */
        !           292:        fseek (fring, ringpos, SEEK_SET);
        !           293:        *pringpos = ringpos;
        !           294:        return(0);
        !           295: } /* mergekeys */
        !           296: 
        !           297: 
        !           298: int addto_keyring(char *keyfile, char *ringfile, boolean query)
        !           299: /*     Adds (prepends) key file to key ring file.  If query is TRUE, ask
        !           300:        before doing any actual changes. */
        !           301: {      FILE *f, *g, *h;
        !           302:        long file_position,fp;
        !           303:        int pktlen;     /* unused, just to satisfy getpublickey */
        !           304:        byte ctb;
        !           305:        int status;
        !           306:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
        !           307:        unit n1[MAX_UNIT_PRECISION];
        !           308:        byte keyID[KEYFRAGSIZE];
        !           309:        byte userid[256];               /* key certificate userid */
        !           310:        byte userid1[256];
        !           311:        word32 tstamp; byte *timestamp = (byte *) &tstamp;              /* key certificate timestamp */
        !           312:        char trans_keyfile[MAX_PATH];
        !           313:        boolean is_armored = FALSE;
        !           314:        boolean userid_seen = FALSE;
        !           315:        int commonkeys = 0;
        !           316:        int copying;
        !           317:        struct nkey {
        !           318:                byte keyID[KEYFRAGSIZE];
        !           319:                struct nkey *next;
        !           320:        } *nkey, *nkeys = NULL;
        !           321:        char *scratchf;
        !           322: 
        !           323:        setoutdir(ringfile);
        !           324:        scratchf = tempfile(0);
        !           325: 
        !           326:        /* check if the keyfile to be added is armored */
        !           327:        if ((is_armored = is_armor_file(keyfile, 0L)) == TRUE)
        !           328:        {   /* decode it into the actual keyfile */
        !           329:                boolean changed_name;
        !           330:                strcpy(trans_keyfile,keyfile);
        !           331:                keyfile = tempfile(TMP_TMPDIR|TMP_WIPE);
        !           332:                if (de_armor_file(trans_keyfile,keyfile,NULL) < 0)
        !           333:                        return(-1);
        !           334:        }
        !           335: 
        !           336:        userid[0] = '\0';
        !           337:        if (dokeycheck((char *) userid, keyfile, NULL) < 0)
        !           338:        {       fprintf(pgpout, PSTR("\007Keyring check error. ") );
        !           339:                fprintf(pgpout, PSTR("\nKey(s) will not be added to keyring.\n"));
        !           340:                goto err;
        !           341:        }
        !           342: 
        !           343:        /* open file f for read, in binary (not text) mode...*/
        !           344:        if ((f = fopen(keyfile,FOPRBIN)) == NULL)
        !           345:        {       fprintf(pgpout,PSTR("\n\007Can't open key file '%s'\n"),keyfile);
        !           346:                goto err;
        !           347:        }
        !           348:        if (!file_exists(ringfile))
        !           349:        {       /* ringfile does not exist.  Can it be created? */
        !           350:                /* open file g for writing, in binary (not text) mode...*/
        !           351:                g = fopen(ringfile,FOPWBIN);
        !           352:                if (g==NULL)
        !           353:                {       fprintf(pgpout,PSTR("\nKey ring file '%s' cannot be created.\n"),ringfile);
        !           354:                        fclose(f);
        !           355:                        goto err;
        !           356:                }
        !           357:                fclose(g);
        !           358:        }
        !           359: 
        !           360:        /* Create working output file */
        !           361:        /* open file g for writing, in binary (not text) mode...*/
        !           362:        if ((g = fopen(scratchf,FOPWBIN)) == NULL)
        !           363:        {       fclose(f);
        !           364:                goto err;
        !           365:        }
        !           366:        newkeys = newsigs = newids = newrvks = 0;
        !           367: 
        !           368:        /* Pass 1 - copy all keys from f which aren't in ring file */
        !           369:        /* Also copy userid and signature packets. */
        !           370:        copying = FALSE;
        !           371:        for ( ; ; )
        !           372:        {       file_position = ftell(f);
        !           373: 
        !           374:                status = readkeypacket(f,FALSE,&ctb,timestamp,(char *)userid,n,e,
        !           375:                                NULL,NULL,NULL,NULL,NULL,NULL);
        !           376:                /* Note that readkeypacket has called set_precision */
        !           377:                if (status == -1)       /* EOF */
        !           378:                        break;
        !           379:                if (status == -3)
        !           380:                {       fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"),
        !           381:                                keyfile);
        !           382:                        fclose(f);      /* close key file */
        !           383:                        fclose(g);
        !           384:                        goto err;
        !           385:                }
        !           386:                if (status < 0)
        !           387:                {
        !           388:                        copying = FALSE;
        !           389:                        continue;       /* don't merge keys from unrecognized version */
        !           390:                }
        !           391: 
        !           392:                /* Check to see if key is already on key ring */
        !           393:                if (is_key_ctb(ctb))
        !           394:                {
        !           395:                        extract_keyID(keyID, n);        /* from keyfile, not ringfile */
        !           396:        
        !           397:                        /*      Check for duplicate key in key ring: */
        !           398:                        if (getpublickey(TRUE, FALSE, ringfile, &fp, &pktlen, keyID, timestamp, userid, n1, e) >= 0)
        !           399:                        {       if (mp_compare (n, n1) != 0)
        !           400:                                {       fprintf(pgpout, PSTR("\n\007Warning: Key ID %s matches key ID of key already on \n\
        !           401: key ring '%s', but the keys themselves differ.\n\
        !           402: This is highly suspicious.  This key will not be added to ring.\n\
        !           403: Acknowledge by pressing return: "), keyIDstring(keyID), ringfile);
        !           404:                                        getyesno('n');
        !           405:                                        fclose(f);      /* close key file */
        !           406:                                        fclose(g);
        !           407:                                        goto err;
        !           408:                                }
        !           409:                                else
        !           410:                                {       if (verbose)
        !           411:                                                fprintf(pgpout,PSTR("Key ID %s is already included in key ring '%s'.\n"),
        !           412:                                                        keyIDstring(keyID), ringfile);
        !           413:                                        ++commonkeys;
        !           414:                                }
        !           415:                                copying = FALSE;
        !           416:                        }
        !           417:                        else
        !           418:                        {
        !           419:                                ++newkeys;
        !           420: #if 0
        !           421:                                if (query)
        !           422:                                {       if (is_ctb_type(ctb, CTB_CERT_SECKEY_TYPE))
        !           423:                                                fprintf (pgpout, PSTR ("\nAdd secret key to key ring '%s' (y/N)? "),
        !           424:                                                                ringfile);
        !           425:                                        else
        !           426:                                                fprintf (pgpout, PSTR ("\nAdd public key to key ring '%s' (y/N)? "),
        !           427:                                                                ringfile);
        !           428:                                                
        !           429:                                        if (! getyesno( 'n' ))
        !           430:                                        {       fclose(f);
        !           431:                                                fclose(g);
        !           432:                                                rmtemp(scratchf);
        !           433:                                                return(0);      /* user chose to abort */
        !           434:                                        }
        !           435:                                        query = FALSE;          /* Don't ask subsequently */
        !           436:                                }
        !           437: #endif
        !           438: 
        !           439:                                if ((nkey = (struct nkey *) malloc(sizeof(struct nkey))) == NULL)
        !           440:                                {
        !           441:                                        fprintf(stderr, PSTR("\n\007Out of memory.\n"));
        !           442:                                        exitPGP(7);
        !           443:                                }
        !           444:                                memcpy(nkey->keyID, keyID, KEYFRAGSIZE);
        !           445:                                nkey->next = nkeys;
        !           446:                                nkeys = nkey;
        !           447:        
        !           448:                                fprintf(pgpout, PSTR("New key ID: %s\n"), keyIDstring(keyID));
        !           449:                                copying = TRUE;
        !           450:                        }
        !           451:                }
        !           452:                /* Now, we copy according to the copying flag */
        !           453:                /*      The key is prepended to the ring to give it search precedence
        !           454:                        over other keys with that same userid. */
        !           455:        
        !           456:                if (copying  &&  (is_key_ctb(ctb) || ctb==CTB_USERID ||
        !           457:                                                                is_ctb_type(ctb,CTB_SKE_TYPE)))
        !           458:                {       pktlen = (int) (ftell(f) - file_position);
        !           459:                        copyfilepos(f,g,pktlen,file_position);  /* copy packet from f */
        !           460:                        /* Initialize trust packets after keys and signatures */
        !           461:                        if (is_key_ctb(ctb))
        !           462:                        {
        !           463:                                write_trust (g, KC_OWNERTRUST_UNDEFINED);
        !           464:                                userid_seen = FALSE;
        !           465:                        }
        !           466:                        else if (is_ctb_type(ctb,CTB_SKE_TYPE))
        !           467:                        {
        !           468:                                if (userid_seen)
        !           469:                                        write_trust (g, KC_SIGTRUST_UNDEFINED);
        !           470:                                else
        !           471:                                /* signature certificate before userid must be compromise cert. */
        !           472:                                        fprintf(pgpout, PSTR("Key has been revoked.\n"));
        !           473:                        }
        !           474:                        else if (is_ctb_type(ctb,CTB_USERID_TYPE))
        !           475:                        {
        !           476:                                write_trust (g, KC_LEGIT_UNKNOWN);
        !           477:                                userid_seen = TRUE;
        !           478:                        }
        !           479:                }
        !           480:        }
        !           481: 
        !           482:        /* Now copy the remainder of the ringfile, h, to g.  commonkeys tells
        !           483:                how many keys are common to keyfile and ringfile.  As long as that is
        !           484:                nonzero we will check each key in ringfile to see if it has a match
        !           485:                in keyfile.
        !           486:        */
        !           487:        if ((h = fopen(ringfile,FOPRBIN)) != NULL)
        !           488:        {       while (commonkeys)              /* Loop for each key in ringfile */
        !           489:                {       file_position = ftell(h);
        !           490:                        status = readkeypacket(h,FALSE,&ctb,NULL,(char *)userid,n,e,
        !           491:                                                NULL,NULL,NULL,NULL,NULL,NULL);
        !           492:                        if (status == -1 || status == -3)
        !           493:                        {       if (status == -1)       /* hit EOF */
        !           494:                                        fprintf(pgpout, PSTR("\n\007Key file contains duplicate keys: cannot be added to keyring\n"));
        !           495:                                else
        !           496:                                        fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"),
        !           497:                                                ringfile);
        !           498:                                fclose(f);
        !           499:                                fclose(g);
        !           500:                                fclose(h);
        !           501:                                goto err;
        !           502:                        }
        !           503:                        PascalToC ((char *) userid);
        !           504:                        pktlen = ftell(h) - file_position;
        !           505:                        if (is_key_ctb(ctb))
        !           506:                        {       long    tfp;
        !           507:                                int             tpktlen;
        !           508:                                /* See if there is a match in keyfile */
        !           509:                                extract_keyID(keyID, n);        /* from ringfile, not keyfile */
        !           510:                                /* unknow version or bad data: copy (don't remove packets from ringfile) */
        !           511:                                if (status == 0 && (getpublickey(TRUE, FALSE, keyfile, &tfp, &tpktlen,
        !           512:                                         keyID, timestamp, userid1, n1, e) >= 0)  &&
        !           513:                                                (mp_compare(n, n1) == 0))
        !           514:                                {       
        !           515:                                        if (verbose)
        !           516:                                                fprintf (pgpout, PSTR("Merging key ID: %s\n"),keyIDstring(keyID));
        !           517:                                        if (mergekeys (f,keyfile,tfp, h,ringfile,&file_position, g) < 0)
        !           518:                                        {       fclose(f);
        !           519:                                                fclose(g);
        !           520:                                                fclose(h);
        !           521:                                                goto err;
        !           522:                                        }
        !           523:                                        copying = FALSE;
        !           524:                                        --commonkeys;
        !           525:                                }
        !           526:                                else
        !           527:                                        copying = TRUE;
        !           528:                        }
        !           529:                        if (copying)
        !           530:                        {       /* Copy ringfile key to g, without its sigs */
        !           531:                                copyfilepos (h,g,pktlen,file_position);
        !           532:                                file_position += pktlen;
        !           533:                        }
        !           534:                }       /* End of loop for each key in ringfile */
        !           535:                copyfile(h,g,-1L);      /* copy rest of file from file h to g */
        !           536:                fclose(h);
        !           537:        }
        !           538:        fclose(f);
        !           539:        if (write_error(g))
        !           540:        {       fclose(g);
        !           541:                goto err;
        !           542:        }
        !           543:        fclose(g);
        !           544:        if (newsigs == 0 && newkeys == 0 && newids == 0 && newrvks == 0)
        !           545:        {
        !           546:                fprintf(pgpout, PSTR("No new keys or signatures in keyfile.\n"));
        !           547:                rmtemp(scratchf);
        !           548:                return(0);
        !           549:        }
        !           550: 
        !           551:        for (nkey = nkeys; nkey; nkey = nkey->next)
        !           552:        {
        !           553:                if (dokeycheck(NULL, scratchf, nkey->keyID))
        !           554:                        goto err;
        !           555:        }
        !           556:        fprintf(pgpout, PSTR("\nKeyfile contains:\n"));
        !           557:        if (newkeys)
        !           558:                fprintf(pgpout, PSTR("%4d new key(s)\n"), newkeys);
        !           559:        if (newsigs)
        !           560:                fprintf(pgpout, PSTR("%4d new signatures(s)\n"), newsigs);
        !           561:        if (newids)
        !           562:                fprintf(pgpout, PSTR("%4d new user ID(s)\n"), newids);
        !           563:        if (newrvks)
        !           564:                fprintf(pgpout, PSTR("%4d new revocation(s)\n"), newrvks);
        !           565:        if (query)
        !           566:        {
        !           567:                fprintf(pgpout, PSTR("\nDo you want to add this keyfile to keyring '%s' (y/N)? "), ringfile);
        !           568:                if (!getyesno('n'))
        !           569:                {       rmtemp(scratchf);
        !           570:                        return(1);
        !           571:                }
        !           572:        }
        !           573:        if ((status = maintenance(scratchf, MAINT_SILENT)) == 0)
        !           574:                for (nkey = nkeys; nkey; nkey = nkey->next)
        !           575:                {       fprintf(pgpout,PSTR("Adding key ID %s from file '%s' to key ring '%s'.\n"),
        !           576:                                keyIDstring(nkey->keyID),(is_armored?trans_keyfile:keyfile),ringfile);
        !           577:                        ask_to_sign(nkey->keyID, scratchf);
        !           578:                }
        !           579: 
        !           580:        savetempbak(scratchf,ringfile);
        !           581: 
        !           582:        if (is_armored)
        !           583:                rmtemp(keyfile);        /* zap decoded keyfile */
        !           584:        return(0);      /* normal return */
        !           585: 
        !           586: err:
        !           587:        /* make sure we remove any garbage files we may have created */
        !           588:        if (is_armored)
        !           589:                rmtemp(keyfile);        /* zap decoded keyfile */
        !           590:        rmtemp(scratchf);
        !           591:        return(-1);
        !           592: }      /* addto_keyring */
        !           593: 
        !           594: 
        !           595: static int ask_to_sign(byte *keyID, char *ringfile)
        !           596: {
        !           597:        FILE *f;
        !           598:        word32 timestamp;
        !           599:        byte ctb, trust;
        !           600:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
        !           601:        byte userid[256];
        !           602:        long fpos;
        !           603:        int pktlen;     /* unused, just to satisfy getpublickey */
        !           604:        int status;
        !           605:        extern char my_name[];
        !           606: 
        !           607:        if (getpublickey(TRUE, FALSE, ringfile, &fpos, &pktlen, 
        !           608:                        keyID, (byte *)&timestamp, userid, n, e) < 0)
        !           609:                return(-1);
        !           610: 
        !           611:        if ((f = fopen(ringfile, FOPRBIN)) == NULL)
        !           612:                return(-1);
        !           613: 
        !           614:        fseek(f, fpos, SEEK_SET);
        !           615:        if (is_compromised(f))
        !           616:        {       fclose(f);
        !           617:                return(0);
        !           618:        }
        !           619:        if (nextkeypacket(f, &ctb) < 0)
        !           620:        {       fclose(f);
        !           621:                return(-1);
        !           622:        }
        !           623:        if (ctb != CTB_CERT_PUBKEY)
        !           624:        {       fclose(f);
        !           625:                return(0);      /* don't ask to sign secret key */
        !           626:        }
        !           627:        while (nextkeypacket(f, &ctb) == 0 && !is_key_ctb(ctb))
        !           628:                if (ctb == CTB_USERID)  /* check first userid */
        !           629:                        break;
        !           630:        if (ctb != CTB_USERID)
        !           631:        {
        !           632:                fclose(f);
        !           633:                return(-1);
        !           634:        }
        !           635: 
        !           636:        if ((status = read_trust(f, &trust)) < 0)
        !           637:        {
        !           638:                fclose(f);
        !           639:                return(status);
        !           640:        }
        !           641:        if ((trust & KC_LEGIT_MASK) == KC_LEGIT_COMPLETE)
        !           642:        {
        !           643:                fclose(f);
        !           644:                return(0);
        !           645:        }
        !           646:        show_key(f, fpos, SHOW_ALL);
        !           647:        fclose(f);
        !           648:        PascalToC((char *)userid);
        !           649:        fprintf(pgpout, PSTR("\nDo you want to certify this key yourself (y/N)? "));
        !           650:        if (getyesno('n'))
        !           651:        {
        !           652:                if (signkey((char *)userid, my_name, ringfile) == 0)
        !           653:                        maintenance(ringfile, MAINT_SILENT);
        !           654:        }
        !           655:        return(0);
        !           656: }

unix.superglobalmegacorp.com

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