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
);