aboutsummaryrefslogtreecommitdiffstats
path: root/g10/pipemode.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/pipemode.c')
-rw-r--r--g10/pipemode.c98
1 files changed, 77 insertions, 21 deletions
diff --git a/g10/pipemode.c b/g10/pipemode.c
index 4d9f0a31a..986ea8596 100644
--- a/g10/pipemode.c
+++ b/g10/pipemode.c
@@ -38,12 +38,15 @@
#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_signed_data,
STX_wait_init
};
@@ -52,6 +55,7 @@ struct pipemode_context_s {
enum pipemode_state_e state;
int operation;
int stop;
+ int block_mode;
};
@@ -89,12 +93,23 @@ pipemode_filter( void *opaque, int control,
if( control == IOBUFCTRL_UNDERFLOW ) {
*ret_len = 0;
/* reserve some space for one control packet */
- if ( size <= CONTROL_PACKET_SPACE )
+ if ( size <= CONTROL_PACKET_SPACE+FAKED_LITERAL_PACKET_SPACE )
BUG();
- size -= CONTROL_PACKET_SPACE;
+ size -= CONTROL_PACKET_SPACE+FAKED_LITERAL_PACKET_SPACE;
+ if ( stx->block_mode ) {
+ /* reserve 2 bytes for the block length */
+ buf[n++] = 0;
+ buf[n++] = 0;
+ }
+
while ( n < size ) {
+ /* FIXME: we have to make sure that we have a large enough
+ * buffer for a control packet even after we already read
+ * something. The easest way to do this is probably by ungetting
+ * the control sequenceand and returning the buffer we have
+ * already assembled */
int c = iobuf_get (a);
if (c == -1) {
if ( stx->state != STX_init ) {
@@ -120,6 +135,7 @@ pipemode_filter( void *opaque, int control,
return -1;
}
stx->state = STX_wait_operation;
+ stx->block_mode = 0;
break;
case '>': /* end of stream part */
if ( stx->state != STX_wait_init ) {
@@ -141,35 +157,64 @@ pipemode_filter( void *opaque, int control,
return -1;
}
stx->operation = c;
- stx->state = STX_begin;
- n += make_control ( buf, 1, stx->operation );
+ stx->state = c == 'B'? STX_detached_signature
+ : 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_begin ) {
- log_error ("invalid state for @t\n");
- stx->stop = 1;
- return -1;
+ if ( stx->state == STX_detached_signature ) {
+ if ( stx->operation != 'B' ) {
+ log_error ("invalid operation for this state\n");
+ stx->stop = 1;
+ return -1;
+ }
+ stx->state = STX_signed_data;
+ n += make_control ( buf+n, 2, 'B' );
+ /* and now we fake a literal data packet much the same
+ * as in armor.c */
+ buf[n++] = 0xaf; /* old packet format, type 11,
+ var length */
+ buf[n++] = 0; /* set the length header */
+ buf[n++] = 6;
+ buf[n++] = 'b'; /* we ignore it anyway */
+ buf[n++] = 0; /* namelength */
+ memset(buf+n, 0, 4); /* timestamp */
+ n += 4;
+ /* and return now so that we are sure to have
+ * more space in the bufer for the next control
+ * packet */
+ stx->block_mode = 1;
+ goto leave2;
}
- if ( stx->operation != 'E' ) {
- log_error ("invalid operation for @t\n");
+ else {
+ log_error ("invalid state for @t\n");
stx->stop = 1;
return -1;
}
- stx->state = STX_text;
- n += make_control ( buf, 2, c );
- goto leave;
+ break;
case '.': /* ready */
- if ( stx->state == STX_text )
- ;
+ if ( stx->state == STX_signed_data ) {
+ if (stx->block_mode) {
+ buf[0] = (n-2) >> 8;
+ buf[1] = (n-2);
+ if ( buf[0] || buf[1] ) {
+ /* end of blocks marker */
+ buf[n++] = 0;
+ buf[n++] = 0;
+ }
+ stx->block_mode = 0;
+ }
+ n += make_control ( buf+n, 3, 'B' );
+ }
else {
log_error ("invalid state for @.\n");
stx->stop = 1;
return -1;
}
stx->state = STX_wait_init;
- n += make_control ( buf, 3, c );
goto leave;
default:
@@ -191,6 +236,13 @@ pipemode_filter( void *opaque, int control,
stx->stop = 1;
rc = -1; /* eof */
}
+ if ( stx->block_mode ) {
+ /* fixup the block length */
+ buf[0] = (n-2) >> 8;
+ buf[1] = (n-2);
+ }
+ leave2:
+ log_hexdump ("pipemode:", buf, n );
*ret_len = n;
}
else if( control == IOBUFCTRL_DESC )
@@ -211,16 +263,19 @@ 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 );
- if( !opt.no_armor )
- iobuf_push_filter( fp, armor_filter, &afx );
-
do {
- log_debug ("pipemode: begin proc_packets\n");
+ write_status (STATUS_BEGIN_STREAM);
rc = proc_packets( NULL, fp );
- log_debug ("pipemode: end proc_packets: %s\n", g10_errstr (rc));
+ write_status (STATUS_END_STREAM);
} while ( !stx.stop );
}
@@ -229,3 +284,4 @@ run_in_pipemode(void)
+