pgpprsbin.c

来自「著名的加密软件的应用于电子邮件中」· C语言 代码 · 共 2,522 行 · 第 1/5 页

C
2,522
字号
	return size0-size;
}

static size_t
parseCipher (struct PgpPipeline *myself, byte const *buf, size_t size,
	int *error)
{
	struct Context *ctx;
	size_t written = 0;

	pgpAssert (myself);
	pgpAssert (myself->magic == PARSERMAGIC);
	pgpAssert (error);

	ctx = (struct Context *)myself->priv;
	pgpAssert (ctx);
	pgpAssert (ctx->tail);
	pgpAssert (!size || !ctx->eof);

	*error = 0;

	switch (ctx->state) {
	case 0:
		/* Parse header; needed before callbacks are allowed */
		written = inputMerge(&ctx->input, buf, size, IVLEN, error);
		buf += written;
		size -= written;
		if (*error || !size)
			break;
		/* Size is non-zero but we haven't got desired? EOP */
		if (inputMerged(&ctx->input) < IVLEN) {
			pgpAssert(inputFinished(&ctx->input.head));
			*error = ctx->tail->annotate(ctx->tail, myself,
			PGPANN_PACKET_SHORT,
						0, 0);
			if (*error)
				break;
			myself->write = nextScope;
			size -= nextScope (myself, buf, size, error);
			break;
		}

		ctx->needcallback = 1;

		/*
		* If we're already in an encrypted scope (we've already
		* sent some ESKs to the user), don't bother sending another
		* one.
		*/
		if (ctx->end_scope) {	/* Scope alreay open? */
			ctx->state = 2;
			goto got_esk;
		}
		/* No ESKs seen yet - open the scope */
		ctx->end_scope = PGPANN_CIPHER_END;
		*error = ctx->tail->annotate (ctx->tail, myself,
		PGPANN_CIPHER_BEGIN, 0, 0);
		if (*error)
			break;

		ctx->state++;
		/* FALLTHROUGH */
	case 1:
		/* No ESKs seen yet - dummy one up */
		*error = ctx->tail->annotate (ctx->tail, myself,
		PGPANN_SKCIPHER_ESK, 0, 0);
		if (*error)
			break;

		ctx->state++;
		/* FALLTHROUGH */
	case 2:
	got_esk:
		/* Okay, do a commit */
		if (ctx->needcallback) {
			*error = ctx->tail->annotate (ctx->tail, myself,
			PGPANN_COMMIT, 0, 0);
			if (*error)
				break;
		}
		ctx->state++;
		/* FALLTHROUGH */
	case 3:
		if (ctx->needcallback) {
			*error = ProcessCallback (myself,
						PGPANN_PARSER_PASSTHROUGH,
						0, 0);
			if (*error)
				break;
		}
		ctx->state++;
		written += myself->write(myself, buf, size, error);
		break;
	default:
		pgpAssert (0);
	}

	return written;
}

static size_t
parseCompressed (struct PgpPipeline *myself, byte const *buf, size_t size,
		int *error)
{
	struct Context *ctx;
	size_t written = 0;

	pgpAssert (myself);
	pgpAssert (myself->magic == PARSERMAGIC);
	pgpAssert (error);

	ctx = (struct Context *)myself->priv;
	pgpAssert (ctx);
	pgpAssert (ctx->tail);
	pgpAssert (!size || !ctx->eof);

	*error = 0;

	switch (ctx->state) {
	case 0:
		/* Make sure we have the compression type */
		written = inputMerge(&ctx->input, buf, size, 1, error);
		buf += written;
		size -= written;
		if (*error || !size)
			break;
		/* Size is non-zero but we haven't got desired? EOP */
		if (inputMerged(&ctx->input) < 1) {
			pgpAssert(inputFinished(&ctx->input.head));
			*error = ctx->tail->annotate(ctx->tail, myself,
			PGPANN_PACKET_SHORT,
						0, 0);
			if (*error)
				break;
			myself->write = nextScope;
			size -= nextScope (myself, buf, size, error);
			break;
		}

		ctx->needcallback = 1;
		ctx->end_scope = PGPANN_COMPRESSED_END;
		*error = ctx->tail->annotate (ctx->tail, myself,
		PGPANN_COMPRESSED_BEGIN,
		inputMergedPtr(&ctx->input), 1);
		if (*error)
			break;

		ctx->state++;
		/* FALLTHROUGH */
	case 1:
		if (ctx->needcallback) {
			*error = ctx->tail->annotate (ctx->tail, myself,
			PGPANN_COMMIT, 0, 0);
			if (*error)
				break;
		}
		ctx->state++;
		/* FALLTHROUGH */
	case 2:
		if (ctx->needcallback) {
			*error = ProcessCallback (myself,
						PGPANN_PARSER_RECURSE,
						0, 0);
			if (*error)
				break;
		}
		ctx->state++;
		written += myself->write(myself, buf, size, error);
		break;
	default:
		pgpAssert (0);
	}

	return written;
}

/*
* Parse a general headerless packet. Unknown packets, comment packets
* and, in fact, things that aren't packets at all!
*/
static size_t
parseUnknown (struct PgpPipeline *myself, byte const *buf, size_t size,
	int *error)
{
	struct Context *ctx;
	size_t written = 0;
	byte b;
	int begintype;

	pgpAssert (myself);
	pgpAssert (myself->magic == PARSERMAGIC);
	pgpAssert (error);

	ctx = (struct Context *)myself->priv;
	pgpAssert (ctx);
	pgpAssert (ctx->tail);
	pgpAssert (!size || !ctx->eof);

	*error = 0;

	switch (ctx->state) {
	case 0:
		/*
		* As a convenience, we merge a leading prefix of the packet
		* for identification purposes.
		*/
		written = inputMerge(&ctx->input, buf, size, 256, error);
		buf += written;
		size -= written;
		if (*error)
			return written;
		if (inputMerged(&ctx->input) < 256 &&
		!inputFinished(&ctx->input.head))
		{
			pgpAssert(!size);
			return written;
		}

		/*
		* We use this one function to provide different
		* annotations for non-packets, comment packets, and
		* unknown packets. Figure out the right one to use.
		*/
		b = ctx->input.buffer[0];
		if (!IS_OLD_PKTBYTE(b) && !IS_NEW_PKTBYTE(b)) {
			begintype = PGPANN_NONPACKET_BEGIN;
			ctx->end_scope = PGPANN_NONPACKET_END;
		} else if (PKTBYTE_TYPE (b) == PKTBYTE_COMMENT) {
			begintype = PGPANN_COMMENT_BEGIN;
			ctx->end_scope = PGPANN_COMMENT_END;
		} else {
			begintype = PGPANN_UNKNOWN_BEGIN;
			ctx->end_scope = PGPANN_UNKNOWN_END;
		}
		
		ctx->needcallback = 1;
		*error = ctx->tail->annotate (ctx->tail, myself, begintype,
		inputMergedPtr(&ctx->input),
		inputMerged(&ctx->input));
		if (*error)
			break;

		ctx->state++;
		/* FALLTHROUGH */
	case 1:
		if (ctx->needcallback) {
			*error = ctx->tail->annotate (ctx->tail, myself,
			PGPANN_COMMIT, 0, 0);
			if (*error)
				break;
		}
		ctx->state++;
		/* FALLTHROUGH */
	case 2:
		if (ctx->needcallback) {
			*error = ProcessCallback (myself, PGPANN_PARSER_EATIT,
						0, 0);
			if (*error)
				break;
		}
		ctx->state++;
		return written + myself->write(myself, buf, size, error);
		/* NOTREACHED */
	default:
		pgpAssert (0);
	}

	return written;
}

/*
* This is called for most all key-type packets. Keys are just output
* within a key annotation scope. There is no callback, since no
* processing is done.
*/
static size_t
parseKey (struct PgpPipeline *myself, byte const *buf, size_t size, int *error)
{
	struct Context *ctx;
	struct PgpPipeline *tail;
	size_t size0 = size;
	byte const *p;
	size_t len;

	pgpAssert (myself);
	pgpAssert (myself->magic == PARSERMAGIC);
	pgpAssert (error);

	ctx = (struct Context *)myself->priv;
	pgpAssert (ctx);

	tail = ctx->tail;
	pgpAssert (tail);
	pgpAssert (!size || !ctx->eof);

	*error = 0;
	if (ctx->end_scope && ctx->end_scope != PGPANN_PGPKEY_END) {
		/* Umm.. Key block within another scope??? Why??? */
		*error = PGPERR_WRONG_SCOPE;
		return 0;
	}

	/* If we haven't output the begin annotation, do so now. */
	if (!ctx->end_scope) {
		*error = tail->annotate (tail, myself, PGPANN_PGPKEY_BEGIN,
					NULL, 0);
		if (*error)
			return 0;

		ctx->end_scope = PGPANN_PGPKEY_END;

		/* Set the flag to add a header module */
		ctx->needcallback++;
	}

	/* Make sure we only send the annotations once! */
	switch (ctx->state) {
	case 0:
		/*
		* Ask the user what to do with these keys... Really,
		* the only real answers are "EatIt" or "Process"..
		* "Recurse" gets mapped to "Process", and
		* "PassThrough" has the same effect. But let the
		* user decide, anyways. They may wish to eatit.
		*/
		if (ctx->needcallback) {
			*error = tail->annotate (tail, myself, PGPANN_COMMIT,
						0, 0);
			if (*error)
				return 0;
		}
		ctx->state++;
		/* FALLTHROUGH */
	case 1:
		if (ctx->needcallback) {
			*error = ProcessCallback (myself,
						PGPANN_PARSER_PROCESS,
						NULL, 0);
			if (*error)
				return 0;
		}
	}

	/* output this packet */
	/* empty out the buffered data and then the packet */
	for (;;) {
		p = inputRawPeek(&ctx->input, buf, size, &len);
		if (!len)
			break;
		len = tail->write (tail, p, len, error);
		len = inputRawSeek (&ctx->input, buf, size, len);
		buf += len;
		size -= len;
		if (*error)
			return size0-size;
	}
	/*
	* If we've hit the end of the packet, check if we have
	* another one. If so, check if it is a key certificate
	* packet. If so, go parse the new packet. Otherwise, end
	* this scope.
	*/
	if (inputFinished (&ctx->input.head) && (size || ctx->eof)) {
		/* End of input */
		if (size)
			switch (PKTBYTE_TYPE (*buf)) {
			case PKTBYTE_SECKEY:
			case PKTBYTE_PUBKEY:
			case PKTBYTE_SECSUBKEY:
			case PKTBYTE_PUBSUBKEY:
			case PKTBYTE_TRUST:
			case PKTBYTE_NAME:
			case PKTBYTE_SIG:
			case PKTBYTE_COMMENT:
				ctx->findpkt = 1;
				myself->write = parsePacket;
				size -= parsePacket (myself, buf, size, error);
				break;
			default:
				myself->write = nextScope;
				size -= nextScope (myself, buf, size, error);
				break;
			}
		else {
			myself->write = nextScope;
			size -= nextScope (myself, buf, size, error);
		}
	}

	return size0-size;
}

/* Shared entry point for 1-pass and old-style sig header parsing */
static size_t
parseSignature (struct PgpPipeline *myself, byte const *buf, size_t size,
		int *error)
{
	struct Context *ctx;
	size_t written = 0;

	pgpAssert (myself);
	pgpAssert (myself->magic == PARSERMAGIC);
	pgpAssert (error);

	ctx = (struct Context *)myself->priv;
	pgpAssert (ctx);
	pgpAssert (ctx->tail);
	pgpAssert (!size || !ctx->eof);

	switch (ctx->state) {
	case 0:
		/* Suck in the whole packet */

		written = inputMerge(&ctx->input, buf, size, -1u, error);
		buf += written;
		size -= written;

		/* Handle a packet larger than the buffer somehow */
		if (inputOverfull(&ctx->input)) {
			*error = ctx->tail->annotate (ctx->tail, myself,
						PGPANN_SIGNATURE_TOO_BIG,
						inputMergedPtr(&ctx->input),
						inputMerged(&ctx->input));
			if (*error)
				return written;

			/* Skip the body of the packet */
			myself->write = DoSkip;
			return written + DoSkip(myself, buf, size, error);
		}

		/* Have we sucked in the whole packet? */
		if (!inputFinished(&ctx->input.head))
			return written;

		/* We also want one byte of look-ahead */
		if (!size && !ctx->eof)
			return written;

		/* Check if this is a key signature */
		{
			int type;

			type = pgpSigSigType (inputMergedPtr (&ctx->input),
					inputMerged(&ctx->input));
			if (type < 0) {
				*error = type;
				return written;
			}

			if (type & 0xF0) {
				/* This is a key signature */
				myself->write = parseKey;
				return written + parseKey (myself, buf, size,
							error);
			}
		}

		/*
		* We can get here if there is a normal signed message
		* just after a key packet. In this case we need to
		* end the PGPKEY scope and then start a new one.
		*/
		if (ctx->end_scope == PGPANN_PGPKEY_END) {
			/* we need to end the PGPKEY scope. Yikes! */
			*error = ctx->tail->annotate (ctx->tail, myself,
						ctx->end_scope, NULL, 0);
			if (*error)
				return 0;

			ctx->end_scope = 0;
		}

		if (ctx->eof ||
		(!IS_OLD_PKTBYTE(*buf) && !IS_NEW_PKTBYTE(*buf)))
		{
			/* Do separate signature thing */
			ctx->state = 20;
			goto sepsig;
		}

		if (PKTBYTE_TYPE(*buf) == PKTBYTE_LITERAL ||
			PKTBYTE_TYPE(*buf) == PKTBYTE_OLDLITERAL) {
			/* Do signature on literal */
			ctx->state = 10;
			goto sigliteral;
		}

		ctx->state++;
		/* FALLTHROUGH */
	case 1:
		/* It's a signed PGP file (not a literal) */
		ctx->needcallback = 1;
		/* Send only one BEGIN annotation */
		if (ctx->end_scope != PGPANN_SIGNED_END) {
			ctx->end_scope = PGPANN_SIGNED_END;
			*error = ctx->tail->annotate (ctx->tail, myself,
						PGPANN_SIGNED_BEGIN,0,0);
			if (*error)
				break;
		}
		ctx->state++;
		/* FALLTHROUGH */
	case 2:
		/* Dump the signature as an annotation */

⌨️ 快捷键说明

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