pgpprsbin.c
来自「著名的加密软件的应用于电子邮件中」· C语言 代码 · 共 2,522 行 · 第 1/5 页
C
2,522 行
return size0-size;
}
static size_t
parseCipher (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);
*error = 0;
switch (ctx->state) {
case 0:
/* Parse header; needed before callbacks are allowed */
written = inputMerge(&ctx->input, buf, size, IVLEN, error);
buf += written;
size -= written;
if (*error || !size)
break;
/* Size is non-zero but we haven't got desired? EOP */
if (inputMerged(&ctx->input) < IVLEN) {
pgpAssert(inputFinished(&ctx->input.head));
*error = ctx->tail->annotate(ctx->tail, myself,
PGPANN_PACKET_SHORT,
0, 0);
if (*error)
break;
myself->write = nextScope;
size -= nextScope (myself, buf, size, error);
break;
}
ctx->needcallback = 1;
/*
* If we're already in an encrypted scope (we've already
* sent some ESKs to the user), don't bother sending another
* one.
*/
if (ctx->end_scope) { /* Scope alreay open? */
ctx->state = 2;
goto got_esk;
}
/* No ESKs seen yet - open the 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:
/* No ESKs seen yet - dummy one up */
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_SKCIPHER_ESK, 0, 0);
if (*error)
break;
ctx->state++;
/* FALLTHROUGH */
case 2:
got_esk:
/* Okay, do a commit */
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_PASSTHROUGH,
0, 0);
if (*error)
break;
}
ctx->state++;
written += myself->write(myself, buf, size, error);
break;
default:
pgpAssert (0);
}
return written;
}
static size_t
parseCompressed (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);
*error = 0;
switch (ctx->state) {
case 0:
/* Make sure we have the compression type */
written = inputMerge(&ctx->input, buf, size, 1, error);
buf += written;
size -= written;
if (*error || !size)
break;
/* Size is non-zero but we haven't got desired? EOP */
if (inputMerged(&ctx->input) < 1) {
pgpAssert(inputFinished(&ctx->input.head));
*error = ctx->tail->annotate(ctx->tail, myself,
PGPANN_PACKET_SHORT,
0, 0);
if (*error)
break;
myself->write = nextScope;
size -= nextScope (myself, buf, size, error);
break;
}
ctx->needcallback = 1;
ctx->end_scope = PGPANN_COMPRESSED_END;
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_COMPRESSED_BEGIN,
inputMergedPtr(&ctx->input), 1);
if (*error)
break;
ctx->state++;
/* FALLTHROUGH */
case 1:
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_RECURSE,
0, 0);
if (*error)
break;
}
ctx->state++;
written += myself->write(myself, buf, size, error);
break;
default:
pgpAssert (0);
}
return written;
}
/*
* Parse a general headerless packet. Unknown packets, comment packets
* and, in fact, things that aren't packets at all!
*/
static size_t
parseUnknown (struct PgpPipeline *myself, byte const *buf, size_t size,
int *error)
{
struct Context *ctx;
size_t written = 0;
byte b;
int begintype;
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:
/*
* As a convenience, we merge a leading prefix of the packet
* for identification purposes.
*/
written = inputMerge(&ctx->input, buf, size, 256, error);
buf += written;
size -= written;
if (*error)
return written;
if (inputMerged(&ctx->input) < 256 &&
!inputFinished(&ctx->input.head))
{
pgpAssert(!size);
return written;
}
/*
* We use this one function to provide different
* annotations for non-packets, comment packets, and
* unknown packets. Figure out the right one to use.
*/
b = ctx->input.buffer[0];
if (!IS_OLD_PKTBYTE(b) && !IS_NEW_PKTBYTE(b)) {
begintype = PGPANN_NONPACKET_BEGIN;
ctx->end_scope = PGPANN_NONPACKET_END;
} else if (PKTBYTE_TYPE (b) == PKTBYTE_COMMENT) {
begintype = PGPANN_COMMENT_BEGIN;
ctx->end_scope = PGPANN_COMMENT_END;
} else {
begintype = PGPANN_UNKNOWN_BEGIN;
ctx->end_scope = PGPANN_UNKNOWN_END;
}
ctx->needcallback = 1;
*error = ctx->tail->annotate (ctx->tail, myself, begintype,
inputMergedPtr(&ctx->input),
inputMerged(&ctx->input));
if (*error)
break;
ctx->state++;
/* FALLTHROUGH */
case 1:
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 written + myself->write(myself, buf, size, error);
/* NOTREACHED */
default:
pgpAssert (0);
}
return written;
}
/*
* This is called for most all key-type packets. Keys are just output
* within a key annotation scope. There is no callback, since no
* processing is done.
*/
static size_t
parseKey (struct PgpPipeline *myself, byte const *buf, size_t size, int *error)
{
struct Context *ctx;
struct PgpPipeline *tail;
size_t size0 = size;
byte const *p;
size_t len;
pgpAssert (myself);
pgpAssert (myself->magic == PARSERMAGIC);
pgpAssert (error);
ctx = (struct Context *)myself->priv;
pgpAssert (ctx);
tail = ctx->tail;
pgpAssert (tail);
pgpAssert (!size || !ctx->eof);
*error = 0;
if (ctx->end_scope && ctx->end_scope != PGPANN_PGPKEY_END) {
/* Umm.. Key block within another scope??? Why??? */
*error = PGPERR_WRONG_SCOPE;
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.
*/
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_SIG:
case PKTBYTE_COMMENT:
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 (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 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;
/* We also want one byte of look-ahead */
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 = type;
return written;
}
if (type & 0xF0) {
/* This is a key signature */
myself->write = parseKey;
return written + parseKey (myself, buf, size,
error);
}
}
/*
* 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 */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?