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

📄 pgpprsasc.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * pgpPrsAsc.c -- ascii dearmor parser.  This is fairly complicated.  Read
 * 	the comment a page down for a description of how this system works.
 *	The nice part is that you can input multipart armor in any order
 *	and it will work.  In fact, you can intersperse armor parts from
 *	multiple messages and it will work.  Moreover, you can input binary
 *	PGP messages and it will still work!  My god, can this man think
 *	of everything or what?
 *
 * Written by:	Derek Atkins <warlord@MIT.EDU>
 *
 * $Id: pgpPrsAsc.c,v 1.50.6.1 1999/06/03 23:26:00 heller Exp $
 */

#include "pgpConfig.h"

#include <ctype.h>
#include <stdio.h>
#include <string.h>

#ifndef MIMEPARSE
#define MIMEPARSE		1
#endif

#include "pgpDebug.h"
#include "pgpCharMap.h"		/* for charMapIdentity */
#include "pgpCopyMod.h"
#include "pgpCRC.h"
#include "pgpPrsAsc.h"
#include "pgpRadix64.h"
#include "pgpAnnotate.h"
#include "pgpFIFO.h"
#include "pgpFileType.h"
#include "pgpHashPriv.h"
#include "pgpJoin.h"
#include "pgpMem.h"
#include "pgpPrsBin.h"
#include "pgpEnv.h"
#include "pgpErrors.h"
#include "pgpPipeline.h"
#include "pgpSplit.h"
#include "pgpTextFilt.h"
#include "pgpUsuals.h"
#include "pgpVerifyRa.h"
#include "pgpContext.h"

/*
 * This is a complicated piece of code.  Less politely, this code is a
 * bitch.  It needs to be able to keep track of many different things
 * at the same time in order to combine pieces of armor into whole messages.
 *
 * There are three entities defined here.  First is an armor part, which
 * is defined as the range from BEGIN PGP MESSAGE to the END.  Second is
 * a message, which is PGP message made up of one or more parts.
 * And third, there are files, which can contain parts.
 *
 * Parts must be fully contained within a file, however there can be
 * multiple parts in a single file.  On the other hand, messages can
 * cross file boundaries.
 *
 * This code will output PGP messages in a stream of input "files"
 * wherever the first part of the message came in the stream.  In a
 * multipart message, this will require the least amount of buffering
 * since buffering is only required when pieces come out of order.
 * This can also handle the degenerate cases of interleaved messages,
 * although that requires possibly large amounts of buffering.
 * That case happens rarely enough that the resource requirement is
 * not onsidered a problem.
 *
 * A picture best describes this behavior:
 *
 *  W1          W2   X1     X2      X3   Y1      Y2      Y3   Z1    Z2
 * |  |   A2   |  | |  | B |  | A1 |  | |  | C2 |  | C1 |  | |  |A3|  |
 * |  +--------+  | |  +---+  +----+  | |  +----+  +----+  | |  +--+  |
 * +--------------+ +-----------------+ +------------------+ +--------+
 *     File 1              File 2              File 3          File 4
 *                                 ^                            ^
 *                                 |   Everything is buffered   |
 *                                 +----------------------------+
 *
 * W,X,Y,Z are file header and footer text which is outside the PGP armor.
 * The numbers are used to associate where in the data stream they occur.
 *
 * A,B,C are 3 PGP messages.  The numbers are the actual multipart parts
 * which may occur out of order.
 *
 * If this input stream were given to this armor parser, the following
 * output would occur:
 *
 *  | W1 ~ W2 | X1 B X2 A X3 | Y1 ~ Y2 C Y3 | Z1 ~ Z2 |
 *
 * Where:	| == A file separation annotation (or multiple annotations)
 *			~ == An armor annotation (an armor part occured here)
 *			W,X,Y,Z == The exact unencrypted text that arrived in the
 *			           input.
 *			A,B,C == The full messages, wrapped in "PGP data" annotations,
 *			         which will be sent to a binary parser for decryption.
 *
 * As you can see, the messages are output in the order B, A, C, each
 * message occurring in the place in the unenecrpted text stream where
 * part 1 is located.  Other parts are replaced with an annotation that just
 * notes the deletion.
 *
 * While decrypting message A, all the data between A1 and A3 (including
 * annotations) needs to be buffered.  In the usual case where the text
 * between parts is short (e-mail headers, mostly) and there aren't
 * multiple interleaved parts, not very much needs to be buffered.
 * Not much can be done to improve the worst case.
 */

#define kPGPPrsAscCmdBufSize	4096

#define DEARMORMAGIC	0xdea4304

/* List of commands */
#define CMD_WRITE	1
#define CMD_ANNOTATE	2

#define LINE_LEN	256	/* 256 bytes is MORE than Ascii armorsize! */

/* Some explanations of the various pipeline pointers (as usual, the
 * "tail" pointers are PGPPipeline **, that is, pointers to the "next"
 * pointer in the relevant object):
 *
 * context->tail	Points at next stage set up by our caller, usually
 *					an annotation reader.  Downstream of msg->tail.
 * context->myself	Points at this very pipeline module.
 * msg->tail		Points at a copy module which precedes context->tail.
 *					Part of downstream pipeline of part->mod.
 * part->mod		Points at the 1st-nth stage of a join input, which leads
 *					to a binary parser, 1 stage for each part.  Now NULL for
 *					clearsigned messages.
 * part->text		Used for clearsigned text, points at a split which
 *					feeds into both the sig verifier (via a textfilt) and
 *					into the main msg->tail output (anno reader).  (Used to
 *					point to 2nd stage of join input, where part->mod pointed
 *					at first stage.  This caused unnecessary buffering.)
 *					and we pass the raw data to context->tail.
 * part->sig		Used for clearsigned signatures, points at a binary
 *					parser that feeds into a sig verifier.
 */

typedef struct Message	Message;

typedef struct MsgPart	MsgPart;
struct MsgPart {
	PGPContextRef	cdkContext;
	
	unsigned num;		/* Which part number is this? */
	PGPPipeline *mod; /* Pointer to the join module for this part */
	PGPPipeline *text; /* clearsigned: the text goes here */
	PGPPipeline *sig; /* clearsigned: the sig goes here */
	Message *msg;	/* What message does this belong to? */
	MsgPart *next;	/* Pointer to the next part */
	PGPByte first;		/* Is this the first section left to do? */
	PGPByte done;		/* Is this part complete? */
	DEBUG_STRUCT_CONSTRUCTOR( MsgPart )
};

struct Message {
	PGPContextRef	cdkContext;
	
	char *name;		/* The name of this message */
	unsigned size;		/* How many parts does this have, if known */
	PGPPipeline **tail; /* Tail pointer for this message */
	MsgPart *parts;	/* The message parts */
	Message *next;	/* The next message */
	int msg_number;		/* What is this message number */
	PGPByte writing;		/* Are we writing? */
	PGPByte foundpart1;	/* Did we find part 1? */
	DEBUG_STRUCT_CONSTRUCTOR( Message )
} ;

typedef struct PrsAscContext {
	PGPPipeline		pipe;
	
	PGPFifoDesc const *fifod;	/* Fifo Descriptor */
	PGPFifoContext *ann; /* Fifo to hold the saved annotations */
	PGPFifoContext *data; /* Fifo to hold saved non-PGP data */
	Message *msgs;	/* List of current messages */
	MsgPart *part;	/* The current message part */
	PGPPipeline *myself; /* Pointer to this pipeline module */
	PGPPipeline *tail; /* Tail pointer for rest of the pipeline */
	PGPUICb const *ui;
	PGPEnv const *env;
	void *ui_arg;
	unsigned long written;	/* Fifo delta from last command */
	unsigned long left;	/* Bytes left in fifo until next command */
	unsigned thispart;	/* This part, obtained from the PGP header */
	unsigned maxparts;	/* Max parts, obtained from the PGP header */
	int state;		/* FSM state */
	int annotation;		/* Annotation State */
	int depth_at_ann;	/* Scope depth when we sent the annotation */
	int scope_depth;	/* Count of scopes we're inside */
	char messageid[LINE_LEN]; /* Message ID, obtained from the PGP header*/
	PGPByte databuf[65];	/* Space to hold raw data 60+slush */
	PGPByte *dataptr;		/* Pointer into the data buffer */
	unsigned datalen;	/* length of data buffer */
	PGPByte armorline[LINE_LEN]; /* line of armor */
	PGPByte *armorptr;		/* pointer into armorline */
	unsigned armorlen;	/* length of line */
	unsigned long crc;	/* CRC Checksum */
	PGPByte hashlist[255];	/* List of hashes */
	PGPByte hashlen;		/* Length of the list of hashes */
	PGPByte cmdarg[kPGPPrsAscCmdBufSize];	/* buffered command */
	unsigned cmdlen;	/* length of buffered command */
	int msg_count;		/* A count of the number of messages */
	PGPByte command;		/* the command that is buffered */
	PGPByte buffering;		/* A flag -- are we buffering everything? */
	PGPByte eol;		/* Our readLine EOL flag */
	PGPByte eob;		/* End of Buffer flag (from readLine) */
	PGPByte expectcrc;		/* Are we expecting the CRC line next? */
	PGPByte noarmorblanks;	/* Armor data starts on next line after BEGIN */
	PGPLineEndType crlf;	/* The type of crlf we have */
	PGPByte saved_crlf;	/* Save it off... */
	PGPSize bytesread;		/* Number of bytes read, total */
	PGPSize prevlineoff;	/* bytesread value at start of last line */
	PGPSize sectoff;		/* bytesread value at start of last section */
	size_t	skipPrefixLength; /* Number of chars preceding -----BEGIN PGP... */
	PGPByte	skipPrefix[LINE_LEN]; /* Chars preceding -----BEGIN PGP... */
	PGPByte crcendline;		/* CRC at end of last armor line */
	PGPByte	passthrough;	/* Passing armor or cleartext data unchanged */
	PGPByte passthroughcleartext;	/* Request passthrough on cleartext */
	PGPByte passthroughkey;	/* Request passthrough on key blocks */
#if MIMEPARSE
	PGPByte mime_signed;	/* Dealing with a PGP/MIME clearsigned message */
	PGPByte no_mime_headers;		/* Don't have mime headers, look in body */
	PGPByte mime_boundary[256];	/* MIME boundary with "--" */
	int mime_bound_len;	/* strlen(mime_boundary) */
#endif
	DEBUG_STRUCT_CONSTRUCTOR( PrsAscContext )
} PrsAscContext;


static char const *	sDearmorTable = NULL;	/* enforce 'const' access */

/* forward references */
static PGPError writeMessage (PrsAscContext *ctx, Message *msg);
static PGPError sendAnnotate (PrsAscContext *ctx, PGPPipeline *origin,
					 int type, PGPByte const *string, size_t size);
static PGPError flushMessage (PrsAscContext *ctx, Message *msg);


/* Case-insensitive compare routine */
static int
strncmp_ignorecase (const char *str1, const char *str2, int len)
{
	while (len--) {
		char c1 = tolower(*str1++);
		char c2 = tolower(*str2++);
		if (c1 != c2) {
			return (int)c1 - (int)c2;
		}
	}
	return 0;
}


/*
 * Close this part.  This makes sure that this message is being written
 * before it does this.  It will call a sizeAdvise (0) on the join
 * module and then possibly a teardown, too.
 */
static PGPError
closePart (MsgPart *part)
{
	PGPError	error;

	if (! part->msg->writing)
		return kPGPError_NoErr;

	if (part->sig) {
		error = part->sig->sizeAdvise (part->sig, 0);
		if (error)
			return error;
	}

	if (part->mod) {
		error = part->mod->sizeAdvise (part->mod, 0);
		if (error)
			return error;
	}

	if (part->text) {
		error = part->text->sizeAdvise (part->text, 0);
		if (error)
			return error;
	}

	part->done = 2;
	return kPGPError_NoErr;
}

/*
 * Free a message part; this tears down the join module, which must be
 * unhooked from the pipeline first.
 */
static void
freePart (MsgPart *part)
{
	MsgPart **partp = &part->msg->parts;
	PGPContextRef	cdkContext;
	
	pgpAssertAddrValid( *partp, MsgPart );
	cdkContext	= (*partp)->cdkContext;

	if (part->mod)
		part->mod->teardown (part->mod);
	if (part->text)
		part->text->teardown (part->text);
	if (part->sig)
		part->sig->teardown (part->sig);

	while (*partp) {
		if (*partp == part) {
			*partp = part->next;
			pgpClearMemory( part,  sizeof (*part));
			pgpContextMemFree( cdkContext, part);
			return;
		}
	}
	/* no match found */
	return;
}

/*
 * We are done with the current part, so mark it as done.  We should
 * also close this part if we are writing this message and either
 * there is a next part or this is the last part.  Then try to flush
 * the message, in case we have anything buffered.  Finally, clear the
 * part from the context so we know we don't have a current part.
 */
static PGPError
donePart (PrsAscContext *ctx)
{
	MsgPart *part = ctx->part;
	PGPError	error;

	pgpAssert (part);

	part->done = 1;
	if (part->msg->writing) {
		if (part->next || part->num == part->msg->size) {
			error = closePart (part);
			if (error)
				return error;
		}
		error = flushMessage (ctx, part->msg);
		if (error)
			return error;
	}

	ctx->part = NULL;
	return( kPGPError_NoErr );
}

/*
 * We're going to start a new part.  Therefore we need to pass in the
 * message that it is a part of, and then create the new part or
 * return the pre-created part.  If we ask for a part number in this
 * message that is beyond the highest number in the list, then we
 * create that many more parts up to the number passed in.
 *
 * Should we close old parts if we can?  I don't know, yet.  If we've
 * already written out part one and we just got part two, should I close
 * part one here?  I don't know, yet.
 */
static MsgPart *
getPart (PrsAscContext *ctx, Message *msg, unsigned num)
{
	MsgPart *temp = NULL, **part = &msg->parts;
	PGPPipeline *last = NULL;
	unsigned highest = 0;
	PGPContextRef	cdkContext;

	pgpAssert( IsntNull( ctx ) && IsntNull( ctx->myself ) );
	cdkContext	= ctx->myself->cdkContext;
	
	/* Initialize the CRC counter! */
	ctx->crc = CRC_INIT;

	while (*part) {
		if (num == (*part)->num)
			return *part;
		highest = (*part)->num;
		last = (*part)->mod;
		part = &(*part)->next;
	}

	/* We need to allocate a bunch of parts */
	for (highest++; highest <= num; highest++) {
		temp = (MsgPart *)pgpContextMemAlloc( cdkContext,
			sizeof (*temp), kPGPMemoryMgrFlags_Clear);
		if (!temp)
			return NULL;

		temp->num = highest;
		temp->msg = msg;
		temp->cdkContext	= cdkContext;

		if (last) {
			temp->mod = pgpJoinAppend (last);
		} else {
			msg->tail = pgpJoinCreate ( cdkContext, &(temp->mod), ctx->fifod);
			temp->first = 1;
			msg->tail = pgpParseBinCreate ( cdkContext, msg->tail, ctx->env,
											ctx->ui, ctx->ui_arg );
			/*
			 * Binary parser may add modules after itself, and in some
			 * error recovery situations they are still there when we try
			 * to close things.  Create a copy module to act as a stable
			 * predecessor to context->tail.
			 */
			msg->tail = pgpCopyModCreate ( cdkContext, msg->tail);

			/* connect the join module to the rest of the pipe */
			if (msg->tail)
				*(msg->tail) = ctx->tail;
		}

		if (!temp->mod) {
			pgpContextMemFree( cdkContext, temp);
			return NULL;
		}

		*part = temp;
		last = temp->mod;
		part = &temp->next;
	}
			
	return temp;
}

/*
 * We have a part of a message "name" of size "size" -- lets try to
 * find the message that this is a part of, and either return that
 * message pointer or create a new one and return that.  If name is
 * non-NULL, then it will compare the name passed in with older names
 * (i.e., a messageID).  If name is NULL, then it will compare sizes
 * for old-style multipart armor.  Do not return messages that have
 * only one part.
 *
 * This means that you can only have one old-style multipart message
 * going of any particular size (number of parts).  I don't consider
 * this a big problem, since interleaved messages are rarely a
 * problem.  Out-of-order messages, on the other hand.....
 */
static Message *
getMessage (PrsAscContext *ctx, char const *name, unsigned size)
{
	Message **msg = &ctx->msgs;
	char *newname;
	PGPContextRef		cdkContext	= ctx->pipe.cdkContext;

	/* Just remove name if it is a NULL string */
	if (name && !*name)
		name = NULL;

	if (!name && !size)

⌨️ 快捷键说明

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