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

📄 pgpprsbin.c

📁 PGP—Pretty Good Privacy
💻 C
📖 第 1 页 / 共 5 页
字号:
parseKey (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
{
	PrsBinContext *ctx;
	PGPPipeline *tail;
	size_t size0 = size;
	PGPByte const *p;
	size_t len;

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

	ctx = (PrsBinContext *)myself->priv;
	pgpAssert (ctx);

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

	*error = kPGPError_NoErr;
	if (ctx->end_scope && ctx->end_scope != PGPANN_PGPKEY_END) {
		/* Umm.. Key block within another scope??? Why??? */
		*error = kPGPError_WrongScope;
		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.
	 * NOTE: This is not robust against the addition of new kinds of
	 * key packets.  We should instead assume that we are still in the
	 * keyring until we hit a known non-key packet, or we get an
	 * annotation from the ascii armor parser that we are no longer
	 * in the same input block.
	 */
	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_ATTRIBUTE:
			case PKTBYTE_SIG:
			case PKTBYTE_COMMENT:
			case PKTBYTE_CRL:
				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 (PGPPipeline *myself, PGPByte const *buf, size_t size,
		PGPError *error)
{
	PrsBinContext *ctx;
	size_t written = 0;

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

	ctx = (PrsBinContext *)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, (unsigned)-1, error);
		buf += written;
		size -= written;

		/*
		 * Proceed with our key signature test if finished or overfull;
		 * we can handle oversized sigs in keyrings as we're just passing
		 * them through.
		 */
		if ( !( inputFinished(&ctx->input.head) ||
				inputOverfull(&ctx->input) ) )
			return written;

		/* We need at least one byte of look-ahead for next test */
		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 = (PGPError)type;
				return written;
			}

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

			/* A buggy keyring could have a non-key signature in it.
			 * We recognize that by being in a PGPKEY scope and having
			 * the next packet not being a literal.  This could eliminate
			 * some extremely rare cases where a key block was followed by
			 * a signature on a non-literal, but sigs on non-literals are
			 * themselves rare.
			 */
			if (ctx->end_scope == PGPANN_PGPKEY_END &&
				!ctx->eof &&
				PKTBYTE_TYPE(*buf) != PKTBYTE_LITERAL &&
				PKTBYTE_TYPE(*buf) != PKTBYTE_OLDLITERAL) {
				/* Treat as a key signature */
				myself->write = parseKey;
				return written + parseKey (myself, buf, size,
							   error);
			}
		}

		/* Report a packet larger than the buffer */
		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 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 */
		*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 (PGPPipeline *myself, PGPByte const *buf,
		size_t size, PGPError *error)
{
	PrsBinContext *ctx;
	size_t written = 0;

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

	ctx = (PrsBinContext *)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, (unsigned)-1, 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))
	

⌨️ 快捷键说明

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