1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-02-01 16:33:02 +01: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
Jos Backus Jos.Backus@nl.origin-it.com
Jun Kuriyama kuriyama@sky.rim.or.jp
Kahil D. Jallad kdj4@cs.columbia.edu
Karl Fogel kfogel@guanabana.onshore.com
Karsten Thygesen karthy@kom.auc.dk
Katsuhiro Kondou kondou@nec.co.jp
@ -154,6 +155,7 @@ Timo Schulz towaday@freakmail.de
Tom Spindler dogcow@home.merit.edu
Tom Zerucha tzeruch@ceddec.com
Tomas Fasth tomas.fasth@twinspot.net
Tommi Komulainen Tommi.Komulainen@iki.fi
Thomas Klausner wiz@danbala.ifoer.tuwien.ac.at
Tomasz Kozlowski tomek@rentec.com
Thomas Mikkelsen tbm@image.dk

3
TODO
View File

@ -29,7 +29,7 @@
will have commands --{add,remove}-trusted-key which keeps them in
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.
@ -43,7 +43,6 @@
* Add an is_valid flag to each user ID.
* Make --pipemode work.
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>
* 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;
qbits++;
progress('>');
mpi_free (q);
q = gen_prime( qbits, 0, 0 );
goto next_try;
}
@ -201,6 +202,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
count2 = 0;
qbits--;
progress('<');
mpi_free (q);
q = gen_prime( qbits, 0, 0 );
goto next_try;
}
@ -227,8 +229,8 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
if( ret_factors ) { /* caller wants the factors */
*ret_factors = m_alloc_clear( (n+2) * sizeof **ret_factors);
i = 0;
if( mode == 1 ) {
i = 0;
(*ret_factors)[i++] = mpi_copy( q_factor );
for(; i <= n; 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(perms);
mpi_free(val_2);
mpi_free(q);
return prime;
}

View File

@ -723,10 +723,10 @@ Here is the format we use for detached signatures:
"@<" - Begin of new stream
"@B" - Detached signature follows.
This emits a control packet (1,'B')
detached_signature
<detached_signature>
"@t" - Signed text follows.
This emits the control packet (2, 'B')
signed_text
<signed_text>
"@." - End of operation. The final control packet forces signature
verification
"@>" - 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>
* 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.
(open_outfile): Allow to enter an alternate filename. Thanks to
Stefan Bellon.

View File

@ -151,8 +151,9 @@ initialize(void)
}
/****************
* Check whether this is an armored file or not
* See also parse-packet.c for details on this code
* Check whether this is an armored file or not See also
* 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
*/
static int
@ -195,6 +196,7 @@ use_armor_filter( IOBUF a )
byte buf[1];
int n;
/* fixme: there might be a problem with iobuf_peek */
n = iobuf_peek(a, buf, 1 );
if( n == -1 )
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;
}
/***********************************************
* 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;
u32 n;
n = ed->len ? (ed->len + 10) : 0;
n = ed->len ? (ed->len + ed->extralen) : 0;
write_header(out, ctb, n );
/* 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 );
n = ed->len ? (ed->len + 10) : 0;
n = ed->len ? (ed->len + ed->extralen) : 0;
write_header(out, ctb, n );
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 );
ed.len = cfx->datalen;
ed.extralen = blocksize+2;
ed.new_ctb = !ed.len && !opt.rfc1991;
if( use_mdc ) {
ed.mdc_method = DIGEST_ALGO_SHA1;

View File

@ -64,6 +64,9 @@ typedef struct {
int pending_lf; /* used together with faked */
} armor_filter_context_t;
struct unarmor_pump_s;
typedef struct unarmor_pump_s *UnarmorPump;
typedef struct {
int status;
@ -113,6 +116,9 @@ void free_md_filter_context( md_filter_context_t *mfx );
int use_armor_filter( IOBUF a );
int armor_filter( void *opaque, int control,
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 --*/
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 ) {
if ( sec->pkt->pkttype == PKT_SECRET_SUBKEY ) {
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;
}
}
}
if ( !sec ) {
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 */
assert ( last );
/* find the next subkey */

View File

@ -355,6 +355,7 @@ dump_kbnode( KBNODE node )
case PKT_PLAINTEXT: s="plaintext"; break;
case PKT_COMPRESSED: s="compressed"; break;
case PKT_ENCRYPTED: s="encrypted"; break;
case PKT_GPG_CONTROL: s="gpg-control"; break;
default: s="unknown"; break;
}
fprintf(stderr, "node %p %02x/%02x type=%s",
@ -370,6 +371,11 @@ dump_kbnode( KBNODE node )
node->pkt->pkt.signature->sig_class,
(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
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
fprintf(stderr, " keyid=%08lX\n", (ulong)
@ -379,4 +385,3 @@ dump_kbnode( KBNODE node )
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 ) {
/* 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 )
log_fatal ("invalid pipemode control packet length\n");
if (pkt->pkt.gpg_control->data[0] == 1) {
@ -522,16 +520,29 @@ proc_plaintext( CTX c, PACKET *pkt )
if ( c->mfx.md2 )
md_start_debug( c->mfx.md2, "verify2" );
}
rc = handle_plaintext( pt, &c->mfx, c->sigs_only, 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 ( c->pipemode.op == 'B' )
rc = handle_plaintext( pt, &c->mfx, 1, 0 );
else {
rc = handle_plaintext( pt, &c->mfx, c->sigs_only, 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 )
log_error( "handle plaintext failed: %s\n", g10_errstr(rc));
free_packet(pkt);
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, we could also see this a one data with 2 signatures and then
* 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
* error when we use onepass packets or cleartext signatures because
* 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;
int tmp=0;
int n_sig=0;
for(n=c->list; n; n=n->next ) {
if ( tmp && n->pkt->pkttype == PKT_SIGNATURE ) {
log_error("can't handle these multiple signatures\n");
return 0;
for (n=c->list; n; n=n->next ) {
if ( n->pkt->pkttype == PKT_SIGNATURE )
n_sig++;
}
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 )
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->trustletter = ' ';
if( node->pkt->pkttype == PKT_PUBLIC_KEY
@ -1456,14 +1505,19 @@ proc_tree( CTX c, KBNODE node )
log_error (_("not a detached signature\n") );
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"));
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"));
dump_kbnode (node);
}
}

View File

@ -58,7 +58,8 @@ typedef struct packet_struct PACKET;
/* PKT_GPG_CONTROL types */
typedef enum {
CTRLPKT_CLEARSIGN_START = 1,
CTRLPKT_PIPEMODE = 2
CTRLPKT_PIPEMODE = 2,
CTRLPKT_PLAINTEXT_MARK =3
} ctrlpkttype_t;
@ -199,6 +200,7 @@ typedef struct {
typedef struct {
u32 len; /* length of encrypted data */
int extralen; /* this is (blocksize+2) */
byte new_ctb; /* uses a new CTB */
byte mdc_method; /* > 0: integrity protected encrypted data packet */
IOBUF buf; /* IOBUF reference */
@ -331,6 +333,8 @@ const byte *parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype,
size_t *ret_n );
const byte *parse_sig_subpkt2( PKT_signature *sig,
sigsubpkttype_t reqtype, size_t *ret_n );
PACKET *create_gpg_control ( ctrlpkttype_t type,
const byte *data, size_t datalen );
/*-- build-packet.c --*/
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->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->new_ctb = new_ctb;
ed->mdc_method = 0;
@ -1894,4 +1900,25 @@ parse_gpg_control( IOBUF inp,
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 FAKED_LITERAL_PACKET_SPACE (9+2+2)
enum pipemode_state_e {
STX_init = 0,
STX_wait_operation,
STX_begin,
STX_text,
STX_detached_signature,
STX_detached_signature_wait_text,
STX_signed_data,
STX_wait_init
};
struct pipemode_context_s {
enum pipemode_state_e state;
int operation;
int stop;
int block_mode;
UnarmorPump unarmor_ctx;
};
@ -80,6 +82,7 @@ make_control ( byte *buf, int code, int operation )
}
static int
pipemode_filter( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len)
@ -126,6 +129,14 @@ pipemode_filter( void *opaque, int control,
buf[n++] = c;
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");
return -1;
case '<': /* begin of stream part */
@ -136,6 +147,8 @@ pipemode_filter( void *opaque, int control,
}
stx->state = STX_wait_operation;
stx->block_mode = 0;
unarmor_pump_release (stx->unarmor_ctx);
stx->unarmor_ctx = NULL;
break;
case '>': /* end of stream part */
if ( stx->state != STX_wait_init ) {
@ -157,13 +170,20 @@ pipemode_filter( void *opaque, int control,
return -1;
}
stx->operation = c;
stx->state = c == 'B'? STX_detached_signature
: STX_begin;
if ( stx->operation == 'B') {
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 );
/* must leave after a control packet */
goto leave;
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->operation != 'B' ) {
log_error ("invalid operation for this state\n");
@ -227,8 +247,24 @@ pipemode_filter( void *opaque, int control,
}
else if (c == '@')
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
buf[n++] = c;
buf[n++] = c;
}
leave:
@ -242,7 +278,7 @@ pipemode_filter( void *opaque, int control,
buf[1] = (n-2);
}
leave2:
log_hexdump ("pipemode:", buf, n );
/*log_hexdump ("pipemode:", buf, n );*/
*ret_len = n;
}
else if( control == IOBUFCTRL_DESC )
@ -263,12 +299,6 @@ run_in_pipemode(void)
memset( &afx, 0, sizeof afx);
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("-");
iobuf_push_filter (fp, pipemode_filter, &stx );

View File

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