📄 pgpdecode.c
字号:
}
}
/* Detect bad parsing situations */
if (type == PGPANN_ESK_TOO_BIG
|| type == PGPANN_SIGNATURE_TOO_BIG
|| type == PGPANN_PACKET_SHORT
|| type == PGPANN_PACKET_TRUNCATED
|| type == PGPANN_SCOPE_TRUNCATED) {
err = kPGPError_BadPacket;
goto error;
} else if (type == PGPANN_ARMOR_TOOLONG
|| type == PGPANN_ARMOR_BADLINE
|| type == PGPANN_ARMOR_NOCRC
|| type == PGPANN_ARMOR_CRCCANT
|| type == PGPANN_ARMOR_CRCBAD) {
err = kPGPError_AsciiParseIncomplete;
goto error;
}
/* Fall through */
error:
return err;
}
/*
* Display a message as appropriate.
* Nothing is appropriate for us, as we have no UI. Assert an error
* if it happens. (Perhaps better simply to ignore it.)
*/
static PGPError
pgpDecodeShowMessage(
void *arg,
PGPInt32 type,
PGPInt32 msg,
PGPUInt32 numargs,
...
)
{
PGPDecodeJob *s; /* Parameters for callbacks */
s = (PGPDecodeJob *) arg;
(void)type;
(void)msg;
(void)numargs;
return kPGPError_NoErr;
}
/*
* Decide whether to work on a section or to skip it.
*/
static PGPError
pgpDecodeDoCommit(
void *arg,
PGPInt32 scope
)
{
PGPDecodeJob *s; /* Parameters for callbacks */
PGPError err; /* Error code */
s = (PGPDecodeJob *) arg;
if( s->analyzeState == kAnalyzeGotType ) {
/* Tell user of results, let him say if we should continue */
s->analyzeState = kAnalyzeSegmentEndWait;
err = pgpEventBeginLex( s->context, &s->newOptionList,
s->func, s->userValue, s->sectionNumber,
s->sectOffset );
pgpCleanupOptionList( &s->newOptionList );
if( IsPGPError( err ) )
return err;
/* Give user analysis callback, let him tell us to skip section */
err = pgpEventAnalyze( s->context, &s->newOptionList,
s->func, s->userValue, s->analyzeType );
pgpCleanupOptionList( &s->newOptionList );
if( err == kPGPError_SkipSection ) {
return PGPANN_PARSER_EATIT;
}
if( IsPGPError( err ) )
return err;
}
/* Don't recurse into literal recursion packets unless set up for it */
/* Must be in recurse and passthrough mode to do it, else don't recurse */
if (scope == PGPANN_LITERAL_BEGIN && s->literalType == PGP_LITERAL_RECURSE
&& (s->passThroughFifo == NULL || !s->recurse))
return PGPANN_PARSER_PROCESS;
return PGPANN_PARSER_RECURSE;
}
/* Set up the output pipeline as appropriate */
static PGPError
pgpDecodeSetupNewOutput(
void *arg,
PGPPipeline **output,
PGPInt32 type,
char const *suggested_name
)
{
PGPDecodeJob *s; /* Parameters for callbacks */
PGPError err; /* Error code */
PGPUInt32 outputCount; /* How many output options we got */
PGPFileOpenFlags fileFlags; /* Flags for opening output file */
PGPFileType fileType; /* Type field for output file */
PGPByte *charMap; /* Charmap for output text filter */
PGPUInt32 passThroughNonPGP;
PGPUInt32 dummyLocalEncodeFlags;
PGPLineEndType dummyLineEnd;
PGPContextRef cdkContext = NULL;
PGPMemoryMgrRef memoryMgr = NULL;
PGPBoolean fFYEO = FALSE;
s = (PGPDecodeJob *) arg;
err = kPGPError_NoErr;
cdkContext = s->context;
memoryMgr = PGPGetContextMemoryMgr( cdkContext );
/*
* We need to adjust the pipeline at other stages, so we will save
* the output pointer. For those to work, it must always be the
* same whenever we are called. (The output pointer is the _address_
* of a pointer to the output portion of the pipeline, not the pointer
* to the pipeline itself.)
*/
if( IsNull( s->prevOutput ) )
s->prevOutput = output;
pgpAssert( s->prevOutput == output );
/* If have a prevoutput pipeline saved, switch back to that first. */
if( s->fPrevOutput ) {
if( IsPGPError( err = pgpCloseOutput( s, output ) ) )
goto error;
sRestoreOutputState( s, output );
}
if( type == PGPANN_PGPKEY_BEGIN && !s->passThrough ) {
/*
* Here we are adding a key. We must copy the data somewhere,
* and then convert it to a key set and then add it.
* We handle keys in passthrough mode below.
*/
sSaveOutputState( s, output );
if ( IsNull( s->outKey = pgpVariableMemModCreate( cdkContext,
output, ~(PGPSize)0 ) ) ) {
/* Guess at the cause */
err = kPGPError_OutOfMemory;
}
/* Return with success or failure */
goto error;
}
if( type == PGPANN_NONPGP_BEGIN ) {
if( IsPGPError( pgpFindOptionArgs( s->optionList,
kPGPOptionType_PassThroughIfUnrecognized, FALSE,
"%d", &passThroughNonPGP ) ) )
goto error;
if( !passThroughNonPGP ) {
/*
* Trash non-PGP data if not requesting passthrough.
* We will use the prevOutput mechanism to go back to what our
* output was before when we are through with it.
*/
sSaveOutputState( s, output );
if ( IsNull( pgpDevNullCreate ( cdkContext, output ) ) ) {
/* Guess at the cause */
err = kPGPError_OutOfMemory;
}
/* Return with success or failure */
goto error;
}
}
/* If have fixed output, just leave it open */
if( s->fixedOutput && IsntNull( *output ) ) {
/* Leave things open */
goto checkpassthrough;
}
/* Close previous output if any */
if( IsPGPError( err = pgpCloseOutput( s, output ) ) )
goto error;
if( !s->fixedOutput ) {
/* Get output for next part from user */
pgpAssert( IsntNull( s->func ) );
fFYEO = IsntNull( suggested_name ) &&
0==strcmp( suggested_name, "_CONSOLE" );
/* Turn empty names and magic ones into a null suggested_name */
if( IsntNull( suggested_name ) &&
( fFYEO || *suggested_name == '\0' ) )
suggested_name = NULL;
if( IsPGPError (err = pgpEventOutput( s->context, &s->newOptionList,
s->func, s->userValue,
type, suggested_name, fFYEO ) ) )
goto error;
/* Parse new output information if any */
if( IsntNull( s->outFileRef ) ) {
PFLFreeFileSpec( s->outFileRef );
s->outFileRef = NULL;
}
err = pgpSetupOutput( s->newOptionList,
s->env, &s->outFileRef,
&s->outBufPtr, &s->outBufPtrPtr,
&s->outBufMaxLength, &s->outBufUsedLength,
&s->outDiscard, &dummyLocalEncodeFlags,
&dummyLineEnd, &s->fAppendOutput );
pgpCleanupOptionList( &s->newOptionList );
if( IsPGPError( err ) )
goto error;
/* Make sure he gave us exactly one output option */
outputCount = !!IsntNull( s->outFileRef ) +
!!IsntNull( s->outBufPtr ) +
!!IsntNull( s->outBufPtrPtr ) +
!!s->outDiscard;
if( outputCount == 0 ) {
pgpDebugMsg( "Error: no output options" );
err = kPGPError_BadParams;
goto error;
} else if( outputCount > 1 ) {
pgpDebugMsg( "Error: multiple output options" );
err = kPGPError_BadParams;
goto error;
}
}
/* No support for other types than text or binary now */
if( type == PGPANN_NONPGP_BEGIN ) {
/* Treat non-PGP data similarly to text input data */
type = PGP_LITERAL_TEXT;
} else if( type != PGP_LITERAL_TEXT ) {
type = PGP_LITERAL_BINARY;
}
if( type==PGP_LITERAL_TEXT ) {
/* Convert to local line endings if appropriate */
charMap = (PGPByte *)pgpenvGetPointer( s->env, PGPENV_CHARMAPTOLATIN1,
NULL );
output = pgpTextFiltCreate( s->context,
output, charMap, 0, s->lineEnd );
}
/* Now open output modules as needed */
if( IsntNull( s->outFileRef ) ) {
/* Open output file */
pgpAssert((s->localEncodeFlags & ~(kPGPFileOpenMaybeLocalEncode
| kPGPFileOpenNoMacBinCRCOkay)) == 0);
/* Create output file pipeline */
fileFlags = s->fAppendOutput ? kPGPFileOpenStdAppendFlags :
kPGPFileOpenStdWriteFlags ;
fileFlags |= s->localEncodeFlags;
#if PGP_MACINTOSH
/* always force decoding of MacBinary */
fileFlags |= kPGPFileOpenForceLocalEncode;
#endif
fileType = type == PGP_LITERAL_TEXT ?
kPGPFileTypeDecryptedText :
kPGPFileTypeDecryptedBin;
s->pfout = pgpFileRefOpen( cdkContext,
(PFLConstFileSpecRef)s->outFileRef,
fileFlags, fileType, &err );
if( IsNull( s->pfout ) )
goto error;
/* Set up output pipeline */
if( IsNull( pgpFileWriteCreate( cdkContext,
output, s->pfout, 0 ) ) ) {
/* Guess at the cause */
err = kPGPError_OutOfMemory;
pgpFileClose( s->pfout );
goto error;
}
} else if( IsntNull( s->outBufPtr ) ) {
/* Open fixed-size memory buffer */
if ( IsNull( s->outPipe = pgpMemModCreate( cdkContext, output,
(char *)s->outBufPtr, s->outBufMaxLength ) ) ) {
/* Guess at the cause */
err = kPGPError_OutOfMemory;
goto error;
}
if( s->fAppendOutput ) {
/* Skip past existing buffer contents */
if( IsPGPError( err = (s->outPipe)->annotate( s->outPipe, NULL,
PGPANN_MEM_PREPEND,
(unsigned char *)s->outBufPtr, *s->outBufUsedLength ) ) )
goto error;
}
} else if( IsntNull( s->outBufPtrPtr ) ) {
/* Open variable-size memory buffer */
/* Use secure mode if a FYEO buffer */
s->outPipe = fFYEO ? pgpSecureVariableMemModCreate( cdkContext,
output, s->outBufMaxLength )
: pgpVariableMemModCreate( cdkContext,
output, s->outBufMaxLength );
if ( IsNull( s->outPipe ) ) {
/* Guess at the cause */
err = kPGPError_OutOfMemory;
goto error;
}
if( s->fAppendOutput && *s->outBufUsedLength != 0 ) {
/* Prepend existing buffer contents */
if( IsPGPError( err = (s->outPipe)->annotate( s->outPipe, NULL,
PGPANN_MEM_PREPEND, (unsigned char *)*s->outBufPtrPtr,
*s->outBufUsedLength ) ) )
goto error;
/* Free buffer now that we have captured it */
PGPFreeData( *s->outBufPtrPtr );
*s->outBufPtrPtr = NULL;
}
} else if( s->outDiscard ) {
/* Pass to the bit bucket */
if ( IsNull( pgpDevNullCreate ( cdkContext, output ) ) ) {
/* Guess at the cause */
err = kPGPError_OutOfMemory;
goto error;
}
} else {
/* Checked for this case above */
pgpAssert( 0 );
}
checkpassthrough:
/* Passthrough mode means we want to use data from annotations for
* output rather than the data coming down the pipe. Save the output
* we've set up, and then convert output pipe to /dev/null for clearsign
* or to a memmod buffer for keys.
*/
if( s->passThrough ) {
/*
* Handle passthrough for clearsign and keys.
* May have changed output temporarily for textfilt setup, so restore
* from prevOutput
*/
output = s->prevOutput;
sSaveOutputState( s, output );
sDrainPassThroughFifo( s );
if( s->analyzeType == kPGPAnalyze_Key ) {
if ( IsNull( s->outKey = pgpVariableMemModCreate( s->context,
output, ~(PGPSize)0 ) ) ) {
/* Guess at the cause */
err = kPGPError_OutOfMemory;
}
} else {
if ( IsNull( pgpDevNullCreate ( cdkContext, output ) ) ) {
/* Guess at the cause */
err = kPGPError_OutOfMemory;
}
}
}
return kPGPError_NoErr;
error:
return err;
}
/* Local callback function */
static PGPError
decodeLocalCallBack (
void *arg,
PGPFileOffset soFar,
PGPFileOffset total
)
{
PGPError err = kPGPError_NoErr;
PGPDecodeJob *s = ( PGPDecodeJob * ) arg;
if( IsntNull( s->func ) && s->fNullEvents ) {
err = pgpEventNull( s->context, &s->newOptionList, s->func,
s->userValue, soFar, total );
pgpCleanupOptionList( &s->newOptionList );
}
return err;
}
/*
* Look for input file when we find a detached signature.
*/
static PGPError
pgpDecodeFindAltInput(
void *arg,
PGPPipeline *head
)
{
PGPDecodeJob *s; /* Parameters for callbacks */
PFLConstFileSpecRef detFileRef; /* Input fileref */
PGPFileRead *pfrdet; /* Input PGPFile pointer */
PGPByte *detBufPtr; /* Input buffer pointer */
PGPSize detBufLength; /* Input buffer length */
PGPOption op; /* Selected option from list */
PGPOptionListRef setupOp; /* Optlist for setting up input */
PGPError err; /* Error codes */
PGPFileDataType inFileDataType; /* Unused */
PGPOptionListRef freshOpList; /* Fresh options from the user */
(void) head;
s = (PGPDecodeJob *) arg;
freshOpList = kInvalidPGPOptionListRef;
/* See if there was a detached-signature option specified */
if( IsPGPError( err = pgpSearchOptionSingle( s->optionList,
kPGPOptionType_DetachedSignature, &op ) ) )
goto error;
if( !s->fUsedDetachedSigOp && IsOp( op ) && IsntNull( op.subOptions ) ) {
/* Only use the detachedsig op once, after that we will ask user */
s->fUsedDetachedSigOp = TRUE;
setupOp = op.subOptions;
} else {
/* Ask user for detached signature input */
if( IsNull( s->func ) ) {
err = kPGPError_DetachedSignatureFound;
goto error;
}
if( IsPGPError (err = pgpEventDetachedSignature( s->context,
&s->newOptionList, s->func, s->userValue ) ) )
goto error;
if( IsPGPError( err = pgpSearchOptionSingle( s->newOptionList,
kPGPOptionType_DetachedSignature, &op ) ) )
goto error;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -