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

📄 pgpprsbin.c

📁 著名的加密软件的应用于电子邮件中
💻 C
📖 第 1 页 / 共 5 页
字号:
		*error = ctx->tail->annotate (ctx->tail, myself,
		PGPANN_SIGNED_SIG,
		inputMergedPtr(&ctx->input),
		inputMerged(&ctx->input));
		if (*error)
			break;
		ctx->state++;
		/* FALLTHROUGH */
	case 3:
		if (ctx->sig1pass) {
			if (!pgpSigNestFlag(inputMergedPtr(&ctx->input),
					inputMerged(&ctx->input))) {
				/* No nest flag means another sighdr follows */
				myself->write = nextScope;
				break;	/* Call nextScope next time */
			} else if (IS_NEW_PKTBYTE(*buf) &&
				PKTBYTE_TYPE(*buf)==PKTBYTE_SIG) {
				/*
				* A 1-pass header immediately followed by
				* a 1-pass footer can only mean one thing:
				* a separate signature. With these, the
				* reader will try to check sigs as soon as
				* we ask it to commit. So we can't do that
				* until we have read our footer signatures.
				*/
				ctx->sepsig = 1;
				*error = ctx->tail->annotate (ctx->tail,
						myself,
						PGPANN_SIGNED_SEP, 0, 0);

				/* Process end of message sigs */
				myself->write = nextScope;
				break; /* Call nextScope next time */
			}
		}


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

	/* Signature on literal case */
	case 10:
sigliteral:
		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 11:
		/* Dump the signature as an annotation */
		*error = ctx->tail->annotate (ctx->tail, myself,
					PGPANN_SIGNED_SIG,
		inputMergedPtr(&ctx->input),
		inputMerged(&ctx->input));
		if (*error)
			break;
		ctx->state++;
		/* FALLTHROUGH */
	case 12:
		if (ctx->needcallback) {
			*error = ctx->tail->annotate (ctx->tail, myself,
			PGPANN_COMMIT, 0, 0);
			if (*error)
				break;
		}
		ctx->state++;
		/* FALLTHROUGH */
	case 13:
		if (ctx->needcallback) {
			*error = ProcessCallback (myself,
						PGPANN_PARSER_RECURSE,
						0, 0);
			if (*error)
				break;
		}
		ctx->state = 0;
		written += myself->write(myself, buf, size, error);
		break;

	/* Separate signature case */
	case 20:
sepsig:
		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 21:
		/*
		* Say that this will be a separate signature.
		* Note that we don't set the sepsig flag here, as we don't
		* need to know. That flag is just for 1-pass signatures.
		*/
		*error = ctx->tail->annotate (ctx->tail, myself,
		PGPANN_SIGNED_SEP, 0, 0);
		if (*error)
			break;
		ctx->state++;
		/* FALLTHROUGH */
	case 22:
		*error = ctx->tail->annotate (ctx->tail, myself,
		PGPANN_SIGNED_SIG,
		inputMergedPtr(&ctx->input),
		inputMerged(&ctx->input));
		if (*error)
			break;
		ctx->state++;
		/* FALLTHROUGH */
	case 23:
		if (ctx->needcallback) {
			*error = ctx->tail->annotate (ctx->tail, myself,
			PGPANN_COMMIT, 0, 0);
			if (*error)
				break;
		}
		ctx->state++;
		/* FALLTHROUGH */
	case 24:
		if (ctx->needcallback) {
			*error = ProcessCallback (myself, PGPANN_PARSER_EATIT,
						0, 0);
			if (*error)
				break;
		}
		ctx->state = 0;
		written += myself->write(myself, buf, size, error);
		break;

	default:
		pgpAssert (0);
	}

	return written;
}


/*
* Parse 2nd signature packet after the signed packet after a
* 1-pass signature packet. These are the "sig footer" packets
* which are full-sized signature packets, paired with the 1-pass
* sig header packets.
*/
static size_t
parseSignature1Pass2 (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 signature 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;
		/* FALLTHROUGH */
	case 1:
		/* Dump the signature data as an annotation */
		ctx->needcallback = 1;
		*error = ctx->tail->annotate (ctx->tail, myself,
		PGPANN_SIGNED_SIG2,
					inputMergedPtr(&ctx->input),
					inputMerged(&ctx->input));
		if (*error)
			break;

		/* Decrement count of sig footers needing to be seen */
		--ctx->sig1pass;

		if (!ctx->sepsig || ctx->sig1pass != 0) {
			/*
			* In normal case, we are done now.
			* nextScope will end sig scope if sig1pass is 0.
			*/
			myself->write = nextScope;
			written += nextScope(myself, buf, size, error);
			break;
		}

		/* Here on last sig footer of separate signature */
		ctx->state++;
		ctx->needcallback = 1;
		/* FALLTHROUGH */
	case 2:
		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_EATIT,
						0, 0);
			if (*error)
				break;
		}
		ctx->state = 0;
		written += myself->write(myself, buf, size, error);
		break;
	}

	return written;
}

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


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

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

	b = PKTBYTE_TYPE (ctx->input.buffer[0]);
	*error = 0;

	switch (ctx->state) {
	case 0:
		/* It's a public-key-encrypted PGP file */
		if (!ctx->end_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:
		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_ESK_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;

		ctx->state++;
		/* FALLTHROUGH */
	case 2:
		/* Dump the ESK as an annotation */
		*error = ctx->tail->annotate (ctx->tail, myself,
					(b == PKTBYTE_ESK ?
					PGPANN_PKCIPHER_ESK :
					(b == PKTBYTE_CONVESK ?
						PGPANN_SKCIPHER_ESK :
						-1)), /* XXX */
		inputMergedPtr(&ctx->input),
		inputMerged(&ctx->input));
		if (*error)
			break;

		ctx->state++;	/* This really isn't needed */
		myself->write = nextESK;
		return written + nextESK(myself, buf, size, error);
		/* NOTREACHED */
	default:
		pgpAssert (0);
	}

	return written;
}

/*
* This just sends appropriate messages about the lack of text downstream.
*/
static size_t
parseCipherNoText (struct PgpPipeline *myself, byte const *buf, size_t size,
int *error)
{
	struct Context *ctx;

	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:
		ctx->needcallback = 1;
		/* Send an annotation */
		*error = ctx->tail->annotate (ctx->tail, myself,
		PGPANN_CIPHER_NOTEXT, 0, 0);
		if (*error)
			break;
		ctx->state++;
		/*FALLTHROUGH*/
	case 1:
		/* Send a commit */
		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 myself->write(myself, buf, size, error);
	default:
		pgpAssert (0);
	}
	return 0;	 /* Never executed; makes compilers happy. */
}

/*
* The default state when starting to parse a packet. Once the type and
* size of the packet has been determined, we don't come back until
* the end of the packet. This function *is* called after each packet
* (by the sizeAdvise(0) handler if necessary), because post-packet
* cleanup code also resides here.
*
* Because the functions in this module rely heavily on tail recursion,
* if we get called with a large packet (say 16K), it could have literally
* hundreds of objects on it, and we go hundreds of levels deep on recursion.
* This exhausts stack space. Therefore we will limit the amount of data we
* will accept on one call to PARSER_SIZE_LIMIT.
*/
static size_t
parsePacket (struct PgpPipeline *myself, byte const *buf, size_t size,
	int *error)
{
	struct Context *ctx;
	size_t written = 0;
	unsigned b;

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

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

	*error = 0;

	/* Prevent excessive recursion within this module */
	size = min(size, PARSER_SIZE_LIMIT);

	/*
	* findpkt is set to 1 by create and every time we change to
	* the parsePacket state, and indicates that the first packet
	* byte has not been found.
	*/
	if (ctx->findpkt) {
		inputReset(&ctx->input);

		if (!size)
			return 0;	 /* I need a packet header! */
		ctx->findpkt = 0;
		b = *(buf++);
		size--;
		
		if (inputStart(&ctx->input, b) < 0) {
			ctx->state = 0;	/* Need to set this */
					/* before jumping ahead */
			myself->write = parseUnknown;
			return 1+parseUnknown (myself, buf, size, error);
		}
		
		written = 1;
	}

	/*
	* Okay, now we have a packet, with the parser state set up
	* and the header byte in ctx->input.buffer[0].
	*
	* The packet-specific parsers use a state variable, and
	* expect it to be set to 0 when they begin.
	*/
	ctx->state = 0;

	b = PKTBYTE_TYPE (ctx->input.buffer[0]);

	if (ctx->end_scope == PGPANN_CIPHER_END) {
		switch (b) {
		case PKTBYTE_CONVENTIONAL:
			myself->write = parseCipher;
			break;
		case PKTBYTE_CONVESK:
		case PKTBYTE_ESK:
			myself->write = parseESK;
			break;
		default:
			myself->write = parseCipherNoText;
			break;
		}
	} else {
		switch (b) {
		case PKTBYTE_CONVENTIONAL:
			myself->write = parseCipher;
			break;
		case PKTBYTE_OLDLITERAL:
			/*
			* This may be a dummy header we created, or it may be a
			* mistaken value from a PGP compatible program, or it may
			* conceivably be an obsolete old-style literal packet from a
			* pre-release version of PGP 2.0!
			* Flag special treatment, and distinguish the cases in
			* parseLiteral.
			*/
			ctx->state = 10;
			/* FALLTHROUGH */
		case PKTBYTE_LITERAL:
			myself->wr

⌨️ 快捷键说明

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