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:
parent
64f6858920
commit
c9e908e734
2
THANKS
2
THANKS
@ -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
3
TODO
@ -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
|
||||
-----------------
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
224
g10/armor.c
224
g10/armor.c
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
15
g10/getkey.c
15
g10/getkey.c
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 );
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user