void formatcells(void) /* Prompts the user for a selected format and range of cells */ { int col, row, col1, col2, row1, row2, temp, newformat = 0; writeprompt(MSGCELL1); if (!getcell(&col1, &row1)) return; writeprompt(MSGCELL2); if (!getcell(&col2, &row2)) return; if ((col1 != col2) && (row1 != row2)) errormsg(MSGDIFFCOLROW); else { if (col1 > col2) swap(&col1, &col2); if (row1 > row2) swap(&row1, &row2); if (!getyesno(&temp, MSGRIGHTJUST)) return; newformat += (temp == 'Y') * RJUSTIFY; if (!getyesno(&temp, MSGDOLLAR)) return; newformat += (temp == 'Y') * DOLLAR; if (!getyesno(&temp, MSGCOMMAS)) return; newformat += (temp == 'Y') * COMMAS; if (newformat & DOLLAR) newformat += 2; else { writeprompt(MSGPLACES); if (!getint(&temp, 0, MAXPLACES)) return; newformat += temp; } for (col = col1; col <= col2; col++) { for (row = row1; row <= row2; row++) { format[col][row] = (format[col][row] & OVERWRITE) | newformat; if ((col >= leftcol) && (col <= rightcol) && (row >= toprow) && (row <= bottomrow)) displaycell(col, row, NOHIGHLIGHT, NOUPDATE); } } } changed = TRUE; } /* formatcells */
void checkforsave(void) /* If the spreadsheet has been changed, will ask the user if they want to save it. */ { int save; if (changed && getyesno(&save, MSGSAVESHEET) && (save == 'Y')) savesheet(); } /* checkforsave */
char *ck_dup_output(char *newname, boolean notest, boolean delete_dup) { int overwrite; static char buf[MAX_PATH]; while (file_exists(newname)) { if (batchmode && !force_flag) { fprintf(pgpout,LANG("\n\007Output file '%s' already exists.\n"), newname); return NULL; } if (is_regular_file(newname)) { if (force_flag) { /* remove without asking */ if (delete_dup) remove(newname); break; } fprintf(pgpout, LANG("\n\007Output file '%s' already exists. Overwrite (y/N)? "), newname); overwrite = getyesno('n'); } else { fprintf(pgpout, LANG("\n\007Output file '%s' already exists.\n"),newname); if (force_flag) /* never remove special file */ return NULL; overwrite = FALSE; } if (!overwrite) { fprintf(pgpout, "\n"); fprintf(pgpout, LANG("Enter new file name:")); fprintf(pgpout, " "); #ifdef MACTC5 if (!GetFilePath(LANG("Enter new file name:"), buf, PUTFILE)) return(NULL); strcpy(newname, buf); fprintf(pgpout, "%s\n",buf); #else getstring(buf, MAX_PATH - 1, TRUE); if (buf[0] == '\0') return(NULL); newname = buf; #endif } else if (delete_dup) remove(newname); else break; if (notest) break; } return(newname); } /* ck_dup_output */
/* if user consents to it, change the filename extension. */ char *maybe_force_extension(char *filename, char *extension) { static char newname[MAX_PATH]; if (!has_extension(filename, extension)) { strcpy(newname, filename); force_extension(newname, extension); if (!file_exists(newname)) { fprintf(pgpout, LANG("\nShould '%s' be renamed to '%s' (Y/n)? "), filename, newname); if (getyesno('y')) return newname; } } return NULL; } /* maybe_force_extension */
/* if user consents to it, change the filename extension. */ char *maybeForceExtension( struct pgpfileBones *filebPtr, char *filename, char *extension ) { struct pgpenvBones *envbPtr = filebPtr->envbPtr; PGPEnv *env = envbPtr->m_env; PGPInt32 pri; PGPError err; static char newname[MAX_PATH]; if (!hasExtension(filename, extension)) { strcpy(newname, filename); forceExtension( filebPtr, newname, extension ); if (!fileExists(newname)) { fprintf(filebPtr->pgpout, LANG("\nShould '%s' be renamed to '%s' [Y/n]? "), filename, newname); if (getyesno(filebPtr, 'y', (PGPBoolean)pgpenvGetInt( env, PGPENV_BATCHMODE, &pri, &err ))) return newname; } } return NULL; }/* maybe_force_extension */
void printsheet(void) /* Prints a copy of the spreadsheet to a file or to the printer */ { char filename[MAXINPUT + 1], s[133], colstr[MAXCOLWIDTH + 1]; FILE *file; int columns, counter1, counter2, counter3, col = 0, row, border, toppage, lcol, lrow, dummy, printed, oldlastcol; filename[0] = 0; writeprompt(MSGPRINT); if (!editstring(filename, "", MAXINPUT)) return; if (filename[0] == 0) strcpy(filename, "PRN"); if ((file = fopen(filename, "wt")) == NULL) { errormsg(MSGNOOPEN); return; } oldlastcol = lastcol; for (counter1 = 0; counter1 <= lastrow; counter1++) { for (counter2 = lastcol; counter2 < MAXCOLS; counter2++) { if (format[counter2][counter1] >= OVERWRITE) lastcol = counter2; } } if (!getyesno(&columns, MSGCOLUMNS)) return; columns = (columns == 'Y') ? 131 : 79; if (!getyesno(&border, MSGBORDER)) return; border = (border == 'Y'); while (col <= lastcol) { row = 0; toppage = TRUE; lcol = pagecols(col, border, columns) + col; while (row <= lastrow) { lrow = pagerows(row, toppage, border) + row; printed = 0; if (toppage) { for (counter1 = 0; counter1 < TOPMARGIN; counter1++) { fprintf(file, "\n"); printed++; } } for (counter1 = row; counter1 < lrow; counter1++) { if ((border) && (counter1 == row) && (toppage)) { if ((col == 0) && (border)) sprintf(s, "%*s", LEFTMARGIN, ""); else s[0] = 0; for (counter3 = col; counter3 < lcol; counter3++) { centercolstring(counter3, colstr); strcat(s, colstr); } fprintf(file, "%s\n", s); printed++; } if ((col == 0) && (border)) sprintf(s, "%-*d", LEFTMARGIN, counter1 + 1); else s[0] = 0; for (counter2 = col; counter2 < lcol; counter2++) strcat(s, cellstring(counter2, counter1, &dummy, FORMAT)); fprintf(file, "%s\n", s); printed++; } row = lrow; toppage = FALSE; if (printed < 66) fprintf(file, "%c", FORMFEED); } col = lcol; } fclose(file); lastcol = oldlastcol; } /* printsheet */
void savesheet(void) /* Saves the current spreadsheet */ { char filename[MAXINPUT+1], eof = 26; int size, col, row, overwrite, file; CELLPTR cellptr; filename[0] = 0; writeprompt(MSGFILENAME); if (!editstring(filename, "", MAXINPUT)) return; if (!access(filename, 0)) { if (!getyesno(&overwrite, MSGOVERWRITE) || (overwrite == 'N')) return; } if ((file = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE)) == -1) { errormsg(MSGNOOPEN); return; } writef(1, 25, PROMPTCOLOR, 79, MSGSAVING); gotoxy(strlen(MSGSAVING) + 1, 25); write(file, name, strlen(name) + 1); write(file, &eof, 1); write(file, (char *)&lastcol, 2); write(file, (char *)&lastrow, 2); size = MAXCOLS; write(file, (char *)&size, 2); write(file, colwidth, sizeof(colwidth)); for (row = 0; row <= lastrow; row++) { for (col = lastcol; col >= 0; col--) { if (cell[col][row] != NULL) { cellptr = cell[col][row]; switch(cellptr->attrib) { case TEXT : size = strlen(cellptr->v.text) + 2; break; case VALUE : size = sizeof(double) + 1; break; case FORMULA : size = strlen(cellptr->v.f.formula) + 2 + sizeof(double); break; } /* switch */ write(file, (char *)&col, 2); write(file, (char *)&row, 2); write(file, (char *)&format[col][row], 1); write(file, (char *)&size, 2); write(file, (char *)cellptr, size); } } } close(file); writef(1, 25, WHITE, strlen(MSGSAVING), ""); gotoxy(1, 25); changed = FALSE; } /* savesheet */
PGPError pgpUserChooseAndDisableKeys( struct pgpmainBones *mainbPtr, PGPKeySetRef keysToDisable ) { struct pgpfileBones *filebPtr = mainbPtr->filebPtr; PGPError err; PGPKeyListRef keylist; PGPKeyIterRef keyiter; PGPKeyRef key; err = PGPOrderKeySet( keysToDisable, kPGPAnyOrdering, &keylist ); pgpAssertNoErr(err); err = PGPNewKeyIter( keylist, &keyiter ); pgpAssertNoErr(err); err = PGPKeyIterRewind( keyiter ); pgpAssertNoErr(err); err = PGPKeyIterNext( keyiter, &key ); while( key != NULL ) { PGPBoolean propData = FALSE; pgpShowKeyBrief( filebPtr, key ); err = PGPGetKeyBoolean( key, kPGPKeyPropIsDisabled, &propData ); pgpAssertNoErr( err ); if( propData ) { fprintf( filebPtr->pgpout, LANG("\nKey is already disabled.\n" "Do you want to enable this key again (y/N)? ")); if( getyesno( filebPtr,'n',0) ) { if( mainbPtr->workingKeyServer ) { PGPKeySetRef single,failed=NULL; err = PGPNewSingletonKeySet( key, &single ); pgpAssertNoErr(err); /* does it get re-enabled??*/ err = PGPDisableFromKeyServer( mainbPtr->workingKeyServer, single, &failed ); if( IsPGPError(err) ) { pgpShowError( filebPtr, err, 0,0); if( failed ) PGPFreeKeySet(failed); } PGPFreeKeySet( single ); } else { err = PGPEnableKey( key ); pgpAssertNoErr( err ); } } } else { fprintf( filebPtr->pgpout, LANG("\nDisable this key (y/N)? ")); if( getyesno( filebPtr,'n',0) ) { if( mainbPtr->workingKeyServer ) { PGPKeySetRef single,failed=NULL; err = PGPNewSingletonKeySet( key, &single ); pgpAssertNoErr(err); err = PGPDisableFromKeyServer( mainbPtr->workingKeyServer, single, &failed ); if( IsPGPError(err) ) { pgpShowError( filebPtr, err, 0,0); if( failed ) PGPFreeKeySet(failed); } PGPFreeKeySet( single ); } else { err = PGPDisableKey( key ); pgpAssertNoErr( err ); } } } err = PGPKeyIterNext( keyiter, &key ); } if( err == kPGPError_EndOfIteration ) err = kPGPError_NoErr; return err; }
int revokeOrDisableKey(struct pgpmainBones *mainbPtr, char *keyguffin, PGPFileSpecRef keyfilespec) { PGPContextRef context = mainbPtr->pgpContext; struct pgpfileBones *filebPtr = mainbPtr->filebPtr; PGPEnv *env = mainbPtr->envbPtr->m_env; PGPBoolean compatible = mainbPtr->envbPtr->compatible; PGPKeySetRef ringset = NULL; PGPKeyListRef keylist = NULL; PGPKeyIterRef keyiter = NULL; PGPKeyRef key; PGPBoolean propData = FALSE; PGPError err, er2; PGPUInt32 pri; PGPBoolean needsfree = FALSE; char* passphrase = 0; int nkeysrevoked = 0; err = pgpOpenKeyringsFromPubringSpec( mainbPtr, keyfilespec, &ringset, kPGPKeyRingOpenFlags_Mutable ); if ( IsPGPError(err)) goto done; mainbPtr->workingRingSet=ringset; /*mainbPtr->workingGroupSet=NULL;*/ err = pgpGetMatchingKeyList( mainbPtr, keyguffin, kMatch_NotKeyServer, &keylist ); pgpAssertNoErr(err); err = PGPNewKeyIter( keylist, &keyiter ); pgpAssertNoErr(err); err = PGPKeyIterRewind( keyiter ); pgpAssertNoErr(err); err = PGPKeyIterNext( keyiter, &key ); while( key != NULL ) { pgpShowKeyBrief( filebPtr, key ); pgpShowKeyFingerprint( filebPtr, key ); /* XXX the old version used to ask for your password here... now is different a bit*/ err = PGPGetKeyBoolean( key, kPGPKeyPropIsSecret, &propData ); if( propData ) { PGPUserIDRef alias; PGPSize actual; char useridstr[ kPGPMaxUserIDSize ]; err = PGPGetPrimaryUserID( key, &alias ); pgpAssertNoErr(err); err = PGPGetUserIDStringBuffer( alias, kPGPUserIDPropName, kPGPMaxUserIDSize, useridstr, &actual ); pgpAssertNoErr(err); fprintf(filebPtr->pgpout, LANG("\nDo you want to permanently revoke your public key\n" "by issuing a secret key compromise certificate\n" "for \"%s\" (y/N)? "), useridstr ); if( getyesno( filebPtr, 'n', 0 ) ) { err = pgpGetValidPassphrase( mainbPtr, key, &passphrase, &needsfree); if( err == 0 ) { nkeysrevoked++; err = PGPRevokeKey( key, PGPOPassphrase( context, passphrase ), PGPOLastOption( context ) ); pgpAssertNoErr( err ); } goto tail; } } err = PGPGetKeyBoolean( key, kPGPKeyPropIsDisabled, &propData ); pgpAssertNoErr( err ); if( propData ) { fprintf( filebPtr->pgpout, LANG("\nKey is already disabled.\n" "Do you want to enable this key again (y/N)? ")); if( getyesno( filebPtr,'n',0) ) { err = PGPEnableKey( key ); pgpAssertNoErr( err ); } } else { fprintf( filebPtr->pgpout, LANG("\nDisable this key (y/N)? ")); if( getyesno( filebPtr,'n',0) ) { err = PGPDisableKey( key ); pgpAssertNoErr( err ); } } tail: err = PGPKeyIterNext( keyiter, &key ); } /*if( nkeysrevoked > 0 ) { err = PGPPropagateTrust( ringset ); pgpAssertNoErr( err ); }*/ if( PGPKeySetNeedsCommit( ringset ) ) { err = PGPCommitKeyRingChanges( ringset ); } done: if( needsfree ) { PGPFreeData( passphrase ); pgpRemoveFromPointerList( mainbPtr->leaks, passphrase ); } if (ringset) er2 = PGPFreeKeySet( ringset ); mainbPtr->workingRingSet = NULL; if (keyiter) er2 = PGPFreeKeyIter( keyiter ); if (keylist) er2 = PGPFreeKeyList( keylist ); if ( !compatible && IsPGPError(err) && pgpenvGetInt( env, PGPENV_VERBOSE, &pri, &er2) ) pgpShowError(filebPtr, err,__FILE__,__LINE__); return err; }
PGPError addToWorkingRingSet(struct pgpmainBones *mainbPtr, PGPKeySetRef keySet, PGPBoolean bAddToDefault ) { PGPContextRef context = mainbPtr->pgpContext; PGPEnv *env = pgpContextGetEnvironment( context ); struct pgpfileBones *filebPtr = mainbPtr->filebPtr; struct pgpenvBones *envbPtr = mainbPtr->envbPtr; PGPKeyIterRef iter = NULL; PGPError err; PGPKeyRef key = 0; PGPKeyRef origkey = 0; PGPKeyID keyid; int copying = 0; int newkeys = 0, newsigs = 0, newuids = 0, newrvks = 0; PGPKeyListRef keylist = 0; char* ringfile = ""; PGPInt32 pri; PGPInt32 verbose = pgpenvGetInt( env, PGPENV_VERBOSE, &pri, &err ); PGPInt32 interactive = envbPtr->interactiveAdd; PGPBoolean batchmode = pgpenvGetInt( env, PGPENV_BATCHMODE, &pri, &err ); PGPKeySetRef keepset = NULL, origset = NULL; PGPBoolean ans; PGPKeySetRef defKeySet = kPGPInvalidRef; err = PGPOpenDefaultKeyRings(context, kPGPKeyRingOpenFlags_Mutable, &defKeySet); if(IsPGPError(err)) goto done; if(bAddToDefault) mainbPtr->workingRingSet = defKeySet; pgpAssertAddrValid( mainbPtr, struct pgpmainBones ); pgpAssertAddrValid( mainbPtr->workingRingSet, PGPKeySetRef ); err = PGPNewEmptyKeySet( mainbPtr->workingRingSet, &origset ); pgpAssertNoErr(err); err = PGPOrderKeySet( keySet, kPGPAnyOrdering, &keylist ); pgpAssertNoErr(err); err = PGPNewKeyIter( keylist, &iter ); pgpAssertNoErr(err); if(verbose) fprintf(filebPtr->pgpout, LANG("\nPASS 1.. find the existing keys\n")); err = PGPKeyIterRewind( iter ); pgpAssertNoErr(err); err = PGPKeyIterNext( iter, &key); if( err ) { fprintf( filebPtr->pgpout,LANG("Could not read key from keyfile.")); goto done; } while( key ) { err = PGPGetKeyIDFromKey( key, &keyid ); pgpAssertNoErr(err); err = PGPGetKeyByKeyID( defKeySet, &keyid, kPGPPublicKeyAlgorithm_Invalid, &origkey ); if(err == 0 ) err = pgpAddKeyToKeySet( origkey, origset ); err = PGPKeyIterNext( iter, &key ); } if(verbose) fprintf(filebPtr->pgpout, LANG("\nPASS 2.. ask whether to add the new keys\n")); err = PGPKeyIterRewind( iter ); pgpAssertNoErr(err); err = PGPKeyIterNext( iter, &key); if( err ) { fprintf( filebPtr->pgpout,LANG("Could not read key from keyfile.")); goto done; } while( key ) { PGPBoolean isnew; err = PGPGetKeyIDFromKey( key, &keyid ); pgpAssertNoErr(err); err = PGPGetKeyByKeyID( defKeySet, &keyid, kPGPPublicKeyAlgorithm_Invalid, &origkey ); /* Copy if all criteria are met */ copying = 0; isnew = FALSE; if(err == 0 ) { copying = 1; } else { /* is a new key*/ err = pgpShowKeyListFormat( filebPtr, mainbPtr->workingRingSet, iter, key, kShow_Sigs | kShow_Checks ); if( interactive ) { fprintf( filebPtr->pgpout, LANG( "\nDo you want to add this key to keyring '%s' (y/N)? "), ringfile); copying = getyesno(filebPtr,'n', batchmode ) ? 1 : 0; } else copying = 1; if(copying) { isnew=TRUE; newkeys++; } } if( copying ) { if(keepset == NULL) { err = PGPNewKeySet( context, &keepset ); pgpAssertNoErr(err); } err = pgpAddKeyToKeySet( key, keepset ); if(IsPGPError(err)) { pgpShowError(filebPtr, err,__FILE__,__LINE__); } if( isnew && !batchmode ) { /* This is not efficient, because it loops on keepset, so avoid calling it in batchmode. */ err = pgpMarkKeyInSet( keepset, key ); } } err = PGPKeyIterNext( iter, &key ); if( err != 0 || key == 0 ) { break; } } if(err == kPGPError_EndOfIteration) err = 0; if( newkeys > 0 && !interactive ) { fprintf( filebPtr->pgpout, LANG("\nkeyfile contains %d new keys. "), newkeys); fprintf( filebPtr->pgpout, LANG( "Add these keys to keyring ? (Y/n) ")); fflush( filebPtr->pgpout ); ans = getyesno(filebPtr, 'y', batchmode); /* add a newline to make it easier to read */ fprintf(filebPtr->pgpout, "\n"); fflush(filebPtr->pgpout); if(!ans) goto done; } if(verbose) fprintf(filebPtr->pgpout, LANG( "\nPASS 3.. show the new userids and new sigs\n")); { PGPSize keys,uids,sigs,rvks; err = pgpMarkKeySet( origset ); pgpAssertNoErr(err); err = PGPAddKeys( origset, keepset ); pgpAssertNoErr(err); /* * mark default key set to determine which keys are * being added in, need to do this because mainbPtr->workingRingSet * might be a in memory key set */ err = pgpMarkKeySet( defKeySet ); pgpAssertNoErr(err); err = PGPAddKeys( keepset, defKeySet ); pgpAssertNoErr(err); err = pgpShowKeySetUnmarked( filebPtr, defKeySet, &keys, &uids, &sigs, &rvks ); pgpAssertNoErr(err); /*newkeys += keys;*/ newuids += uids; newsigs += sigs; newrvks += rvks; } if(verbose) fprintf(filebPtr->pgpout, LANG("\nPASS 4... add them to the keyring\n")); if(!bAddToDefault) { err = PGPAddKeys( keepset, mainbPtr->workingRingSet ); pgpAssertNoErr(err); } /* For now AddKeys should be more or less the same as mergekeys */ /* User feedback */ if( newsigs == 0 && newkeys == 0 && newuids == 0 && newrvks == 0 ) { goto done; } /* Check signatures */ PGPCheckKeyRingSigs( keepset, mainbPtr->workingRingSet, 0, NULL, NULL ); if( err ) { if( verbose ) { fprintf(filebPtr->pgpout, LANG( "addToWorkingRingSet: pgpDoCheckKeySet() returned %d\n"), err); } goto done; } /* More user feedback */ fprintf(filebPtr->pgpout, LANG("\nKeyfile contains:\n")); if (newkeys) fprintf(filebPtr->pgpout, LANG("%4d new key(s)\n"), newkeys); if (newsigs) fprintf(filebPtr->pgpout, LANG("%4d new signatures(s)\n"), newsigs); if (newuids) fprintf(filebPtr->pgpout, LANG("%4d new user ID(s)\n"), newuids); if (newrvks) fprintf(filebPtr->pgpout, LANG("%4d new revocation(s)\n"), newrvks); err = PGPPropagateTrust( mainbPtr->workingRingSet ); pgpAssertNoErr(err); /* mainbPtr->workingRingSet = ringSet;*/ /* mainbPtr->workingGroupSet = NULL;*/ err = pgpProcessUncertifiedKeys( mainbPtr, keepset ); if( IsPGPError(err)) { if(err == kPGPError_UserAbort) err = kPGPError_NoErr; goto done; } err = pgpProcessUntrustedKeys( mainbPtr, keepset, mainbPtr->workingRingSet ); done: if(PGPKeySetNeedsCommit(mainbPtr->workingRingSet)) PGPCommitKeyRingChanges(mainbPtr->workingRingSet); if(defKeySet != kPGPInvalidRef) PGPFreeKeySet(defKeySet); if(keepset != NULL) PGPFreeKeySet( keepset ); if( iter ) PGPFreeKeyIter( iter ); if( keylist) PGPFreeKeyList( keylist ); if( origset ) PGPFreeKeySet( origset ); /* The event handler will call addToRingSetFinish( ringSet ); before this is done */ return err; }
PGPError pgpShowKeyMarked( struct pgpfileBones *filebPtr, PGPKeyIterRef iterContext, PGPKeyRef key, PGPSize *newKeyCount, PGPSize *newUIDCount, PGPSize *newSigCount, PGPSize *newRevokeCount ) { PGPError err; PGPUserIDRef alias; struct pgpenvBones *envbPtr = filebPtr->envbPtr; PGPEnv *env = envbPtr->m_env; PGPInt32 pri; PGPBoolean batchmode = pgpenvGetInt( env, PGPENV_BATCHMODE, &pri, &err ); PGPBoolean verbose = pgpenvGetInt( env, PGPENV_VERBOSE, &pri, &err ); PGPUserValue val; PGPBoolean iskrev,issec; PGPBoolean compatible = envbPtr->compatible; PGPInt32 interactive = envbPtr->interactiveAdd; if(newKeyCount) *newKeyCount = 0; if(newUIDCount) *newUIDCount = 0; if(newSigCount) *newSigCount = 0; if(newRevokeCount) *newRevokeCount = 0; err = PGPGetKeyBoolean( key, kPGPKeyPropIsRevoked, &iskrev ); pgpAssertNoErr(err); err = PGPGetKeyBoolean( key, kPGPKeyPropIsSecret, &issec ); pgpAssertNoErr(err); err = PGPGetKeyUserVal( key, &val ); if( iskrev ) { if( ( (PGPInt32)val & kMark_Revocation ) ) { if(verbose) fprintf( filebPtr->pgpout, LANG("\nNew revocation\n") ); if(newRevokeCount) (*newRevokeCount)++; } } else { if( ( (PGPInt32)val & kMark_Ordinary ) ) { if(verbose) fprintf( filebPtr->pgpout, LANG("\nnew key\n") ); /* new key. return early.*/ if(newKeyCount) (*newKeyCount)++; /*return kPGPError_NoErr;*/ } } if( issec ) { if( ( (PGPInt32)val & kMark_Secret ) ) { if(verbose) fprintf( filebPtr->pgpout, LANG("\nNew secret key\n") ); if(newKeyCount) (*newKeyCount)++; } } err = PGPKeyIterRewindUserID( iterContext ); pgpAssertNoErr(err); err = PGPKeyIterNextUserID( iterContext, &alias); while( alias ) { PGPSize actual; char useridstr[ kPGPMaxUserIDSize ]; err = PGPGetUserIDStringBuffer( alias, kPGPUserIDPropName, kPGPMaxUserIDSize, useridstr, &actual ); pgpAssertNoErr(err); err = PGPGetUserIDUserVal( alias, &val); pgpAssertNoErr(err); if( val != (PGPUserValue) kMark_Ordinary ) { PGPBoolean ans; if( interactive ) { fprintf( filebPtr->pgpout, LANG("\nNew userid: \"%s\".\n"), useridstr); fprintf( filebPtr->pgpout, LANG("\nWill be added to the following key:\n")); pgpShowKeyBrief( filebPtr, key ); fprintf( filebPtr->pgpout, LANG("Add this userid (y/N)? ")); fflush( filebPtr->pgpout ); ans = getyesno( filebPtr, 'n', batchmode ); } if( interactive && !ans ) { err = PGPRemoveUserID( alias ); pgpAssertNoErr(err); } else if(newUIDCount) (*newUIDCount)++; } else { PGPSigRef cert; err = PGPKeyIterRewindUIDSig( iterContext ); pgpAssertNoErr(err); err = PGPKeyIterNextUIDSig( iterContext, &cert ); /*if err, there are none.*/ while( cert ) { PGPKeyID kid; char kstr[kPGPMaxKeyIDStringSize]; PGPBoolean isrev; err = PGPGetKeyIDOfCertifier( cert, &kid ); pgpAssertNoErr(err); err = pgpGetKeyIDStringCompat( &kid, TRUE, compatible, kstr ); pgpAssertNoErr(err); err = PGPGetSigBoolean( cert, kPGPSigPropIsRevoked, &isrev ); pgpAssertNoErr(err); if( isrev ) { err = PGPGetSigUserVal( cert, &val ); if( val == (PGPUserValue) kMark_Revocation ) { fprintf( filebPtr->pgpout, LANG( "New revocation from keyID %s on userid %s\n"), kstr, useridstr); if(newRevokeCount) (*newRevokeCount)++; } } else { err = PGPGetSigUserVal( cert, &val ); if( val == (PGPUserValue) kMark_Ordinary ) { fprintf( filebPtr->pgpout, LANG( "New signature from keyID %s on userid %s\n"), kstr, useridstr); if(newSigCount) (*newSigCount)++; } } err = PGPKeyIterNextUIDSig( iterContext, &cert ); /*if err, there are no more.*/ } } err = PGPKeyIterNextUserID( iterContext, &alias); } if(err == kPGPError_EndOfIteration) err = kPGPError_NoErr; return err; }
static PGPError askToSign( struct pgpmainBones *mainbPtr, PGPKeyRef key, PGPBoolean firsttimeaskfirst ) { PGPContextRef context = mainbPtr->pgpContext; struct pgpfileBones *filebPtr = mainbPtr->filebPtr; /* - seems to get your public key - then it opens the ringfile i guess for the target key - and if key is compromised then it returns 0 - and on a file i/o error it returns -1 - and if not a key then it returns zero - and it scans till it reaches the userid - or fails - and then it reads the trust level - and if the trust is fine then it returns 0 - and if asking is enabled it asks you generally speaking - and then it shows the key - and then it asks you specifically if you want to certify - and then it does another maint update pass */ PGPError err; PGPInt32 pri; PGPEnv *env = pgpContextGetEnvironment( context ); PGPBoolean batchmode = pgpenvGetInt( env, PGPENV_BATCHMODE, &pri, &err ); PGPBoolean issec; pgpAssertAddrValid( mainbPtr, struct pgpmainBones ); pgpAssertAddrValid( mainbPtr->workingRingSet, PGPKeySetRef ); if( pgpGetKeyValidity( key ) > kPGPValidity_Unknown ) { return kPGPError_ItemAlreadyExists; } PGPGetKeyBoolean( key, kPGPKeyPropIsSecret, &issec ); if(issec) return kPGPError_ItemAlreadyExists; if( firsttimeaskfirst == TRUE ) { fprintf(filebPtr->pgpout,LANG( "\nOne or more of the new keys are not fully certified.\n" "Do you want to certify any of these keys yourself (y/N)? ")); if(!getyesno(filebPtr,'n',batchmode )) { return kPGPError_UserAbort; } } pgpShowKeyBrief( filebPtr, key ); fprintf(filebPtr->pgpout, LANG( "\nDo you want to certify this key yourself (y/N)? ")); if( getyesno(filebPtr,'n',batchmode )) { PGPKeyRef sigkey; /* mainbPtr->workingRingSet=ringSet;*/ /* mainbPtr->workingGroupSet=NULL;*/ err = pgpGetMySigningKey( mainbPtr, &sigkey ); if( err ) { return err; } if( pgpSignKey( mainbPtr, sigkey, key, NULL ) ) { PGPPropagateTrust( mainbPtr->workingRingSet ); } } return kPGPError_NoErr; }
/* Adds (prepends) key file to key ring file. */ int _addto_keyring(char *keyfile, char *ringfile) { FILE *f, *g, *h; long file_position, fp; int pktlen; byte ctb; int status; unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION]; unit n1[MAX_UNIT_PRECISION]; byte keyID[KEYFRAGSIZE]; byte userid[256]; /* key certificate userid */ byte userid1[256]; word32 tstamp; byte *timestamp = (byte *) & tstamp; /* key certificate timestamp */ boolean userid_seen = FALSE; int commonkeys = 0; int copying; struct newkey *nkey, *nkeys = NULL; char *scratchf; /* open file f for read, in binary (not text) mode... */ if ((f = fopen(keyfile, FOPRBIN)) == NULL) { fprintf(pgpout, LANG("\n\007Can't open key file '%s'\n"), keyfile); return -1; } ctb = 0; if (fread(&ctb, 1, 1, f) != 1 || !is_key_ctb(ctb)) { fclose(f); return -1; } rewind(f); setoutdir(ringfile); scratchf = tempfile(0); /* * get userids from both files, maybe should also use the default public * keyring if ringfile is not the default ring. */ setkrent(ringfile); setkrent(keyfile); init_userhash(); if (!file_exists(ringfile)) { /* ringfile does not exist. Can it be created? */ /* open file g for writing, in binary (not text) mode... */ g = fopen(ringfile, FOPWBIN); if (g == NULL) { fprintf(pgpout, LANG("\nKey ring file '%s' cannot be created.\n"), ringfile); fclose(f); goto err; } fclose(g); } /* Create working output file */ /* open file g for writing, in binary (not text) mode... */ if ((g = fopen(scratchf, FOPWBIN)) == NULL) { fclose(f); goto err; } newkeys = newsigs = newids = newrvks = 0; /* Pass 1 - copy all keys from f which aren't in ring file */ /* Also copy userid and signature packets. */ fprintf(pgpout, LANG("\nLooking for new keys...\n")); copying = FALSE; if (gpk_open(ringfile) < 0) { fclose(f); /* close key file */ fclose(g); goto err; } for (;;) { file_position = ftell(f); status = readkeypacket(f, FALSE, &ctb, timestamp, (char *) userid, n, e, NULL, NULL, NULL, NULL, NULL, NULL); /* Note that readkeypacket has called set_precision */ if (status == -1) /* EOF */ break; if (status == -2 || status == -3) { fprintf(pgpout, LANG("\n\007Could not read key from file '%s'.\n"), keyfile); fclose(f); /* close key file */ fclose(g); goto err; } if (status < 0) { copying = FALSE; continue; /* don't merge keys from unrecognized version */ } /* Check to see if key is already on key ring */ if (is_key_ctb(ctb)) { extract_keyID(keyID, n); /* from keyfile, not ringfile */ publickey = is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE); /* Check for duplicate key in key ring: */ status = get_publickey(&fp, NULL, keyID, timestamp, userid, n1, e); if (status == 0) { /* key in both keyring and keyfile */ if (mp_compare(n, n1) != 0) { fprintf(pgpout, LANG("\n\007Warning: Key ID %s matches key ID of key already on \n\ key ring '%s', but the keys themselves differ.\n\ This is highly suspicious. This key will not be added to ring.\n\ Acknowledge by pressing return: "), keyIDstring(keyID), ringfile); getyesno('n'); } else { ++commonkeys; } copying = FALSE; } else if (status == -1) { /* key NOT in keyring */
/* Merge key from fkey (which is keyfile) at keypos with key from * fring (which is ringfile) at ringpos, appending result to out. */ static int mergekeys(FILE * fkey, char *keyfile, long keypos, FILE * fring, char *ringfile, long *pringpos, FILE * out) { long ringkeypos, keykeypos, ringpos; int ringpktlen, keypktlen; int status; byte ctb; int copying; boolean ring_compromise = FALSE; byte userid[256]; /* First, copy the key packet itself, plus any comments or ctrls */ ringkeypos = ringpos = *pringpos; fseek(fring, ringpos, SEEK_SET); (void) nextkeypacket(fring, &ctb); ringpktlen = ftell(fring) - ringpos; copyfilepos(fring, out, ringpktlen, ringpos); for (;;) { ringpos = ftell(fring); status = nextkeypacket(fring, &ctb); if (status < 0 || is_key_ctb(ctb) || ctb == CTB_USERID) break; if (is_ctb_type(ctb, CTB_SKE_TYPE)) ring_compromise = TRUE; /* compromise cert on keyring */ ringpktlen = ftell(fring) - ringpos; copyfilepos(fring, out, ringpktlen, ringpos); } fseek(fring, ringpos, SEEK_SET); /* Now, ringpos points just past key packet and ctrl packet. */ /* Advance keypos to the analogous location. */ fseek(fkey, keypos, SEEK_SET); keykeypos = keypos; (void) nextkeypacket(fkey, &ctb); keypktlen = ftell(fkey) - keypos; /* for check_key_sig() */ for (;;) { keypos = ftell(fkey); status = nextkeypacket(fkey, &ctb); if (status < 0 || ctb == CTB_USERID || is_ctb_type(ctb, CTB_SKE_TYPE)) break; } if (!ring_compromise && is_ctb_type(ctb, CTB_SKE_TYPE)) { /* found a compromise cert on keyfile that is not in ringfile */ word32 timestamp; byte sig_class; int cert_pktlen; cert_pktlen = ftell(fkey) - keypos; if (check_key_sig(fkey, keykeypos, keypktlen, (char *) userid, fkey, keypos, ringfile, (char *) userid, (byte *) & timestamp, &sig_class) == 0 && sig_class == KC_SIGNATURE_BYTE) { PascalToC((char *) userid); fprintf(pgpout, LANG("Key revocation certificate from \"%s\".\n"), LOCAL_CHARSET((char *) userid)); copyfilepos(fkey, out, cert_pktlen, keypos); /* Show updates */ if (batchmode) show_key(fring, *pringpos, SHOW_CHANGE); ++newrvks; } else fprintf(pgpout, LANG("\n\007WARNING: File '%s' contains bad revocation certificate.\n"), keyfile); } fseek(fkey, keypos, SEEK_SET); /* Second, copy all keyfile userid's plus signatures that aren't * in ringfile. */ copying = FALSE; for (;;) { /* Read next userid from keyfile; see if it is in ringfile; * set copying true/false accordingly. If copying is true * and it is a userid or a signature, copy it. Loop till hit * a new key in keyfile, or EOF. */ keypos = ftell(fkey); status = readkeypacket(fkey, FALSE, &ctb, NULL, (char *) userid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (status == -3) /* unrecoverable error: bad packet length etc. */ return status; keypktlen = ftell(fkey) - keypos; if (status == -1 || is_key_ctb(ctb)) break; /* EOF or next key */ if (status < 0) continue; /* bad packet, skip it */ if (ctb == CTB_USERID) { long userid_pos; int userid_len; PascalToC((char *) userid); /* Set copying true if userid is not in the ringfile */ copying = (getpubuserid(ringfile, ringkeypos, userid, &userid_pos, &userid_len, TRUE) < 0); if (copying) { putc('\n', pgpout); fprintf(pgpout, LANG("New userid: \"%s\".\n"), LOCAL_CHARSET((char *) userid)); fprintf(pgpout, LANG("\nWill be added to the following key:\n")); show_key(fring, *pringpos, 0); fprintf(pgpout, LANG("\nAdd this userid (y/N)? ")); if (batchmode || getyesno('n')) { ++newids; /* Show an update string */ if (batchmode) { fprintf(pgpout, "\n"); show_key(fring, *pringpos, SHOW_CHANGE); } } else { copying = FALSE; } } } if (copying) { if (ctb == CTB_USERID || is_ctb_type(ctb, CTB_SKE_TYPE)) { copyfilepos(fkey, out, keypktlen, keypos); if (publickey) { if (is_ctb_type(ctb, CTB_SKE_TYPE)) write_trust(out, KC_SIGTRUST_UNDEFINED); else write_trust(out, KC_LEGIT_UNKNOWN); } } } } /* Third, for all ring userid's, if not in keyfile, copy the userid * plus its dependant signatures. */ fseek(fring, ringpos, SEEK_SET); /* Grab the keyID here */ readkeypacket(fring, FALSE, &ctb, NULL, (char *) userid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); fseek(fring, ringpos, SEEK_SET); for (;;) { ringpos = ftell(fring); status = readkeypacket(fring, FALSE, &ctb, NULL, (char *) userid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); ringpktlen = ftell(fring) - ringpos; if (status == -3) return status; if (status == -1 || is_key_ctb(ctb)) break; if (ctb == CTB_USERID) { long userid_pos; int userid_len; /* See if there is a match in keyfile */ PascalToC((char *) userid); /* don't use substring match (exact_match = TRUE) */ if (getpubuserid(keyfile, keykeypos, userid, &userid_pos, &userid_len, TRUE) >= 0) { if ((status = mergesigs(fkey, keyfile, userid_pos, fring, ringfile, &ringpos, out)) < 0) return status; copying = FALSE; } else { copying = TRUE; } } if (copying) { /* Copy ringfile userid and sigs to out */ copyfilepos(fring, out, ringpktlen, ringpos); } } /* End of loop for each key in ringfile */ fseek(fring, ringpos, SEEK_SET); *pringpos = ringpos; return 0; } /* mergekeys */