1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-04-17 15:44:34 +02:00

Improved pipemode and tweaked handling of multiple signatures.

This commit is contained in:
Werner Koch 2001-04-05 12:21:43 +00:00
parent 64f6858920
commit c9e908e734
17 changed files with 454 additions and 47 deletions

2
THANKS
View File

@ -85,6 +85,7 @@ Johnny Teve
Jörg Schilling schilling@fokus.gmd.de Jörg Schilling schilling@fokus.gmd.de
Jos Backus Jos.Backus@nl.origin-it.com Jos Backus Jos.Backus@nl.origin-it.com
Jun Kuriyama kuriyama@sky.rim.or.jp Jun Kuriyama kuriyama@sky.rim.or.jp
Kahil D. Jallad kdj4@cs.columbia.edu
Karl Fogel kfogel@guanabana.onshore.com Karl Fogel kfogel@guanabana.onshore.com
Karsten Thygesen karthy@kom.auc.dk Karsten Thygesen karthy@kom.auc.dk
Katsuhiro Kondou kondou@nec.co.jp Katsuhiro Kondou kondou@nec.co.jp
@ -154,6 +155,7 @@ Timo Schulz towaday@freakmail.de
Tom Spindler dogcow@home.merit.edu Tom Spindler dogcow@home.merit.edu
Tom Zerucha tzeruch@ceddec.com Tom Zerucha tzeruch@ceddec.com
Tomas Fasth tomas.fasth@twinspot.net Tomas Fasth tomas.fasth@twinspot.net
Tommi Komulainen Tommi.Komulainen@iki.fi
Thomas Klausner wiz@danbala.ifoer.tuwien.ac.at Thomas Klausner wiz@danbala.ifoer.tuwien.ac.at
Tomasz Kozlowski tomek@rentec.com Tomasz Kozlowski tomek@rentec.com
Thomas Mikkelsen tbm@image.dk Thomas Mikkelsen tbm@image.dk

3
TODO
View File

@ -29,7 +29,7 @@
will have commands --{add,remove}-trusted-key which keeps them in will have commands --{add,remove}-trusted-key which keeps them in
special trustdb records. special trustdb records.
* Use DSA keys with the test suite. * Use DSA keys with the test suite (partly done)
* g10/trustdb.c (make_sig_records): fix the fixme. * g10/trustdb.c (make_sig_records): fix the fixme.
@ -43,7 +43,6 @@
* Add an is_valid flag to each user ID. * Add an is_valid flag to each user ID.
* Make --pipemode work.
Scheduled for 1.1 Scheduled for 1.1
----------------- -----------------

View File

@ -1,3 +1,8 @@
2001-04-02 Werner Koch <wk@gnupg.org>
* primegen.c (generate_elg_prime): I was not initialized for mode
!= 1. Freed q at 3 places. Thanks to Tommi Komulainen.
2001-03-28 Werner Koch <wk@gnupg.org> 2001-03-28 Werner Koch <wk@gnupg.org>
* md5.c (md5_final): Fixed calculation of hashed length. Thanks * md5.c (md5_final): Fixed calculation of hashed length. Thanks

View File

@ -190,6 +190,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
count1 = 0; count1 = 0;
qbits++; qbits++;
progress('>'); progress('>');
mpi_free (q);
q = gen_prime( qbits, 0, 0 ); q = gen_prime( qbits, 0, 0 );
goto next_try; goto next_try;
} }
@ -201,6 +202,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
count2 = 0; count2 = 0;
qbits--; qbits--;
progress('<'); progress('<');
mpi_free (q);
q = gen_prime( qbits, 0, 0 ); q = gen_prime( qbits, 0, 0 );
goto next_try; goto next_try;
} }
@ -227,8 +229,8 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
if( ret_factors ) { /* caller wants the factors */ if( ret_factors ) { /* caller wants the factors */
*ret_factors = m_alloc_clear( (n+2) * sizeof **ret_factors); *ret_factors = m_alloc_clear( (n+2) * sizeof **ret_factors);
i = 0;
if( mode == 1 ) { if( mode == 1 ) {
i = 0;
(*ret_factors)[i++] = mpi_copy( q_factor ); (*ret_factors)[i++] = mpi_copy( q_factor );
for(; i <= n; i++ ) for(; i <= n; i++ )
(*ret_factors)[i] = mpi_copy( factors[i] ); (*ret_factors)[i] = mpi_copy( factors[i] );
@ -283,6 +285,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
m_free( pool ); m_free( pool );
m_free(perms); m_free(perms);
mpi_free(val_2); mpi_free(val_2);
mpi_free(q);
return prime; return prime;
} }

View File

@ -723,10 +723,10 @@ Here is the format we use for detached signatures:
"@<" - Begin of new stream "@<" - Begin of new stream
"@B" - Detached signature follows. "@B" - Detached signature follows.
This emits a control packet (1,'B') This emits a control packet (1,'B')
detached_signature <detached_signature>
"@t" - Signed text follows. "@t" - Signed text follows.
This emits the control packet (2, 'B') This emits the control packet (2, 'B')
signed_text <signed_text>
"@." - End of operation. The final control packet forces signature "@." - End of operation. The final control packet forces signature
verification verification
"@>" - End of stream "@>" - End of stream

View File

@ -1,5 +1,48 @@
2001-04-05 Werner Koch <wk@gnupg.org>
* armor.c (unarmor_pump_new,unarmor_pump_release): New.
(unarmor_pump): New.
* pipemode.c (pipemode_filter): Use the unarmor_pump to handle
armored or non-armored detached signatures. We can't use the
regular armor_filter becuase this does only chack for armored
signatures the very first time. In pipemode we may have a mix of
armored and binary detached signatures.
* mainproc.c (proc_tree): Do not print the "old style" notice when
this is a pipemode processes detached signature.
(proc_plaintext): Special handling of pipemode detached sigs.
* packet.h (CTRLPKT_PLAINTEXT_MARK): New.
* parse-packet.c (create_gpg_control): New.
* kbnode.c (dump_kbnode): Support it here.
* mainproc.c (check_sig_and_print): Fixed the check for bad
sequences of multiple signatures.
(proc_plaintext): Add the marker packet.
(proc_tree): We can now check multiple detached signatures.
2001-04-02 Werner Koch <wk@gnupg.org>
The length of encrypted packets for blocksizes != 8 was not
correct encoded. I think this is a minor problem, because we
usually use partial length packets. Kudos to Kahil D. Jallad for
pointing this out.
* packet.h: Add extralen to PKT_encrypted.
* cipher.c (write_header): Set extralen.
* build-packet.c (do_encrypted): Use extralen instead of const 10.
(do_encrypted_mdc): Ditto.
* parse-packet.c (parse_encrypted): Set extralen to 0 becuase we
don't know it here.
2001-03-30 Werner Koch <wk@gnupg.org>
* getkey.c (premerge_public_with_secret): Changed wording an add
the keyID to the info message.
2001-03-29 Werner Koch <wk@gnupg.org> 2001-03-29 Werner Koch <wk@gnupg.org>
* getkey.c (premerge_public_with_secret): Use log_info instead of
log_error when no secret key was found for a public one.
Fix the usage if the secret parts of a key are not available.
* openfile.c (ask_outfile_name): Trim spaces. * openfile.c (ask_outfile_name): Trim spaces.
(open_outfile): Allow to enter an alternate filename. Thanks to (open_outfile): Allow to enter an alternate filename. Thanks to
Stefan Bellon. Stefan Bellon.

View File

@ -151,8 +151,9 @@ initialize(void)
} }
/**************** /****************
* Check whether this is an armored file or not * Check whether this is an armored file or not See also
* See also parse-packet.c for details on this code * parse-packet.c for details on this code For unknown historic
* reasons we use a string here but only the first byte will be used.
* Returns: True if it seems to be armored * Returns: True if it seems to be armored
*/ */
static int static int
@ -195,6 +196,7 @@ use_armor_filter( IOBUF a )
byte buf[1]; byte buf[1];
int n; int n;
/* fixme: there might be a problem with iobuf_peek */
n = iobuf_peek(a, buf, 1 ); n = iobuf_peek(a, buf, 1 );
if( n == -1 ) if( n == -1 )
return 0; /* EOF, doesn't matter whether armored or not */ return 0; /* EOF, doesn't matter whether armored or not */
@ -1093,3 +1095,221 @@ make_radix64_string( const byte *data, size_t len )
return buffer; return buffer;
} }
/***********************************************
* For the pipemode command we can't use the armor filter for various
* reasons, so we use this new unarmor_pump stuff to remove the armor
*/
enum unarmor_state_e {
STA_init = 0,
STA_bypass,
STA_wait_newline,
STA_wait_dash,
STA_first_dash,
STA_compare_header,
STA_found_header_wait_newline,
STA_skip_header_lines,
STA_skip_header_lines_non_ws,
STA_read_data,
STA_wait_crc,
STA_read_crc,
STA_ready
};
struct unarmor_pump_s {
enum unarmor_state_e state;
byte val;
int checkcrc;
int pos; /* counts from 0..3 */
u32 crc;
u32 mycrc; /* the one store in the data */
};
UnarmorPump
unarmor_pump_new (void)
{
UnarmorPump x;
if( !is_initialized )
initialize();
x = m_alloc_clear (sizeof *x);
return x;
}
void
unarmor_pump_release (UnarmorPump x)
{
m_free (x);
}
/*
* Get the next character from the ascii armor taken from the IOBUF
* created earlier by unarmor_pump_new().
* Return: c = Character
* 256 = ignore this value
* -1 = End of current armor
* -2 = Premature EOF (not used)
* -3 = Invalid armor
*/
int
unarmor_pump (UnarmorPump x, int c)
{
int rval = 256; /* default is to ignore the return value */
switch (x->state) {
case STA_init:
{
byte tmp[1];
tmp[0] = c;
if ( is_armored (tmp) )
x->state = c == '-'? STA_first_dash : STA_wait_newline;
else {
x->state = STA_bypass;
return c;
}
}
break;
case STA_bypass:
return c; /* return here to avoid crc calculation */
case STA_wait_newline:
if (c == '\n')
x->state = STA_wait_dash;
break;
case STA_wait_dash:
x->state = c == '-'? STA_first_dash : STA_wait_newline;
break;
case STA_first_dash: /* just need for initalization */
x->pos = 0;
x->state = STA_compare_header;
case STA_compare_header:
if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) {
if ( x->pos == 28 )
x->state = STA_found_header_wait_newline;
}
else
x->state = c == '\n'? STA_wait_dash : STA_wait_newline;
break;
case STA_found_header_wait_newline:
/* to make CR,LF issues easier we simply allow for white space
behind the 5 dashes */
if ( c == '\n' )
x->state = STA_skip_header_lines;
else if ( c != '\r' && c != ' ' && c != '\t' )
x->state = STA_wait_dash; /* garbage after the header line */
break;
case STA_skip_header_lines:
/* i.e. wait for one empty line */
if ( c == '\n' ) {
x->state = STA_read_data;
x->crc = CRCINIT;
x->val = 0;
x->pos = 0;
}
else if ( c != '\r' && c != ' ' && c != '\t' )
x->state = STA_skip_header_lines_non_ws;
break;
case STA_skip_header_lines_non_ws:
/* like above but we already encountered non white space */
if ( c == '\n' )
x->state = STA_skip_header_lines;
break;
case STA_read_data:
/* fixme: we don't check for the trailing dash lines but rely
* on the armor stop characters */
if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
break; /* skip all kind of white space */
if( c == '=' ) { /* pad character: stop */
if( x->pos == 1 ) /* in this case val has some value */
rval = x->val;
x->state = STA_wait_crc;
break;
}
{
int c2;
if( (c = asctobin[(c2=c)]) == 255 ) {
log_error(_("invalid radix64 character %02x skipped\n"), c2);
break;
}
}
switch(x->pos) {
case 0:
x->val = c << 2;
break;
case 1:
x->val |= (c>>4)&3;
rval = x->val;
x->val = (c<<4)&0xf0;
break;
case 2:
x->val |= (c>>2)&15;
rval = x->val;
x->val = (c<<6)&0xc0;
break;
case 3:
x->val |= c&0x3f;
rval = x->val;
break;
}
x->pos = (x->pos+1) % 4;
break;
case STA_wait_crc:
if( c == '\n' || c == ' ' || c == '\r' || c == '\t' || c == '=' )
break; /* skip ws and pad characters */
/* assume that we are at the next line */
x->state = STA_read_crc;
x->pos = 0;
x->mycrc = 0;
case STA_read_crc:
if( (c = asctobin[c]) == 255 ) {
rval = -1; /* ready */
if( x->crc != x->mycrc ) {
log_info (_("CRC error; %06lx - %06lx\n"),
(ulong)x->crc, (ulong)x->mycrc);
if ( invalid_crc() )
rval = -3;
}
x->state = STA_ready; /* not sure whether this is correct */
break;
}
switch(x->pos) {
case 0:
x->val = c << 2;
break;
case 1:
x->val |= (c>>4)&3;
x->mycrc |= x->val << 16;
x->val = (c<<4)&0xf0;
break;
case 2:
x->val |= (c>>2)&15;
x->mycrc |= x->val << 8;
x->val = (c<<6)&0xc0;
break;
case 3:
x->val |= c&0x3f;
x->mycrc |= x->val;
break;
}
x->pos = (x->pos+1) % 4;
break;
case STA_ready:
rval = -1;
break;
}
if ( !(rval & ~255) ) { /* compute the CRC */
x->crc = (x->crc << 8) ^ crc_table[((x->crc >> 16)&0xff) ^ rval];
x->crc &= 0x00ffffff;
}
return rval;
}

View File

@ -535,7 +535,7 @@ do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed )
int rc = 0; int rc = 0;
u32 n; u32 n;
n = ed->len ? (ed->len + 10) : 0; n = ed->len ? (ed->len + ed->extralen) : 0;
write_header(out, ctb, n ); write_header(out, ctb, n );
/* This is all. The caller has to write the real data */ /* This is all. The caller has to write the real data */
@ -551,7 +551,7 @@ do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed )
assert( ed->mdc_method ); assert( ed->mdc_method );
n = ed->len ? (ed->len + 10) : 0; n = ed->len ? (ed->len + ed->extralen) : 0;
write_header(out, ctb, n ); write_header(out, ctb, n );
iobuf_put(out, 1 ); /* version */ iobuf_put(out, 1 ); /* version */

View File

@ -59,6 +59,7 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
memset( &ed, 0, sizeof ed ); memset( &ed, 0, sizeof ed );
ed.len = cfx->datalen; ed.len = cfx->datalen;
ed.extralen = blocksize+2;
ed.new_ctb = !ed.len && !opt.rfc1991; ed.new_ctb = !ed.len && !opt.rfc1991;
if( use_mdc ) { if( use_mdc ) {
ed.mdc_method = DIGEST_ALGO_SHA1; ed.mdc_method = DIGEST_ALGO_SHA1;

View File

@ -64,6 +64,9 @@ typedef struct {
int pending_lf; /* used together with faked */ int pending_lf; /* used together with faked */
} armor_filter_context_t; } armor_filter_context_t;
struct unarmor_pump_s;
typedef struct unarmor_pump_s *UnarmorPump;
typedef struct { typedef struct {
int status; int status;
@ -113,6 +116,9 @@ void free_md_filter_context( md_filter_context_t *mfx );
int use_armor_filter( IOBUF a ); int use_armor_filter( IOBUF a );
int armor_filter( void *opaque, int control, int armor_filter( void *opaque, int control,
IOBUF chain, byte *buf, size_t *ret_len); IOBUF chain, byte *buf, size_t *ret_len);
UnarmorPump unarmor_pump_new (void);
void unarmor_pump_release (UnarmorPump x);
int unarmor_pump (UnarmorPump x, int c);
/*-- compress.c --*/ /*-- compress.c --*/
int compress_filter( void *opaque, int control, int compress_filter( void *opaque, int control,

View File

@ -1881,14 +1881,23 @@ premerge_public_with_secret ( KBNODE pubblock, KBNODE secblock )
for (sec=secblock->next; sec; sec = sec->next ) { for (sec=secblock->next; sec; sec = sec->next ) {
if ( sec->pkt->pkttype == PKT_SECRET_SUBKEY ) { if ( sec->pkt->pkttype == PKT_SECRET_SUBKEY ) {
PKT_secret_key *sk = sec->pkt->pkt.secret_key; PKT_secret_key *sk = sec->pkt->pkt.secret_key;
if ( !cmp_public_secret_key ( pk, sk ) ) if ( !cmp_public_secret_key ( pk, sk ) ) {
if ( sk->protect.s2k.mode == 1001 ) {
/* The secret parts are not available so
we can't use that key for signing etc.
Fix the pubkey usage */
pk->pubkey_usage &= ~PUBKEY_USAGE_SIG;
}
break; break;
}
} }
} }
if ( !sec ) { if ( !sec ) {
KBNODE next, ll; KBNODE next, ll;
log_error ( "no corresponding secret subkey "
"for public subkey - removing\n" ); log_info ( "no secret subkey "
"for public subkey %08lX - ignoring\n",
(ulong)keyid_from_pk (pk,NULL) );
/* we have to remove the subkey in this case */ /* we have to remove the subkey in this case */
assert ( last ); assert ( last );
/* find the next subkey */ /* find the next subkey */

View File

@ -355,6 +355,7 @@ dump_kbnode( KBNODE node )
case PKT_PLAINTEXT: s="plaintext"; break; case PKT_PLAINTEXT: s="plaintext"; break;
case PKT_COMPRESSED: s="compressed"; break; case PKT_COMPRESSED: s="compressed"; break;
case PKT_ENCRYPTED: s="encrypted"; break; case PKT_ENCRYPTED: s="encrypted"; break;
case PKT_GPG_CONTROL: s="gpg-control"; break;
default: s="unknown"; break; default: s="unknown"; break;
} }
fprintf(stderr, "node %p %02x/%02x type=%s", fprintf(stderr, "node %p %02x/%02x type=%s",
@ -370,6 +371,11 @@ dump_kbnode( KBNODE node )
node->pkt->pkt.signature->sig_class, node->pkt->pkt.signature->sig_class,
(ulong)node->pkt->pkt.signature->keyid[1] ); (ulong)node->pkt->pkt.signature->keyid[1] );
} }
else if( node->pkt->pkttype == PKT_GPG_CONTROL ) {
fprintf(stderr, " ctrl=%d len=%u\n",
node->pkt->pkt.gpg_control->control,
(unsigned int)node->pkt->pkt.gpg_control->datalen);
}
else if( node->pkt->pkttype == PKT_PUBLIC_KEY else if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
fprintf(stderr, " keyid=%08lX\n", (ulong) fprintf(stderr, " keyid=%08lX\n", (ulong)
@ -379,4 +385,3 @@ dump_kbnode( KBNODE node )
fputs("\n", stderr); fputs("\n", stderr);
} }
} }

View File

@ -143,8 +143,6 @@ add_gpg_control( CTX c, PACKET *pkt )
} }
else if ( pkt->pkt.gpg_control->control == CTRLPKT_PIPEMODE ) { else if ( pkt->pkt.gpg_control->control == CTRLPKT_PIPEMODE ) {
/* Pipemode control packet */ /* Pipemode control packet */
#warning the --pipemode does not yet work
/* FIXME: We have to do more sanity checks all over the place */
if ( pkt->pkt.gpg_control->datalen < 2 ) if ( pkt->pkt.gpg_control->datalen < 2 )
log_fatal ("invalid pipemode control packet length\n"); log_fatal ("invalid pipemode control packet length\n");
if (pkt->pkt.gpg_control->data[0] == 1) { if (pkt->pkt.gpg_control->data[0] == 1) {
@ -522,16 +520,29 @@ proc_plaintext( CTX c, PACKET *pkt )
if ( c->mfx.md2 ) if ( c->mfx.md2 )
md_start_debug( c->mfx.md2, "verify2" ); md_start_debug( c->mfx.md2, "verify2" );
} }
rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig ); if ( c->pipemode.op == 'B' )
if( rc == G10ERR_CREATE_FILE && !c->sigs_only) { rc = handle_plaintext( pt, &c->mfx, 1, 0 );
/* can't write output but we hash it anyway to else {
* check the signature */ rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig );
rc = handle_plaintext( pt, &c->mfx, 1, clearsig ); if( rc == G10ERR_CREATE_FILE && !c->sigs_only) {
/* can't write output but we hash it anyway to
* check the signature */
rc = handle_plaintext( pt, &c->mfx, 1, clearsig );
}
} }
if( rc ) if( rc )
log_error( "handle plaintext failed: %s\n", g10_errstr(rc)); log_error( "handle plaintext failed: %s\n", g10_errstr(rc));
free_packet(pkt); free_packet(pkt);
c->last_was_session_key = 0; c->last_was_session_key = 0;
/* We add a marker control packet instead of the plaintext packet.
* This is so that we can later detect invalid packet sequences.
*/
n = new_kbnode (create_gpg_control (CTRLPKT_PLAINTEXT_MARK, NULL, 0));
if (c->list)
add_kbnode (c->list, n);
else
c->list = n;
} }
@ -1193,22 +1204,48 @@ check_sig_and_print( CTX c, KBNODE node )
* data+sig, sig+data,sig+data and we have not yet encountered the last * data+sig, sig+data,sig+data and we have not yet encountered the last
* data, we could also see this a one data with 2 signatures and then * data, we could also see this a one data with 2 signatures and then
* data+sig. * data+sig.
* To protect against this we check that we all signatures follow * To protect against this we check that all signatures follow
* without any intermediate packets. Note, that we won't get this * without any intermediate packets. Note, that we won't get this
* error when we use onepass packets or cleartext signatures because * error when we use onepass packets or cleartext signatures because
* we reset the list every time * we reset the list every time
*
* FIXME: Now that we have these marker packets, we should create a
* real grammar and check against this.
*/ */
{ {
KBNODE n; KBNODE n;
int tmp=0; int n_sig=0;
for(n=c->list; n; n=n->next ) { for (n=c->list; n; n=n->next ) {
if ( tmp && n->pkt->pkttype == PKT_SIGNATURE ) { if ( n->pkt->pkttype == PKT_SIGNATURE )
log_error("can't handle these multiple signatures\n"); n_sig++;
return 0; }
if (n_sig > 1) { /* more than one signature - check sequence */
int tmp, onepass;
for (tmp=onepass=0,n=c->list; n; n=n->next ) {
if (n->pkt->pkttype == PKT_ONEPASS_SIG)
onepass++;
else if (n->pkt->pkttype == PKT_GPG_CONTROL
&& n->pkt->pkt.gpg_control->control
== CTRLPKT_CLEARSIGN_START ) {
onepass++; /* handle the same way as a onepass */
}
else if ( (tmp && n->pkt->pkttype != PKT_SIGNATURE) ) {
log_error(_("can't handle these multiple signatures\n"));
return 0;
}
else if ( n->pkt->pkttype == PKT_SIGNATURE )
tmp = 1;
else if (!tmp && !onepass
&& n->pkt->pkttype == PKT_GPG_CONTROL
&& n->pkt->pkt.gpg_control->control
== CTRLPKT_PLAINTEXT_MARK ) {
/* plaintext before signatures but no one-pass packets*/
log_error(_("can't handle these multiple signatures\n"));
return 0;
}
} }
else if ( n->pkt->pkttype == PKT_SIGNATURE )
tmp = 1;
} }
} }
@ -1336,6 +1373,18 @@ proc_tree( CTX c, KBNODE node )
if( opt.list_packets || opt.list_only ) if( opt.list_packets || opt.list_only )
return; return;
/* we must skip our special plaintext marker packets here becuase
they may be the root packet. These packets are only used in
addionla checks and skipping them here doesn't matter */
while ( node
&& node->pkt->pkttype == PKT_GPG_CONTROL
&& node->pkt->pkt.gpg_control->control
== CTRLPKT_PLAINTEXT_MARK ) {
node = node->next;
}
if (!node)
return;
c->local_id = 0; c->local_id = 0;
c->trustletter = ' '; c->trustletter = ' ';
if( node->pkt->pkttype == PKT_PUBLIC_KEY if( node->pkt->pkttype == PKT_PUBLIC_KEY
@ -1456,14 +1505,19 @@ proc_tree( CTX c, KBNODE node )
log_error (_("not a detached signature\n") ); log_error (_("not a detached signature\n") );
return; return;
} }
else else if ( c->pipemode.op == 'B' )
; /* this is a detached signature trough the pipemode handler */
else
log_info(_("old style (PGP 2.x) signature\n")); log_info(_("old style (PGP 2.x) signature\n"));
check_sig_and_print( c, node ); for( n1 = node; n1; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )) )
check_sig_and_print( c, n1 );
} }
else else {
dump_kbnode (c->list);
log_error(_("invalid root packet detected in proc_tree()\n")); log_error(_("invalid root packet detected in proc_tree()\n"));
dump_kbnode (node);
}
} }

View File

@ -58,7 +58,8 @@ typedef struct packet_struct PACKET;
/* PKT_GPG_CONTROL types */ /* PKT_GPG_CONTROL types */
typedef enum { typedef enum {
CTRLPKT_CLEARSIGN_START = 1, CTRLPKT_CLEARSIGN_START = 1,
CTRLPKT_PIPEMODE = 2 CTRLPKT_PIPEMODE = 2,
CTRLPKT_PLAINTEXT_MARK =3
} ctrlpkttype_t; } ctrlpkttype_t;
@ -199,6 +200,7 @@ typedef struct {
typedef struct { typedef struct {
u32 len; /* length of encrypted data */ u32 len; /* length of encrypted data */
int extralen; /* this is (blocksize+2) */
byte new_ctb; /* uses a new CTB */ byte new_ctb; /* uses a new CTB */
byte mdc_method; /* > 0: integrity protected encrypted data packet */ byte mdc_method; /* > 0: integrity protected encrypted data packet */
IOBUF buf; /* IOBUF reference */ IOBUF buf; /* IOBUF reference */
@ -331,6 +333,8 @@ const byte *parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype,
size_t *ret_n ); size_t *ret_n );
const byte *parse_sig_subpkt2( PKT_signature *sig, const byte *parse_sig_subpkt2( PKT_signature *sig,
sigsubpkttype_t reqtype, size_t *ret_n ); sigsubpkttype_t reqtype, size_t *ret_n );
PACKET *create_gpg_control ( ctrlpkttype_t type,
const byte *data, size_t datalen );
/*-- build-packet.c --*/ /*-- build-packet.c --*/
int build_packet( IOBUF inp, PACKET *pkt ); int build_packet( IOBUF inp, PACKET *pkt );

View File

@ -1766,6 +1766,12 @@ parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
ed = pkt->pkt.encrypted = m_alloc(sizeof *pkt->pkt.encrypted ); ed = pkt->pkt.encrypted = m_alloc(sizeof *pkt->pkt.encrypted );
ed->len = pktlen; ed->len = pktlen;
/* we don't know the extralen which is (cipher_blocksize+2)
because the algorithm ist not specified in this packet.
However, it is only important to know this for somesanity
checks on the pkacet length - it doesn't matter that we can't
do it */
ed->extralen = 0;
ed->buf = NULL; ed->buf = NULL;
ed->new_ctb = new_ctb; ed->new_ctb = new_ctb;
ed->mdc_method = 0; ed->mdc_method = 0;
@ -1894,4 +1900,25 @@ parse_gpg_control( IOBUF inp,
return G10ERR_INVALID_PACKET; return G10ERR_INVALID_PACKET;
} }
/* create a gpg control packet to be used internally as a placeholder */
PACKET *
create_gpg_control( ctrlpkttype_t type, const byte *data, size_t datalen )
{
PACKET *packet;
byte *p;
packet = m_alloc( sizeof *packet );
init_packet(packet);
packet->pkttype = PKT_GPG_CONTROL;
packet->pkt.gpg_control = m_alloc(sizeof *packet->pkt.gpg_control
+ datalen - 1);
packet->pkt.gpg_control->control = type;
packet->pkt.gpg_control->datalen = datalen;
p = packet->pkt.gpg_control->data;
for( ; datalen; datalen--, p++ )
*p = *data++;
return packet;
}

View File

@ -40,22 +40,24 @@
#define CONTROL_PACKET_SPACE 30 #define CONTROL_PACKET_SPACE 30
#define FAKED_LITERAL_PACKET_SPACE (9+2+2) #define FAKED_LITERAL_PACKET_SPACE (9+2+2)
enum pipemode_state_e { enum pipemode_state_e {
STX_init = 0, STX_init = 0,
STX_wait_operation, STX_wait_operation,
STX_begin, STX_begin,
STX_text, STX_text,
STX_detached_signature, STX_detached_signature,
STX_detached_signature_wait_text,
STX_signed_data, STX_signed_data,
STX_wait_init STX_wait_init
}; };
struct pipemode_context_s { struct pipemode_context_s {
enum pipemode_state_e state; enum pipemode_state_e state;
int operation; int operation;
int stop; int stop;
int block_mode; int block_mode;
UnarmorPump unarmor_ctx;
}; };
@ -80,6 +82,7 @@ make_control ( byte *buf, int code, int operation )
} }
static int static int
pipemode_filter( void *opaque, int control, pipemode_filter( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len) IOBUF a, byte *buf, size_t *ret_len)
@ -126,6 +129,14 @@ pipemode_filter( void *opaque, int control,
buf[n++] = c; buf[n++] = c;
break; break;
} }
else if ( stx->state == STX_detached_signature ) {
esc = 0;
goto do_unarmor; /* not a very elegant solution */
}
else if ( stx->state == STX_detached_signature_wait_text) {
esc = 0;
break; /* just ignore it in this state */
}
log_error ("@@ not allowed in current state\n"); log_error ("@@ not allowed in current state\n");
return -1; return -1;
case '<': /* begin of stream part */ case '<': /* begin of stream part */
@ -136,6 +147,8 @@ pipemode_filter( void *opaque, int control,
} }
stx->state = STX_wait_operation; stx->state = STX_wait_operation;
stx->block_mode = 0; stx->block_mode = 0;
unarmor_pump_release (stx->unarmor_ctx);
stx->unarmor_ctx = NULL;
break; break;
case '>': /* end of stream part */ case '>': /* end of stream part */
if ( stx->state != STX_wait_init ) { if ( stx->state != STX_wait_init ) {
@ -157,13 +170,20 @@ pipemode_filter( void *opaque, int control,
return -1; return -1;
} }
stx->operation = c; stx->operation = c;
stx->state = c == 'B'? STX_detached_signature if ( stx->operation == 'B') {
: STX_begin; stx->state = STX_detached_signature;
if ( !opt.no_armor )
stx->unarmor_ctx = unarmor_pump_new ();
}
else
stx->state = STX_begin;
n += make_control ( buf+n, 1, stx->operation ); n += make_control ( buf+n, 1, stx->operation );
/* must leave after a control packet */ /* must leave after a control packet */
goto leave; goto leave;
case 't': /* plaintext text follows */ case 't': /* plaintext text follows */
if ( stx->state == STX_detached_signature_wait_text )
stx->state = STX_detached_signature;
if ( stx->state == STX_detached_signature ) { if ( stx->state == STX_detached_signature ) {
if ( stx->operation != 'B' ) { if ( stx->operation != 'B' ) {
log_error ("invalid operation for this state\n"); log_error ("invalid operation for this state\n");
@ -227,8 +247,24 @@ pipemode_filter( void *opaque, int control,
} }
else if (c == '@') else if (c == '@')
esc = 1; esc = 1;
else if (stx->unarmor_ctx) {
do_unarmor: /* used to handle a @@ */
c = unarmor_pump (stx->unarmor_ctx, c);
if ( !(c & ~255) )
buf[n++] = c;
else if ( c < 0 ) {
/* end of armor or error - we don't care becuase
the armor can be modified anyway. The unarmored
stuff should stand for itself. */
unarmor_pump_release (stx->unarmor_ctx);
stx->unarmor_ctx = NULL;
stx->state = STX_detached_signature_wait_text;
}
}
else if (stx->state == STX_detached_signature_wait_text)
; /* just wait */
else else
buf[n++] = c; buf[n++] = c;
} }
leave: leave:
@ -242,7 +278,7 @@ pipemode_filter( void *opaque, int control,
buf[1] = (n-2); buf[1] = (n-2);
} }
leave2: leave2:
log_hexdump ("pipemode:", buf, n ); /*log_hexdump ("pipemode:", buf, n );*/
*ret_len = n; *ret_len = n;
} }
else if( control == IOBUFCTRL_DESC ) else if( control == IOBUFCTRL_DESC )
@ -263,12 +299,6 @@ run_in_pipemode(void)
memset( &afx, 0, sizeof afx); memset( &afx, 0, sizeof afx);
memset( &stx, 0, sizeof stx); memset( &stx, 0, sizeof stx);
/* FIXME: We have to handle de-armoring somehow. We can't rely on
* the standard armor filter becuase it checks only once whether armoring
* is required and it would try to unarmor everything which is not good.
* So, currently only non-armored detached signatures do work.
*/
fp = iobuf_open("-"); fp = iobuf_open("-");
iobuf_push_filter (fp, pipemode_filter, &stx ); iobuf_push_filter (fp, pipemode_filter, &stx );

View File

@ -5,9 +5,8 @@
2001-03-18 Werner Koch <wk@gnupg.org> 2001-03-18 Werner Koch <wk@gnupg.org>
* config.links (mpi_sflags): Use i386 code for i386. According to * config.links: Use i386 code for i386. According to tests by
tests by Kevin Ryde the i586 code runs slow on i386 CPUs. Ditto Kevin Ryde the i586 code runs slow on i386 CPUs. Ditto for i786.
for i786.
2000-10-24 Werner Koch <wk@gnupg.org> 2000-10-24 Werner Koch <wk@gnupg.org>