⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgpprsasc.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 5 页
字号:
				return kPGPError_FIFOReadError;
			cmdlen -= sizeof (ctx->cmdlen);

			if (pgpFifoRead (ctx->fifod, ctx->ann, ctx->cmdarg,
					 ctx->cmdlen) != ctx->cmdlen)
				return kPGPError_FIFOReadError;
			cmdlen -= ctx->cmdlen;
		} else {
			/*
			 * If this can happen then we need to do this
			 * and keep track of the amount of data left in
			 * the fifo.
			 */

			ctx->left = datalen;
			ctx->written = datalen;
		}

	} while (datalen || cmdlen || ctx->cmdlen);

	/* If we get here then everything has been written out. */
	ctx->written = 0;

	return( kPGPError_NoErr );
}

/*
 * TBD for MIME support:
 * Add a filter to remove some MIME transforms.  To wit:
 *	First read headers, looking for blank line.  If see any header other
 *	than Content-Type: text/plain... or Content-Transfer-Encoding
 *	other than quoted-printable (or whatever the plain one is), we can't
 *	handle it, and we should just pass the whole thing through.  Otherwise
 *	we delete the header and trailing blank line.  We then run through the
 *	filter which undoes the content-transfer-encoding transformation if
 *	necessary, or else just passes data through.
 * This filter should be added just before the copymod, below.  It might
 * even replace the copymod, but I don't remember what it is for.  Something
 * to do with some error recovery state, where we needed to know we were
 * pointing at the last thing in the pipeline before context->tail?
 */

/*
 * This is a clearsigned message.  We need to setup the verification
 * pipeline to get this to work.  First we have a join module.  It is a
 * placeholder for the message.  The clearsigned text goes into the
 * second input of the join module.  The output of the join module goes
 * to a split.  The first output of the split goes to the annotation
 * reader.  The second output of the split goes into a textfilt module
 * to strip the spaces and then into a signature verification module.
 */
static PGPError
createClearsig (
	PGPContextRef cdkContext,
	PrsAscContext *ctx,
	Message *msg,
	MsgPart *part)
{
	/*
	 * We don't need a join module for clearsigning.  That causes the
	 * entire clearsigned part to be buffered in the join module until
	 * we get to the cleanup phase!  Redo that.
	 */
#if 0
	PGPPipeline *join = NULL, *split = NULL, *text = NULL;
	PGPPipeline **tail, **temp;
	PGPPipeline *sighead = NULL, **sigtail;

	/* First, build up a replacement "join/split" module */
	tail = pgpJoinCreate (cdkContext, &join, ctx->fifod);
	if (!tail)
		return kPGPError_OutOfMemory;

	temp = tail;
	tail = pgpSplitCreate (cdkContext, temp);
	if (!tail) {
		return kPGPError_OutOfMemory;
	}
	split = *temp;

	/* Splice in the join/split in place of the old join/parser */
	*(msg->tail) = NULL;
	part->mod->teardown (part->mod);

	part->mod = join;
	msg->tail = tail;

	/*
	 * Binary parser may add modules after itself, and in some
	 * error recovery situations they are still there when we try
	 * to close things.  Create a copy module to act as a stable
	 * predecessor to context->tail.
	 */
	msg->tail = pgpCopyModCreate ( cdkContext, msg->tail);

	/* And connect the tail */
	if (msg->tail)
		*(msg->tail) = ctx->tail;

	/* Create the text input */
	text = pgpJoinAppend (join);
	if (! text) {
		return kPGPError_OutOfMemory;
	}

	/* add a textfilt module */
	tail = pgpSplitAdd (split);
	if (!tail) {
		text->teardown (text);
		return kPGPError_OutOfMemory;
	}

#if MIMEPARSE
	tail = pgpTextFiltCreate (cdkContext, tail, charMapIdentity, 1,
			(ctx->mime_signed ? kPGPLineEnd_CRLF : kPGPLineEnd_Default));
#else
	tail = pgpTextFiltCreate ( cdkContext,
		tail, charMapIdentity, 1, kPGPLineEnd_Default);
#endif
	if (!tail) {
		text->teardown (text);
		return kPGPError_OutOfMemory;
	}

	/* Create the signature parser... */
	sigtail = pgpParseBinCreate ( cdkContext, &sighead, ctx->env,
								  ctx->ui, ctx->ui_arg );
	if (!sigtail) {
		text->teardown (text);
		return kPGPError_OutOfMemory;
	}

	/* ...and the signature verifier */
	if (!pgpVerifyReaderCreate ( cdkContext,
				tail, sigtail, ctx->env, ctx->fifod,
				    (ctx->hashlen ? ctx->hashlist : NULL),
				    ctx->hashlen, (ctx->hashlen ? 1 : 0),
				    ctx->ui, ctx->ui_arg)) {
		text->teardown (text);
		sighead->teardown (sighead);
		return kPGPError_OutOfMemory;
	}

	/* Now put it all together in this message */
	part->text = text;
	part->sig = sighead;
#else
	PGPPipeline *text = NULL;
	PGPPipeline **tail;
	PGPPipeline *sighead = NULL, **sigtail;

	tail = pgpSplitCreate (cdkContext, &text);

	/* Splice in the split in place of the old join/parser */
	*(msg->tail) = NULL;
	part->mod->teardown (part->mod);

	part->mod = NULL;		/* No join module */
	msg->tail = tail;

	/*
	 * Binary parser may add modules after itself, and in some
	 * error recovery situations they are still there when we try
	 * to close things.  Create a copy module to act as a stable
	 * predecessor to context->tail.
	 */
	msg->tail = pgpCopyModCreate ( cdkContext, msg->tail);

	/* And connect the tail */
	if (msg->tail)
		*(msg->tail) = ctx->tail;

	/* add a textfilt module */
	tail = pgpSplitAdd (text);
	if (!tail) {
		return kPGPError_OutOfMemory;
	}

	/* Not clear about using Default on non-MIME here */
	tail = pgpTextFiltCreate (cdkContext, tail, charMapIdentity, 1,
			(ctx->mime_signed ? kPGPLineEnd_CRLF : kPGPLineEnd_Default));
	if (!tail) {
		return kPGPError_OutOfMemory;
	}

	/* Create the signature parser... */
	sigtail = pgpParseBinCreate ( cdkContext, &sighead, ctx->env,
								  ctx->ui, ctx->ui_arg);
	if (!sigtail) {
		return kPGPError_OutOfMemory;
	}

	/* ...and the signature verifier */
	if (!pgpVerifyReaderCreate ( cdkContext,
				tail, sigtail, ctx->env, ctx->fifod,
				    (ctx->hashlen ? ctx->hashlist : NULL),
				    ctx->hashlen, (ctx->hashlen ? 1 : 0),
				    ctx->ui, ctx->ui_arg)) {
		sighead->teardown (sighead);
		return kPGPError_OutOfMemory;
	}

	/* Now put it all together in this message */
	part->text = text;
	part->sig = sighead;
#endif

	return( kPGPError_NoErr );
}

/*
 * Build up the Ascii Parser Table in order to dearmor data.  For all
 * values, set it to -1 if it is not a valid armor character and then
 * set the valid characters out of the armorTable.
 *
 * To make it thread-safe, init using local table, then copy table
 * to global.
 */
void
pgpParseAscInit (void)
{
	#define kDearmorTableSize		( (PGPSize)256 )
	static char 		sDearmorTableStorage[ kDearmorTableSize ];
	static PGPBoolean	sInited = FALSE;
	
	int		i;
	char	tempTable[ kDearmorTableSize ];

	if ( sInited )
		return;

	for (i = 0; i < (int)kDearmorTableSize; i++)
		tempTable[i] = -1;

	for (i = 0; i < (int)(sizeof(armorTable) - 1); i++)
		tempTable[armorTable[i] & 0xff] = (char)i;

	pgpCopyMemory( tempTable, sDearmorTableStorage, sizeof(tempTable) );
	sDearmorTable	= &sDearmorTableStorage[ 0 ];
	
	/* set 'sInited' only after everything has been setup above */
	sInited			= 1;
	return;
}

/*
 * Convert input bytes to output bytes.  Returns the number of
 * input bytes successfully converted.  The number of output
 * bytes available is one less than this number.
 */
static int
dearmorMorsel (PGPByte const in[4], PGPByte out[3])
{
	signed char c0, c1;

	c0 = sDearmorTable[in[0] & 255];
	if (c0 < 0)
		return 0;
	c1 = sDearmorTable[in[1] & 255];
	if (c1 < 0)
		return 1;

	out[0] = (c0 & 63u) << 2 | (c1 & 63u) >> 4;

	c0 = sDearmorTable[in[2] & 255];
	if (c0 < 0)
		return 2;

	out[1] = (c1 & 63u) << 4 | (c0 & 63u) >> 2;

	c1 = sDearmorTable[in[3] & 255];
	if (c1 < 0)
		return 3;

	out[2] = (c0 & 63u) << 6 | (c1 & 63u);

	return 4;
}

/*
 * Given a line of a certain length, convert to binary and
 * return the number of binary bytes that result, or -1 on error.
 *
 * This is very fussy about trailing junk and whatnot.
 * There is some complexity due to accepting "=3D" in place
 * of a normal "=".  This is to allow MIME-encapsulated messages
 * to be input directly, without having MIME unencapsulate them
 * first.
 *
 * This will ignore trailing white space and give an error if there
 * is too much data on the line.
 */
	int
pgpDearmorLine (PGPByte const *in, PGPByte *out, unsigned inlen)
{
	int outlen = 0;
	int t;

	while ((t = dearmorMorsel (in, out)) == 4) {
		in += 4;
		out += 3;
		inlen -= 4;
		outlen += 3;
		if (inlen < 4)
			return inlen ? -1 : outlen;
	}
	switch (t) {
	  case 2:
		if (inlen == 4) {
			if (in[2] == '=' && in[3] == '=')
				return outlen + 1;
		} else if (inlen == 8) {
			if (in[2] == '=' && in[3] == '3' && in[4] == 'D' &&
			    in[5] == '=' && in[6] == '3' && in[7] == 'D')
				return outlen + 1;
		}
		break;
	  case 3:
		if (inlen == 4) {
			if (in[3] == '=')
				return outlen + 2;
		} else if (inlen == 6) {
			if (in[3] == '=' && in[4] == '3' && in[5] == 'D')
				return outlen + 2;
		}
		break;
	}
	/* None of the above - we have an error */
	return -1;

}

/*
 * Return true if the line is a valid candidate as an armor line,
 * one with no bad characters.  This will allow us to have ascii armor
 * with no headers and no blanks before the armor data.
 * A better check would look for mults of 4 or trailing '=', but we don't
 * do that yet.
 */
static int
validArmorLine (PGPByte const *in, unsigned inlen)
{
	while (inlen--) {
		/* Fail if bad character */
		if( sDearmorTable[in[0] & 255] < 0  && in[0] != '=')
			return FALSE;
		++in;
	}
	return TRUE;
}

/*
 * Given a line thought to contain a CRC, this returns the 24-bit
 * CRC, or -1 on error.  Handles possible MIME expansion
 * of "=" to "=3D".
 */
static long
dearmorCrc (PGPByte const *in, unsigned inlen)
{
	PGPByte buf[3];

	/* skip trailing white space */
	while (inlen && isspace (in[inlen - 1]))
		inlen--;

	if (*in != '=')
		return -1;
	if (inlen == 5)
	{
		if (dearmorMorsel (in + 1, buf) != 4)
		{
			return -1;
		}
		else if (inlen == 7)
		{
			if (in[1] != '3' || in[2] != 'D' ||
			    dearmorMorsel (in + 3, buf) != 4)
			{
				return -1;
			}
			else
			{
				return -1;
			}
		}
	}
	
	/*
	 * Welcome to the famous ANSI C glitch.  ANSI C
	 * promotes to signed values where possible when preserving
	 * the value.  Thus, buf[1]<<8 is promoted to signed, then
	 * shifted, then promoted to long (on a 16-bit int machine,
	 * this causes sign-extension!), and merged with the other
	 * values.  Not Good.
	 * I'm beginning to see why people preferred the K&R unsigned-
	 * preserving rules.  Sigh.
	 */
	return (long)buf[0] << 16 | (unsigned)(buf[1] << 8 | buf[2]);
}

/*
 * try to fill up ctx->armorline up to LINE_LEN-1 bytes or a newline,
 * whichever comes first.
 * 
 * This will set ctx->eol when an EOL condition occurs.  eol == 1
 * means armorline is ready for processing.  eol == 2 means that
 * readLine needs to be called with more data (looking for \n).
 *
 * The return value is the number of bytes used.  If all the bytes are
 * used and EOL is not set, then more data is required and readLine
 * should be called with more data.
 */
static size_t
readLine (PrsAscContext *ctx, PGPByte const *buf, size_t size)
{
	size_t size0 = size;
	unsigned t, retlen;
	PGPByte eol = ctx->eol;
	PGPByte *ptr = ctx->armorline + ctx->armorlen;

	if (!size)
		return 0;

	/* If start of new line, remember total byte offset */
	if (eol == 0) {
		ctx->prevlineoff = ctx->bytesread;
	}

	/*
	 * This test is needed in case the '\r' and \'n' come in
	 * different write calls.
	 */
	if (eol == 2) {
		/* Must have hit a '\r' as last char in previous input buffer */
		if (*buf == '\n') {
			*ptr = *buf;
			ctx->armorlen++;
			ctx->eol = 1;
			ctx->crlf = kPGPLineEnd_CRLF;
			ctx->bytesread++;
			return 1;
		}
		/* 
		 * Bug fix here - wasn't doing this.  This happens when we have CR
		 * terminated lines and a CR right before end of buffer.  Should just
		 * reset our state on start of next buffer.
		 */
		ctx->eol = 1;
		return 0;
	}

	/* try to fill the input buffer with a line */
	t = (unsigned)pgpMin (LINE_LEN-1 - ctx->armorlen, size);
	for (eol = 0, retlen = 0; retlen < t && !eol; retlen++) {
		*ptr++ = *buf;
		if (*buf == '\r' || *buf == '\n')
			eol = (*buf == '\r' ? 2 : 1);
		buf++;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -