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