1
/* pipemode.c - pipemode handler
2
* Copyright (C) 1998, 1990, 2000, 2001 Free Software Foundation, Inc.
4
* This file is part of GnuPG.
6
* GnuPG is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* GnuPG is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
40
#define CONTROL_PACKET_SPACE 30
41
#define FAKED_LITERAL_PACKET_SPACE (9+2+2)
44
enum pipemode_state_e {
49
STX_detached_signature,
50
STX_detached_signature_wait_text,
55
struct pipemode_context_s {
56
enum pipemode_state_e state;
60
UnarmorPump unarmor_ctx;
65
make_control ( byte *buf, int code, int operation )
68
size_t sesmarklen, n=0;;
70
sesmark = get_session_marker( &sesmarklen );
71
if ( sesmarklen > 20 )
74
buf[n++] = 0xff; /* new format, type 63, 1 length byte */
75
n++; /* length will fixed below */
76
memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
77
buf[n++] = CTRLPKT_PIPEMODE;
87
pipemode_filter( void *opaque, int control,
88
iobuf_t a, byte *buf, size_t *ret_len)
90
size_t size = *ret_len;
91
struct pipemode_context_s *stx = opaque;
96
if( control == IOBUFCTRL_UNDERFLOW ) {
98
/* reserve some space for one control packet */
99
if ( size <= CONTROL_PACKET_SPACE+FAKED_LITERAL_PACKET_SPACE )
101
size -= CONTROL_PACKET_SPACE+FAKED_LITERAL_PACKET_SPACE;
103
if ( stx->block_mode ) {
104
/* reserve 2 bytes for the block length */
111
/* FIXME: we have to make sure that we have a large enough
112
* buffer for a control packet even after we already read
113
* something. The easest way to do this is probably by ungetting
114
* the control sequence and returning the buffer we have
115
* already assembled */
116
int c = iobuf_get (a);
118
if ( stx->state != STX_init ) {
119
log_error ("EOF encountered at wrong state\n");
128
if ( stx->state == STX_text ) {
132
else if ( stx->state == STX_detached_signature ) {
134
goto do_unarmor; /* not a very elegant solution */
136
else if ( stx->state == STX_detached_signature_wait_text) {
138
break; /* just ignore it in this state */
140
log_error ("@@ not allowed in current state\n");
142
case '<': /* begin of stream part */
143
if ( stx->state != STX_init ) {
144
log_error ("nested begin of stream\n");
148
stx->state = STX_wait_operation;
150
unarmor_pump_release (stx->unarmor_ctx);
151
stx->unarmor_ctx = NULL;
153
case '>': /* end of stream part */
154
if ( stx->state != STX_wait_init ) {
155
log_error ("invalid state for @>\n");
159
stx->state = STX_init;
161
case 'V': /* operation = verify */
162
case 'E': /* operation = encrypt */
163
case 'S': /* operation = sign */
164
case 'B': /* operation = detach sign */
165
case 'C': /* operation = clearsign */
166
case 'D': /* operation = decrypt */
167
if ( stx->state != STX_wait_operation ) {
168
log_error ("invalid state for operation code\n");
173
if ( stx->operation == 'B') {
174
stx->state = STX_detached_signature;
176
stx->unarmor_ctx = unarmor_pump_new ();
179
stx->state = STX_begin;
180
n += make_control ( buf+n, 1, stx->operation );
181
/* must leave after a control packet */
184
case 't': /* plaintext text follows */
185
if ( stx->state == STX_detached_signature_wait_text )
186
stx->state = STX_detached_signature;
187
if ( stx->state == STX_detached_signature ) {
188
if ( stx->operation != 'B' ) {
189
log_error ("invalid operation for this state\n");
193
stx->state = STX_signed_data;
194
n += make_control ( buf+n, 2, 'B' );
195
/* and now we fake a literal data packet much the same
197
buf[n++] = 0xaf; /* old packet format, type 11,
199
buf[n++] = 0; /* set the length header */
201
buf[n++] = 'b'; /* we ignore it anyway */
202
buf[n++] = 0; /* namelength */
203
memset(buf+n, 0, 4); /* timestamp */
205
/* and return now so that we are sure to have
206
* more space in the bufer for the next control
212
log_error ("invalid state for @t\n");
218
case '.': /* ready */
219
if ( stx->state == STX_signed_data ) {
220
if (stx->block_mode) {
223
if ( buf[0] || buf[1] ) {
224
/* end of blocks marker */
230
n += make_control ( buf+n, 3, 'B' );
233
log_error ("invalid state for @.\n");
237
stx->state = STX_wait_init;
241
log_error ("invalid escape sequence 0x%02x in stream\n",
250
else if (stx->unarmor_ctx) {
251
do_unarmor: /* used to handle a @@ */
252
c = unarmor_pump (stx->unarmor_ctx, c);
256
/* end of armor or error - we don't care becuase
257
the armor can be modified anyway. The unarmored
258
stuff should stand for itself. */
259
unarmor_pump_release (stx->unarmor_ctx);
260
stx->unarmor_ctx = NULL;
261
stx->state = STX_detached_signature_wait_text;
264
else if (stx->state == STX_detached_signature_wait_text)
275
if ( stx->block_mode ) {
276
/* fixup the block length */
281
/*log_hexdump ("pipemode:", buf, n );*/
284
else if( control == IOBUFCTRL_DESC )
285
*(char**)buf = "pipemode_filter";
292
run_in_pipemode(void)
295
armor_filter_context_t afx;
296
struct pipemode_context_s stx;
299
memset( &afx, 0, sizeof afx);
300
memset( &stx, 0, sizeof stx);
302
fp = iobuf_open("-");
303
iobuf_push_filter (fp, pipemode_filter, &stx );
306
write_status (STATUS_BEGIN_STREAM);
307
rc = proc_packets( NULL, fp );
308
write_status (STATUS_END_STREAM);
309
} while ( !stx.stop );