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

📄 pgpprsbin.c

📁 著名的加密软件的应用于电子邮件中
💻 C
📖 第 1 页 / 共 5 页
字号:

/* How many merged bytes are available? */
static size_t
inputMerged(struct Input const *input)
{
	return (size_t)(input->bufend - input->bufptr);
}

/* Pointer to the merged bytes */
static unsigned char const *
inputMergedPtr(struct Input const *input)
{
	return input->bufptr;
}

/*
 * Return a buffer and length corresponding to the next batch of
 * raw (unparsed) characters in the current packet.
 * The bytes might come from one of three places:
 * - The FIFO where they have been copied by inputMerge()
 * - The input buffer
 * - the passed-in external buffer
 * In the latter case, this parses ahead in the input buffer as many
 * subpackets as possible to give the largest block of data possible.
 *
 * Returns NULL with a length of 0 if there are no more bytes in the current
 * packet. Returns "buf" with a length of 0 if size is 0.
 * That may or may not be NULL, depending on the caller.
 */
static byte const *
inputRawPeek(struct Input const *input, byte const *buf, size_t size,
size_t *len)
{
	byte const *p;
	size_t s;
	size_t size0;
	unsigned ulen;
	struct Header head;

	pgpAssert(buf || !size);
	
	/* Try the byte FIFO */
	p = pgpFifoPeek (&pgpByteFifoDesc, input->fifo, &ulen);
	if (p) {
		*len = (size_t)ulen;
		return p;
	}
	/* Then the buffered data */
	if (input->passptr != input->bufend) {
		*len = input->bufend - input->passptr;
		return input->passptr;
	}
	/* Finally, the external buffer */

	size0 = size;
	p = buf;
	head = input->head;

	while (size && !inputFinished(&head)) {
		s = inputHeadSeek(&head, p, size);
		size -= s;
		if (!size)
			break;
		p += s;
		if (size <= head.pktlen) {
			size = 0;
			break;
		}
		size -= head.pktlen;
		p += head.pktlen;
		head.pktlen = 0;
	}

	*len = size0 - size;
	return buf;
}

/*
 * Skip forward over a given number of bytes of raw input data.
 * The number of bytes must be <= the number returned from
 * inputRawPeek().
 *
 * The FIFO and buffered data are simple. If those are empty,
 * parse forward in the external buffer until the desired number of
 * bytes have been skipped, then store the parsing state.
 */
static size_t
inputRawSeek(struct Input *input, byte const *buf, size_t size, unsigned len)
{
	size_t s;

	pgpAssert(buf || !size);
	
	/* If there's data in the FIFO, skip that... */
	if (pgpFifoSize (&pgpByteFifoDesc, input->fifo)) {
		pgpFifoSeek (&pgpByteFifoDesc, input->fifo, len);
		return 0;
	}
	/* Otherwise the buffered data */
	if (input->passptr != input->bufend) {
		pgpAssert(len <= (size_t)(input->bufend - input->passptr));
		input->passptr += len;
		if (input->bufptr < input->passptr)
			input->bufptr = input->passptr;
		return 0;
	}

	/* Finally, the external buffer */
	pgpAssert(len <= size);

	size = len;
	while (size) {
		s = inputHeadSeek(&input->head, buf, size);
		size -= s;
		if (!len)
			break;
		buf += s;
		if (size <= input->head.pktlen) {
			input->head.pktlen -= size;
			break;
		}
		size -= input->head.pktlen;
		buf += input->head.pktlen;
		input->head.pktlen = 0;
	}
	return len;
}

/* Get rid of the header we've processed from the system. */
static void
inputPurge(struct Input *input)
{
	pgpFifoFlush (&pgpByteFifoDesc, input->fifo);
	input->passptr = input->bufptr = input->bufend = input->buffer;
}

/*
* Write all the already-buffered bytes from the current packet.
* Return an error, if any is encountered.
*/
static int
DoRawFlush (struct Context *ctx, struct PgpPipeline *tail)
{
	int error = 0;
	size_t len;
	byte const *p;

	do {
		p = inputRawPeek(&ctx->input, NULL, 0, &len);
		if (!p)
			break;
		len = tail->write (tail, p, len, &error);
		(void)inputRawSeek(&ctx->input, NULL, 0, len);
	} while (!error);

	return error;
}

static size_t
DoSkip (struct PgpPipeline *myself, byte const *buf, size_t size, int *error)
{
	struct Context *ctx;
	size_t size0 = size;
	byte const *p;
	size_t len;

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

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

	*error = 0;

	inputPurge (&ctx->input);

	for (;;) {
		p = inputPeek(&ctx->input, buf, size, &len);
		if (!p) {
			if (inputFinished(&ctx->input.head)) {
				/* End of input */
				myself->write = nextScope;
				size -= nextScope (myself, buf, size, error);
			}
			break;
		}
		if (!len && !size)
			break;
		len = inputSeek(&ctx->input, buf, size, len);
		size -= len;
		buf += len;
	}

	return size0-size;
}

/*
* Write out the as-yet-unread body of this packet to the tail of this module.
* At the end of the packet (inputFinished), set the state back to
* nextScope.
*/
static size_t
DoWrite (struct PgpPipeline *myself, byte const *buf, size_t size, int *error)
{
	struct Context *ctx;
	size_t len;
	size_t size0 = size;
	byte const *p;

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

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

	*error = 0;

	do {
		p = inputPeek(&ctx->input, buf, size, &len);
		if (!p) {
			if (inputFinished(&ctx->input.head)) {
				/* End of input */
				myself->write = nextScope;
				size -= nextScope (myself, buf, size, error);
			}
			break;
		}
		if (!len && !size)
			break;
		len = ctx->tail->write (ctx->tail, p, len, error);
		len = inputSeek(&ctx->input, buf, size, len);
		size -= len;
		buf += len;
	} while (!*error);

	return size0-size;
}


/*
* Write out a series of packets to the tail of this module, keeping
* track of packet boundaries, and counting pairs of signature headers
* and footers. When come to an unpaired footer, exit to process it.
*/
static size_t
DoWriteSignedPackets(struct PgpPipeline *myself, byte const *buf, size_t size,
	int *error)
{
	struct Context *ctx;
	size_t len;
	size_t size0 = size;
	byte const *p;
	byte b;

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

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

	*error = 0;

	switch (ctx->state) {
	case 0:
		/* Here at the start of a packet */

		inputReset(&ctx->input);

		if (!size)
			return 0;	 /* I need a packet header! */

		/*
		* Track signature nesting.
		* sig1nest holds the excess 1pass sig hdrs we've seen
		* We distinguish old-style sig packets from new style by
		* whether the packet type byte is old or new style.
		*/
		if (IS_NEW_PKTBYTE(buf[0])) {
			byte bt = PKTBYTE_TYPE(buf[0]);
			if (bt==PKTBYTE_SIG && ctx->sig1nest==0) {
				/* This footer is what we are looking for */
				myself->write = nextScope;
				size -= nextScope (myself, buf, size, error);
				break;
			} else if (bt==PKTBYTE_1PASSSIG) { /* sig header */
				++ctx->sig1nest;
			} else if (bt==PKTBYTE_SIG) { /* sig footer */
				--ctx->sig1nest;
			}
		}

		/* Else read and pass on this packet */
		b = *(buf++);
		size--;

		if (inputStart(&ctx->input, b) < 0) {
			pgpAssert (0);	/* what to do here? */
		}


		ctx->state++;
		/* FALLTHROUGH */
	case 1:
		while (!inputFinished(&ctx->input.head)) {
			p = inputRawPeek(&ctx->input, buf, size, &len);
			if (!len)
				return size0-size;
			len = ctx->tail->write(ctx->tail, p, len, error);
			len = inputRawSeek(&ctx->input, buf, size, len);
			size -= len;
			buf += len;
			if (*error)
				return size0-size;
		}
		/* Here at end of packet */
		ctx->state = 0;
		break;
	}
		
	return size0-size;
}


/*
* This function flushes the raw header bytes from the beginning of
* the parser's buffer "over" the following module on to the following
* parser, then falls through to writing the payload bytes to the following
* module and the header bytes "over" it.
*/
static size_t
DoWriteNext (struct PgpPipeline *myself, byte const *buf, size_t size,
	int *error)
{
	struct Context *ctx;
	byte const *p;
	size_t size0 = size;
	size_t len;
	struct PgpPipeline *tail, *next;

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

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

	next = ctx->nextparser;
	*error = 0;

	for (;;) {
		p = inputRawPeek(&ctx->input, NULL, 0, &len);
		if (!len)
			break;
		len = next->write (next, p, len, error);
		(void)inputRawSeek(&ctx->input, NULL, 0, len);
		if (*error)
			return 0;
	}

	tail = ctx->tail;
	do {
		p = inputHeadPeek(&ctx->input.head, buf, size, &len);
		if (len) {
			len = next->write(next, p, len, error);
			(void)inputHeadSeek(&ctx->input.head, buf, len);
			buf += len;
			size -= len;
		} else {
			p = inputPeek(&ctx->input, buf, size, &len);
			if (len) {
				len = tail->write(tail, p, len, error);
				/* Note double "len" to prevent header skip */
				len = inputSeek(&ctx->input, buf, len, len);
				buf += len;
				size -= len;
			} else
				break;
		}
		if (*error)
			return size0-size;
	} while (size);

	/* If that's the end of this packet, continue with the next. */
	if (inputFinished(&ctx->input.head)) {
		/* End of input */
		myself->write = nextScope;
		size -= nextScope (myself, buf, size, error);
	}

	return size0-size;
}

/*
 * This function is called when we are checking the signature on a literal
 * packet. The reason it is needed is that signatures are only on the BODY
 * of the literal packet, not the headers. OOPS. So find the size of
 * the literal packet header and pass it (external header and internal
 * header) "over" the hash module to the ctx->nextparser using
 * DoWriteNext.
 *
 * This does NOT report errors on a short or truncated literal packet, since
 * we're pretending not to be parsing it - the downstream parser will
 * notice it and do any necessary complaining. It DOES, however, try
 * to write out such packets to the downstream parser so it can do the
 * reporting.
 */
static size_t
parseSignedLiteralMagic (struct PgpPipeline *myself,
byte const *buf, size_t size, int *error)
{
	struct Context *ctx;
	size_t len;
	byte const *p;
	size_t size0 = size;

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

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

	/* Make sure nothing confusing can happen here! */
	pgpAssert(!ctx->needcallback);

	/* Do NOT complain on truncation. */
	ctx->input.silent_trunc = 1;

	/* No error until told otherwise */
	*error = 0;

	switch (ctx->state) {
	case 0:	/* Get packet header byte */
		if (!size)
			return 0;

		/* We know it's a literal packet, so no worries. */
		(void)inputStart(&ctx->input, *buf);
		buf++;
		size--;
		ctx->state++;
		/* FALLTHROUGH */
	case 1:	/* Get internal header */
		len = inputMerge(&ctx->input, buf, size, 2, error);
		buf += len;
		size -= len;
		if (*error)
			break;
		p = inputPeek(&ctx->input, NULL, 0, &len);
		if (len < 2) {
			if (!inputFinished(&ctx->input.head))
				break;
		} else {
			len = inputMerge(&ctx->input, buf, size, 6+p[1],
					error);
			buf += len;
			size -= len;
			if (*error)
				break;
			if (inputMerged(&ctx->input) < (size_t)6+p[1]) {
				if (!inputFinished(&ctx->input.head))
					break;
			}
		}
		/* We've got as much as we need */
		ctx->state++;
		myself->write = DoWriteNext;
		size -= DoWriteNext (myself, buf, size, error);
		break;
	default:
		pgpAssert(0);
	}
	return size0-size;
}

/*
* This function just does a little bit of trivial initialization,
* including setting the state to 0, and then falls through to
* parseSignedLiteralMagic. The Do functions can be called from a
* variety of states, due to the way they are set up from callbacks
* that may be called from a variety of states, so they can't depend on
* the ctx->state. Thus, the need for this little wrapper function.
*/
static size_t
DoSignedLiteralMagic (struct PgpPipeline *myself, byte const *buf, size_t size,
		int *error)
{
	struct Context *ctx;

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

⌨️ 快捷键说明

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