📄 pgpprsbin.c
字号:
*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 (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 signature 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;
/* FALLTHROUGH */
case 1:
/* Dump the signature data as an annotation */
ctx->needcallback = 1;
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_SIGNED_SIG2,
inputMergedPtr(&ctx->input),
inputMerged(&ctx->input));
if (*error)
break;
/* Decrement count of sig footers needing to be seen */
--ctx->sig1pass;
if (!ctx->sepsig || ctx->sig1pass != 0) {
/*
* In normal case, we are done now.
* nextScope will end sig scope if sig1pass is 0.
*/
myself->write = nextScope;
written += nextScope(myself, buf, size, error);
break;
}
/* Here on last sig footer of separate signature */
ctx->state++;
ctx->needcallback = 1;
/* FALLTHROUGH */
case 2:
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_EATIT,
0, 0);
if (*error)
break;
}
ctx->state = 0;
written += myself->write(myself, buf, size, error);
break;
}
return written;
}
static size_t
parseESK (struct PgpPipeline *myself, byte const *buf, size_t size, int *error)
{
struct Context *ctx;
size_t written = 0;
byte b;
pgpAssert (myself);
pgpAssert (myself->magic == PARSERMAGIC);
pgpAssert (error);
ctx = (struct Context *)myself->priv;
pgpAssert (ctx);
pgpAssert (ctx->tail);
pgpAssert (!size || !ctx->eof);
b = PKTBYTE_TYPE (ctx->input.buffer[0]);
*error = 0;
switch (ctx->state) {
case 0:
/* It's a public-key-encrypted PGP file */
if (!ctx->end_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:
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_ESK_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;
ctx->state++;
/* FALLTHROUGH */
case 2:
/* Dump the ESK as an annotation */
*error = ctx->tail->annotate (ctx->tail, myself,
(b == PKTBYTE_ESK ?
PGPANN_PKCIPHER_ESK :
(b == PKTBYTE_CONVESK ?
PGPANN_SKCIPHER_ESK :
-1)), /* XXX */
inputMergedPtr(&ctx->input),
inputMerged(&ctx->input));
if (*error)
break;
ctx->state++; /* This really isn't needed */
myself->write = nextESK;
return written + nextESK(myself, buf, size, error);
/* NOTREACHED */
default:
pgpAssert (0);
}
return written;
}
/*
* This just sends appropriate messages about the lack of text downstream.
*/
static size_t
parseCipherNoText (struct PgpPipeline *myself, byte const *buf, size_t size,
int *error)
{
struct Context *ctx;
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:
ctx->needcallback = 1;
/* Send an annotation */
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_CIPHER_NOTEXT, 0, 0);
if (*error)
break;
ctx->state++;
/*FALLTHROUGH*/
case 1:
/* Send a commit */
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 myself->write(myself, buf, size, error);
default:
pgpAssert (0);
}
return 0; /* Never executed; makes compilers happy. */
}
/*
* The default state when starting to parse a packet. Once the type and
* size of the packet has been determined, we don't come back until
* the end of the packet. This function *is* called after each packet
* (by the sizeAdvise(0) handler if necessary), because post-packet
* cleanup code also resides here.
*
* Because the functions in this module rely heavily on tail recursion,
* if we get called with a large packet (say 16K), it could have literally
* hundreds of objects on it, and we go hundreds of levels deep on recursion.
* This exhausts stack space. Therefore we will limit the amount of data we
* will accept on one call to PARSER_SIZE_LIMIT.
*/
static size_t
parsePacket (struct PgpPipeline *myself, byte const *buf, size_t size,
int *error)
{
struct Context *ctx;
size_t written = 0;
unsigned b;
pgpAssert (myself);
pgpAssert (myself->magic == PARSERMAGIC);
pgpAssert (error);
ctx = (struct Context *)myself->priv;
pgpAssert (ctx);
pgpAssert (ctx->tail);
pgpAssert (!size || !ctx->eof);
*error = 0;
/* Prevent excessive recursion within this module */
size = min(size, PARSER_SIZE_LIMIT);
/*
* findpkt is set to 1 by create and every time we change to
* the parsePacket state, and indicates that the first packet
* byte has not been found.
*/
if (ctx->findpkt) {
inputReset(&ctx->input);
if (!size)
return 0; /* I need a packet header! */
ctx->findpkt = 0;
b = *(buf++);
size--;
if (inputStart(&ctx->input, b) < 0) {
ctx->state = 0; /* Need to set this */
/* before jumping ahead */
myself->write = parseUnknown;
return 1+parseUnknown (myself, buf, size, error);
}
written = 1;
}
/*
* Okay, now we have a packet, with the parser state set up
* and the header byte in ctx->input.buffer[0].
*
* The packet-specific parsers use a state variable, and
* expect it to be set to 0 when they begin.
*/
ctx->state = 0;
b = PKTBYTE_TYPE (ctx->input.buffer[0]);
if (ctx->end_scope == PGPANN_CIPHER_END) {
switch (b) {
case PKTBYTE_CONVENTIONAL:
myself->write = parseCipher;
break;
case PKTBYTE_CONVESK:
case PKTBYTE_ESK:
myself->write = parseESK;
break;
default:
myself->write = parseCipherNoText;
break;
}
} else {
switch (b) {
case PKTBYTE_CONVENTIONAL:
myself->write = parseCipher;
break;
case PKTBYTE_OLDLITERAL:
/*
* This may be a dummy header we created, or it may be a
* mistaken value from a PGP compatible program, or it may
* conceivably be an obsolete old-style literal packet from a
* pre-release version of PGP 2.0!
* Flag special treatment, and distinguish the cases in
* parseLiteral.
*/
ctx->state = 10;
/* FALLTHROUGH */
case PKTBYTE_LITERAL:
myself->wr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -