aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2001-04-05 12:21:43 +0000
committerWerner Koch <[email protected]>2001-04-05 12:21:43 +0000
commitc9e908e734a553ee78a9cf95b8e1f015c75e215d (patch)
treed5e2bec7ca4a8031a111bc3de97c644a3591ab55
parentwhy no X509 (diff)
downloadgnupg-c9e908e734a553ee78a9cf95b8e1f015c75e215d.tar.gz
gnupg-c9e908e734a553ee78a9cf95b8e1f015c75e215d.zip
Improved pipemode and tweaked handling of multiple signatures.
-rw-r--r--THANKS2
-rw-r--r--TODO3
-rw-r--r--cipher/ChangeLog5
-rw-r--r--cipher/primegen.c5
-rw-r--r--doc/DETAILS4
-rw-r--r--g10/ChangeLog43
-rw-r--r--g10/armor.c224
-rw-r--r--g10/build-packet.c4
-rw-r--r--g10/cipher.c1
-rw-r--r--g10/filter.h6
-rw-r--r--g10/getkey.c15
-rw-r--r--g10/kbnode.c7
-rw-r--r--g10/mainproc.c92
-rw-r--r--g10/packet.h6
-rw-r--r--g10/parse-packet.c27
-rw-r--r--g10/pipemode.c52
-rw-r--r--mpi/ChangeLog5
17 files changed, 454 insertions, 47 deletions
diff --git a/THANKS b/THANKS
index 8e89aec60..6fd875f95 100644
--- a/THANKS
+++ b/THANKS
@@ -85,6 +85,7 @@ Johnny Teve�en [email protected]
J�rg Schilling [email protected]
Jos Backus [email protected]
Jun Kuriyama [email protected]
+Kahil D. Jallad [email protected]
Karl Fogel [email protected]
Karsten Thygesen [email protected]
Katsuhiro Kondou [email protected]
@@ -154,6 +155,7 @@ Timo Schulz [email protected]
Tom Spindler [email protected]
Tom Zerucha [email protected]
Tomas Fasth [email protected]
+Tommi Komulainen [email protected]
Thomas Klausner [email protected]
Tomasz Kozlowski [email protected]
Thomas Mikkelsen [email protected]
diff --git a/TODO b/TODO
index 7420e489d..f5dee0385 100644
--- a/TODO
+++ b/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
-----------------
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index 778517628..ede3b892b 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,8 @@
+2001-04-02 Werner Koch <[email protected]>
+
+ * 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 <[email protected]>
* md5.c (md5_final): Fixed calculation of hashed length. Thanks
diff --git a/cipher/primegen.c b/cipher/primegen.c
index b6c569de7..7eaf6641f 100644
--- a/cipher/primegen.c
+++ b/cipher/primegen.c
@@ -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;
}
diff --git a/doc/DETAILS b/doc/DETAILS
index 45a677410..4249d24a1 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -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
diff --git a/g10/ChangeLog b/g10/ChangeLog
index dedaf7e50..fd516b458 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,5 +1,48 @@
+2001-04-05 Werner Koch <[email protected]>
+
+ * 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 <[email protected]>
+
+ 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 <[email protected]>
+
+ * getkey.c (premerge_public_with_secret): Changed wording an add
+ the keyID to the info message.
+
2001-03-29 Werner Koch <[email protected]>
+ * 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.
diff --git a/g10/armor.c b/g10/armor.c
index e84fb3709..8ffa5e6ea 100644
--- a/g10/armor.c
+++ b/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;
+}
+
+
diff --git a/g10/build-packet.c b/g10/build-packet.c
index e48770e83..a0493efd2 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -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 */
diff --git a/g10/cipher.c b/g10/cipher.c
index 4def8fa24..6ad204cc4 100644
--- a/g10/cipher.c
+++ b/g10/cipher.c
@@ -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;
diff --git a/g10/filter.h b/g10/filter.h
index 16875a61c..2261a3cf2 100644
--- a/g10/filter.h
+++ b/g10/filter.h
@@ -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,
diff --git a/g10/getkey.c b/g10/getkey.c
index 09633c98a..975d567fe 100644
--- a/g10/getkey.c
+++ b/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 */
diff --git a/g10/kbnode.c b/g10/kbnode.c
index 7138eaaa5..261a2b4da 100644
--- a/g10/kbnode.c
+++ b/g10/kbnode.c
@@ -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);
}
}
-
diff --git a/g10/mainproc.c b/g10/mainproc.c
index 76e7f4167..bb0d922fb 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -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);
+ }
}
diff --git a/g10/packet.h b/g10/packet.h
index 7da7cb20c..9692d5a74 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -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 );
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 191c0f13e..0e24f6b7e 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -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;
+}
+
diff --git a/g10/pipemode.c b/g10/pipemode.c
index eb69995e3..f3351277e 100644
--- a/g10/pipemode.c
+++ b/g10/pipemode.c
@@ -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 );
diff --git a/mpi/ChangeLog b/mpi/ChangeLog
index a69de0cff..9fbb36ab0 100644
--- a/mpi/ChangeLog
+++ b/mpi/ChangeLog
@@ -5,9 +5,8 @@
2001-03-18 Werner Koch <[email protected]>
- * 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 <[email protected]>