/* parse-packet.c - read packets * Copyright (c) 1997 by Werner Koch (dd9jn) * * This file is part of G10. * * G10 is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * G10 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * 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 */ #include #include #include #include #include #include "packet.h" #include "iobuf.h" #include "mpi.h" #include "util.h" #include "cipher.h" #include "memory.h" #include "filter.h" #include "options.h" static mpi_print_mode = 0; static list_mode = 0; static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen ); static void skip_rest( IOBUF inp, unsigned long pktlen ); static int parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); static int parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, PKT_signature *sig ); static int parse_certificate( 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 void parse_comment( IOBUF inp, int pkttype, unsigned long pktlen ); static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen ); static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ); static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); static u16 checksum( byte *p ) { u16 n, a; n = *p++ << 8; n |= *p++; for(a=0; n; n-- ) a += *p++; return a; } static unsigned short read_16(IOBUF inp) { unsigned short a; a = iobuf_get_noeof(inp) << 8; a |= iobuf_get_noeof(inp); return a; } static unsigned long read_32(IOBUF inp) { unsigned long a; a = iobuf_get_noeof(inp) << 24; a |= iobuf_get_noeof(inp) << 16; a |= iobuf_get_noeof(inp) << 8; a |= iobuf_get_noeof(inp); return a; } int set_packet_list_mode( int mode ) { int old = list_mode; list_mode = mode; mpi_print_mode = DBG_MPI; return old; } /**************** * Parse a Packet and return it in packet * Returns: 0 := valid packet in pkt * -1 := no more packets * >0 := error * Note: The function may return an error and a partly valid packet; * caller must free this packet. */ int parse_packet( IOBUF inp, PACKET *pkt ) { int rc, ctb, pkttype, lenbytes; unsigned long pktlen; byte hdr[5]; int hdrlen; assert( !pkt->pkt.generic ); if( (ctb = iobuf_get(inp)) == -1 ) return -1; hdrlen=0; hdr[hdrlen++] = ctb; if( !(ctb & 0x80) ) { log_error("invalid packet at '%s'\n", iobuf_where(inp) ); return G10ERR_INVALID_PACKET; } /* we handle the pgp 3 extensions here, so that we can skip such packets*/ pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf); lenbytes = (ctb & 0x40) || ((ctb&3)==3)? 0 : (1<<(ctb & 3)); pktlen = 0; if( !lenbytes ) { pktlen = 0; /* don't know the value */ if( pkttype != PKT_COMPRESSED ) iobuf_set_block_mode(inp, 1); } else { for( ; lenbytes; lenbytes-- ) { pktlen <<= 8; pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp); } } if( DBG_PACKET ) log_debug("parse_packet(iob=%d): type=%d length=%lu\n", iobuf_id(inp), pkttype, pktlen ); pkt->pkttype = pkttype; rc = G10ERR_UNKNOWN_PACKET; /* default to no error */ switch( pkttype ) { case PKT_PUBLIC_CERT: pkt->pkt.public_cert = m_alloc_clear(sizeof *pkt->pkt.public_cert ); rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt ); break; case PKT_SECRET_CERT: case PKT_SECKEY_SUBCERT: pkt->pkt.secret_cert = m_alloc_clear(sizeof *pkt->pkt.secret_cert ); rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt ); break; case PKT_PUBKEY_ENC: rc = parse_publickey(inp, pkttype, pktlen, pkt ); break; case PKT_SIGNATURE: pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature ); rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature ); break; case PKT_USER_ID: rc = parse_user_id(inp, pkttype, pktlen, pkt ); break; case PKT_COMMENT: parse_comment(inp, pkttype, pktlen); break; case PKT_RING_TRUST: parse_trust(inp, pkttype, pktlen); break; case PKT_PLAINTEXT: rc = parse_plaintext(inp, pkttype, pktlen, pkt ); break; case PKT_COMPRESSED: rc = parse_compressed(inp, pkttype, pktlen, pkt ); break; case PKT_ENCRYPTED: rc = parse_encrypted(inp, pkttype, pktlen, pkt ); break; default: skip_packet(inp, pkttype, pktlen); break; } return rc; } static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen ) { if( list_mode ) printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen ); skip_rest(inp,pktlen); } static void skip_rest( IOBUF inp, unsigned long pktlen ) { if( iobuf_in_block_mode(inp) ) { while( iobuf_get(inp) != -1 ) ; } else { for( ; pktlen; pktlen-- ) iobuf_get(inp); } } static int parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) { int version; unsigned n; PKT_pubkey_enc *k; k = packet->pkt.pubkey_enc = m_alloc(sizeof *packet->pkt.pubkey_enc ); if( pktlen < 12 ) { log_error("packet(%d) too short\n", pkttype); goto leave; } version = iobuf_get_noeof(inp); pktlen--; if( version != 2 && version != 3 ) { log_error("packet(%d) with unknown version %d\n", pkttype, version); goto leave; } k->keyid[0] = read_32(inp); pktlen -= 4; k->keyid[1] = read_32(inp); pktlen -= 4; k->pubkey_algo = iobuf_get_noeof(inp); pktlen--; if( list_mode ) printf(":public key packet: keyid %08lX%08lX\n", k->keyid[0], k->keyid[1]); if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { n = pktlen; k->d.elg.a = mpi_decode(inp, &n ); pktlen -=n; k->d.elg.b = mpi_decode(inp, &n ); pktlen -=n; if( list_mode ) { printf("\telg a: "); mpi_print(stdout, k->d.elg.a, mpi_print_mode ); printf("\n\telg b: "); mpi_print(stdout, k->d.elg.b, mpi_print_mode ); putchar('\n'); } } else if( k->pubkey_algo == PUBKEY_ALGO_RSA ) { n = pktlen; k->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n; if( list_mode ) { printf("\trsa integer: "); mpi_print(stdout, k->d.rsa.rsa_integer, mpi_print_mode ); putchar('\n'); } } else if( list_mode ) printf("\tunknown algorithm %d\n", k->pubkey_algo ); leave: skip_rest(inp, pktlen); return 0; } static int parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, PKT_signature *sig ) { int version, md5_len; unsigned n; if( pktlen < 16 ) { log_error("packet(%d) too short\n", pkttype); goto leave; } version = iobuf_get_noeof(inp); pktlen--; if( version != 2 && version != 3 ) { log_error("packet(%d) with unknown version %d\n", pkttype, version); goto leave; } md5_len = iobuf_get_noeof(inp); pktlen--; sig->sig_class = iobuf_get_noeof(inp); pktlen--; sig->timestamp = read_32(inp); pktlen -= 4; sig->keyid[0] = read_32(inp); pktlen -= 4; sig->keyid[1] = read_32(inp); pktlen -= 4; sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--; if( list_mode ) printf(":signature packet: keyid %08lX%08lX\n" "\tversion %d, created %lu, md5len %d, sigclass %02x\n", sig->keyid[0], sig->keyid[1], version, sig->timestamp, md5_len, sig->sig_class ); if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { if( pktlen < 5 ) { log_error("packet(%d) too short\n", pkttype); goto leave; } sig->d.elg.digest_algo = iobuf_get_noeof(inp); pktlen--; sig->d.elg.digest_start[0] = iobuf_get_noeof(inp); pktlen--; sig->d.elg.digest_start[1] = iobuf_get_noeof(inp); pktlen--; n = pktlen; sig->d.elg.a = mpi_decode(inp, &n ); pktlen -=n; sig->d.elg.b = mpi_decode(inp, &n ); pktlen -=n; if( list_mode ) { printf("\tdigest algo %d, begin of digest %02x %02x\n", sig->d.elg.digest_algo, sig->d.elg.digest_start[0], sig->d.elg.digest_start[1] ); printf("\telg a: "); mpi_print(stdout, sig->d.elg.a, mpi_print_mode ); printf("\n\telg b: "); mpi_print(stdout, sig->d.elg.a, mpi_print_mode ); putchar('\n'); } } else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) { if( pktlen < 5 ) { log_error("packet(%d) too short\n", pkttype); goto leave; } sig->d.rsa.digest_algo = iobuf_get_noeof(inp); pktlen--; sig->d.rsa.digest_start[0] = iobuf_get_noeof(inp); pktlen--; sig->d.rsa.digest_start[1] = iobuf_get_noeof(inp); pktlen--; n = pktlen; sig->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n; if( list_mode ) { printf("\tdigest algo %d, begin of digest %02x %02x\n", sig->d.rsa.digest_algo, sig->d.rsa.digest_start[0], sig->d.rsa.digest_start[1] ); printf("\trsa integer: "); mpi_print(stdout, sig->d.rsa.rsa_integer, mpi_print_mode ); putchar('\n'); } } else if( list_mode ) printf("\tunknown algorithm %d\n", sig->pubkey_algo ); leave: skip_rest(inp, pktlen); return 0; } static int parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen, byte *hdr, int hdrlen, PACKET *pkt ) { int i, version, algorithm; unsigned n; unsigned long timestamp; unsigned short valid_period; int is_v4=0; if( pkttype == PKT_PUBLIC_CERT ) { pkt->pkt.public_cert->mfx.md5 = md5_open(0); pkt->pkt.public_cert->mfx.rmd160 = rmd160_open(0); pkt->pkt.public_cert->mfx.maxbuf_size = 1; md5_write(pkt->pkt.public_cert->mfx.md5, hdr, hdrlen); rmd160_write(pkt->pkt.public_cert->mfx.rmd160, hdr, hdrlen); iobuf_push_filter( inp, md_filter, &pkt->pkt.public_cert->mfx ); } if( pktlen < 12 ) { log_error("packet(%d) too short\n", pkttype); goto leave; } version = iobuf_get_noeof(inp); pktlen--; if( version == 4 ) is_v4=1; else if( version != 2 && version != 3 ) { log_error("packet(%d) with unknown version %d\n", pkttype, version); goto leave; } timestamp = read_32(inp); pktlen -= 4; if( is_v4 ) valid_period = 0; else valid_period = read_16(inp); pktlen -= 2; algorithm = iobuf_get_noeof(inp); pktlen--; if( list_mode ) printf(":%s key certification packet:\n" "\tversion %d, created %lu, valid for %hu days\n", pkttype == PKT_PUBLIC_CERT? "public": "secret", version, timestamp, valid_period ); if( pkttype == PKT_SECRET_CERT ) { pkt->pkt.secret_cert->timestamp = timestamp; pkt->pkt.secret_cert->valid_days = valid_period; pkt->pkt.secret_cert->pubkey_algo = algorithm; } else { pkt->pkt.public_cert->timestamp = timestamp; pkt->pkt.public_cert->valid_days = valid_period; pkt->pkt.public_cert->pubkey_algo = algorithm; } if( algorithm == PUBKEY_ALGO_ELGAMAL ) { MPI elg_p, elg_g, elg_y; n = pktlen; elg_p = mpi_decode(inp, &n ); pktlen -=n; n = pktlen; elg_g = mpi_decode(inp, &n ); pktlen -=n; n = pktlen; elg_y = mpi_decode(inp, &n ); pktlen -=n; if( list_mode ) { printf( "\telg p: "); mpi_print(stdout, elg_p, mpi_print_mode ); printf("\n\telg g: "); mpi_print(stdout, elg_g, mpi_print_mode ); printf("\n\telg y: "); mpi_print(stdout, elg_y, mpi_print_mode ); putchar('\n'); } if( pkttype == PKT_PUBLIC_CERT ) { pkt->pkt.public_cert->d.elg.p = elg_p; pkt->pkt.public_cert->d.elg.g = elg_g; pkt->pkt.public_cert->d.elg.y = elg_y; } else { PKT_secret_cert *cert = pkt->pkt.secret_cert; byte temp[8]; byte *mpibuf; pkt->pkt.secret_cert->d.elg.p = elg_p; pkt->pkt.secret_cert->d.elg.g = elg_g; pkt->pkt.secret_cert->d.elg.y = elg_y; cert->d.elg.protect_algo = iobuf_get_noeof(inp); pktlen--; if( list_mode ) printf( "\tprotect algo: %d\n", cert->d.elg.protect_algo); if( cert->d.elg.protect_algo ) { cert->d.elg.is_protected = 1; for(i=0; i < 8 && pktlen; i++, pktlen-- ) temp[i] = iobuf_get_noeof(inp); if( list_mode ) { printf( "\tprotect IV: "); for(i=0; i < 8; i++ ) printf(" %02x", temp[i] ); putchar('\n'); } if( cert->d.elg.protect_algo == CIPHER_ALGO_BLOWFISH ) memcpy(cert->d.elg.protect.blowfish.iv, temp, 8 ); } else cert->d.elg.is_protected = 0; n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2); cert->d.elg.x = (MPI)mpibuf; cert->d.elg.csum = read_16(inp); pktlen -= 2; cert->d.elg.calc_csum = 0; if( list_mode ) { printf("\t[secret value x is not shown]\n" "\tchecksum: %04hx\n", cert->d.elg.csum); } if( !cert->d.elg.is_protected ) { /* convert buffer to MPIs */ mpibuf = (byte*)cert->d.elg.x; cert->d.elg.calc_csum += checksum( mpibuf ); cert->d.elg.x = mpi_decode_buffer( mpibuf ); m_free( mpibuf ); /*log_mpidump("elg p=", cert->d.elg.p ); log_mpidump("elg g=", cert->d.elg.g ); log_mpidump("elg y=", cert->d.elg.y ); log_mpidump("elg x=", cert->d.elg.x ); */ } } } else if( algorithm == PUBKEY_ALGO_RSA ) { MPI rsa_pub_mod, rsa_pub_exp; n = pktlen; rsa_pub_mod = mpi_decode(inp, &n ); pktlen -=n; n = pktlen; rsa_pub_exp = mpi_decode(inp, &n ); pktlen -=n; if( list_mode ) { printf( "\tpublic modulus n: "); mpi_print(stdout, rsa_pub_mod, mpi_print_mode ); printf("\n\tpublic exponent e: "); mpi_print(stdout, rsa_pub_exp, mpi_print_mode ); putchar('\n'); } if( pkttype == PKT_PUBLIC_CERT ) { pkt->pkt.public_cert->d.rsa.rsa_n = rsa_pub_mod; pkt->pkt.public_cert->d.rsa.rsa_e = rsa_pub_exp; } else { PKT_secret_cert *cert = pkt->pkt.secret_cert; byte temp[8]; byte *mpibuf; pkt->pkt.secret_cert->d.rsa.rsa_n = rsa_pub_mod; pkt->pkt.secret_cert->d.rsa.rsa_e = rsa_pub_exp; cert->d.rsa.protect_algo = iobuf_get_noeof(inp); pktlen--; if( list_mode ) printf( "\tprotect algo: %d\n", cert->d.rsa.protect_algo); if( cert->d.rsa.protect_algo ) { cert->d.rsa.is_protected = 1; for(i=0; i < 8 && pktlen; i++, pktlen-- ) temp[i] = iobuf_get_noeof(inp); if( list_mode ) { printf( "\tprotect IV: "); for(i=0; i < 8; i++ ) printf(" %02x", temp[i] ); putchar('\n'); } if( cert->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH ) memcpy(cert->d.rsa.protect.blowfish.iv, temp, 8 ); } else cert->d.rsa.is_protected = 0; n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2); cert->d.rsa.rsa_d = (MPI)mpibuf; n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2); cert->d.rsa.rsa_p = (MPI)mpibuf; n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2); cert->d.rsa.rsa_q = (MPI)mpibuf; n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2); cert->d.rsa.rsa_u = (MPI)mpibuf; cert->d.rsa.csum = read_16(inp); pktlen -= 2; cert->d.rsa.calc_csum = 0; if( list_mode ) { printf("\t[secret values d,p,q,u are not shown]\n" "\tchecksum: %04hx\n", cert->d.rsa.csum); } if( !cert->d.rsa.is_protected ) { /* convert buffer to MPIs */ #define X(a) do { \ mpibuf = (byte*)cert->d.rsa.rsa_##a; \ cert->d.rsa.calc_csum += checksum( mpibuf ); \ cert->d.rsa.rsa_##a = mpi_decode_buffer( mpibuf ); \ m_free( mpibuf ); \ } while(0) X(d); X(p); X(q); X(u); #undef X /* log_mpidump("rsa n=", cert->d.rsa.rsa_n ); log_mpidump("rsa e=", cert->d.rsa.rsa_e ); log_mpidump("rsa d=", cert->d.rsa.rsa_d ); log_mpidump("rsa p=", cert->d.rsa.rsa_p ); log_mpidump("rsa q=", cert->d.rsa.rsa_q ); log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */ } } } else if( list_mode ) printf("\tunknown algorithm %d\n", algorithm ); leave: if( pkttype == PKT_PUBLIC_CERT ) iobuf_pop_filter( inp, md_filter, &pkt->pkt.public_cert->mfx ); skip_rest(inp, pktlen); return 0; } static int 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 - 1); packet->pkt.user_id->len = pktlen; p = packet->pkt.user_id->name; for( ; pktlen; pktlen--, p++ ) *p = iobuf_get_noeof(inp); if( list_mode ) { int n = packet->pkt.user_id->len; printf(":user id packet: \""); for(p=packet->pkt.user_id->name; n; p++, n-- ) { if( *p >= ' ' && *p <= 'z' ) putchar(*p); else printf("\\x%02x", *p ); } printf("\"\n"); } return 0; } static void parse_comment( IOBUF inp, int pkttype, unsigned long pktlen ) { if( list_mode ) { printf(":comment packet: \"" ); for( ; pktlen; pktlen-- ) { int c; c = iobuf_get_noeof(inp); if( c >= ' ' && c <= 'z' ) putchar(c); else printf("\\x%02x", c ); } printf("\"\n"); } skip_rest(inp, pktlen); } static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen ) { int c; c = iobuf_get_noeof(inp); if( list_mode ) printf(":trust packet: flag=%02x\n", c ); #if 0 /* fixme: depending on the context we have different interpretations*/ if( prev_packet_is_a_key_packet ) { int ot = c & 7; /* ownertrust bits (for the key owner) */ !ot ? "undefined" : ot == 1 ? "unknown" : /* we don't know the owner of this key */ ot == 2 ? "no" : /* usually we do not trust this key owner */ /* to sign other keys */ ot == 5 ? "usually" : /* usually we trust this key owner to sign */ ot == 6 ? "always" : /* always trust this key owner to sign */ ot == 7 ? "ultimate" : /* also present in the secret keyring */ "" /* reserved value */ if( c & (1<<5) ) "key is disabled" if( c & (1<<7) ) "buckstop" else if( prev_packet_is_user_is_packet ) { int kl = c & 3; /* keylegit bits */ 0 = "unknown, undefined, or uninitialized trust" 1 = "we do not trust this key's ownership" 2 = "we have marginal confidence of this key's ownership" 3 = "we completely trust this key's ownership." /* This one (3) requires either: * - 1 ultimately trusted signature (SIGTRUST=7) * - COMPLETES_NEEDED completely trusted signatures (SIGTRUST=6) * - MARGINALS_NEEDED marginally trusted signatures (SIGTRUST=5) */ if( c & 0x80 ) "warnonly" else if( prev_packet_is_a_signature ) { Bits 0-2 - SIGTRUST bits - Trust bits for this signature. Value is copied directly from OWNERTRUST bits of signer: 000 - undefined, or uninitialized trust. 001 - unknown 010 - We do not trust this signature. 011 - reserved 100 - reserved 101 - We reasonably trust this signature. 110 - We completely trust this signature. 111 - ultimately trusted signature (from the owner of the ring) Bit 6 - CHECKED bit - This means that the key checking pass (pgp -kc, also invoked automatically whenever keys are added to the keyring) has tested this signature and found it good. If this bit is not set, the maintenance pass considers this signature untrustworthy. Bit 7 - CONTIG bit - Means this signature leads up a contiguous trusted certification path all the way back to the ultimately- trusted keyring owner, where the buck stops. This bit is derived from other trust packets. It is currently not used for anything in PGP. } #endif } static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ) { int mode, namelen; PKT_plaintext *pt; byte *p; int c, i; if( pktlen && pktlen < 6 ) { log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen); goto leave; } mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--; namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--; pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1); pt->mode = mode; pt->namelen = namelen; if( pktlen ) { for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ ) pt->name[i] = iobuf_get_noeof(inp); } else { for( i=0; i < namelen; i++ ) if( (c=iobuf_get(inp)) == -1 ) break; else pt->name[i] = c; } pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4; pt->len = pktlen; pt->buf = inp; pktlen = 0; if( list_mode ) { printf(":literal data packet:\n" "\tmode %c, created %lu, name=\"", mode >= ' ' && mode <'z'? mode : '?', pt->timestamp ); for(p=pt->name,i=0; i < namelen; p++, i++ ) { if( *p >= ' ' && *p <= 'z' ) putchar(*p); else printf("\\x%02x", *p ); } printf("\",\n\traw data: %lu bytes\n", pt->len ); } leave: return 0; } static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ) { PKT_compressed *zd; int algorithm; /* pktlen is here 0, but data follows * (this should be the last object in a file or * the compress algorithm should know the length) */ zd = pkt->pkt.compressed = m_alloc(sizeof *pkt->pkt.compressed ); zd->len = 0; /* not yet used */ zd->algorithm = iobuf_get_noeof(inp); zd->buf = inp; if( list_mode ) printf(":compressed packet: algo=%d\n", zd->algorithm); return 0; } static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ) { PKT_encrypted *ed; ed = pkt->pkt.encrypted = m_alloc(sizeof *pkt->pkt.encrypted ); ed->len = pktlen; ed->buf = NULL; if( pktlen && pktlen < 10 ) { log_error("packet(%d) too short\n", pkttype); skip_rest(inp, pktlen); goto leave; } if( list_mode ) if( pktlen ) printf(":encrypted data packet:\n\tlength: %lu\n", pktlen-10); else printf(":encrypted data packet:\n\tlength: unknown\n"); ed->buf = inp; pktlen = 0; leave: return 0; }