diff options
Diffstat (limited to 'g10/parse-packet.c')
-rw-r--r-- | g10/parse-packet.c | 159 |
1 files changed, 127 insertions, 32 deletions
diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 1de7c85c6..60c45b56b 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -61,7 +61,7 @@ static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen, byte *hdr, int hdrlen, PACKET *packet ); static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); -static int parse_photo_id( IOBUF inp, int pkttype, unsigned long pktlen, +static int parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); @@ -438,9 +438,9 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, case PKT_USER_ID: rc = parse_user_id(inp, pkttype, pktlen, pkt ); break; - case PKT_PHOTO_ID: + case PKT_ATTRIBUTE: pkt->pkttype = pkttype = PKT_USER_ID; /* we store it in the userID */ - rc = parse_photo_id(inp, pkttype, pktlen, pkt); + rc = parse_attribute(inp, pkttype, pktlen, pkt); break; case PKT_OLD_COMMENT: case PKT_COMMENT: @@ -1657,6 +1657,98 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, return rc; } +/* Attribute subpackets have the same format as v4 signature + subpackets. This is not part of OpenPGP, but is done in several + versions of PGP nevertheless. */ +int +parse_attribute_subpkts(PKT_user_id *uid) +{ + size_t n; + int count=0; + struct user_attribute *attribs=NULL; + const byte *buffer=uid->attrib_data; + int buflen=uid->attrib_len; + byte type; + + m_free(uid->attribs); + + while(buflen) + { + n = *buffer++; buflen--; + if( n == 255 ) { /* 4 byte length header */ + if( buflen < 4 ) + goto too_short; + n = (buffer[0] << 24) | (buffer[1] << 16) + | (buffer[2] << 8) | buffer[3]; + buffer += 4; + buflen -= 4; + } + else if( n >= 192 ) { /* 2 byte special encoded length header */ + if( buflen < 2 ) + goto too_short; + n = (( n - 192 ) << 8) + *buffer + 192; + buffer++; + buflen--; + } + if( buflen < n ) + goto too_short; + + attribs=m_realloc(attribs,(count+1)*sizeof(struct user_attribute)); + memset(&attribs[count],0,sizeof(struct user_attribute)); + + type=*buffer; + buffer++; + buflen--; + n--; + + /* In order: is it an image, is it large enough to carry the + image header, is it version 1, and is it a JPEG? */ + if(type==1 && n>=16 && buffer[2]==1 && buffer[3]==1) + { + /* For historical reasons (i.e. "oops!"), headerlen is + little endian. */ + u16 headerlen=(buffer[1]<<8) | buffer[0]; + + attribs[count].type=ATTRIB_JPEG; + + buffer+=headerlen; + buflen-=headerlen; + n-=headerlen; + } + else + attribs[count].type=ATTRIB_UNKNOWN; + + attribs[count].data=buffer; + attribs[count].len=n; + buffer+=n; + buflen-=n; + count++; + } + + uid->attribs=attribs; + uid->numattribs=count; + return count; + + too_short: + log_error("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->created = 0; + packet->pkt.user_id->help_key_usage = 0; + packet->pkt.user_id->help_key_expire = 0; + packet->pkt.user_id->prefs = NULL; +} static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) @@ -1664,16 +1756,9 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) byte *p; packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + pktlen); - packet->pkt.user_id->ref = 1; packet->pkt.user_id->len = pktlen; - packet->pkt.user_id->photo = NULL; - packet->pkt.user_id->photolen = 0; - packet->pkt.user_id->is_primary = 0; - packet->pkt.user_id->is_revoked = 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; + + setup_user_id(packet); p = packet->pkt.user_id->name; for( ; pktlen; pktlen--, p++ ) @@ -1695,35 +1780,45 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) return 0; } +void +make_attribute_uidname(PKT_user_id *uid) +{ + /* List the first attribute as the "user id" */ + if(uid->attribs) + sprintf( uid->name, "[%s of size %lu]", + uid->attribs->type==ATTRIB_JPEG?"image":"unknown attribute", + uid->attribs->len); + else + sprintf( uid->name, "[bad attribute of size %lu]", + uid->attrib_len ); + + uid->len = strlen(uid->name); +} -/**************** - * PGP generates a packet of type 17. We assume this is a photo ID and - * simply store it here as a comment packet. - */ static int -parse_photo_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) { byte *p; - packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + 30); - packet->pkt.user_id->ref = 1; - sprintf( packet->pkt.user_id->name, "[image of size %lu]", pktlen ); - packet->pkt.user_id->len = strlen(packet->pkt.user_id->name); - packet->pkt.user_id->is_primary = 0; - packet->pkt.user_id->is_revoked = 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->photo = m_alloc(sizeof *packet->pkt.user_id + pktlen); - packet->pkt.user_id->photolen = pktlen; - p = packet->pkt.user_id->photo; + packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + 50); + + setup_user_id(packet); + + packet->pkt.user_id->attrib_data = m_alloc(pktlen); + packet->pkt.user_id->attrib_len = pktlen; + p = packet->pkt.user_id->attrib_data; for( ; pktlen; pktlen--, p++ ) *p = iobuf_get_noeof(inp); + /* Now parse out the individual attribute subpackets. This is + somewhat pointless since there is only one currently defined + attribute type (jpeg), but it is correct by the spec. */ + parse_attribute_subpkts(packet->pkt.user_id); + + make_attribute_uidname(packet->pkt.user_id); + if( list_mode ) { - printf(":photo_id packet: %s\n", packet->pkt.user_id->name ); + printf(":attribute packet: %s\n", packet->pkt.user_id->name ); } return 0; } |