diff options
Diffstat (limited to '')
-rw-r--r-- | g10/build-packet.c | 629 |
1 files changed, 373 insertions, 256 deletions
diff --git a/g10/build-packet.c b/g10/build-packet.c index d2c538477..cbf037483 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -1,6 +1,6 @@ /* build-packet.c - assemble packets and write them - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 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> @@ -24,40 +25,38 @@ #include <stdlib.h> #include <string.h> #include <assert.h> +#include <ctype.h> #include "gpg.h" #include "packet.h" #include "errors.h" #include "iobuf.h" -#include "mpi.h" #include "util.h" #include "cipher.h" -#include "memory.h" +#include "i18n.h" #include "options.h" - -static int do_comment( iobuf_t out, int ctb, PKT_comment *rem ); -static int do_user_id( iobuf_t out, int ctb, PKT_user_id *uid ); -static int do_public_key( iobuf_t out, int ctb, PKT_public_key *pk ); -static int do_secret_key( iobuf_t out, int ctb, PKT_secret_key *pk ); -static int do_symkey_enc( iobuf_t out, int ctb, PKT_symkey_enc *enc ); -static int do_pubkey_enc( iobuf_t out, int ctb, PKT_pubkey_enc *enc ); +static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ); +static int do_public_key( IOBUF out, int ctb, PKT_public_key *pk ); +static int do_secret_key( IOBUF out, int ctb, PKT_secret_key *pk ); +static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ); +static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ); static u32 calc_plaintext( PKT_plaintext *pt ); -static int do_plaintext( iobuf_t out, int ctb, PKT_plaintext *pt ); -static int do_encrypted( iobuf_t out, int ctb, PKT_encrypted *ed ); -static int do_encrypted_mdc( iobuf_t out, int ctb, PKT_encrypted *ed ); -static int do_compressed( iobuf_t out, int ctb, PKT_compressed *cd ); -static int do_signature( iobuf_t out, int ctb, PKT_signature *sig ); -static int do_onepass_sig( iobuf_t out, int ctb, PKT_onepass_sig *ops ); +static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ); +static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ); +static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ); +static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd ); +static int do_signature( IOBUF out, int ctb, PKT_signature *sig ); +static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ); static int calc_header_length( u32 len, int new_ctb ); -static int write_16(iobuf_t inp, u16 a); -static int write_32(iobuf_t inp, u32 a); -static int write_header( iobuf_t out, int ctb, u32 len ); -static int write_sign_packet_header( iobuf_t out, int ctb, u32 len ); -static int write_header2( iobuf_t out, int ctb, u32 len, int hdrlen, int blkmode ); -static int write_new_header( iobuf_t out, int ctb, u32 len, int hdrlen ); -static int write_version( iobuf_t out, int ctb ); +static int write_16(IOBUF inp, u16 a); +static int write_32(IOBUF inp, u32 a); +static int write_header( IOBUF out, int ctb, u32 len ); +static int write_sign_packet_header( IOBUF out, int ctb, u32 len ); +static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen ); +static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ); +static int write_version( IOBUF out, int ctb ); /**************** * Build a packet and write it to INP @@ -66,7 +65,7 @@ static int write_version( iobuf_t out, int ctb ); * Note: Caller must free the packet */ int -build_packet( iobuf_t out, PACKET *pkt ) +build_packet( IOBUF out, PACKET *pkt ) { int new_ctb=0, rc=0, ctb; int pkttype; @@ -75,30 +74,38 @@ build_packet( iobuf_t out, PACKET *pkt ) log_debug("build_packet() type=%d\n", pkt->pkttype ); assert( pkt->pkt.generic ); - switch( (pkttype = pkt->pkttype) ) { - case PKT_OLD_COMMENT: pkttype = pkt->pkttype = PKT_COMMENT; break; + switch( (pkttype = pkt->pkttype) ) + { case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break; case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break; case PKT_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break; case PKT_USER_ID: - if( pkt->pkt.user_id->attrib_data ) - pkttype = PKT_ATTRIBUTE; - break; + if( pkt->pkt.user_id->attrib_data ) + pkttype = PKT_ATTRIBUTE; + break; default: break; - } + } if( new_ctb || pkttype > 15 ) /* new format */ ctb = 0xc0 | (pkttype & 0x3f); else ctb = 0x80 | ((pkttype & 15)<<2); - switch( pkttype ) { + switch( pkttype ) + { case PKT_ATTRIBUTE: case PKT_USER_ID: rc = do_user_id( out, ctb, pkt->pkt.user_id ); break; + case PKT_OLD_COMMENT: case PKT_COMMENT: - rc = do_comment( out, ctb, pkt->pkt.comment ); + /* + Ignore these. Theoretically, this will never be called as + we have no way to output comment packets any longer, but + just in case there is some code path that would end up + outputting a comment that was written before comments were + dropped (in the public key?) this is a no-op. + */ break; case PKT_PUBLIC_SUBKEY: case PKT_PUBLIC_KEY: @@ -138,11 +145,32 @@ build_packet( iobuf_t out, PACKET *pkt ) default: log_bug("invalid packet type in build_packet()\n"); break; - } + } return rc; } + +/* + * Write the mpi A to OUT. + */ +static int +mpi_write (iobuf_t out, gcry_mpi_t a) +{ + char buffer[(MAX_EXTERN_MPI_BITS+7)/8]; + size_t nbytes; + int rc; + + nbytes = (MAX_EXTERN_MPI_BITS+7)/8; + rc = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, &nbytes, a ); + if( !rc ) + rc = iobuf_write( out, buffer, nbytes ); + + return rc; +} + + + /**************** * calculate the length of a packet described by PKT */ @@ -180,56 +208,42 @@ calc_packet_length( PACKET *pkt ) } static void -write_fake_data( iobuf_t out, gcry_mpi_t a ) +write_fake_data (IOBUF out, gcry_mpi_t a) { - if( a ) { - unsigned int n; - void *p; - - assert( gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)); - p = gcry_mpi_get_opaque (a, &n); - iobuf_write (out, p, (n+7)/8); - } -} - - -static int -do_comment (iobuf_t out, int ctb, PKT_comment *rem) -{ - int rc = 0; - - if (opt.sk_comments) + if (a) { - write_header(out, ctb, rem->len); - rc = iobuf_write( out, rem->data, rem->len ); + unsigned int n; + void *p; + + p = gcry_mpi_get_opaque ( a, &n ); + iobuf_write (out, p, (n+7)/8 ); } - return rc; } static int -do_user_id( iobuf_t out, int ctb, PKT_user_id *uid ) +do_user_id( IOBUF out, int ctb, PKT_user_id *uid ) { - int rc; + int rc; - if (uid->attrib_data) - { - write_header (out, ctb, uid->attrib_len); - rc = iobuf_write (out, uid->attrib_data, uid->attrib_len ); - } - else - { - write_header (out, ctb, uid->len); - rc = iobuf_write (out, uid->name, uid->len ); - } - return rc; + if( uid->attrib_data ) + { + write_header(out, ctb, uid->attrib_len); + rc = iobuf_write( out, uid->attrib_data, uid->attrib_len ); + } + else + { + write_header2( out, ctb, uid->len, 2 ); + rc = iobuf_write( out, uid->name, uid->len ); + } + return 0; } static int -do_public_key( iobuf_t out, int ctb, PKT_public_key *pk ) +do_public_key( IOBUF out, int ctb, PKT_public_key *pk ) { int rc = 0; int n, i; - iobuf_t a = iobuf_temp(); + IOBUF a = iobuf_temp(); if( !pk->version ) iobuf_put( a, 3 ); @@ -251,99 +265,20 @@ do_public_key( iobuf_t out, int ctb, PKT_public_key *pk ) for(i=0; i < n; i++ ) mpi_write(a, pk->pkey[i] ); - write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes, 1 ); - rc = iobuf_write_temp (out, a); + write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes); + rc = iobuf_write_temp( out, a ); iobuf_close(a); return rc; } -/**************** - * Make a hash value from the public key certificate - */ -void -hash_public_key( MD_HANDLE md, PKT_public_key *pk ) -{ - PACKET pkt; - int rc = 0; - int ctb; - ulong pktlen; - int c; - iobuf_t a = iobuf_temp(); -#if 0 - FILE *fp = fopen("dump.pk", "a"); - int i=0; - - fprintf(fp, "\nHashing PK (v%d):\n", pk->version); -#endif - - /* build the packet */ - init_packet(&pkt); - pkt.pkttype = PKT_PUBLIC_KEY; - pkt.pkt.public_key = pk; - if( (rc = build_packet( a, &pkt )) ) - log_fatal("build public_key for hashing failed: %s\n", gpg_strerror (rc)); - - if( !(pk->version == 3 && pk->pubkey_algo == 16) ) { - /* skip the constructed header but don't do this for our very old - * v3 ElG keys */ - ctb = iobuf_get_noeof(a); - pktlen = 0; - if( (ctb & 0x40) ) { - c = iobuf_get_noeof(a); - if( c < 192 ) - pktlen = c; - else if( c < 224 ) { - pktlen = (c - 192) * 256; - c = iobuf_get_noeof(a); - pktlen += c + 192; - } - else if( c == 255 ) { - pktlen = iobuf_get_noeof(a) << 24; - pktlen |= iobuf_get_noeof(a) << 16; - pktlen |= iobuf_get_noeof(a) << 8; - pktlen |= iobuf_get_noeof(a); - } - } - else { - int lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3)); - for( ; lenbytes; lenbytes-- ) { - pktlen <<= 8; - pktlen |= iobuf_get_noeof(a); - } - } - /* hash a header */ - gcry_md_putc ( md, 0x99 ); - pktlen &= 0xffff; /* can't handle longer packets */ - gcry_md_putc ( md, pktlen >> 8 ); - gcry_md_putc ( md, pktlen & 0xff ); - } - /* hash the packet body */ - while( (c=iobuf_get(a)) != -1 ) { -#if 0 - fprintf( fp," %02x", c ); - if( (++i == 24) ) { - putc('\n', fp); - i=0; - } -#endif - gcry_md_putc ( md, c ); - } -#if 0 - putc('\n', fp); - fclose(fp); -#endif - iobuf_cancel(a); -} - - static int -do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) +do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk ) { int rc = 0; int i, nskey, npkey; - iobuf_t a = iobuf_temp(); /* build in a self-enlarging buffer */ + IOBUF a = iobuf_temp(); /* build in a self-enlarging buffer */ /* Write the version number - if none is specified, use 3 */ if( !sk->version ) @@ -371,7 +306,7 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) /* If we don't have any public parameters - which is the case if we don't know the algorithm used - the parameters are stored as - one blob in a faked (opaque) gcry_mpi_t */ + one blob in a faked (opaque) MPI */ if( !npkey ) { write_fake_data( a, sk->skey[0] ); goto leave; @@ -415,9 +350,9 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) if( sk->protect.s2k.mode == 3 ) iobuf_put(a, sk->protect.s2k.count ); - /* For our special modes 1001 and 1002 we do not need an IV */ - if( sk->protect.s2k.mode != 1001 - && sk->protect.s2k.mode != 1002 ) + /* For out special modes 1001, 1002 we do not need an IV */ + if( sk->protect.s2k.mode != 1001 + && sk->protect.s2k.mode != 1002 ) iobuf_write(a, sk->protect.iv, sk->protect.ivlen ); } } @@ -437,19 +372,21 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) else if( sk->is_protected && sk->version >= 4 ) { /* The secret key is protected - write it out as it is */ byte *p; - assert( gcry_mpi_get_flag( sk->skey[npkey], GCRYMPI_FLAG_OPAQUE ) ); - p = gcry_mpi_get_opaque( sk->skey[npkey], &i ); - iobuf_write(a, p, (i+7)/8 ); + unsigned int ndatabits; + + assert (gcry_mpi_get_flag (sk->skey[npkey], GCRYMPI_FLAG_OPAQUE)); + p = gcry_mpi_get_opaque (sk->skey[npkey], &ndatabits ); + iobuf_write (a, p, (ndatabits+7)/8 ); } else if( sk->is_protected ) { - /* The secret key is protected the old v4 way. */ + /* The secret key is protected te old v4 way. */ for( ; i < nskey; i++ ) { byte *p; - size_t n; + unsigned int ndatabits; - assert( gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE)); - p = gcry_mpi_get_opaque( sk->skey[i], &n ); - iobuf_write (a, p, (n+7)/8); + assert (gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE)); + p = gcry_mpi_get_opaque (sk->skey[i], &ndatabits); + iobuf_write (a, p, (ndatabits+7)/8); } write_16(a, sk->csum ); } @@ -463,19 +400,19 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) leave: /* Build the header of the packet - which we must do after writing all the other stuff, so that we know the length of the packet */ - write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 ); + write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes); /* And finally write it out the real stream */ - rc = iobuf_write_temp (out, a ); + rc = iobuf_write_temp( out, a ); iobuf_close(a); /* close the remporary buffer */ return rc; } static int -do_symkey_enc( iobuf_t out, int ctb, PKT_symkey_enc *enc ) +do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) { int rc = 0; - iobuf_t a = iobuf_temp(); + IOBUF a = iobuf_temp(); assert( enc->version == 4 ); switch( enc->s2k.mode ) { @@ -495,21 +432,19 @@ do_symkey_enc( iobuf_t out, int ctb, PKT_symkey_enc *enc ) iobuf_write(a, enc->seskey, enc->seskeylen ); write_header(out, ctb, iobuf_get_temp_length(a) ); - rc = iobuf_write_temp (out, a); + rc = iobuf_write_temp( out, a ); iobuf_close(a); return rc; } - - static int -do_pubkey_enc( iobuf_t out, int ctb, PKT_pubkey_enc *enc ) +do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) { int rc = 0; int n, i; - iobuf_t a = iobuf_temp(); + IOBUF a = iobuf_temp(); write_version( a, ctb ); if( enc->throw_keyid ) { @@ -528,55 +463,56 @@ do_pubkey_enc( iobuf_t out, int ctb, PKT_pubkey_enc *enc ) mpi_write(a, enc->data[i] ); write_header(out, ctb, iobuf_get_temp_length(a) ); - rc = iobuf_write_temp (out, a); + rc = iobuf_write_temp( out, a ); iobuf_close(a); return rc; } - - static u32 calc_plaintext( PKT_plaintext *pt ) { - return pt->len? (1 + 1 + pt->namelen + 4 + pt->len) : 0; + /* Truncate namelen to the maximum 255 characters. Note this means + that a function that calls build_packet with an illegal literal + packet will get it back legalized. */ + + if(pt->namelen>255) + pt->namelen=255; + + return pt->len? (1 + 1 + pt->namelen + 4 + pt->len) : 0; } static int -do_plaintext( iobuf_t out, int ctb, PKT_plaintext *pt ) +do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) { int i, rc = 0; u32 n; byte buf[1000]; /* this buffer has the plaintext! */ int nbytes; - /* Truncate namelen to the maximum 255 characters. This does mean - that a function that calls build_packet with an illegal literal - packet will get it back legalized. */ - if(pt->namelen>255) - pt->namelen=255; - write_header(out, ctb, calc_plaintext( pt ) ); iobuf_put(out, pt->mode ); iobuf_put(out, pt->namelen ); for(i=0; i < pt->namelen; i++ ) iobuf_put(out, pt->name[i] ); - rc = write_32 (out, pt->timestamp); + rc = write_32(out, pt->timestamp ); + if (rc) + return rc; n = 0; while( (nbytes=iobuf_read(pt->buf, buf, 1000)) != -1 ) { - rc = iobuf_write(out, buf, nbytes); - if (rc) - break; - n += nbytes; + rc = iobuf_write (out, buf, nbytes); + if (rc) + break; + n += nbytes; } wipememory(buf,1000); /* burn the buffer */ - if( !pt->len ) - iobuf_set_block_mode(out, 0 ); /* write end marker */ - else if( n != pt->len ) - log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n", - (ulong)n, (ulong)pt->len ); + if( (ctb&0x40) && !pt->len ) + iobuf_set_partial_block_mode(out, 0 ); /* turn off partial */ + if( pt->len && n != pt->len ) + log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n", + (ulong)n, (ulong)pt->len ); return rc; } @@ -584,7 +520,7 @@ do_plaintext( iobuf_t out, int ctb, PKT_plaintext *pt ) static int -do_encrypted( iobuf_t out, int ctb, PKT_encrypted *ed ) +do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ) { int rc = 0; u32 n; @@ -598,7 +534,7 @@ do_encrypted( iobuf_t out, int ctb, PKT_encrypted *ed ) } static int -do_encrypted_mdc( iobuf_t out, int ctb, PKT_encrypted *ed ) +do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ) { int rc = 0; u32 n; @@ -617,7 +553,7 @@ do_encrypted_mdc( iobuf_t out, int ctb, PKT_encrypted *ed ) static int -do_compressed( iobuf_t out, int ctb, PKT_compressed *cd ) +do_compressed( IOBUF out, int ctb, PKT_compressed *cd ) { int rc = 0; @@ -626,7 +562,7 @@ do_compressed( iobuf_t out, int ctb, PKT_compressed *cd ) set, CTB is already formatted as new style and write_header2 does create a partial length encoding using new the new style. */ - write_header2(out, ctb, 0, 0, 0 ); + write_header2(out, ctb, 0, 0); iobuf_put(out, cd->algorithm ); /* This is all. The caller has to write the real data */ @@ -734,6 +670,7 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, case SIGSUBPKT_NOTATION: case SIGSUBPKT_POLICY: case SIGSUBPKT_REV_KEY: + case SIGSUBPKT_SIGNATURE: /* we do allow multiple subpackets */ break; @@ -803,18 +740,20 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, else nlen = 1; /* just a 1 byte length header */ - switch( type ) { + switch( type ) + { /* The issuer being unhashed is a historical oddity. It should work equally as well hashed. Of course, if even an unhashed issuer is tampered with, it makes it awfully hard to verify the sig... */ case SIGSUBPKT_ISSUER: + case SIGSUBPKT_SIGNATURE: hashed = 0; break; default: hashed = 1; break; - } + } if( critical ) type |= SIGSUBPKT_FLAG_CRITICAL; @@ -966,12 +905,179 @@ build_attribute_subpkt(PKT_user_id *uid,byte type, uid->attrib_len+=idx+headerlen+buflen; } +struct notation * +string_to_notation(const char *string,int is_utf8) +{ + const char *s; + int saw_at=0; + struct notation *notation; + + notation=xmalloc_clear(sizeof(*notation)); + + if(*string=='-') + { + notation->flags.ignore=1; + string++; + } + + if(*string=='!') + { + notation->flags.critical=1; + string++; + } + + /* If and when the IETF assigns some official name tags, we'll have + to add them here. */ + + for( s=string ; *s != '='; s++ ) + { + if( *s=='@') + saw_at++; + + /* -notationname is legal without an = sign */ + if(!*s && notation->flags.ignore) + break; + + if( !*s || !isascii (*s) || (!isgraph(*s) && !isspace(*s)) ) + { + log_error(_("a notation name must have only printable characters" + " or spaces, and end with an '='\n") ); + goto fail; + } + } + + notation->name=xmalloc((s-string)+1); + strncpy(notation->name,string,s-string); + notation->name[s-string]='\0'; + + if(!saw_at && !opt.expert) + { + log_error(_("a user notation name must contain the '@' character\n")); + goto fail; + } + + if (saw_at > 1) + { + log_error(_("a notation name must not contain more than" + " one '@' character\n")); + goto fail; + } + + if(*s) + { + const char *i=s+1; + int highbit=0; + + /* we only support printable text - therefore we enforce the use + of only printable characters (an empty value is valid) */ + for(s++; *s ; s++ ) + { + if ( !isascii (*s) ) + highbit=1; + else if (iscntrl(*s)) + { + log_error(_("a notation value must not use any" + " control characters\n")); + goto fail; + } + } + + if(!highbit || is_utf8) + notation->value=xstrdup(i); + else + notation->value=native_to_utf8(i); + } + + return notation; + + fail: + free_notation(notation); + return NULL; +} + +struct notation * +sig_to_notation(PKT_signature *sig) +{ + const byte *p; + size_t len; + int seq=0,crit; + struct notation *list=NULL; + + while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,&len,&seq,&crit))) + { + int n1,n2; + struct notation *n=NULL; + + if(len<8) + { + log_info(_("WARNING: invalid notation data found\n")); + continue; + } + + n1=(p[4]<<8)|p[5]; + n2=(p[6]<<8)|p[7]; + + if(8+n1+n2!=len) + { + log_info(_("WARNING: invalid notation data found\n")); + continue; + } + + n=xmalloc_clear(sizeof(*n)); + n->name=xmalloc(n1+1); + + memcpy(n->name,&p[8],n1); + n->name[n1]='\0'; + + if(p[0]&0x80) + { + n->value=xmalloc(n2+1); + memcpy(n->value,&p[8+n1],n2); + n->value[n2]='\0'; + } + else + { + n->bdat=xmalloc(n2); + n->blen=n2; + memcpy(n->bdat,&p[8+n1],n2); + + n->value=xmalloc(2+strlen(_("not human readable"))+2+1); + strcpy(n->value,"[ "); + strcat(n->value,_("not human readable")); + strcat(n->value," ]"); + } + + n->flags.critical=crit; + + n->next=list; + list=n; + } + + return list; +} + +void +free_notation(struct notation *notation) +{ + while(notation) + { + struct notation *n=notation; + + xfree(n->name); + xfree(n->value); + xfree(n->altvalue); + xfree(n->bdat); + notation=n->next; + xfree(n); + } +} + static int -do_signature( iobuf_t out, int ctb, PKT_signature *sig ) +do_signature( IOBUF out, int ctb, PKT_signature *sig ) { int rc = 0; int n, i; - iobuf_t a = iobuf_temp(); + IOBUF a = iobuf_temp(); if( !sig->version ) iobuf_put( a, 3 ); @@ -1013,7 +1119,7 @@ do_signature( iobuf_t out, int ctb, PKT_signature *sig ) write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) ); else write_header(out, ctb, iobuf_get_temp_length(a) ); - rc = iobuf_write_temp (out, a); + rc = iobuf_write_temp( out, a ); iobuf_close(a); return rc; @@ -1021,10 +1127,10 @@ do_signature( iobuf_t out, int ctb, PKT_signature *sig ) static int -do_onepass_sig( iobuf_t out, int ctb, PKT_onepass_sig *ops ) +do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ) { int rc = 0; - iobuf_t a = iobuf_temp(); + IOBUF a = iobuf_temp(); write_version( a, ctb ); iobuf_put(a, ops->sig_class ); @@ -1035,7 +1141,7 @@ do_onepass_sig( iobuf_t out, int ctb, PKT_onepass_sig *ops ) iobuf_put(a, ops->last ); write_header(out, ctb, iobuf_get_temp_length(a) ); - rc = iobuf_write_temp (out, a); + rc = iobuf_write_temp( out, a ); iobuf_close(a); return rc; @@ -1043,19 +1149,21 @@ do_onepass_sig( iobuf_t out, int ctb, PKT_onepass_sig *ops ) static int -write_16(iobuf_t out, u16 a) +write_16(IOBUF out, u16 a) { iobuf_put(out, a>>8); - return iobuf_put(out,a); + if( iobuf_put(out,a) ) + return -1; + return 0; } static int -write_32(iobuf_t out, u32 a) +write_32(IOBUF out, u32 a) { iobuf_put(out, a>> 24); iobuf_put(out, a>> 16); iobuf_put(out, a>> 8); - return iobuf_put (out, a); + return iobuf_put(out, a); } @@ -1088,14 +1196,14 @@ calc_header_length( u32 len, int new_ctb ) * Write the CTB and the packet length */ static int -write_header( iobuf_t out, int ctb, u32 len ) +write_header( IOBUF out, int ctb, u32 len ) { - return write_header2( out, ctb, len, 0, 1 ); + return write_header2( out, ctb, len, 0 ); } static int -write_sign_packet_header( iobuf_t out, int ctb, u32 len ) +write_sign_packet_header( IOBUF out, int ctb, u32 len ) { /* work around a bug in the pgp read function for signature packets, * which are not correctly coded and silently assume at some @@ -1106,57 +1214,66 @@ write_sign_packet_header( iobuf_t out, int ctb, u32 len ) } /**************** - * if HDRLEN is > 0, try to build a header of this length. - * we need this, so that we can hash packets without reading them again. + * If HDRLEN is > 0, try to build a header of this length. We need + * this so that we can hash packets without reading them again. If + * len is 0, write a partial or indeterminate length header, unless + * hdrlen is specified in which case write an actual zero length + * (using the specified hdrlen). */ static int -write_header2( iobuf_t out, int ctb, u32 len, int hdrlen, int blkmode ) +write_header2( IOBUF out, int ctb, u32 len, int hdrlen ) { - if( ctb & 0x40 ) - return write_new_header( out, ctb, len, hdrlen ); - - if( hdrlen ) { - if( !len ) - ctb |= 3; - else if( hdrlen == 2 && len < 256 ) - ; - else if( hdrlen == 3 && len < 65536 ) - ctb |= 1; - else - ctb |= 2; - } - else { - if( !len ) - ctb |= 3; - else if( len < 256 ) - ; - else if( len < 65536 ) - ctb |= 1; - else - ctb |= 2; + if( ctb & 0x40 ) + return write_new_header( out, ctb, len, hdrlen ); + + if( hdrlen ) + { + if( hdrlen == 2 && len < 256 ) + ; + else if( hdrlen == 3 && len < 65536 ) + ctb |= 1; + else + ctb |= 2; } - if( iobuf_put(out, ctb ) ) - return -1; - if( !len ) { - if( blkmode ) - iobuf_set_block_mode(out, 8196 ); + else + { + if( !len ) + ctb |= 3; + else if( len < 256 ) + ; + else if( len < 65536 ) + ctb |= 1; + else + ctb |= 2; } - else { - if( ctb & 2 ) { - iobuf_put(out, len >> 24 ); - iobuf_put(out, len >> 16 ); - } - if( ctb & 3 ) - iobuf_put(out, len >> 8 ); - if( iobuf_put(out, len ) ) + + if( iobuf_put(out, ctb ) ) + return -1; + + if( len || hdrlen ) + { + if( ctb & 2 ) + { + if(iobuf_put(out, len >> 24 )) + return -1; + if(iobuf_put(out, len >> 16 )) return -1; + } + + if( ctb & 3 ) + if(iobuf_put(out, len >> 8 )) + return -1; + + if( iobuf_put(out, len ) ) + return -1; } - return 0; + + return 0; } static int -write_new_header( iobuf_t out, int ctb, u32 len, int hdrlen ) +write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ) { if( hdrlen ) log_bug("can't cope with hdrlen yet\n"); @@ -1195,7 +1312,7 @@ write_new_header( iobuf_t out, int ctb, u32 len, int hdrlen ) } static int -write_version( iobuf_t out, int ctb ) +write_version( IOBUF out, int ctb ) { if( iobuf_put( out, 3 ) ) return -1; |