aboutsummaryrefslogtreecommitdiffstats
path: root/g10/parse-packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/parse-packet.c')
-rw-r--r--g10/parse-packet.c1101
1 files changed, 598 insertions, 503 deletions
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index c922eb5d9..b4dfb8c84 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -1,6 +1,6 @@
/* parse-packet.c - read packets
- * Copyright (C) 1998, 1999, 2000, 2001, 2002,
- * 2003 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ * 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -16,7 +16,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
*/
#include <config.h>
@@ -25,63 +26,61 @@
#include <string.h>
#include <assert.h>
+#include "gpg.h"
#include "packet.h"
#include "iobuf.h"
-#include "mpi.h"
#include "util.h"
#include "cipher.h"
-#include "memory.h"
#include "filter.h"
#include "photoid.h"
#include "options.h"
#include "main.h"
#include "i18n.h"
-static int mpi_print_mode = 0;
-static int list_mode = 0;
+static int mpi_print_mode;
+static int list_mode;
+static FILE *listfp;
-static int parse( iobuf_t inp, PACKET *pkt, int onlykeypkts,
- off_t *retpos, int *skip, iobuf_t out, int do_skip
+static int parse( IOBUF inp, 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
);
-static int copy_packet( iobuf_t inp, iobuf_t out, int pkttype,
- unsigned long pktlen );
-static void skip_packet( iobuf_t inp, int pkttype, unsigned long pktlen );
-static void skip_rest( iobuf_t inp, unsigned long pktlen );
-static void *read_rest( iobuf_t inp, size_t pktlen );
-static int parse_symkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen,
+static int copy_packet( IOBUF inp, IOBUF out, int pkttype,
+ unsigned long pktlen, int partial );
+static void skip_packet( IOBUF inp, int pkttype,
+ unsigned long pktlen, int partial );
+static void *read_rest( IOBUF inp, size_t pktlen, int partial );
+static int parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
-static int parse_pubkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen,
+static int parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
-static int parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen,
- PKT_signature *sig );
-static int parse_onepass_sig( iobuf_t inp, int pkttype, unsigned long pktlen,
+static int parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_onepass_sig *ops );
-static int parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
+static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
byte *hdr, int hdrlen, PACKET *packet );
-static int parse_user_id( iobuf_t inp, int pkttype, unsigned long pktlen,
+static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
-static int parse_attribute( iobuf_t inp, int pkttype, unsigned long pktlen,
+static int parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
-static int parse_comment( iobuf_t inp, int pkttype, unsigned long pktlen,
+static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
-static void parse_trust( iobuf_t inp, int pkttype, unsigned long pktlen,
+static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
-static int parse_plaintext( iobuf_t inp, int pkttype, unsigned long pktlen,
- PACKET *packet, int new_ctb);
-static int parse_compressed( iobuf_t inp, int pkttype, unsigned long pktlen,
+static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
+ PACKET *packet, int new_ctb, int partial);
+static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet, int new_ctb );
-static int parse_encrypted( iobuf_t inp, int pkttype, unsigned long pktlen,
- PACKET *packet, int new_ctb);
-static int parse_mdc( iobuf_t inp, int pkttype, unsigned long pktlen,
+static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
+ PACKET *packet, int new_ctb, int partial);
+static int parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet, int new_ctb);
-static int parse_gpg_control( iobuf_t inp, int pkttype, unsigned long pktlen,
- PACKET *packet );
+static int parse_gpg_control( IOBUF inp, int pkttype, unsigned long pktlen,
+ PACKET *packet, int partial );
static unsigned short
-read_16(iobuf_t inp)
+read_16(IOBUF inp)
{
unsigned short a;
a = iobuf_get_noeof(inp) << 8;
@@ -90,7 +89,7 @@ read_16(iobuf_t inp)
}
static unsigned long
-read_32(iobuf_t inp)
+read_32(IOBUF inp)
{
unsigned long a;
a = iobuf_get_noeof(inp) << 24;
@@ -101,12 +100,84 @@ read_32(iobuf_t inp)
}
+/* Read an external representation of an mpi and return the MPI. The
+ * external format is a 16 bit unsigned value stored in network byte
+ * order, giving the number of bits for the following integer. The
+ * integer is stored with MSB first (left padded with zeroes to align
+ * on a byte boundary).
+ */
+static gcry_mpi_t
+mpi_read (iobuf_t inp, unsigned int *ret_nread, int secure)
+{
+ /*FIXME: Needs to be synced with gnupg14/mpi/mpicoder.c*/
+
+ int c, c1, c2, i;
+ unsigned int nbits, nbytes, nread=0;
+ gcry_mpi_t a = NULL;
+ byte *buf = NULL;
+ byte *p;
+
+ if( (c = c1 = iobuf_get(inp)) == -1 )
+ goto leave;
+ nbits = c << 8;
+ if( (c = c2 = iobuf_get(inp)) == -1 )
+ goto leave;
+ nbits |= c;
+ if( nbits > MAX_EXTERN_MPI_BITS )
+ {
+ log_error("mpi too large (%u bits)\n", nbits);
+ goto leave;
+ }
+ nread = 2;
+ nbytes = (nbits+7) / 8;
+ buf = secure? gcry_xmalloc_secure( nbytes+2 ) : gcry_xmalloc( nbytes+2 );
+ p = buf;
+ p[0] = c1;
+ p[1] = c2;
+ for( i=0 ; i < nbytes; i++ )
+ {
+ p[i+2] = iobuf_get(inp) & 0xff;
+ nread++;
+ }
+ nread += nbytes;
+ if( gcry_mpi_scan( &a, GCRYMPI_FMT_PGP, buf, nread, &nread ) )
+ a = NULL;
+
+ leave:
+ gcry_free(buf);
+ if( nread > *ret_nread )
+ log_bug("mpi larger than packet");
+ else
+ *ret_nread = nread;
+ return a;
+}
+
+
+
+
int
set_packet_list_mode( int mode )
{
int old = list_mode;
list_mode = mode;
- /* FIXME(gcrypt) mpi_print_mode = DBG_MPI; */
+ /* FIXME(gcrypt) mpi_print_mode = DBG_MPI; */
+ /* We use stdout print only if invoked by the --list-packets
+ command but switch to stderr in all otehr cases. This breaks
+ the previous behaviour but that seems to be more of a bug than
+ intentional. I don't believe that any application makes use of
+ this long standing annoying way of printing to stdout except
+ when doing a --list-packets. If this assumption fails, it will
+ be easy to add an option for the listing stream. Note that we
+ initialize it only once; mainly because some code may switch
+ the option value later back to 1 and we want to have all output
+ to the same stream.
+
+ Using stderr is not actually very clean because it bypasses the
+ logging code but it is a special thing anyay. I am not sure
+ whether using log_stream() would be better. Perhaps we should
+ enable the list mdoe only with a special option. */
+ if (!listfp)
+ listfp = opt.list_packets == 2 ? stdout : stderr;
return old;
}
@@ -133,7 +204,7 @@ unknown_pubkey_warning( int algo )
*/
#ifdef DEBUG_PARSE_PACKET
int
-dbg_parse_packet( iobuf_t inp, PACKET *pkt, const char *dbg_f, int dbg_l )
+dbg_parse_packet( IOBUF inp, PACKET *pkt, const char *dbg_f, int dbg_l )
{
int skip, rc;
@@ -144,7 +215,7 @@ dbg_parse_packet( iobuf_t inp, PACKET *pkt, const char *dbg_f, int dbg_l )
}
#else
int
-parse_packet( iobuf_t inp, PACKET *pkt )
+parse_packet( IOBUF inp, PACKET *pkt )
{
int skip, rc;
@@ -160,7 +231,7 @@ parse_packet( iobuf_t inp, PACKET *pkt )
*/
#ifdef DEBUG_PARSE_PACKET
int
-dbg_search_packet( iobuf_t inp, PACKET *pkt, off_t *retpos, int with_uid,
+dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid,
const char *dbg_f, int dbg_l )
{
int skip, rc;
@@ -172,7 +243,7 @@ dbg_search_packet( iobuf_t inp, PACKET *pkt, off_t *retpos, int with_uid,
}
#else
int
-search_packet( iobuf_t inp, PACKET *pkt, off_t *retpos, int with_uid )
+search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid )
{
int skip, rc;
@@ -188,7 +259,7 @@ search_packet( iobuf_t inp, PACKET *pkt, off_t *retpos, int with_uid )
*/
#ifdef DEBUG_PARSE_PACKET
int
-dbg_copy_all_packets( iobuf_t inp, iobuf_t out,
+dbg_copy_all_packets( IOBUF inp, IOBUF out,
const char *dbg_f, int dbg_l )
{
PACKET pkt;
@@ -200,7 +271,7 @@ dbg_copy_all_packets( iobuf_t inp, iobuf_t out,
}
#else
int
-copy_all_packets( iobuf_t inp, iobuf_t out )
+copy_all_packets( IOBUF inp, IOBUF out )
{
PACKET pkt;
int skip, rc=0;
@@ -217,7 +288,7 @@ copy_all_packets( iobuf_t inp, iobuf_t out )
*/
#ifdef DEBUG_PARSE_PACKET
int
-dbg_copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff,
+dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff,
const char *dbg_f, int dbg_l )
{
PACKET pkt;
@@ -232,7 +303,7 @@ dbg_copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff,
}
#else
int
-copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff )
+copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff )
{
PACKET pkt;
int skip, rc=0;
@@ -250,7 +321,7 @@ copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff )
*/
#ifdef DEBUG_PARSE_PACKET
int
-dbg_skip_some_packets( iobuf_t inp, unsigned n,
+dbg_skip_some_packets( IOBUF inp, unsigned n,
const char *dbg_f, int dbg_l )
{
int skip, rc=0;
@@ -264,7 +335,7 @@ dbg_skip_some_packets( iobuf_t inp, unsigned n,
}
#else
int
-skip_some_packets( iobuf_t inp, unsigned n )
+skip_some_packets( IOBUF inp, unsigned n )
{
int skip, rc=0;
PACKET pkt;
@@ -286,8 +357,8 @@ skip_some_packets( iobuf_t inp, unsigned n )
* if OUT is not NULL, a special copymode is used.
*/
static int
-parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
- int *skip, iobuf_t out, int do_skip
+parse( IOBUF inp, 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
@@ -297,7 +368,7 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
unsigned long pktlen;
byte hdr[8];
int hdrlen;
- int new_ctb = 0;
+ int new_ctb = 0, partial=0;
int with_uid = (onlykeypkts == 2);
*skip = 0;
@@ -313,7 +384,7 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
hdr[hdrlen++] = ctb;
if( !(ctb & 0x80) ) {
log_error("%s: invalid packet (ctb=%02x)\n", iobuf_where(inp), ctb );
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
pktlen = 0;
@@ -322,81 +393,94 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
pkttype = ctb & 0x3f;
if( (c = iobuf_get(inp)) == -1 ) {
log_error("%s: 1st length byte missing\n", iobuf_where(inp) );
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
if (pkttype == PKT_COMPRESSED) {
iobuf_set_partial_block_mode(inp, c & 0xff);
pktlen = 0;/* to indicate partial length */
+ partial=1;
}
else {
hdr[hdrlen++] = c;
if( c < 192 )
- pktlen = c;
- else if( c < 224 ) {
- pktlen = (c - 192) * 256;
- if( (c = iobuf_get(inp)) == -1 ) {
- log_error("%s: 2nd length byte missing\n",
- iobuf_where(inp) );
- rc = GPG_ERR_INV_PACKET;
- goto leave;
- }
- hdr[hdrlen++] = c;
- pktlen += c + 192;
- }
- else if( c == 255 ) {
- pktlen = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24;
- pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16;
- pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8;
- if( (c = iobuf_get(inp)) == -1 ) {
- log_error("%s: 4 byte length invalid\n",
- iobuf_where(inp) );
- rc = GPG_ERR_INV_PACKET;
- goto leave;
- }
- pktlen |= (hdr[hdrlen++] = c );
- }
- else { /* partial body length */
- iobuf_set_partial_block_mode(inp, c & 0xff);
- pktlen = 0;/* to indicate partial length */
- }
+ pktlen = c;
+ else if( c < 224 )
+ {
+ pktlen = (c - 192) * 256;
+ if( (c = iobuf_get(inp)) == -1 )
+ {
+ log_error("%s: 2nd length byte missing\n",
+ iobuf_where(inp) );
+ rc = gpg_error (GPG_ERR_INV_PACKET);
+ goto leave;
+ }
+ hdr[hdrlen++] = c;
+ pktlen += c + 192;
+ }
+ else if( c == 255 )
+ {
+ pktlen = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24;
+ pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16;
+ pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8;
+ if( (c = iobuf_get(inp)) == -1 )
+ {
+ log_error("%s: 4 byte length invalid\n",
+ iobuf_where(inp) );
+ rc = gpg_error (GPG_ERR_INV_PACKET);
+ goto leave;
+ }
+ pktlen |= (hdr[hdrlen++] = c );
+ }
+ else
+ {
+ /* Partial body length. Note that we handled
+ PKT_COMPRESSED earlier. */
+ if(pkttype==PKT_PLAINTEXT || pkttype==PKT_ENCRYPTED
+ || pkttype==PKT_ENCRYPTED_MDC)
+ {
+ iobuf_set_partial_block_mode(inp, c & 0xff);
+ pktlen = 0;/* to indicate partial length */
+ partial=1;
+ }
+ else
+ {
+ log_error("%s: partial length for invalid"
+ " packet type %d\n",iobuf_where(inp),pkttype);
+ rc = gpg_error (GPG_ERR_INV_PACKET);
+ goto leave;
+ }
+ }
}
}
- else {
+ else
+ {
pkttype = (ctb>>2)&0xf;
lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
- if( !lenbytes ) {
+ if( !lenbytes )
+ {
pktlen = 0; /* don't know the value */
- switch (pkttype) {
- case PKT_ENCRYPTED:
- case PKT_PLAINTEXT:
- /* These partial length encodings are from an very
- early GnuPG release and deprecated. However we
- still support them read-wise. Note, that we should
- not allow them for any key related packets, because
- this might render a keyring unusable if an errenous
- packet indicated this mode but not complying to it
- gets imported. */
- iobuf_set_block_mode(inp, 1);
- break;
-
- case PKT_COMPRESSED:
- break; /* the orginal pgp 2 way. */
-
- default:
- log_error ("%s: old style partial length "
- "for invalid packet type\n", iobuf_where(inp) );
+ /* This isn't really partial, but we can treat it the same
+ in a "read until the end" sort of way. */
+ partial=1;
+ if(pkttype!=PKT_ENCRYPTED && pkttype!=PKT_PLAINTEXT
+ && pkttype!=PKT_COMPRESSED)
+ {
+ log_error ("%s: indeterminate length for invalid"
+ " packet type %d\n", iobuf_where(inp), pkttype );
rc = gpg_error (GPG_ERR_INV_PACKET);
- goto leave;
- }
- }
- else {
- for( ; lenbytes; lenbytes-- ) {
+ goto leave;
+ }
+ }
+ else
+ {
+ for( ; lenbytes; lenbytes-- )
+ {
pktlen <<= 8;
pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
- }
- }
- }
+ }
+ }
+ }
if (pktlen == 0xffffffff) {
/* with a some probability this is caused by a problem in the
@@ -407,9 +491,10 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
}
if( out && pkttype ) {
- rc = iobuf_write( out, hdr, hdrlen );
- if (!rc)
- rc = copy_packet(inp, out, pkttype, pktlen );
+ if( iobuf_write( out, hdr, hdrlen ) == -1 )
+ rc = G10ERR_WRITE_FILE;
+ else
+ rc = copy_packet(inp, out, pkttype, pktlen, partial );
goto leave;
}
@@ -421,7 +506,7 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
&& pkttype != PKT_PUBLIC_KEY
&& pkttype != PKT_SECRET_SUBKEY
&& pkttype != PKT_SECRET_KEY ) ) {
- skip_rest(inp, pktlen);
+ iobuf_skip_rest(inp, pktlen, partial);
*skip = 1;
rc = 0;
goto leave;
@@ -438,16 +523,16 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
#endif
}
pkt->pkttype = pkttype;
- rc = GPG_ERR_UNKNOWN_PACKET; /* default error */
+ rc = G10ERR_UNKNOWN_PACKET; /* default error */
switch( pkttype ) {
case PKT_PUBLIC_KEY:
case PKT_PUBLIC_SUBKEY:
- pkt->pkt.public_key = xcalloc (1,sizeof *pkt->pkt.public_key );
+ pkt->pkt.public_key = xmalloc_clear(sizeof *pkt->pkt.public_key );
rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
break;
case PKT_SECRET_KEY:
case PKT_SECRET_SUBKEY:
- pkt->pkt.secret_key = xcalloc (1,sizeof *pkt->pkt.secret_key );
+ pkt->pkt.secret_key = xmalloc_clear(sizeof *pkt->pkt.secret_key );
rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
break;
case PKT_SYMKEY_ENC:
@@ -457,11 +542,11 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt );
break;
case PKT_SIGNATURE:
- pkt->pkt.signature = xcalloc (1,sizeof *pkt->pkt.signature );
+ pkt->pkt.signature = xmalloc_clear(sizeof *pkt->pkt.signature );
rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
break;
case PKT_ONEPASS_SIG:
- pkt->pkt.onepass_sig = xcalloc (1,sizeof *pkt->pkt.onepass_sig );
+ pkt->pkt.onepass_sig = xmalloc_clear(sizeof *pkt->pkt.onepass_sig );
rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig );
break;
case PKT_USER_ID:
@@ -480,29 +565,29 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
rc = 0;
break;
case PKT_PLAINTEXT:
- rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb );
+ rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb, partial );
break;
case PKT_COMPRESSED:
rc = parse_compressed(inp, pkttype, pktlen, pkt, new_ctb );
break;
case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC:
- rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb );
+ rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb, partial );
break;
case PKT_MDC:
rc = parse_mdc(inp, pkttype, pktlen, pkt, new_ctb );
break;
case PKT_GPG_CONTROL:
- rc = parse_gpg_control(inp, pkttype, pktlen, pkt );
+ rc = parse_gpg_control(inp, pkttype, pktlen, pkt, partial );
break;
default:
- skip_packet(inp, pkttype, pktlen);
+ skip_packet(inp, pkttype, pktlen, partial);
break;
}
leave:
if( !rc && iobuf_error(inp) )
- rc = GPG_ERR_INV_KEYRING;
+ rc = G10ERR_INV_KEYRING;
return rc;
}
@@ -511,34 +596,36 @@ dump_hex_line( int c, int *i )
{
if( *i && !(*i%8) ) {
if( *i && !(*i%24) )
- printf("\n%4d:", *i );
+ fprintf (listfp, "\n%4d:", *i );
else
- putchar(' ');
+ putc (' ', listfp);
}
if( c == -1 )
- printf(" EOF" );
+ fprintf (listfp, " EOF" );
else
- printf(" %02x", c );
+ fprintf (listfp, " %02x", c );
++*i;
}
static int
-copy_packet( iobuf_t inp, iobuf_t out, int pkttype, unsigned long pktlen )
+copy_packet( IOBUF inp, IOBUF out, int pkttype,
+ unsigned long pktlen, int partial )
{
- int rc, n;
+ int rc;
+ int n;
char buf[100];
- if( iobuf_in_block_mode(inp) ) {
+ if( partial ) {
while( (n = iobuf_read( inp, buf, 100 )) != -1 )
- if( (rc = iobuf_write(out, buf, n )) )
+ if( (rc=iobuf_write(out, buf, n )) )
return rc; /* write error */
}
else if( !pktlen && pkttype == PKT_COMPRESSED ) {
log_debug("copy_packet: compressed!\n");
/* compressed packet, copy till EOF */
while( (n = iobuf_read( inp, buf, 100 )) != -1 )
- if( (rc = iobuf_write(out, buf, n )) )
+ if( (rc=iobuf_write(out, buf, n )) )
return rc; /* write error */
}
else {
@@ -546,8 +633,8 @@ copy_packet( iobuf_t inp, iobuf_t out, int pkttype, unsigned long pktlen )
n = pktlen > 100 ? 100 : pktlen;
n = iobuf_read( inp, buf, n );
if( n == -1 )
- return GPG_ERR_GENERAL; /* FIXME(gcrypt): read error*/;
- if( (rc = iobuf_write(out, buf, n )) )
+ return gpg_error (GPG_ERR_EOF);
+ if( (rc=iobuf_write(out, buf, n )) )
return rc; /* write error */
}
}
@@ -556,18 +643,19 @@ copy_packet( iobuf_t inp, iobuf_t out, int pkttype, unsigned long pktlen )
static void
-skip_packet( iobuf_t inp, int pkttype, unsigned long pktlen )
+skip_packet( IOBUF inp, int pkttype, unsigned long pktlen, int partial )
{
if( list_mode ) {
if( pkttype == PKT_MARKER )
- fputs(":marker packet:\n", stdout );
+ fputs(":marker packet:\n", listfp );
else
- printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen);
+ fprintf (listfp, ":unknown packet: type %2d, length %lu\n",
+ pkttype, pktlen);
if( pkttype ) {
int c, i=0 ;
if( pkttype != PKT_MARKER )
- fputs("dump:", stdout );
- if( iobuf_in_block_mode(inp) ) {
+ fputs("dump:", listfp );
+ if( partial ) {
while( (c=iobuf_get(inp)) != -1 )
dump_hex_line(c, &i);
}
@@ -575,40 +663,26 @@ skip_packet( iobuf_t inp, int pkttype, unsigned long pktlen )
for( ; pktlen; pktlen-- )
dump_hex_line(iobuf_get(inp), &i);
}
- putchar('\n');
+ putc ('\n', listfp);
return;
}
}
- skip_rest(inp,pktlen);
-}
-
-static void
-skip_rest( iobuf_t inp, unsigned long pktlen )
-{
- if( iobuf_in_block_mode(inp) ) {
- while( iobuf_get(inp) != -1 )
- ;
- }
- else {
- for( ; pktlen; pktlen-- )
- if( iobuf_get(inp) == -1 )
- break;
- }
+ iobuf_skip_rest(inp,pktlen,partial);
}
static void *
-read_rest( iobuf_t inp, size_t pktlen )
+read_rest( IOBUF inp, size_t pktlen, int partial )
{
byte *p;
int i;
- if( iobuf_in_block_mode(inp) ) {
+ if( partial ) {
log_error("read_rest: can't store stream data\n");
p = NULL;
}
else {
- p = xmalloc ( pktlen );
+ p = xmalloc( pktlen );
for(i=0; pktlen; pktlen--, i++ )
p[i] = iobuf_get(inp);
}
@@ -618,7 +692,7 @@ read_rest( iobuf_t inp, size_t pktlen )
static int
-parse_symkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet )
+parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
{
PKT_symkey_enc *k;
int rc = 0;
@@ -626,18 +700,18 @@ parse_symkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet
if( pktlen < 4 ) {
log_error("packet(%d) too short\n", pkttype);
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
version = iobuf_get_noeof(inp); pktlen--;
if( version != 4 ) {
log_error("packet(%d) with unknown version %d\n", pkttype, version);
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
if( pktlen > 200 ) { /* (we encode the seskeylen in a byte) */
log_error("packet(%d) too large\n", pkttype);
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
cipher_algo = iobuf_get_noeof(inp); pktlen--;
@@ -659,11 +733,11 @@ parse_symkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet
}
if( minlen > pktlen ) {
log_error("packet with S2K %d too short\n", s2kmode );
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
seskeylen = pktlen - minlen;
- k = packet->pkt.symkey_enc = xcalloc (1, sizeof *packet->pkt.symkey_enc
+ k = packet->pkt.symkey_enc = xmalloc_clear( sizeof *packet->pkt.symkey_enc
+ seskeylen - 1 );
k->version = version;
k->cipher_algo = cipher_algo;
@@ -677,46 +751,59 @@ parse_symkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet
k->s2k.count = iobuf_get(inp); pktlen--;
}
k->seskeylen = seskeylen;
- for(i=0; i < seskeylen && pktlen; i++, pktlen-- )
- k->seskey[i] = iobuf_get_noeof(inp);
+ if(k->seskeylen)
+ {
+ for(i=0; i < seskeylen && pktlen; i++, pktlen-- )
+ k->seskey[i] = iobuf_get_noeof(inp);
+
+ /* What we're watching out for here is a session key decryptor
+ with no salt. The RFC says that using salt for this is a
+ MUST. */
+ if(s2kmode!=1 && s2kmode!=3)
+ log_info(_("WARNING: potentially insecure symmetrically"
+ " encrypted session key\n"));
+ }
assert( !pktlen );
if( list_mode ) {
- printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n",
- version, cipher_algo, s2kmode, hash_algo);
+ fprintf (listfp, ":symkey enc packet: version %d, cipher %d, s2k %d, hash %d",
+ version, cipher_algo, s2kmode, hash_algo);
+ if(seskeylen)
+ fprintf (listfp, ", seskey %d bits",(seskeylen-1)*8);
+ fprintf (listfp, "\n");
if( s2kmode == 1 || s2kmode == 3 ) {
- printf("\tsalt ");
+ fprintf (listfp, "\tsalt ");
for(i=0; i < 8; i++ )
- printf("%02x", k->s2k.salt[i]);
+ fprintf (listfp, "%02x", k->s2k.salt[i]);
if( s2kmode == 3 )
- printf(", count %lu\n", (ulong)k->s2k.count );
- printf("\n");
+ fprintf (listfp, ", count %lu", (ulong)k->s2k.count );
+ fprintf (listfp, "\n");
}
}
leave:
- skip_rest(inp, pktlen);
+ iobuf_skip_rest(inp, pktlen, 0);
return rc;
}
static int
-parse_pubkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet )
+parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
{
unsigned int n;
int rc = 0;
int i, ndata;
PKT_pubkey_enc *k;
- k = packet->pkt.pubkey_enc = xcalloc (1,sizeof *packet->pkt.pubkey_enc);
+ k = packet->pkt.pubkey_enc = xmalloc_clear(sizeof *packet->pkt.pubkey_enc);
if( pktlen < 12 ) {
log_error("packet(%d) too short\n", pkttype);
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
k->version = iobuf_get_noeof(inp); pktlen--;
if( k->version != 2 && k->version != 3 ) {
log_error("packet(%d) with unknown version %d\n", pkttype, k->version);
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
k->keyid[0] = read_32(inp); pktlen -= 4;
@@ -724,13 +811,13 @@ parse_pubkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet
k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
k->throw_keyid = 0; /* only used as flag for build_packet */
if( list_mode )
- printf(":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n",
+ fprintf (listfp, ":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n",
k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]);
ndata = pubkey_get_nenc(k->pubkey_algo);
if( !ndata ) {
if( list_mode )
- printf("\tunsupported algorithm %d\n", k->pubkey_algo );
+ fprintf (listfp, "\tunsupported algorithm %d\n", k->pubkey_algo );
unknown_pubkey_warning( k->pubkey_algo );
k->data[0] = NULL; /* no need to store the encrypted data */
}
@@ -739,17 +826,17 @@ parse_pubkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet
n = pktlen;
k->data[i] = mpi_read(inp, &n, 0); pktlen -=n;
if( list_mode ) {
- printf("\tdata: ");
- mpi_print(stdout, k->data[i], mpi_print_mode );
- putchar('\n');
+ fprintf (listfp, "\tdata: ");
+ mpi_print(listfp, k->data[i], mpi_print_mode );
+ putc ('\n', listfp);
}
if (!k->data[i])
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
}
}
leave:
- skip_rest(inp, pktlen);
+ iobuf_skip_rest(inp, pktlen, 0);
return rc;
}
@@ -765,82 +852,83 @@ dump_sig_subpkt( int hashed, int type, int critical,
* detect the ARRs - we print our old message here when it is a faked
* ARR and add an additional notice */
if ( type == SIGSUBPKT_ARR && !hashed ) {
- printf("\tsubpkt %d len %u (additional recipient request)\n"
- "WARNING: PGP versions > 5.0 and < 6.5.8 will automagically "
- "encrypt to this key and thereby reveal the plaintext to "
- "the owner of this ARR key. Detailed info follows:\n",
- type, (unsigned)length );
+ fprintf (listfp,
+ "\tsubpkt %d len %u (additional recipient request)\n"
+ "WARNING: PGP versions > 5.0 and < 6.5.8 will automagically "
+ "encrypt to this key and thereby reveal the plaintext to "
+ "the owner of this ARR key. Detailed info follows:\n",
+ type, (unsigned)length );
}
buffer++;
length--;
- printf("\t%s%ssubpkt %d len %u (", /*)*/
+ fprintf (listfp, "\t%s%ssubpkt %d len %u (", /*)*/
critical ? "critical ":"",
hashed ? "hashed ":"", type, (unsigned)length );
if( length > buflen ) {
- printf("too short: buffer is only %u)\n", (unsigned)buflen );
+ fprintf (listfp, "too short: buffer is only %u)\n", (unsigned)buflen );
return;
}
switch( type ) {
case SIGSUBPKT_SIG_CREATED:
if( length >= 4 )
- printf("sig created %s", strtimestamp( buffer_to_u32(buffer) ) );
+ fprintf (listfp, "sig created %s", strtimestamp( buffer_to_u32(buffer) ) );
break;
case SIGSUBPKT_SIG_EXPIRE:
if( length >= 4 )
- printf("sig expires after %s",
+ fprintf (listfp, "sig expires after %s",
strtimevalue( buffer_to_u32(buffer) ) );
break;
case SIGSUBPKT_EXPORTABLE:
if( length )
- printf("%sexportable", *buffer? "":"not ");
+ fprintf (listfp, "%sexportable", *buffer? "":"not ");
break;
case SIGSUBPKT_TRUST:
if(length!=2)
p="[invalid trust subpacket]";
else
- printf("trust signature of depth %d, value %d",buffer[0],buffer[1]);
+ fprintf (listfp, "trust signature of depth %d, value %d",buffer[0],buffer[1]);
break;
case SIGSUBPKT_REGEXP:
if(!length)
p="[invalid regexp subpacket]";
else
- printf("regular expression: \"%s\"",buffer);
+ fprintf (listfp, "regular expression: \"%s\"",buffer);
break;
case SIGSUBPKT_REVOCABLE:
if( length )
- printf("%srevocable", *buffer? "":"not ");
+ fprintf (listfp, "%srevocable", *buffer? "":"not ");
break;
case SIGSUBPKT_KEY_EXPIRE:
if( length >= 4 )
- printf("key expires after %s",
+ fprintf (listfp, "key expires after %s",
strtimevalue( buffer_to_u32(buffer) ) );
break;
case SIGSUBPKT_PREF_SYM:
- fputs("pref-sym-algos:", stdout );
+ fputs("pref-sym-algos:", listfp );
for( i=0; i < length; i++ )
- printf(" %d", buffer[i] );
+ fprintf (listfp, " %d", buffer[i] );
break;
case SIGSUBPKT_REV_KEY:
- fputs("revocation key: ", stdout );
+ fputs("revocation key: ", listfp );
if( length < 22 )
p = "[too short]";
else {
- printf("c=%02x a=%d f=", buffer[0], buffer[1] );
+ fprintf (listfp, "c=%02x a=%d f=", buffer[0], buffer[1] );
for( i=2; i < length; i++ )
- printf("%02X", buffer[i] );
+ fprintf (listfp, "%02X", buffer[i] );
}
break;
case SIGSUBPKT_ISSUER:
if( length >= 8 )
- printf("issuer key ID %08lX%08lX",
+ fprintf (listfp, "issuer key ID %08lX%08lX",
(ulong)buffer_to_u32(buffer),
(ulong)buffer_to_u32(buffer+4) );
break;
case SIGSUBPKT_NOTATION:
{
- fputs("notation: ", stdout );
+ fputs("notation: ", listfp );
if( length < 8 )
p = "[too short]";
else {
@@ -853,11 +941,11 @@ dump_sig_subpkt( int hashed, int type, int critical,
if( 8+n1+n2 != length )
p = "[error]";
else {
- print_string( stdout, s, n1, ')' );
- putc( '=', stdout );
+ print_string( listfp, s, n1, ')' );
+ putc( '=', listfp );
if( *buffer & 0x80 )
- print_string( stdout, s+n1, n2, ')' );
+ print_string( listfp, s+n1, n2, ')' );
else
p = "[not human readable]";
}
@@ -865,60 +953,71 @@ dump_sig_subpkt( int hashed, int type, int critical,
}
break;
case SIGSUBPKT_PREF_HASH:
- fputs("pref-hash-algos:", stdout );
+ fputs("pref-hash-algos:", listfp );
for( i=0; i < length; i++ )
- printf(" %d", buffer[i] );
+ fprintf (listfp, " %d", buffer[i] );
break;
case SIGSUBPKT_PREF_COMPR:
- fputs("pref-zip-algos:", stdout );
+ fputs("pref-zip-algos:", listfp );
for( i=0; i < length; i++ )
- printf(" %d", buffer[i] );
+ fprintf (listfp, " %d", buffer[i] );
break;
case SIGSUBPKT_KS_FLAGS:
- fputs("key server preferences:",stdout);
+ fputs("key server preferences:",listfp);
for(i=0;i<length;i++)
- printf(" %02X", buffer[i]);
+ fprintf (listfp, " %02X", buffer[i]);
break;
case SIGSUBPKT_PREF_KS:
- fputs("preferred key server: ", stdout );
- print_string( stdout, buffer, length, ')' );
+ fputs("preferred key server: ", listfp );
+ print_string( listfp, buffer, length, ')' );
break;
case SIGSUBPKT_PRIMARY_UID:
p = "primary user ID";
break;
case SIGSUBPKT_POLICY:
- fputs("policy: ", stdout );
- print_string( stdout, buffer, length, ')' );
+ fputs("policy: ", listfp );
+ print_string( listfp, buffer, length, ')' );
break;
case SIGSUBPKT_KEY_FLAGS:
- fputs ( "key flags:", stdout );
+ fputs ( "key flags:", listfp );
for( i=0; i < length; i++ )
- printf(" %02X", buffer[i] );
+ fprintf (listfp, " %02X", buffer[i] );
break;
case SIGSUBPKT_SIGNERS_UID:
p = "signer's user ID";
break;
case SIGSUBPKT_REVOC_REASON:
if( length ) {
- printf("revocation reason 0x%02x (", *buffer );
- print_string( stdout, buffer+1, length-1, ')' );
+ fprintf (listfp, "revocation reason 0x%02x (", *buffer );
+ print_string( listfp, buffer+1, length-1, ')' );
p = ")";
}
break;
case SIGSUBPKT_ARR:
- fputs("Big Brother's key (ignored): ", stdout );
+ fputs("Big Brother's key (ignored): ", listfp );
if( length < 22 )
p = "[too short]";
else {
- printf("c=%02x a=%d f=", buffer[0], buffer[1] );
+ fprintf (listfp, "c=%02x a=%d f=", buffer[0], buffer[1] );
for( i=2; i < length; i++ )
- printf("%02X", buffer[i] );
+ fprintf (listfp, "%02X", buffer[i] );
}
break;
case SIGSUBPKT_FEATURES:
- fputs ( "features:", stdout );
+ fputs ( "features:", listfp );
for( i=0; i < length; i++ )
- printf(" %02x", buffer[i] );
+ fprintf (listfp, " %02x", buffer[i] );
+ break;
+ case SIGSUBPKT_SIGNATURE:
+ fputs("signature: ",listfp);
+ if(length<17)
+ p="[too short]";
+ else
+ fprintf (listfp, "v%d, class 0x%02X, algo %d, digest algo %d",
+ buffer[0],
+ buffer[0]==3?buffer[2]:buffer[1],
+ buffer[0]==3?buffer[15]:buffer[2],
+ buffer[0]==3?buffer[16]:buffer[3]);
break;
default:
if(type>=100 && type<=110)
@@ -928,101 +1027,115 @@ dump_sig_subpkt( int hashed, int type, int critical,
break;
}
- printf("%s)\n", p? p: "");
+ fprintf (listfp, "%s)\n", p? p: "");
}
/****************
- * Returns: >= 0 offset into buffer
- * -1 unknown type
- * -2 unsupported type
- * -3 subpacket too short
+ * Returns: >= 0 use this offset into buffer
+ * -1 explicitly reject returning this type
+ * -2 subpacket too short
*/
int
parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
{
- switch( type ) {
- case SIGSUBPKT_REV_KEY:
- if(n < 22)
- break;
- return 0;
- case SIGSUBPKT_SIG_CREATED:
- case SIGSUBPKT_SIG_EXPIRE:
- case SIGSUBPKT_KEY_EXPIRE:
- if( n < 4 )
- break;
- return 0;
- case SIGSUBPKT_KEY_FLAGS:
- case SIGSUBPKT_KS_FLAGS:
- case SIGSUBPKT_PREF_SYM:
- case SIGSUBPKT_PREF_HASH:
- case SIGSUBPKT_PREF_COMPR:
- case SIGSUBPKT_POLICY:
- case SIGSUBPKT_PREF_KS:
- case SIGSUBPKT_FEATURES:
- case SIGSUBPKT_REGEXP:
- return 0;
- case SIGSUBPKT_EXPORTABLE:
- case SIGSUBPKT_REVOCABLE:
- if( !n )
- break;
- return 0;
- case SIGSUBPKT_ISSUER: /* issuer key ID */
- if( n < 8 )
- break;
- return 0;
- case SIGSUBPKT_NOTATION:
- if( n < 8 ) /* minimum length needed */
- break;
- return 0;
- case SIGSUBPKT_REVOC_REASON:
- if( !n )
- break;
- return 0;
- case SIGSUBPKT_PRIMARY_UID:
- if ( n != 1 )
- break;
- return 0;
- case SIGSUBPKT_TRUST:
- if ( n != 2 )
- break;
- return 0;
- default: return -1;
+ switch( type )
+ {
+ case SIGSUBPKT_REV_KEY:
+ if(n < 22)
+ break;
+ return 0;
+ case SIGSUBPKT_SIG_CREATED:
+ case SIGSUBPKT_SIG_EXPIRE:
+ case SIGSUBPKT_KEY_EXPIRE:
+ if( n < 4 )
+ break;
+ return 0;
+ case SIGSUBPKT_KEY_FLAGS:
+ case SIGSUBPKT_KS_FLAGS:
+ case SIGSUBPKT_PREF_SYM:
+ case SIGSUBPKT_PREF_HASH:
+ case SIGSUBPKT_PREF_COMPR:
+ case SIGSUBPKT_POLICY:
+ case SIGSUBPKT_PREF_KS:
+ case SIGSUBPKT_FEATURES:
+ case SIGSUBPKT_REGEXP:
+ return 0;
+ case SIGSUBPKT_SIGNATURE:
+ case SIGSUBPKT_EXPORTABLE:
+ case SIGSUBPKT_REVOCABLE:
+ case SIGSUBPKT_REVOC_REASON:
+ if( !n )
+ break;
+ return 0;
+ case SIGSUBPKT_ISSUER: /* issuer key ID */
+ if( n < 8 )
+ break;
+ return 0;
+ case SIGSUBPKT_NOTATION:
+ /* minimum length needed, and the subpacket must be well-formed
+ where the name length and value length all fit inside the
+ packet. */
+ if(n<8 || 8+((buffer[4]<<8)|buffer[5])+((buffer[6]<<8)|buffer[7]) != n)
+ break;
+ return 0;
+ case SIGSUBPKT_PRIMARY_UID:
+ if ( n != 1 )
+ break;
+ return 0;
+ case SIGSUBPKT_TRUST:
+ if ( n != 2 )
+ break;
+ return 0;
+ default: return 0;
}
- return -3;
+ return -2;
}
-
+/* Not many critical notations we understand yet... */
static int
-can_handle_critical( const byte *buffer, size_t n, int type )
+can_handle_critical_notation(const byte *name,size_t len)
{
- switch( type ) {
- case SIGSUBPKT_NOTATION:
- if( n >= 8 && (*buffer & 0x80) )
- return 1; /* human readable is handled */
- return 0;
+ if(len==32 && memcmp(name,"[email protected]",32)==0)
+ return 1;
+ if(len==21 && memcmp(name,"[email protected]",21)==0)
+ return 1;
- case SIGSUBPKT_SIG_CREATED:
- case SIGSUBPKT_SIG_EXPIRE:
- case SIGSUBPKT_KEY_EXPIRE:
- case SIGSUBPKT_EXPORTABLE:
- case SIGSUBPKT_REVOCABLE:
- case SIGSUBPKT_REV_KEY:
- case SIGSUBPKT_ISSUER:/* issuer key ID */
- case SIGSUBPKT_PREF_SYM:
- case SIGSUBPKT_PREF_HASH:
- case SIGSUBPKT_PREF_COMPR:
- case SIGSUBPKT_KEY_FLAGS:
- case SIGSUBPKT_PRIMARY_UID:
- case SIGSUBPKT_FEATURES:
- case SIGSUBPKT_TRUST:
- case SIGSUBPKT_REGEXP:
- /* Is it enough to show the policy or keyserver? */
- case SIGSUBPKT_POLICY:
- case SIGSUBPKT_PREF_KS:
- return 1;
+ return 0;
+}
- default:
+static int
+can_handle_critical( const byte *buffer, size_t n, int type )
+{
+ switch( type )
+ {
+ case SIGSUBPKT_NOTATION:
+ if(n>=8)
+ return can_handle_critical_notation(buffer+8,(buffer[4]<<8)|buffer[5]);
+ else
return 0;
+ case SIGSUBPKT_SIGNATURE:
+ case SIGSUBPKT_SIG_CREATED:
+ case SIGSUBPKT_SIG_EXPIRE:
+ case SIGSUBPKT_KEY_EXPIRE:
+ case SIGSUBPKT_EXPORTABLE:
+ case SIGSUBPKT_REVOCABLE:
+ case SIGSUBPKT_REV_KEY:
+ case SIGSUBPKT_ISSUER:/* issuer key ID */
+ case SIGSUBPKT_PREF_SYM:
+ case SIGSUBPKT_PREF_HASH:
+ case SIGSUBPKT_PREF_COMPR:
+ case SIGSUBPKT_KEY_FLAGS:
+ case SIGSUBPKT_PRIMARY_UID:
+ case SIGSUBPKT_FEATURES:
+ case SIGSUBPKT_TRUST:
+ case SIGSUBPKT_REGEXP:
+ /* Is it enough to show the policy or keyserver? */
+ case SIGSUBPKT_POLICY:
+ case SIGSUBPKT_PREF_KS:
+ return 1;
+
+ default:
+ return 0;
}
}
@@ -1106,13 +1219,11 @@ enum_sig_subpkt( const subpktarea_t *pktbuf, sigsubpkttype_t reqtype,
*ret_n = n;
offset = parse_one_sig_subpkt(buffer, n, type );
switch( offset ) {
- case -3:
- log_error("subpacket of type %d too short\n", type);
- return NULL;
case -2:
+ log_error("subpacket of type %d too short\n", type);
return NULL;
case -1:
- BUG(); /* not yet needed */
+ return NULL;
default:
break;
}
@@ -1130,7 +1241,8 @@ enum_sig_subpkt( const subpktarea_t *pktbuf, sigsubpkttype_t reqtype,
return NULL; /* end of packets; not found */
too_short:
- log_error("buffer shorter than subpacket\n");
+ if(opt.verbose)
+ log_info("buffer shorter than subpacket\n");
if( start )
*start = -1;
return NULL;
@@ -1182,8 +1294,8 @@ void parse_revkeys(PKT_signature *sig)
}
}
-static int
-parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen,
+int
+parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_signature *sig )
{
int md5_len=0;
@@ -1200,8 +1312,9 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen,
if( sig->version == 4 )
is_v4=1;
else if( sig->version != 2 && sig->version != 3 ) {
- log_error("packet(%d) with unknown version %d\n", pkttype, sig->version);
- rc = GPG_ERR_INV_PACKET;
+ log_error("packet(%d) with unknown version %d\n",
+ pkttype, sig->version);
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
@@ -1222,7 +1335,7 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen,
n = read_16(inp); pktlen -= 2; /* length of hashed data */
if( n > 10000 ) {
log_error("signature packet: hashed data too long\n");
- rc = GPG_ERR_INV_PACKET;
+ rc = G10ERR_INVALID_PACKET;
goto leave;
}
if( n ) {
@@ -1240,7 +1353,7 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen,
n = read_16(inp); pktlen -= 2; /* length of unhashed data */
if( n > 10000 ) {
log_error("signature packet: unhashed data too long\n");
- rc = GPG_ERR_INV_PACKET;
+ rc = G10ERR_INVALID_PACKET;
goto leave;
}
if( n ) {
@@ -1259,46 +1372,47 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen,
if( pktlen < 5 ) { /* sanity check */
log_error("packet(%d) too short\n", pkttype);
- rc = GPG_ERR_INV_PACKET;
+ rc = G10ERR_INVALID_PACKET;
goto leave;
}
sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--;
sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--;
- if( is_v4 && sig->pubkey_algo ) { /*extract required information */
+ if( is_v4 && sig->pubkey_algo )
+ { /*extract required information */
const byte *p;
size_t len;
/* set sig->flags.unknown_critical if there is a
* critical bit set for packets which we do not understand */
if( !parse_sig_subpkt (sig->hashed, SIGSUBPKT_TEST_CRITICAL, NULL)
- || !parse_sig_subpkt (sig->unhashed, SIGSUBPKT_TEST_CRITICAL,
- NULL) )
- {
- sig->flags.unknown_critical = 1;
- }
+ || !parse_sig_subpkt (sig->unhashed, SIGSUBPKT_TEST_CRITICAL,
+ NULL) )
+ sig->flags.unknown_critical = 1;
p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_CREATED, NULL );
if(p)
sig->timestamp = buffer_to_u32(p);
- else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110))
- log_error("signature packet without timestamp\n");
+ else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110)
+ && opt.verbose)
+ log_info ("signature packet without timestamp\n");
p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL );
- if( p )
- {
- sig->keyid[0] = buffer_to_u32(p);
- sig->keyid[1] = buffer_to_u32(p+4);
- }
- else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110))
- log_error("signature packet without keyid\n");
+ if(p)
+ {
+ sig->keyid[0] = buffer_to_u32(p);
+ sig->keyid[1] = buffer_to_u32(p+4);
+ }
+ else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110)
+ && opt.verbose)
+ log_info ("signature packet without keyid\n");
p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL);
if(p)
sig->expiredate=sig->timestamp+buffer_to_u32(p);
if(sig->expiredate && sig->expiredate<=make_timestamp())
- sig->flags.expired=1;
+ sig->flags.expired=1;
p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,NULL);
if(p)
@@ -1345,10 +1459,10 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen,
/* Find all revocation keys. */
if(sig->sig_class==0x1F)
parse_revkeys(sig);
- }
+ }
if( list_mode ) {
- printf(":signature packet: algo %d, keyid %08lX%08lX\n"
+ fprintf (listfp, ":signature packet: algo %d, keyid %08lX%08lX\n"
"\tversion %d, created %lu, md5len %d, sigclass %02x\n"
"\tdigest algo %d, begin of digest %02x %02x\n",
sig->pubkey_algo,
@@ -1365,12 +1479,11 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen,
ndata = pubkey_get_nsig(sig->pubkey_algo);
if( !ndata ) {
if( list_mode )
- printf("\tunknown algorithm %d\n", sig->pubkey_algo );
+ fprintf (listfp, "\tunknown algorithm %d\n", sig->pubkey_algo );
unknown_pubkey_warning( sig->pubkey_algo );
/* we store the plain material in data[0], so that we are able
* to write it back with build_packet() */
- sig->data[0] = gcry_mpi_set_opaque(NULL, read_rest(inp, pktlen),
- pktlen*8 );
+ sig->data[0]= mpi_set_opaque(NULL, read_rest(inp, pktlen, 0), pktlen );
pktlen = 0;
}
else {
@@ -1379,23 +1492,23 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen,
sig->data[i] = mpi_read(inp, &n, 0 );
pktlen -=n;
if( list_mode ) {
- printf("\tdata: ");
- mpi_print(stdout, sig->data[i], mpi_print_mode );
- putchar('\n');
+ fprintf (listfp, "\tdata: ");
+ mpi_print(listfp, sig->data[i], mpi_print_mode );
+ putc ('\n', listfp);
}
if (!sig->data[i])
- rc = GPG_ERR_INV_PACKET;
+ rc = G10ERR_INVALID_PACKET;
}
}
leave:
- skip_rest(inp, pktlen);
+ iobuf_skip_rest(inp, pktlen, 0);
return rc;
}
static int
-parse_onepass_sig( iobuf_t inp, int pkttype, unsigned long pktlen,
+parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_onepass_sig *ops )
{
int version;
@@ -1403,13 +1516,13 @@ parse_onepass_sig( iobuf_t inp, int pkttype, unsigned long pktlen,
if( pktlen < 13 ) {
log_error("packet(%d) too short\n", pkttype);
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
version = iobuf_get_noeof(inp); pktlen--;
if( version != 3 ) {
log_error("onepass_sig with unknown version %d\n", version);
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
ops->sig_class = iobuf_get_noeof(inp); pktlen--;
@@ -1419,7 +1532,7 @@ parse_onepass_sig( iobuf_t inp, int pkttype, unsigned long pktlen,
ops->keyid[1] = read_32(inp); pktlen -= 4;
ops->last = iobuf_get_noeof(inp); pktlen--;
if( list_mode )
- printf(":onepass_sig packet: keyid %08lX%08lX\n"
+ fprintf (listfp, ":onepass_sig packet: keyid %08lX%08lX\n"
"\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
(ulong)ops->keyid[0], (ulong)ops->keyid[1],
version, ops->sig_class,
@@ -1427,13 +1540,13 @@ parse_onepass_sig( iobuf_t inp, int pkttype, unsigned long pktlen,
leave:
- skip_rest(inp, pktlen);
+ iobuf_skip_rest(inp, pktlen, 0);
return rc;
}
static gcry_mpi_t
-read_protected_v3_mpi (iobuf_t inp, unsigned long *length)
+read_protected_v3_mpi (IOBUF inp, unsigned long *length)
{
int c;
unsigned int nbits, nbytes;
@@ -1473,14 +1586,14 @@ read_protected_v3_mpi (iobuf_t inp, unsigned long *length)
return NULL;
}
- /* convert buffer into an opaque gcry_mpi_t */
+ /* convert buffer into an opaque MPI */
val = gcry_mpi_set_opaque (NULL, buf, (p-buf)*8);
return val;
}
static int
-parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
+parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
byte *hdr, int hdrlen, PACKET *pkt )
{
int i, version, algorithm;
@@ -1495,31 +1608,31 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
/* early versions of G10 use old PGP comments packets;
* luckily all those comments are started by a hash */
if( list_mode ) {
- printf(":rfc1991 comment packet: \"" );
+ fprintf (listfp, ":rfc1991 comment packet: \"" );
for( ; pktlen; pktlen-- ) {
int c;
c = iobuf_get_noeof(inp);
if( c >= ' ' && c <= 'z' )
- putchar(c);
+ putc (c, listfp);
else
- printf("\\x%02x", c );
+ fprintf (listfp, "\\x%02x", c );
}
- printf("\"\n");
+ fprintf (listfp, "\"\n");
}
- skip_rest(inp, pktlen);
+ iobuf_skip_rest(inp, pktlen, 0);
return 0;
}
else if( version == 4 )
is_v4=1;
else if( version != 2 && version != 3 ) {
log_error("packet(%d) with unknown version %d\n", pkttype, version);
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
if( pktlen < 11 ) {
log_error("packet(%d) too short\n", pkttype);
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
@@ -1540,7 +1653,7 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
}
algorithm = iobuf_get_noeof(inp); pktlen--;
if( list_mode )
- printf(":%s key packet:\n"
+ fprintf (listfp, ":%s key packet:\n"
"\tversion %d, algo %d, created %lu, expires %lu\n",
pkttype == PKT_PUBLIC_KEY? "public" :
pkttype == PKT_SECRET_KEY? "secret" :
@@ -1582,7 +1695,7 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
npkey = pubkey_get_npkey( algorithm );
if( !npkey ) {
if( list_mode )
- printf("\tunknown algorithm %d\n", algorithm );
+ fprintf (listfp, "\tunknown algorithm %d\n", algorithm );
unknown_pubkey_warning( algorithm );
}
@@ -1593,8 +1706,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
size_t snlen = 0;
if( !npkey ) {
- sk->skey[0] = gcry_mpi_set_opaque( NULL, read_rest(inp, pktlen),
- pktlen*8 );
+ sk->skey[0] = mpi_set_opaque( NULL,
+ read_rest(inp, pktlen, 0), pktlen );
pktlen = 0;
goto leave;
}
@@ -1602,12 +1715,12 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
for(i=0; i < npkey; i++ ) {
n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) {
- printf( "\tskey[%d]: ", i);
- mpi_print(stdout, sk->skey[i], mpi_print_mode );
- putchar('\n');
+ fprintf (listfp, "\tskey[%d]: ", i);
+ mpi_print(listfp, sk->skey[i], mpi_print_mode );
+ putc ('\n', listfp);
}
if (!sk->skey[i])
- rc = GPG_ERR_INV_PACKET;
+ rc = G10ERR_INVALID_PACKET;
}
if (rc) /* one of the MPIs were bad */
goto leave;
@@ -1618,7 +1731,7 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
sk->protect.s2k.count = 0;
if( sk->protect.algo == 254 || sk->protect.algo == 255 ) {
if( pktlen < 3 ) {
- rc = GPG_ERR_INV_PACKET;
+ rc = G10ERR_INVALID_PACKET;
goto leave;
}
sk->protect.sha1chk = (sk->protect.algo == 254);
@@ -1634,9 +1747,9 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
temp[i] = iobuf_get_noeof(inp);
if( i < 4 || memcmp( temp, "GNU", 3 ) ) {
if( list_mode )
- printf( "\tunknown S2K %d\n",
+ fprintf (listfp, "\tunknown S2K %d\n",
sk->protect.s2k.mode );
- rc = GPG_ERR_INV_PACKET;
+ rc = G10ERR_INVALID_PACKET;
goto leave;
}
/* here we know that it is a gnu extension
@@ -1655,61 +1768,63 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
break;
}
switch( sk->protect.s2k.mode ) {
- case 0: if( list_mode ) printf( "\tsimple S2K" );
+ case 0: if( list_mode ) fprintf (listfp, "\tsimple S2K" );
break;
- case 1: if( list_mode ) printf( "\tsalted S2K" );
+ case 1: if( list_mode ) fprintf (listfp, "\tsalted S2K" );
break;
- case 3: if( list_mode ) printf( "\titer+salt S2K" );
+ case 3: if( list_mode ) fprintf (listfp, "\titer+salt S2K" );
break;
- case 1001: if( list_mode ) printf( "\tgnu-dummy S2K" );
+ case 1001: if( list_mode ) fprintf (listfp,
+ "\tgnu-dummy S2K" );
break;
- case 1002: if (list_mode) printf("\tgnu-divert-to-card S2K");
+ case 1002: if (list_mode) fprintf (listfp,
+ "\tgnu-divert-to-card S2K");
break;
default:
if( list_mode )
- printf( "\tunknown %sS2K %d\n",
+ fprintf (listfp, "\tunknown %sS2K %d\n",
sk->protect.s2k.mode < 1000? "":"GNU ",
sk->protect.s2k.mode );
- rc = GPG_ERR_INV_PACKET;
+ rc = G10ERR_INVALID_PACKET;
goto leave;
}
if( list_mode ) {
- printf(", algo: %d,%s hash: %d",
+ fprintf (listfp, ", algo: %d,%s hash: %d",
sk->protect.algo,
sk->protect.sha1chk?" SHA1 protection,"
:" simple checksum,",
sk->protect.s2k.hash_algo );
if( sk->protect.s2k.mode == 1
|| sk->protect.s2k.mode == 3 ) {
- printf(", salt: ");
+ fprintf (listfp, ", salt: ");
for(i=0; i < 8; i++ )
- printf("%02x", sk->protect.s2k.salt[i]);
+ fprintf (listfp, "%02x", sk->protect.s2k.salt[i]);
}
- putchar('\n');
+ putc ('\n', listfp);
}
if( sk->protect.s2k.mode == 3 ) {
if( pktlen < 1 ) {
- rc = GPG_ERR_INV_PACKET;
+ rc = G10ERR_INVALID_PACKET;
goto leave;
}
sk->protect.s2k.count = iobuf_get(inp);
pktlen--;
if( list_mode )
- printf("\tprotect count: %lu\n",
+ fprintf (listfp, "\tprotect count: %lu\n",
(ulong)sk->protect.s2k.count);
}
else if( sk->protect.s2k.mode == 1002 ) {
/* Read the serial number. */
if (pktlen < 1) {
- rc = GPG_ERR_INV_PACKET;
+ rc = G10ERR_INVALID_PACKET;
goto leave;
}
snlen = iobuf_get (inp);
pktlen--;
if (pktlen < snlen || snlen == -1) {
- rc = GPG_ERR_INV_PACKET;
+ rc = G10ERR_INVALID_PACKET;
goto leave;
}
}
@@ -1721,7 +1836,7 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
sk->protect.s2k.mode = 0;
sk->protect.s2k.hash_algo = DIGEST_ALGO_MD5;
if( list_mode )
- printf( "\tprotect algo: %d (hash algo: %d)\n",
+ fprintf (listfp, "\tprotect algo: %d (hash algo: %d)\n",
sk->protect.algo, sk->protect.s2k.hash_algo );
}
/* It is really ugly that we don't know the size
@@ -1742,24 +1857,22 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
}
if( sk->protect.s2k.mode == 1001 )
sk->protect.ivlen = 0;
- else if( sk->protect.s2k.mode == 1002 ) {
- if (snlen > 16)
- log_info ("WARNING: serial number of card truncated\n");
+ else if( sk->protect.s2k.mode == 1002 )
sk->protect.ivlen = snlen < 16? snlen : 16;
- }
if( pktlen < sk->protect.ivlen ) {
- rc = GPG_ERR_INV_PACKET;
+ rc = G10ERR_INVALID_PACKET;
goto leave;
}
for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- )
temp[i] = iobuf_get_noeof(inp);
if( list_mode ) {
- printf( sk->protect.s2k.mode == 1002? "\tserial-number: "
- : "\tprotect IV: ");
+ fprintf (listfp,
+ sk->protect.s2k.mode == 1002? "\tserial-number: "
+ : "\tprotect IV: ");
for(i=0; i < sk->protect.ivlen; i++ )
- printf(" %02x", temp[i] );
- putchar('\n');
+ fprintf (listfp, " %02x", temp[i] );
+ putc ('\n', listfp);
}
memcpy(sk->protect.iv, temp, sk->protect.ivlen );
}
@@ -1769,22 +1882,21 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
* If the user is so careless, not to protect his secret key,
* we can assume, that he operates an open system :=(.
* So we put the key into secure memory when we unprotect it. */
- if( sk->protect.s2k.mode == 1001
+ if( sk->protect.s2k.mode == 1001
|| sk->protect.s2k.mode == 1002 ) {
/* better set some dummy stuff here */
- sk->skey[npkey] = gcry_mpi_set_opaque(NULL, xstrdup ("dummydata"),
- 10*8);
+ sk->skey[npkey] = mpi_set_opaque(NULL, xstrdup("dummydata"), 10);
pktlen = 0;
}
else if( is_v4 && sk->is_protected ) {
/* ugly; the length is encrypted too, so we read all
* stuff up to the end of the packet into the first
* skey element */
- sk->skey[npkey] = gcry_mpi_set_opaque(NULL, read_rest(inp, pktlen),
- pktlen*8 );
+ sk->skey[npkey] = mpi_set_opaque(NULL,
+ read_rest(inp, pktlen, 0),pktlen);
pktlen = 0;
if( list_mode ) {
- printf("\tencrypted stuff follows\n");
+ fprintf (listfp, "\tencrypted stuff follows\n");
}
}
else { /* v3 method: the mpi length is not encrypted */
@@ -1792,28 +1904,28 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
if ( sk->is_protected ) {
sk->skey[i] = read_protected_v3_mpi (inp, &pktlen);
if( list_mode )
- printf( "\tskey[%d]: [encrypted]\n", i);
+ fprintf (listfp, "\tskey[%d]: [encrypted]\n", i);
}
else {
n = pktlen;
sk->skey[i] = mpi_read(inp, &n, 0 );
pktlen -=n;
if( list_mode ) {
- printf( "\tskey[%d]: ", i);
- mpi_print(stdout, sk->skey[i], mpi_print_mode );
- putchar('\n');
+ fprintf (listfp, "\tskey[%d]: ", i);
+ mpi_print(listfp, sk->skey[i], mpi_print_mode );
+ putc ('\n', listfp);
}
}
if (!sk->skey[i])
- rc = GPG_ERR_INV_PACKET;
+ rc = G10ERR_INVALID_PACKET;
}
if (rc)
goto leave;
sk->csum = read_16(inp); pktlen -= 2;
if( list_mode ) {
- printf("\tchecksum: %04hx\n", sk->csum);
+ fprintf (listfp, "\tchecksum: %04hx\n", sk->csum);
}
}
}
@@ -1821,8 +1933,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
PKT_public_key *pk = pkt->pkt.public_key;
if( !npkey ) {
- pk->pkey[0] = gcry_mpi_set_opaque( NULL, read_rest(inp, pktlen),
- pktlen*8 );
+ pk->pkey[0] = mpi_set_opaque( NULL,
+ read_rest(inp, pktlen, 0), pktlen );
pktlen = 0;
goto leave;
}
@@ -1830,19 +1942,19 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
for(i=0; i < npkey; i++ ) {
n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) {
- printf( "\tpkey[%d]: ", i);
- mpi_print(stdout, pk->pkey[i], mpi_print_mode );
- putchar('\n');
+ fprintf (listfp, "\tpkey[%d]: ", i);
+ mpi_print(listfp, pk->pkey[i], mpi_print_mode );
+ putc ('\n', listfp);
}
if (!pk->pkey[i])
- rc = GPG_ERR_INV_PACKET;
+ rc = G10ERR_INVALID_PACKET;
}
if (rc)
goto leave;
}
leave:
- skip_rest(inp, pktlen);
+ iobuf_skip_rest(inp, pktlen, 0);
return rc;
}
@@ -1859,7 +1971,7 @@ parse_attribute_subpkts(PKT_user_id *uid)
int buflen=uid->attrib_len;
byte type;
- xfree (uid->attribs);
+ xfree(uid->attribs);
while(buflen)
{
@@ -1903,38 +2015,22 @@ parse_attribute_subpkts(PKT_user_id *uid)
return count;
too_short:
- log_error("buffer shorter than attribute subpacket\n");
+ if(opt.verbose)
+ log_info("buffer shorter than attribute subpacket\n");
uid->attribs=attribs;
uid->numattribs=count;
return count;
}
-static void setup_user_id(PACKET *packet)
-{
- packet->pkt.user_id->ref = 1;
- packet->pkt.user_id->attribs = NULL;
- packet->pkt.user_id->attrib_data = NULL;
- packet->pkt.user_id->attrib_len = 0;
- packet->pkt.user_id->is_primary = 0;
- packet->pkt.user_id->is_revoked = 0;
- packet->pkt.user_id->is_expired = 0;
- packet->pkt.user_id->expiredate = 0;
- packet->pkt.user_id->created = 0;
- packet->pkt.user_id->help_key_usage = 0;
- packet->pkt.user_id->help_key_expire = 0;
- packet->pkt.user_id->prefs = NULL;
- packet->pkt.user_id->namehash = NULL;
-}
static int
-parse_user_id( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet )
+parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
{
byte *p;
- packet->pkt.user_id = xmalloc (sizeof *packet->pkt.user_id + pktlen);
+ packet->pkt.user_id = xmalloc_clear(sizeof *packet->pkt.user_id + pktlen);
packet->pkt.user_id->len = pktlen;
-
- setup_user_id(packet);
+ packet->pkt.user_id->ref=1;
p = packet->pkt.user_id->name;
for( ; pktlen; pktlen--, p++ )
@@ -1943,15 +2039,15 @@ parse_user_id( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet )
if( list_mode ) {
int n = packet->pkt.user_id->len;
- printf(":user ID packet: \"");
+ fprintf (listfp, ":user ID packet: \"");
/* fixme: Hey why don't we replace this with print_string?? */
for(p=packet->pkt.user_id->name; n; p++, n-- ) {
if( *p >= ' ' && *p <= 'z' )
- putchar(*p);
+ putc (*p, listfp);
else
- printf("\\x%02x", *p );
+ fprintf (listfp, "\\x%02x", *p );
}
- printf("\"\n");
+ fprintf (listfp, "\"\n");
}
return 0;
}
@@ -1990,18 +2086,17 @@ make_attribute_uidname(PKT_user_id *uid, size_t max_namelen)
}
static int
-parse_attribute( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet )
+parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
{
byte *p;
#define EXTRA_UID_NAME_SPACE 71
- packet->pkt.user_id = xmalloc (sizeof *packet->pkt.user_id
- + EXTRA_UID_NAME_SPACE);
-
- setup_user_id(packet);
-
- packet->pkt.user_id->attrib_data = xmalloc (pktlen);
+ packet->pkt.user_id = xmalloc_clear(sizeof *packet->pkt.user_id
+ + EXTRA_UID_NAME_SPACE);
+ packet->pkt.user_id->ref=1;
+ packet->pkt.user_id->attrib_data = xmalloc(pktlen);
packet->pkt.user_id->attrib_len = pktlen;
+
p = packet->pkt.user_id->attrib_data;
for( ; pktlen; pktlen--, p++ )
*p = iobuf_get_noeof(inp);
@@ -2014,18 +2109,18 @@ parse_attribute( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet
make_attribute_uidname(packet->pkt.user_id, EXTRA_UID_NAME_SPACE);
if( list_mode ) {
- printf(":attribute packet: %s\n", packet->pkt.user_id->name );
+ fprintf (listfp, ":attribute packet: %s\n", packet->pkt.user_id->name );
}
return 0;
}
static int
-parse_comment( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet )
+parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
{
byte *p;
- packet->pkt.comment = xmalloc (sizeof *packet->pkt.comment + pktlen - 1);
+ packet->pkt.comment = xmalloc(sizeof *packet->pkt.comment + pktlen - 1);
packet->pkt.comment->len = pktlen;
p = packet->pkt.comment->data;
for( ; pktlen; pktlen--, p++ )
@@ -2033,22 +2128,22 @@ parse_comment( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet )
if( list_mode ) {
int n = packet->pkt.comment->len;
- printf(":%scomment packet: \"", pkttype == PKT_OLD_COMMENT?
+ fprintf (listfp, ":%scomment packet: \"", pkttype == PKT_OLD_COMMENT?
"OpenPGP draft " : "" );
for(p=packet->pkt.comment->data; n; p++, n-- ) {
if( *p >= ' ' && *p <= 'z' )
- putchar(*p);
+ putc (*p, listfp);
else
- printf("\\x%02x", *p );
+ fprintf (listfp, "\\x%02x", *p );
}
- printf("\"\n");
+ fprintf (listfp, "\"\n");
}
return 0;
}
static void
-parse_trust( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *pkt )
+parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
{
int c;
@@ -2056,7 +2151,7 @@ parse_trust( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *pkt )
{
c = iobuf_get_noeof(inp);
pktlen--;
- pkt->pkt.ring_trust = xmalloc ( sizeof *pkt->pkt.ring_trust );
+ pkt->pkt.ring_trust = xmalloc( sizeof *pkt->pkt.ring_trust );
pkt->pkt.ring_trust->trustval = c;
pkt->pkt.ring_trust->sigcache = 0;
if (!c && pktlen==1)
@@ -2068,42 +2163,37 @@ parse_trust( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *pkt )
pkt->pkt.ring_trust->sigcache = c;
}
if( list_mode )
- printf(":trust packet: flag=%02x sigcache=%02x\n",
+ fprintf (listfp, ":trust packet: flag=%02x sigcache=%02x\n",
pkt->pkt.ring_trust->trustval,
pkt->pkt.ring_trust->sigcache);
}
else
{
if( list_mode )
- printf(":trust packet: empty\n");
+ fprintf (listfp, ":trust packet: empty\n");
}
- skip_rest (inp, pktlen);
+ iobuf_skip_rest (inp, pktlen, 0);
}
static int
-parse_plaintext( iobuf_t inp, int pkttype, unsigned long pktlen,
- PACKET *pkt, int new_ctb )
+parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
+ PACKET *pkt, int new_ctb, int partial )
{
int rc = 0;
- int mode, namelen, partial=0;
+ int mode, namelen;
PKT_plaintext *pt;
byte *p;
int c, i;
- if( pktlen && pktlen < 6 ) {
+ if( !partial && pktlen < 6 ) {
log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
- /* A packet length of zero indicates partial body length. A zero
- data length isn't a zero length packet due to the header (mode,
- name, etc), so this is accurate. */
- if(pktlen==0)
- partial=1;
mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
- pt = pkt->pkt.plaintext = xmalloc (sizeof *pkt->pkt.plaintext + namelen -1);
+ pt = pkt->pkt.plaintext = xmalloc(sizeof *pkt->pkt.plaintext + namelen -1);
pt->new_ctb = new_ctb;
pt->mode = mode;
pt->namelen = namelen;
@@ -2125,17 +2215,21 @@ parse_plaintext( iobuf_t inp, int pkttype, unsigned long pktlen,
pktlen = 0;
if( list_mode ) {
- printf(":literal data packet:\n"
- "\tmode %c, created %lu, name=\"",
- mode >= ' ' && mode <'z'? mode : '?',
+ fprintf (listfp, ":literal data packet:\n"
+ "\tmode %c (%X), created %lu, name=\"",
+ mode >= ' ' && mode <'z'? mode : '?', mode,
(ulong)pt->timestamp );
for(p=pt->name,i=0; i < namelen; p++, i++ ) {
if( *p >= ' ' && *p <= 'z' )
- putchar(*p);
+ putc (*p, listfp);
else
- printf("\\x%02x", *p );
+ fprintf (listfp, "\\x%02x", *p );
}
- printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len );
+ fprintf (listfp, "\",\n\traw data: ");
+ if(partial)
+ fprintf (listfp, "unknown length\n");
+ else
+ fprintf (listfp, "%lu bytes\n", (ulong)pt->len );
}
leave:
@@ -2144,7 +2238,7 @@ parse_plaintext( iobuf_t inp, int pkttype, unsigned long pktlen,
static int
-parse_compressed( iobuf_t inp, int pkttype, unsigned long pktlen,
+parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *pkt, int new_ctb )
{
PKT_compressed *zd;
@@ -2153,26 +2247,26 @@ parse_compressed( iobuf_t inp, int pkttype, unsigned long pktlen,
* (this should be the last object in a file or
* the compress algorithm should know the length)
*/
- zd = pkt->pkt.compressed = xmalloc (sizeof *pkt->pkt.compressed );
+ zd = pkt->pkt.compressed = xmalloc(sizeof *pkt->pkt.compressed );
zd->algorithm = iobuf_get_noeof(inp);
zd->len = 0; /* not used */
zd->new_ctb = new_ctb;
zd->buf = inp;
if( list_mode )
- printf(":compressed packet: algo=%d\n", zd->algorithm);
+ fprintf (listfp, ":compressed packet: algo=%d\n", zd->algorithm);
return 0;
}
static int
-parse_encrypted( iobuf_t inp, int pkttype, unsigned long pktlen,
- PACKET *pkt, int new_ctb )
+parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
+ PACKET *pkt, int new_ctb, int partial )
{
int rc = 0;
PKT_encrypted *ed;
unsigned long orig_pktlen = pktlen;
- ed = pkt->pkt.encrypted = xmalloc (sizeof *pkt->pkt.encrypted );
+ ed = pkt->pkt.encrypted = xmalloc(sizeof *pkt->pkt.encrypted );
ed->len = pktlen;
/* we don't know the extralen which is (cipher_blocksize+2)
because the algorithm ist not specified in this packet.
@@ -2182,6 +2276,7 @@ parse_encrypted( iobuf_t inp, int pkttype, unsigned long pktlen,
ed->extralen = 0;
ed->buf = NULL;
ed->new_ctb = new_ctb;
+ ed->is_partial = partial;
ed->mdc_method = 0;
if( pkttype == PKT_ENCRYPTED_MDC ) {
/* fixme: add some pktlen sanity checks */
@@ -2194,28 +2289,28 @@ parse_encrypted( iobuf_t inp, int pkttype, unsigned long pktlen,
log_error("encrypted_mdc packet with unknown version %d\n",
version);
/*skip_rest(inp, pktlen); should we really do this? */
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
ed->mdc_method = DIGEST_ALGO_SHA1;
}
if( orig_pktlen && pktlen < 10 ) { /* actually this is blocksize+2 */
log_error("packet(%d) too short\n", pkttype);
- rc = GPG_ERR_INV_PACKET;
- skip_rest(inp, pktlen);
+ rc = G10ERR_INVALID_PACKET;
+ iobuf_skip_rest(inp, pktlen, partial);
goto leave;
}
if( list_mode ) {
if( orig_pktlen )
- printf(":encrypted data packet:\n\tlength: %lu\n", orig_pktlen);
+ fprintf (listfp, ":encrypted data packet:\n\tlength: %lu\n",
+ orig_pktlen);
else
- printf(":encrypted data packet:\n\tlength: unknown\n");
+ fprintf (listfp, ":encrypted data packet:\n\tlength: unknown\n");
if( ed->mdc_method )
- printf("\tmdc_method: %d\n", ed->mdc_method );
+ fprintf (listfp, "\tmdc_method: %d\n", ed->mdc_method );
}
ed->buf = inp;
- pktlen = 0;
leave:
return rc;
@@ -2223,19 +2318,19 @@ parse_encrypted( iobuf_t inp, int pkttype, unsigned long pktlen,
static int
-parse_mdc( iobuf_t inp, int pkttype, unsigned long pktlen,
+parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *pkt, int new_ctb )
{
int rc = 0;
PKT_mdc *mdc;
byte *p;
- mdc = pkt->pkt.mdc= xmalloc (sizeof *pkt->pkt.mdc );
+ mdc = pkt->pkt.mdc= xmalloc(sizeof *pkt->pkt.mdc );
if( list_mode )
- printf(":mdc packet: length=%lu\n", pktlen);
+ fprintf (listfp, ":mdc packet: length=%lu\n", pktlen);
if( !new_ctb || pktlen != 20 ) {
log_error("mdc_packet with invalid encoding\n");
- rc = GPG_ERR_INV_PACKET;
+ rc = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
p = mdc->hash;
@@ -2259,8 +2354,8 @@ parse_mdc( iobuf_t inp, int pkttype, unsigned long pktlen,
*/
static int
-parse_gpg_control( iobuf_t inp,
- int pkttype, unsigned long pktlen, PACKET *packet )
+parse_gpg_control( IOBUF inp, int pkttype,
+ unsigned long pktlen, PACKET *packet, int partial )
{
byte *p;
const byte *sesmark;
@@ -2268,7 +2363,7 @@ parse_gpg_control( iobuf_t inp,
int i;
if ( list_mode )
- printf(":packet 63: length %lu ", pktlen);
+ fprintf (listfp, ":packet 63: length %lu ", pktlen);
sesmark = get_session_marker ( &sesmarklen );
if ( pktlen < sesmarklen+1 ) /* 1 is for the control bytes */
@@ -2280,7 +2375,7 @@ parse_gpg_control( iobuf_t inp,
if ( list_mode )
puts ("- gpg control packet");
- packet->pkt.gpg_control = xmalloc (sizeof *packet->pkt.gpg_control
+ packet->pkt.gpg_control = xmalloc(sizeof *packet->pkt.gpg_control
+ pktlen - 1);
packet->pkt.gpg_control->control = iobuf_get_noeof(inp); pktlen--;
packet->pkt.gpg_control->datalen = pktlen;
@@ -2295,8 +2390,8 @@ parse_gpg_control( iobuf_t inp,
int c;
i=0;
- printf("- private (rest length %lu)\n", pktlen);
- if( iobuf_in_block_mode(inp) ) {
+ fprintf (listfp, "- private (rest length %lu)\n", pktlen);
+ if( partial ) {
while( (c=iobuf_get(inp)) != -1 )
dump_hex_line(c, &i);
}
@@ -2304,10 +2399,10 @@ parse_gpg_control( iobuf_t inp,
for( ; pktlen; pktlen-- )
dump_hex_line(iobuf_get(inp), &i);
}
- putchar('\n');
+ putc ('\n', listfp);
}
- skip_rest(inp,pktlen);
- return GPG_ERR_INV_PACKET;
+ iobuf_skip_rest(inp,pktlen, 0);
+ return gpg_error (GPG_ERR_INV_PACKET);
}
/* create a gpg control packet to be used internally as a placeholder */
@@ -2317,10 +2412,10 @@ create_gpg_control( ctrlpkttype_t type, const byte *data, size_t datalen )
PACKET *packet;
byte *p;
- packet = xmalloc ( sizeof *packet );
+ packet = xmalloc( sizeof *packet );
init_packet(packet);
packet->pkttype = PKT_GPG_CONTROL;
- packet->pkt.gpg_control = xmalloc (sizeof *packet->pkt.gpg_control
+ packet->pkt.gpg_control = xmalloc(sizeof *packet->pkt.gpg_control
+ datalen - 1);
packet->pkt.gpg_control->control = type;
packet->pkt.gpg_control->datalen = datalen;