pgpprsasc.c

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

C
2,441
字号
			/* error in deamorline */
			*error = sendAnnotate (ctx, myself,
					       PGPANN_ARMOR_BADLINE,
					       ctx->armorline, ctx->armorlen);
			if (*error)
				break;
			ctx->state = 26;
			goto case_26;
		}
		ctx->expectcrc = (i < 48);
		ctx->crc = crcUpdate (ctx->crc, ctx->databuf, i);
		ctx->datalen = i;
		ctx->dataptr = ctx->databuf;
		ctx->state++;
		/* FALLTHROUGH */
	case 20:
		/* output the dearmored data, then goto state 17 */

		part = ctx->part;
		while (ctx->datalen) {
			retval = writePartData (part, ctx->dataptr,
						ctx->datalen, error);
			ctx->dataptr += retval;
			ctx->datalen -= retval;
			if (*error)
				return written;
		}
		ctx->state = 17;
		goto case_17;

	case 21:
case_21:
		/* Deal with CRC */

		crc = dearmorCrc (ctx);
		if (crc < 0) {
			/* error */
			*error = sendAnnotate (ctx, myself,
					       PGPANN_ARMOR_CRCCANT,
					       ctx->armorline, ctx->armorlen);
			if (*error)
				break;
			ctx->state = 26;
			goto case_26;
		}
		if ((word32)crc != ctx->crc) {
			/* mismatch */
			*error = sendAnnotate (ctx, myself,
					       PGPANN_ARMOR_CRCBAD,
					       ctx->armorline, ctx->armorlen);
			if (*error)
				break;
			ctx->state = 26;
			goto case_26;
		}
		ctx->state++;
		/* FALLTHROUGH */
	case 22:
		/* read until EOL to get to end of the last line */

		ctx->armorptr = ctx->armorline;
		ctx->armorlen = 0;
		while (ctx->eol != 1) {
			ctx->armorlen = 1;	/* Preserve 1st char for doublespace logic */
			retval = readLine (ctx, buf, size);
			written += retval;
			buf += retval;
			size -= retval;

			if (!size)
				return written;
		}
		ctx->eol = 0;
		ctx->eob = 0;
		ctx->armorlen = 0;
		ctx->state++;
		/* FALLTHROUGH */
	case 23:
		/* call readline until we have EOB or EOL */

		retval = readLine (ctx, buf, size);
		size -= retval;
		buf += retval;
		written += retval;

		if (ctx->eol || ctx->eob)
			ctx->state++;
		else
			break;

		/* FALLTHROUGH */
	case 24:
case_24:
		/* check for END */

		if (ctx->armorlen < sizeof (prefix3) - 1 ||
		    memcmp (ctx->armorline, prefix3, sizeof (prefix3) - 1)) {
			/* missing end -- do what??? */
			;
		}

#if MIMEPARSE
		if (ctx->mime_signed) {
			/* Special cleanup for MIME, wait for final boundary */
			ctx->state = 80;
			goto case_80;
		}
#endif

		ctx->state++;
		/* FALLTHROUGH */
	case 25:
		/* read until EOL to get to end of the last line */

		ctx->armorptr = ctx->armorline;
		ctx->armorlen = 0;
		while (ctx->eol != 1) {
			ctx->armorlen = 1;	 /* Preserve 1st char for doublespace logic */
			retval = readLine (ctx, buf, size);
			written += retval;
			buf += retval;
			size -= retval;

			if (!size)
				return written;
		}

		ctx->state++;
		/* FALLTHROUGH */
	case 26:
case_26:
		/*
		 * finish this part, send an end annotation if we need
		 * to, then clear the context and go to state 0
		 */

		if (ctx->annotation) {
			pgpAssert (ctx->depth_at_ann == ctx->scope_depth);
			*error = sendAnnotate (ctx, myself, ctx->annotation,
						   NULL, 0);
			if (*error)
				break;
			ctx->annotation = 0;
		}

		ctx->state++;
		/* FALLTHROUGH */

	case 27:
		part = ctx->part;
		*error = donePart (ctx);
		if (*error)
			break;

		ctx->part = NULL;
		ctx->thispart = 0;
		ctx->maxparts = 0;
		memset (ctx->messageid, 0, sizeof (ctx->messageid));
		ctx->dataptr = ctx->databuf;
		ctx->datalen = 0;
		ctx->armorptr = ctx->armorline;
		ctx->armorlen = 0;
		ctx->expectcrc = 0;
		ctx->crlf = 0;
		ctx->doublespace = 0;
		ctx->firstheader = 0;
		ctx->saved_crlf = 0;
		ctx->hashlen = 0;
		ctx->eol = 0;
		ctx->eob = 0;
		ctx->state = 0;
		goto case_0;

		/* BEGIN CLEARSIGNED MESSAGE BELOW HERE */
	case 30:
case_30:
		/* Send end-annotation (if we sent a begin annotation) */
		if (ctx->annotation) {
			pgpAssert (ctx->depth_at_ann == ctx->scope_depth);
			*error = sendAnnotate (ctx, myself, ctx->annotation,
						   NULL, 0);
			if (*error)
				break;
			ctx->annotation = 0;
		}
		ctx->state++;
		/* FALLTHROUGH */
	case 31:
		/* Read until EOL == 1 to get to the end of the begin line */
		pgpAssert (ctx->eol);

		ctx->armorptr = ctx->armorline;
		ctx->armorlen = 0;
		while (ctx->eol != 1) {
			ctx->armorlen = 0;
			retval = readLine (ctx, buf, size);
			written += retval;
			buf += retval;
			size -= retval;

			if (!size)
				return written;
		}
		ctx->eol = 0;
		ctx->eob = 0;
		ctx->armorlen = 0;
		ctx->state++;
		/* FALLTHROUGH */
	case 32:
		/* read the line after the begin: call readline until
		 * we have EOB or EOL */

		retval = readLine (ctx, buf, size);
		size -= retval;
		buf += retval;
		written += retval;

		if (ctx->eol || ctx->eob)
			ctx->state++;
		else
			break;

		/* FALLTHROUGH */
	case 33:
		/* Make sure first line after "BEGIN" is empty or "Hash:" */
		lineused = ctx->armorlen;
		ptr = ctx->armorline;

		/* Find trailing white space... */
		while (lineused && isspace (ptr[lineused - 1]))
			lineused--;

		if (lineused && !ctx->hashlen) {
			/* The line MUST be of the form:
			 *	Hash: <ID>[, <ID>]*
			 */
			/* Check for "Hash:" here, put hashes into
			 * ctx->hashlist and number of hashes into
			 * ctx->hashlen
			 */
			if (memcmp (ctx->armorline, "Hash: ", 6)) {
				/* Not a Hash -- Error out */
				/* XXX: Should annotate here */
				ctx->state = 3;
				goto case_3;
			}
			lineused -= 6;
			ptr += 6;

			while (lineused) {
				struct PgpHash const *h;
				byte const *comma = (byte const *)
					strchr ((char const *) ptr, ',');
				unsigned len = comma ? comma-ptr : lineused;
				
				h = pgpHashByName ((char const *)ptr, len);
				if (!h) {
					/* unknown hash.. now what? */
					/*XXX: annotate?*/;
				} else
					ctx->hashlist[ctx->hashlen++] =
						h->type;
				ptr += len;
				lineused -= len;
				if (comma) {
					if (memcmp (comma, ", ", 2)) {
						/* invalid format */
						/* XXX: annotate here */;
					}
					ptr += 2;
					lineused -= 2;
				}
			} /* while */

			if (!ctx->eol) {
				/* Too long a line */
				/* XXX: annotate: bad clearsig */
				ctx->hashlen = 0;
				ctx->state = 3;
				goto case_3;
			}

			/* Now we need to get an *extra* line, the separator */
			ctx->state = 30;
			goto case_30;
		} /* if (lineused && !ctx->hashlen) */

		if (!ctx->eol || lineused) {
			/*
			* We either have a long line or non
			* white-space. I bet someone's trying to
			* trick us into believeing this is a real
			* clearsigned message, but they've added some
			* text to it. I dont buy it. Output as
			* non-pgp text; goto state 3.
			 		*/

			/* XXX: Should send an annotation: bad clearsig */
			ctx->hashlen = 0;
			ctx->state = 3;
			goto case_3;
		}
		ctx->state++;
		/* FALLTHOUGH */
#if MIMEPARSE
case_34:
#endif
	case 34:
		/* Read until EOL == 1 to get to the next line */
		pgpAssert (ctx->eol);

		ctx->armorptr = ctx->armorline;
		ctx->armorlen = 0;
		while (ctx->eol != 1) {
			ctx->armorlen = 0;
			retval = readLine (ctx, buf, size);
			written += retval;
			buf += retval;
			size -= retval;

			if (!size)
				return written;
		}
		ctx->eol = 0;
		ctx->eob = 0;
		ctx->armorlen = 0;
		ctx->saved_crlf = 0;
		ctx->crlf = 0;
		ctx->state++;
		/* FALLTHROUGH */
	case 35:
		/* Ok, this is a clearsigned message. Send a new
		* begin annotation
		*/
		*error = sendAnnotate (ctx, myself, PGPANN_CLEARSIG_BEGIN,
				NULL, 0);
		if (*error)
			break;
		ctx->annotation = PGPANN_CLEARSIG_END;
		ctx->depth_at_ann = ctx->scope_depth;
		ctx->state++;
		/* FALLTHROUGH */
	case 36:
		/* Get a new message part */
		ctx->thispart = 1;
		ctx->maxparts = 1;
		msg = getMessage (ctx, NULL, 1);
		if (!msg) {
			/* This is an error */
			*error = PGPERR_NOMEM;
			break;
		}
		part = getPart (ctx, msg, ctx->thispart);
		if (!part) {
			/* This is an error too */
			*error = PGPERR_NOMEM;
			break;
		}

		/* And set it up as a clearsigned message */
		*error = createClearsig (ctx, msg, part);
		if (*error)
			break;

		ctx->part = part;
		ctx->state = 39;
		/* FALLTHROUGH */

		/*
		* Below starts the main processing loop for
		* clearsigned messages. It reads in a line. If it
		* is a BEGIN line it converts to the signature output
		* and starts de-armoring the signature. Otherwise it
		* will output any saved CRLF chars, then output this
		* new line, saving (but not outputting) the CRLF
		* chars at the end of the line. Then the loop
		* continues.
		*/
case_39:
	case 39:
		/* call readline until we have EOB or EOL */

		retval = readLine (ctx, buf, size);
		size -= retval;
		buf += retval;
		written += retval;

		if (ctx->eol || ctx->eob)
			ctx->state++;
		else
			break;

		/* FALLTHROUGH */
	case 40:
		/*
		* Check if this is a begin line. If so, start
		* parsing the signature by jumping to case 9.
		* Otherwise, if the line begins with '- ', move
		* beyond that and fallthrough
		*/

		lineused = ctx->armorlen;
		ptr = ctx->armorline;
		
		while (lineused && isspace (ptr[lineused - 1]))
			lineused--;
		
#if MIMEPARSE
		if (ctx->mime_signed) {
			if (lineused == ctx->mime_bound_len &&
				!memcmp (ptr, ctx->mime_boundary, ctx->mime_bound_len)) {
				/* Done with MIME body part, go look for sig */
				ctx->state = 75;
				goto case_75;
			}
		} else {
#endif
		if (lineused == sizeof (sigprefix) - 1 &&
		!memcmp (ptr, sigprefix, sizeof (sigprefix) - 1)) {
			ctx->state = 9;
			goto case_9;
		}

		if (!memcmp (ctx->armorline, "- ", 2)) {
			ctx->armorptr = ctx->armorline + 2;
			ctx->armorlen -= 2;
		}
#if MIMEPARSE
		}
#endif
		ctx->state++;
		/* FALLTHROUGH */
	case 41:
		/* output CRLF if we need to */

		while (ctx->saved_crlf) {

			if (ctx->saved_crlf & PGP_TEXTFILT_CR) {
				i = writeExtraData (ctx, (byte const *)"\r",
						1, error);
				if (i)
					ctx->saved_crlf &= ~PGP_TEXTFILT_CR;
				if (*error)
					break;
			}

			if (ctx->saved_crlf & PGP_TEXTFILT_LF) {
				i = writeExtraData (ctx, (byte const *)"\n",
						1, error);
				if (i)
					ctx->saved_crlf &= ~PGP_TEXTFILT_LF;
				if (*error)
					break;
			}
		}

		ctx->state++;
		/* FALLTHROUGH */
	case 42:
case_42:
		/*
		* output armorline buffer; do not output crlf until
		* the next line has been shown to not be the
		* delimiter.
		*/
		ptr = ctx->armorptr + ctx->armorlen - 1;
		while (*ptr == '\r' || *ptr == '\n') {
			ptr--;
			ctx->armorlen--;
		}

		while (ctx->armorlen) {
			retval = writeExtraData (ctx, ctx->armorptr,
						ctx->armorlen, error);
			ctx->armorptr += retval;
			ctx->armorlen -= retval;
			if (*error)
				return written;
		}
		ctx->armorptr = ctx->armorline;
		ctx->state++;
		/* FALLTHROUGH */
	case 43:
		/*
		* if EOL == 1, clear state and goto state 39, 

⌨️ 快捷键说明

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