📄 pgpkeylib.c
字号:
if (!adkeyset)
{
ringIterDestroy (riter);
ringSetDestroy (rsetnew);
return NULL;
}
}
ringSetAddObjectChildren (adkeyset, rset, rkey);
}
}
}
}
ringIterDestroy (riter);
/* Last, merge adkeyset into rsetnew, also stripping secrets */
if (adkeyset) {
ringSetFreeze (adkeyset);
riter = ringIterCreate (adkeyset);
if (!riter) {
ringSetDestroy (adkeyset);
ringSetDestroy (rsetnew);
return NULL;
}
/* Loop over rsetnew iterator, adding non-secret objects */
/* We will always strip ADK secrets, he can export those explicitly */
while ((level = ringIterNextObjectAnywhere(riter)) > 0) {
RingObject *obj = ringIterCurrentObject (riter, level);
if (ringObjectType (obj) == RINGTYPE_SEC)
continue;
ringSetAddObject (rsetnew, obj);
}
ringIterDestroy (riter);
ringSetDestroy (adkeyset);
}
/* Return new set in frozen form */
ringSetFreeze (rsetnew);
return rsetnew;
}
#if PGP_MACINTOSH
#pragma global_optimizer on
#endif
/*
* Frees optionList, unlike most other internal functions. rset
* defines the exact set to be exported; key is the first key in the
* set.
*/
static PGPError
sExportKeySetInternal (PGPContextRef context, PGPKeyRef key,
RingSet const *rset, PGPOptionListRef optionList)
{
PGPUInt32 fExportSecrets;
PGPUInt32 fExportSubSecrets;
PGPBoolean fExportAttributes;
PGPBoolean fExportFormat;
PGPByte *buf;
PGPSize bufSize;
PGPSize bufSizeRead;
PGPFile *pfile;
RingSet const *rsetpub;
PGPOptionListRef optList;
PGPExportFormat exportFormat = kPGPExportFormat_Complete;
PGPUInt32 wExportFormat;
PGPBoolean armorop;
PGPError err = kPGPError_NoErr;
pgpAssert( pgpContextIsValid( context ) );
buf = NULL;
pfile = NULL;
rsetpub = NULL;
optList = NULL;
/* Read optional options */
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_ExportPrivateKeys, FALSE,
"%d", &fExportSecrets ) ) )
goto error;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_ExportPrivateSubkeys, FALSE,
"%d", &fExportSubSecrets ) ) )
goto error;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_ExportFormat, FALSE,
"%b%d", &fExportFormat, &wExportFormat ) ) )
goto error;
if (fExportFormat)
exportFormat = (PGPExportFormat) wExportFormat;
/* Handle X509 export formats */
if (exportFormat == kPGPExportFormat_X509Cert ||
exportFormat >= kPGPExportFormat_X509CertReq) {
err = sExportKeyX509 (context, key, rset,
exportFormat, optionList);
goto error;
}
fExportAttributes = (exportFormat > kPGPExportFormat_Basic);
/* Output public or private portion */
rsetpub = filterPubRingSet (rset, (PGPBoolean)fExportSecrets,
(PGPBoolean)(fExportSubSecrets|fExportSecrets),
FALSE, fExportAttributes);
if (!rsetpub) {
err = kPGPError_OutOfMemory;
goto error;
}
/* Create memory buffer to write to */
pfile = pgpFileMemOpen( context, NULL, 0 );
if( IsNull( pfile ) ) {
err = kPGPError_OutOfMemory;
goto error;
}
/* Output data to memory buffer */
if( IsPGPError( err = ringSetWrite (rsetpub, pfile, NULL, PGPVERSION_3,
0) ) )
goto error;
ringSetDestroy( (RingSet *)rsetpub );
rsetpub = NULL;
/* Read data we just wrote */
bufSize = pgpFileTell (pfile );
buf = (PGPByte *)pgpContextMemAlloc( context, bufSize, 0 );
if( IsNull( buf ) ) {
err = kPGPError_OutOfMemory;
goto error;
}
(void)pgpFileSeek( pfile, 0, SEEK_SET );
bufSizeRead = pgpFileRead( buf, bufSize, pfile );
pgpAssert( bufSizeRead == bufSize );
pgpFileClose( pfile );
pfile = NULL;
/* Do ascii armoring */
/* If user specified an ascii armor option, use his, else use TRUE */
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_ArmorOutput, FALSE,
"%b", &armorop ) ) )
goto error;
/* This next call frees optionList */
if( IsPGPError( err = PGPBuildOptionList( context, &optList, optionList,
(armorop ?
PGPONullOption(context) :
PGPOArmorOutput(context, TRUE)),
PGPORawPGPInput(context, TRUE),
PGPOCompression(context, FALSE),
PGPOLastOption(context) ) ) )
goto error;
optionList = NULL;
if( IsPGPError( err = PGPEncode( context, optList,
PGPOInputBuffer(context, buf, bufSize),
PGPOLastOption(context) ) ) )
goto error;
pgpContextMemFree( context, buf );
buf = NULL;
/*
* If exporting private keys, append public keys to the buffer.
* We can't export them both together, as we end up with an output
* which has private keys followed by names and sigs. This can not
* be safely imported, because of the "version bug". The private key
* may have the incorrect version. So we instead output the public
* part with names and sigs, after the private part with private keys
* and names.
*/
if( fExportSecrets || fExportSubSecrets ) {
/* Get ringset for public portion */
rsetpub = filterPubRingSet (rset, FALSE, FALSE, FALSE,
fExportAttributes);
if (!rsetpub) {
err = kPGPError_OutOfMemory;
goto error;
}
/* Create memory buffer to write to */
pfile = pgpFileMemOpen( context, NULL, 0 );
if( IsNull( pfile ) ) {
err = kPGPError_OutOfMemory;
goto error;
}
/* Output data to memory buffer */
if( IsPGPError( err = ringSetWrite (rsetpub, pfile, NULL,
PGPVERSION_3, 0) ) )
goto error;
ringSetDestroy( (RingSet *)rsetpub );
rsetpub = NULL;
/* Read data we just wrote */
bufSize = pgpFileTell (pfile );
buf = (PGPByte *)pgpContextMemAlloc( context, bufSize, 0 );
if( IsNull( buf ) ) {
err = kPGPError_OutOfMemory;
goto error;
}
(void)pgpFileSeek( pfile, 0, SEEK_SET );
bufSizeRead = pgpFileRead( buf, bufSize, pfile );
pgpAssert( bufSizeRead == bufSize );
pgpFileClose( pfile );
pfile = NULL;
/* Do ascii armoring, append to existing output */
PGPAppendOptionList( optList,
PGPOAppendOutput(context, TRUE),
PGPOLastOption(context) );
if( IsPGPError( err = PGPEncode( context, optList,
PGPOInputBuffer(context, buf, bufSize),
PGPOLastOption(context) ) ) )
goto error;
pgpContextMemFree( context, buf );
buf = NULL;
}
err = kPGPError_NoErr;
/* Fall through */
error:
if( IsntNull( optList ) )
PGPFreeOptionList( optList );
if( IsntNull( optionList ) )
PGPFreeOptionList( optionList );
if( IsntNull( pfile ) )
pgpFileClose( pfile );
if( IsntNull( rsetpub ) )
ringSetDestroy ( (RingSet *)rsetpub);
if( IsntNull( buf ) )
pgpContextMemFree( context, buf );
return err;
}
#if PGP_MACINTOSH
#pragma global_optimizer reset
#endif
static const PGPOptionType expkeyOptionSet[] = {
kPGPOptionType_ExportPrivateKeys,
kPGPOptionType_ExportPrivateSubkeys,
kPGPOptionType_ExportFormat,
kPGPOptionType_OutputFileRef,
kPGPOptionType_OutputBuffer,
kPGPOptionType_OutputAllocatedBuffer,
kPGPOptionType_DiscardOutput,
kPGPOptionType_ArmorOutput,
kPGPOptionType_CommentString,
kPGPOptionType_VersionString,
kPGPOptionType_EventHandler,
kPGPOptionType_SendNullEvents,
kPGPOptionType_OutputLineEndType,
kPGPOptionType_OutputFormat,
/* Used for cert requests */
kPGPOptionType_Passphrase,
kPGPOptionType_Passkey,
kPGPOptionType_AttributeValue,
kPGPOptionType_InputBuffer
};
/* Frees optionList, unlike most other internal functions. */
PGPError
pgpExportKeySetInternal (PGPKeySet *keys, PGPOptionListRef optionList)
{
RingSet const *rset = NULL;
PGPContextRef context;
PGPKeyRef key;
PGPKeyListRef klist;
PGPKeyIterRef kiter;
PGPError err = kPGPError_NoErr;
if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
expkeyOptionSet, elemsof( expkeyOptionSet ) ) ) )
return err;
context = PGPGetKeySetContext( keys );
/* Get ringset corresponding to keyset */
if( IsPGPError( err = pgpKeySetRingSet( keys, TRUE, &rset ) ) )
goto error;
/* Extract first key from keyset */
if( IsPGPError( err = PGPOrderKeySet( keys, kPGPAnyOrdering, &klist ) ) )
goto error;
if( IsPGPError( err = PGPNewKeyIter( klist, &kiter ) ) ) {
PGPFreeKeyList( klist );
goto error;
}
err = PGPKeyIterNext( kiter, &key );
PGPFreeKeyIter( kiter );
PGPFreeKeyList( klist );
if( IsPGPError( err ) )
goto error;
if( IsPGPError( err = sExportKeySetInternal (context, key, rset,
optionList ) ) )
goto error;
/* Fall through */
error:
if( IsntNull( rset ) )
ringSetDestroy ( (RingSet *)rset);
return err;
}
static const PGPOptionType expOptionSet[] = {
kPGPOptionType_ExportPrivateKeys,
kPGPOptionType_ExportPrivateSubkeys,
kPGPOptionType_ExportFormat,
kPGPOptionType_OutputFileRef,
kPGPOptionType_OutputBuffer,
kPGPOptionType_OutputAllocatedBuffer,
kPGPOptionType_DiscardOutput,
kPGPOptionType_ArmorOutput,
kPGPOptionType_CommentString,
kPGPOptionType_VersionString,
kPGPOptionType_EventHandler,
kPGPOptionType_SendNullEvents,
kPGPOptionType_OutputLineEndType,
kPGPOptionType_OutputFormat,
kPGPOptionType_ExportKeySet,
kPGPOptionType_ExportKey,
kPGPOptionType_ExportUserID,
kPGPOptionType_ExportSig,
/* Used for cert requests */
kPGPOptionType_Passphrase,
kPGPOptionType_Passkey,
kPGPOptionType_AttributeValue,
kPGPOptionType_InputBuffer
};
/*
* Frees optionList, unlike most other internal functions. This is
* like exportkeyset, but it allows a single userid or sig to be
* specified. We only export that object, plus its parent object(s)
* and all its children. This is especially convenient when exporting
* a particular X.509 certificate.
*/
PGPError
pgpExportInternal (PGPContextRef context, PGPOptionListRef optionList)
{
PGPKeyRef key;
PGPUserIDRef userid;
PGPSigRef sig;
RingPool *pool;
RingSet *rset = NULL;
PGPKeySet *keys;
RingSet const *dbrset;
PGPBoolean fExportKeyRef, fExportUserIDRef, fExportSigRef;
PGPBoolean fExportKeySetRef;
void *wExportKeyRef, *wExportUserIDRef, *wExportSigRef;
void *wExportKeySetRef;
PGPInt32 successes = 0;
PGPError err = kPGPError_NoErr;
if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
expOptionSet, elemsof( expOptionSet ) ) ) )
return err;
/* See if we have a target key/name/sig to export */
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_ExportKeySet, FALSE,
"%b%d", &fExportKeySetRef, &wExportKeySetRef ) ) )
goto error;
if (fExportKeySetRef)
++successes;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_ExportKey, FALSE,
"%b%d", &fExportKeyRef, &wExportKeyRef ) ) )
goto error;
if (fExportKeyRef)
++successes;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_ExportUserID, FALSE,
"%b%d", &fExportUserIDRef, &wExportUserIDRef ) ) )
goto error;
if (fExportUserIDRef)
++successes;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_ExportSig, FALSE,
"%b%d", &fExportSigRef, &wExportSigRef ) ) )
goto error;
if (fExportSigRef)
++successes;
if (successes > 1) {
pgpDebugMsg( "too many key object selection options for PGPExport" );
err = kPGPError_BadParams;
goto error;
} else if (successes == 0) {
pgpDebugMsg( "no key object selection options for PGPExport" );
err = kPGPError_BadParams;
goto error;
}
/* Create ringset we will export */
pool = pgpContextGetRingPool( context );
pgpAssert( IsntNull( pool ) );
/* Handle the different cases */
if (fExportKeySetRef) {
PGPKeyListRef klist;
PGPKeyIterRef kiter;
keys = (PGPKeySet *) wExportKeySetRef;
/* Extract first key from keyset */
if( IsPGPError( err = PGPOrderKeySet( keys, kPGPAnyOrdering,
&klist ) ) )
goto error;
if( IsPGPError( err = PGPNewKeyIter( klist, &kiter ) ) ) {
PGPFreeKeyList( klist );
goto error;
}
err = PGPKeyIterNext( kiter, &key );
PGPFreeKeyIter( kiter );
PGPFreeKeyList( klist );
if( IsPGPError( err ) )
goto error;
if( IsPGPError( err = pgpKeySetRingSet( keys, TRUE,
(RingSet const **)&rset ) ) )
goto error;
} else {
RingObject *obj = NULL;
rset = ringSetCreate (pool);
if( IsNull( rset ) ) {
err = ringPoolError(pool)->error;
goto error;
}
if (fExportKeyRef) {
key = (PGPKey *) wExportKeyRef;
obj = key->key;
} else if (fExportUserIDRef) {
userid = (PGPUserID *) wExportUserIDRef;
key = userid->key;
obj = userid->userID;
} else if (fExportSigRef) {
sig = (PGPSig *) wExportSigRef;
if (sig->type == keycert) {
key = sig->up.key;
} else {
key = sig->up.userID->key;
}
obj = sig->cert;
} else {
pgpAssert(0);
}
pgpAssert( IsntNull( obj ) );
dbrset = pgpKeyDBRingSet (key->keyDB);
ringSetAddObjectChildren( rset, dbrset, obj );
ringSetFreeze( rset );
}
if( IsPGPError( err = sExportKeySetInternal (context, key, rset,
optionList ) ) )
goto error;
/* Fall through */
error:
if( IsntNull( rset ) )
ringSetDestroy ( (RingSet *)rset);
return err;
}
/*
* Local Variables:
* tab-width: 4
* End:
* vi: ts=4 sw=4
* vim: si
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -