gpg: Change parse_packet to take a context.

* g10/packet.h (struct parse_packet_ctx_s): New.
(parse_packet_ctx_t): New type.
(init_parse_packet): New macro.
* g10/parse-packet.c (parse_packet, dbg_parse_packet): Change to take
a parse context.  Change all callers to provide a context instead of
directly supplying the input stream.
(search_packet, dbg_search_packet): Ditto.
(copy_all_packets, dbg_copy_all_packets): Init an use a parse context.
(copy_some_packets, dbg_copy_some_packets): Ditto.
(skip_some_packets, dbg_skip_some_packets): Ditto.
--

We will need this change to handle ring packets inside the parser.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2017-03-29 10:02:40 +02:00
parent f5b565a5b8
commit 0526c99164
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
7 changed files with 137 additions and 77 deletions

View File

@ -762,6 +762,7 @@ static int
read_block( IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
{
int rc;
struct parse_packet_ctx_s parsectx;
PACKET *pkt;
kbnode_t root = NULL;
int in_cert, in_v3key;
@ -779,8 +780,9 @@ read_block( IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
pkt = xmalloc (sizeof *pkt);
init_packet (pkt);
init_parse_packet (&parsectx, a);
in_v3key = 0;
while ((rc=parse_packet(a, pkt)) != -1)
while ((rc=parse_packet (&parsectx, pkt)) != -1)
{
if (rc && (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY
&& (pkt->pkttype == PKT_PUBLIC_KEY

View File

@ -1156,6 +1156,7 @@ parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no,
const u32 *sigstatus, kbnode_t *r_keyblock)
{
gpg_error_t err;
struct parse_packet_ctx_s parsectx;
PACKET *pkt;
kbnode_t keyblock = NULL;
kbnode_t node, *tail;
@ -1169,12 +1170,13 @@ parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no,
if (!pkt)
return gpg_error_from_syserror ();
init_packet (pkt);
init_parse_packet (&parsectx, iobuf);
save_mode = set_packet_list_mode (0);
in_cert = 0;
n_sigs = 0;
tail = NULL;
pk_count = uid_count = 0;
while ((err = parse_packet (iobuf, pkt)) != -1)
while ((err = parse_packet (&parsectx, pkt)) != -1)
{
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_PACKET)
{

View File

@ -2431,6 +2431,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
char *fname;
PACKET *pkt;
IOBUF a;
struct parse_packet_ctx_s parsectx;
if (!*arg_string)
{
@ -2464,7 +2465,8 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
/* Parse and check that file. */
pkt = xmalloc (sizeof *pkt);
init_packet (pkt);
err = parse_packet (a, pkt);
init_parse_packet (&parsectx, a);
err = parse_packet (&parsectx, pkt);
iobuf_close (a);
iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char *) fname);
if (!err && pkt->pkttype != PKT_SECRET_KEY

View File

@ -378,6 +378,7 @@ int
keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
{
PACKET *pkt;
struct parse_packet_ctx_s parsectx;
int rc;
KBNODE keyblock = NULL, node, lastnode;
IOBUF a;
@ -407,10 +408,11 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
pkt = xmalloc (sizeof *pkt);
init_packet (pkt);
init_parse_packet (&parsectx, a);
hd->found.n_packets = 0;;
lastnode = NULL;
save_mode = set_packet_list_mode(0);
while ((rc=parse_packet (a, pkt)) != -1) {
while ((rc=parse_packet (&parsectx, pkt)) != -1) {
hd->found.n_packets++;
if (gpg_err_code (rc) == GPG_ERR_UNKNOWN_PACKET) {
free_packet (pkt);
@ -985,6 +987,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
{
int rc;
PACKET pkt;
struct parse_packet_ctx_s parsectx;
int save_mode;
off_t offset, main_offset;
size_t n;
@ -1120,12 +1123,13 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
if (DBG_LOOKUP)
log_debug ("%s: %ssearching from start of resource.\n",
__func__, scanned_from_start ? "" : "not ");
init_parse_packet (&parsectx, hd->current.iobuf);
while (1)
{
byte afp[MAX_FINGERPRINT_LEN];
size_t an;
rc = search_packet (hd->current.iobuf, &pkt, &offset, need_uid);
rc = search_packet (&parsectx, &pkt, &offset, need_uid);
if (ignore_legacy && gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
{
free_packet (&pkt);

View File

@ -1330,6 +1330,7 @@ static int
do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
{
PACKET *pkt;
struct parse_packet_ctx_s parsectx;
int rc = 0;
int any_data = 0;
int newpkt;
@ -1341,7 +1342,8 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
pkt = xmalloc( sizeof *pkt );
c->iobuf = a;
init_packet(pkt);
while ((rc=parse_packet(a, pkt)) != -1)
init_parse_packet (&parsectx, a);
while ((rc=parse_packet (&parsectx, pkt)) != -1)
{
any_data = 1;
if (rc)

View File

@ -592,12 +592,26 @@ int list_packets( iobuf_t a );
*/
int set_packet_list_mode( int mode );
/* A context used with parse_packet. */
struct parse_packet_ctx_s
{
iobuf_t inp; /* The input stream with the packets. */
};
typedef struct parse_packet_ctx_s *parse_packet_ctx_t;
#define init_parse_packet(a,i) do { (a)->inp = (i); \
/**/ } while (0)
#if DEBUG_PARSE_PACKET
/* There are debug functions and should not be used directly. */
int dbg_search_packet( iobuf_t inp, PACKET *pkt, off_t *retpos, int with_uid,
int dbg_search_packet (parse_packet_ctx_t ctx, PACKET *pkt,
off_t *retpos, int with_uid,
const char* file, int lineno );
int dbg_parse_packet( iobuf_t inp, PACKET *ret_pkt,
const char* file, int lineno );
int dbg_parse_packet (parse_packet_ctx_t ctx, PACKET *ret_pkt,
const char *file, int lineno);
int dbg_copy_all_packets( iobuf_t inp, iobuf_t out,
const char* file, int lineno );
int dbg_copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff,
@ -616,51 +630,53 @@ int dbg_skip_some_packets( iobuf_t inp, unsigned n,
dbg_skip_some_packets((a),(b), __FILE__, __LINE__ )
#else
/* Return the next valid OpenPGP packet in *PKT. (This function will
skip any packets whose type is 0.)
Returns 0 on success, -1 if EOF is reached, and an error code
otherwise. In the case of an error, the packet in *PKT may be
partially constructed. As such, even if there is an error, it is
necessary to free *PKT to avoid a resource leak. To detect what
has been allocated, clear *PKT before calling this function. */
int parse_packet( iobuf_t inp, PACKET *pkt);
* skip any packets whose type is 0.) CTX must have been setup prior to
* calling this function.
*
* Returns 0 on success, -1 if EOF is reached, and an error code
* otherwise. In the case of an error, the packet in *PKT may be
* partially constructed. As such, even if there is an error, it is
* necessary to free *PKT to avoid a resource leak. To detect what
* has been allocated, clear *PKT before calling this function. */
int parse_packet (parse_packet_ctx_t ctx, PACKET *pkt);
/* Return the first OpenPGP packet in *PKT that contains a key (either
a public subkey, a public key, a secret subkey or a secret key) or,
if WITH_UID is set, a user id.
Saves the position in the pipeline of the start of the returned
packet (according to iobuf_tell) in RETPOS, if it is not NULL.
The return semantics are the same as parse_packet. */
int search_packet( iobuf_t inp, PACKET *pkt, off_t *retpos, int with_uid );
* a public subkey, a public key, a secret subkey or a secret key) or,
* if WITH_UID is set, a user id.
*
* Saves the position in the pipeline of the start of the returned
* packet (according to iobuf_tell) in RETPOS, if it is not NULL.
*
* The return semantics are the same as parse_packet. */
int search_packet (parse_packet_ctx_t ctx, PACKET *pkt,
off_t *retpos, int with_uid);
/* Copy all packets (except invalid packets, i.e., those with a type
of 0) from INP to OUT until either an error occurs or EOF is
reached.
Returns -1 when end of file is reached or an error code, if an
error occurred. (Note: this function never returns 0, because it
effectively keeps going until it gets an EOF.) */
int copy_all_packets( iobuf_t inp, iobuf_t out );
* of 0) from INP to OUT until either an error occurs or EOF is
* reached.
*
* Returns -1 when end of file is reached or an error code, if an
* error occurred. (Note: this function never returns 0, because it
* effectively keeps going until it gets an EOF.) */
int copy_all_packets (iobuf_t inp, iobuf_t out );
/* Like copy_all_packets, but stops at the first packet that starts at
or after STOPOFF (as indicated by iobuf_tell).
Example: if STOPOFF is 100, the first packet in INP goes from 0 to
110 and the next packet starts at offset 111, then the packet
starting at offset 0 will be completely processed (even though it
extends beyond STOPOFF) and the packet starting at offset 111 will
not be processed at all. */
int copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff );
* or after STOPOFF (as indicated by iobuf_tell).
*
* Example: if STOPOFF is 100, the first packet in INP goes from
* 0 to 110 and the next packet starts at offset 111, then the packet
* starting at offset 0 will be completely processed (even though it
* extends beyond STOPOFF) and the packet starting at offset 111 will
* not be processed at all. */
int copy_some_packets (iobuf_t inp, iobuf_t out, off_t stopoff);
/* Skips the next N packets from INP.
If parsing a packet returns an error code, then the function stops
immediately and returns the error code. Note: in the case of an
error, this function does not indicate how many packets were
successfully processed. */
int skip_some_packets( iobuf_t inp, unsigned n );
*
* If parsing a packet returns an error code, then the function stops
* immediately and returns the error code. Note: in the case of an
* error, this function does not indicate how many packets were
* successfully processed. */
int skip_some_packets (iobuf_t inp, unsigned int n);
#endif
/* Parse a signature packet and store it in *SIG.

View File

@ -48,7 +48,7 @@ static int mpi_print_mode;
static int list_mode;
static estream_t listfp;
static int parse (IOBUF inp, PACKET * pkt, int onlykeypkts,
static int parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts,
off_t * retpos, int *skip, IOBUF out, int do_skip
#ifdef DEBUG_PARSE_PACKET
, const char *dbg_w, const char *dbg_f, int dbg_l
@ -263,26 +263,27 @@ unknown_pubkey_warning (int algo)
#ifdef DEBUG_PARSE_PACKET
int
dbg_parse_packet (IOBUF inp, PACKET *pkt, const char *dbg_f, int dbg_l)
dbg_parse_packet (parse_packet_ctx_t ctx, PACKET *pkt,
const char *dbg_f, int dbg_l)
{
int skip, rc;
do
{
rc = parse (inp, pkt, 0, NULL, &skip, NULL, 0, "parse", dbg_f, dbg_l);
rc = parse (ctx, pkt, 0, NULL, &skip, NULL, 0, "parse", dbg_f, dbg_l);
}
while (skip && ! rc);
return rc;
}
#else /*!DEBUG_PARSE_PACKET*/
int
parse_packet (IOBUF inp, PACKET * pkt)
parse_packet (parse_packet_ctx_t ctx, PACKET *pkt)
{
int skip, rc;
do
{
rc = parse (inp, pkt, 0, NULL, &skip, NULL, 0);
rc = parse (ctx, pkt, 0, NULL, &skip, NULL, 0);
}
while (skip && ! rc);
return rc;
@ -296,29 +297,30 @@ parse_packet (IOBUF inp, PACKET * pkt)
*/
#ifdef DEBUG_PARSE_PACKET
int
dbg_search_packet (IOBUF inp, PACKET * pkt, off_t * retpos, int with_uid,
dbg_search_packet (parse_packet_ctx_t ctx, PACKET *pkt,
off_t * retpos, int with_uid,
const char *dbg_f, int dbg_l)
{
int skip, rc;
do
{
rc =
parse (inp, pkt, with_uid ? 2 : 1, retpos, &skip, NULL, 0, "search",
dbg_f, dbg_l);
rc = parse (ctx, pkt, with_uid ? 2 : 1, retpos, &skip, NULL, 0, "search",
dbg_f, dbg_l);
}
while (skip && ! rc);
return rc;
}
#else /*!DEBUG_PARSE_PACKET*/
int
search_packet (IOBUF inp, PACKET * pkt, off_t * retpos, int with_uid)
search_packet (parse_packet_ctx_t ctx, PACKET *pkt,
off_t * retpos, int with_uid)
{
int skip, rc;
do
{
rc = parse (inp, pkt, with_uid ? 2 : 1, retpos, &skip, NULL, 0);
rc = parse (ctx, pkt, with_uid ? 2 : 1, retpos, &skip, NULL, 0);
}
while (skip && ! rc);
return rc;
@ -331,38 +333,45 @@ search_packet (IOBUF inp, PACKET * pkt, off_t * retpos, int with_uid)
*/
#ifdef DEBUG_PARSE_PACKET
int
dbg_copy_all_packets (IOBUF inp, IOBUF out, const char *dbg_f, int dbg_l)
dbg_copy_all_packets (iobuf_t inp, iobuf_t out, const char *dbg_f, int dbg_l)
{
PACKET pkt;
struct parse_packet_ctx_s parsectx;
int skip, rc = 0;
if (! out)
log_bug ("copy_all_packets: OUT may not be NULL.\n");
init_parse_packet (&parsectx, inp);
do
{
init_packet (&pkt);
}
while (!
(rc =
parse (inp, &pkt, 0, NULL, &skip, out, 0, "copy", dbg_f, dbg_l)));
parse (&parsectx, &pkt, 0, NULL, &skip, out, 0, "copy",
dbg_f, dbg_l)));
return rc;
}
#else /*!DEBUG_PARSE_PACKET*/
int
copy_all_packets (IOBUF inp, IOBUF out)
copy_all_packets (iobuf_t inp, iobuf_t out)
{
PACKET pkt;
struct parse_packet_ctx_s parsectx;
int skip, rc = 0;
if (! out)
log_bug ("copy_all_packets: OUT may not be NULL.\n");
init_parse_packet (&parsectx, inp);
do
{
init_packet (&pkt);
}
while (!(rc = parse (inp, &pkt, 0, NULL, &skip, out, 0)));
while (!(rc = parse (&parsectx, &pkt, 0, NULL, &skip, out, 0)));
return rc;
}
#endif /*!DEBUG_PARSE_PACKET*/
@ -375,34 +384,44 @@ copy_all_packets (IOBUF inp, IOBUF out)
*/
#ifdef DEBUG_PARSE_PACKET
int
dbg_copy_some_packets (IOBUF inp, IOBUF out, off_t stopoff,
dbg_copy_some_packets (iobuf_t inp, iobuf_t out, off_t stopoff,
const char *dbg_f, int dbg_l)
{
int rc = 0;
PACKET pkt;
int skip, rc = 0;
int skip;
struct parse_packet_ctx_s parsectx;
init_parse_packet (&parsectx, inp);
do
{
if (iobuf_tell (inp) >= stopoff)
return 0;
init_packet (&pkt);
}
while (!(rc = parse (inp, &pkt, 0, NULL, &skip, out, 0,
while (!(rc = parse (&parsectx, &pkt, 0, NULL, &skip, out, 0,
"some", dbg_f, dbg_l)));
return rc;
}
#else /*!DEBUG_PARSE_PACKET*/
int
copy_some_packets (IOBUF inp, IOBUF out, off_t stopoff)
copy_some_packets (iobuf_t inp, iobuf_t out, off_t stopoff)
{
int rc = 0;
PACKET pkt;
int skip, rc = 0;
struct parse_packet_ctx_s parsectx;
int skip;
init_parse_packet (&parsectx, inp);
do
{
if (iobuf_tell (inp) >= stopoff)
return 0;
init_packet (&pkt);
}
while (!(rc = parse (inp, &pkt, 0, NULL, &skip, out, 0)));
while (!(rc = parse (&parsectx, &pkt, 0, NULL, &skip, out, 0)));
return rc;
}
#endif /*!DEBUG_PARSE_PACKET*/
@ -413,29 +432,38 @@ copy_some_packets (IOBUF inp, IOBUF out, off_t stopoff)
*/
#ifdef DEBUG_PARSE_PACKET
int
dbg_skip_some_packets (IOBUF inp, unsigned n, const char *dbg_f, int dbg_l)
dbg_skip_some_packets (iobuf_t inp, unsigned n, const char *dbg_f, int dbg_l)
{
int skip, rc = 0;
int rc = 0;
int skip;
PACKET pkt;
struct parse_packet_ctx_s parsectx;
init_parse_packet (&parsectx, inp);
for (; n && !rc; n--)
{
init_packet (&pkt);
rc = parse (inp, &pkt, 0, NULL, &skip, NULL, 1, "skip", dbg_f, dbg_l);
rc = parse (&parsectx, &pkt, 0, NULL, &skip, NULL, 1, "skip",
dbg_f, dbg_l);
}
return rc;
}
#else /*!DEBUG_PARSE_PACKET*/
int
skip_some_packets (IOBUF inp, unsigned n)
skip_some_packets (iobuf_t inp, unsigned int n)
{
int skip, rc = 0;
int rc = 0;
int skip;
PACKET pkt;
struct parse_packet_ctx_s parsectx;
init_parse_packet (&parsectx, inp);
for (; n && !rc; n--)
{
init_packet (&pkt);
rc = parse (inp, &pkt, 0, NULL, &skip, NULL, 1);
rc = parse (&parsectx, &pkt, 0, NULL, &skip, NULL, 1);
}
return rc;
}
@ -466,18 +494,20 @@ skip_some_packets (IOBUF inp, unsigned n)
Note: ONLYKEYPKTS and DO_SKIP are only respected if OUT is NULL,
i.e., the packets are not simply being copied.
If RETPOS is not NULL, then the position of INP (as returned by
iobuf_tell) is saved there before any data is read from INP.
If RETPOS is not NULL, then the position of CTX->INP (as returned by
iobuf_tell) is saved there before any data is read from CTX->INP.
*/
static int
parse (IOBUF inp, PACKET * pkt, int onlykeypkts, off_t * retpos,
parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos,
int *skip, IOBUF out, int do_skip
#ifdef DEBUG_PARSE_PACKET
, const char *dbg_w, const char *dbg_f, int dbg_l
#endif
)
{
int rc = 0, c, ctb, pkttype, lenbytes;
int rc = 0;
iobuf_t inp;
int c, ctb, pkttype, lenbytes;
unsigned long pktlen;
byte hdr[8];
int hdrlen;
@ -486,6 +516,8 @@ parse (IOBUF inp, PACKET * pkt, int onlykeypkts, off_t * retpos,
off_t pos;
*skip = 0;
inp = ctx->inp;
log_assert (!pkt->pkt.generic);
if (retpos || list_mode)
{