See ChangeLog: Fri Feb 19 15:49:15 CET 1999 Werner Koch
[gnupg.git] / g10 / armor.c
1 /* armor.c - Armor flter
2  *      Copyright (C) 1998, 1999 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <ctype.h>
28
29 #include "errors.h"
30 #include "iobuf.h"
31 #include "memory.h"
32 #include "util.h"
33 #include "iobuf.h"
34 #include "filter.h"
35 #include "packet.h"
36 #include "options.h"
37 #include "main.h"
38 #include "status.h"
39 #include "i18n.h"
40
41
42 #define MAX_LINELEN 20000
43
44 #define CRCINIT 0xB704CE
45 #define CRCPOLY 0X864CFB
46 #define CRCUPDATE(a,c) do {                                                 \
47                         a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \
48                         a &= 0x00ffffff;                                    \
49                     } while(0)
50 static u32 crc_table[256];
51 static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
52                          "abcdefghijklmnopqrstuvwxyz"
53                          "0123456789+/";
54 static byte asctobin[256]; /* runtime initialized */
55 static int is_initialized;
56
57
58 typedef enum {
59     fhdrHASArmor = 0,
60     fhdrNOArmor,
61     fhdrINIT,
62     fhdrINITCont,
63     fhdrINITSkip,
64     fhdrCHECKBegin,
65     fhdrWAITHeader,
66     fhdrWAITClearsig,
67     fhdrSKIPHeader,
68     fhdrCLEARSIG,
69     fhdrREADClearsig,
70     fhdrNullClearsig,
71     fhdrEMPTYClearsig,
72     fhdrCHECKClearsig,
73     fhdrCHECKClearsig2,
74     fhdrCHECKDashEscaped,
75     fhdrCHECKDashEscaped2,
76     fhdrCHECKDashEscaped3,
77     fhdrREADClearsigNext,
78     fhdrENDClearsig,
79     fhdrENDClearsigHelp,
80     fhdrTESTSpaces,
81     fhdrCLEARSIGSimple,
82     fhdrCLEARSIGSimpleNext,
83     fhdrTEXT,
84     fhdrTEXTSimple,
85     fhdrERROR,
86     fhdrERRORShow,
87     fhdrEOF
88 } fhdr_state_t;
89
90
91 /* if we encounter this armor string with this index, go
92  * into a mode which fakes packets and wait for the next armor */
93 #define BEGIN_SIGNATURE 2
94 #define BEGIN_SIGNED_MSG_IDX 3
95 static char *head_strings[] = {
96     "BEGIN PGP MESSAGE",
97     "BEGIN PGP PUBLIC KEY BLOCK",
98     "BEGIN PGP SIGNATURE",
99     "BEGIN PGP SIGNED MESSAGE",
100     "BEGIN PGP ARMORED FILE",       /* gnupg extension */
101     "BEGIN PGP PRIVATE KEY BLOCK",
102     "BEGIN PGP SECRET KEY BLOCK",   /* only used by pgp2 */
103     NULL
104 };
105 static char *tail_strings[] = {
106     "END PGP MESSAGE",
107     "END PGP PUBLIC KEY BLOCK",
108     "END PGP SIGNATURE",
109     "END dummy",
110     "END PGP ARMORED FILE",
111     "END PGP PRIVATE KEY BLOCK",
112     "END PGP SECRET KEY BLOCK",
113     NULL
114 };
115
116
117
118 static void
119 initialize(void)
120 {
121     int i, j;
122     u32 t;
123     byte *s;
124
125     /* init the crc lookup table */
126     crc_table[0] = 0;
127     for(i=j=0; j < 128; j++ ) {
128         t = crc_table[j];
129         if( t & 0x00800000 ) {
130             t <<= 1;
131             crc_table[i++] = t ^ CRCPOLY;
132             crc_table[i++] = t;
133         }
134         else {
135             t <<= 1;
136             crc_table[i++] = t;
137             crc_table[i++] = t ^ CRCPOLY;
138         }
139     }
140     /* build the helptable for radix64 to bin conversion */
141     for(i=0; i < 256; i++ )
142         asctobin[i] = 255; /* used to detect invalid characters */
143     for(s=bintoasc,i=0; *s; s++,i++ )
144         asctobin[*s] = i;
145
146     is_initialized=1;
147 }
148
149 /****************
150  * Check whether this is an armored file or not
151  * See also parse-packet.c for details on this code
152  * Returns: True if it seems to be armored
153  */
154 static int
155 is_armored( const byte *buf )
156 {
157     int ctb, pkttype;
158
159     ctb = *buf;
160     if( !(ctb & 0x80) )
161         return 1; /* invalid packet: assume it is armored */
162     pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
163     switch( pkttype ) {
164       case PKT_MARKER:
165       case PKT_SYMKEY_ENC:
166       case PKT_PUBLIC_KEY:
167       case PKT_SECRET_KEY:
168       case PKT_PUBKEY_ENC:
169       case PKT_SIGNATURE:
170       case PKT_COMMENT:
171       case PKT_OLD_COMMENT:
172       case PKT_PLAINTEXT:
173       case PKT_COMPRESSED:
174       case PKT_ENCRYPTED:
175         return 0; /* seems to be a regular packet: not armored */
176     }
177
178     return 1;
179 }
180
181
182 /****************
183  * Try to check whether the iobuf is armored
184  * Returns true if this may be the case; the caller should use the
185  *         filter to do further processing.
186  */
187 int
188 use_armor_filter( IOBUF a )
189 {
190     byte buf[1];
191     int n;
192
193     n = iobuf_peek(a, buf, 1 );
194     if( n == -1 )
195         return 0; /* EOF, doesn't matter whether armored or not */
196     if( !n )
197         return 1; /* can't check it: try armored */
198     return is_armored(buf);
199 }
200
201
202
203
204 static void
205 invalid_armor(void)
206 {
207     write_status(STATUS_BADARMOR);
208     g10_exit(1); /* stop here */
209 }
210
211
212 /****************
213  * check whether the armor header is valid on a signed message.
214  * this is for security reasons: the header lines are not included in the
215  * hash and by using some creative formatting rules, Mallory could fake
216  * any text at the beginning of a document; assuming it is read with
217  * a simple viewer. We only allow the Hash Header.
218  */
219 static int
220 parse_hash_header( const char *line )
221 {
222     const char *s, *s2;
223     unsigned found = 0;
224
225     if( strlen(line) < 6  || strlen(line) > 60 )
226         return 0; /* too short or too long */
227     if( memcmp( line, "Hash:", 5 ) )
228         return 0; /* invalid header */
229     s = line+5;
230     for(s=line+5;;s=s2) {
231         for(; *s && (*s==' ' || *s == '\t'); s++ )
232             ;
233         if( !*s )
234             break;
235         for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ )
236             ;
237         if( !strncmp( s, "RIPEMD160", s2-s ) )
238             found |= 1;
239         else if( !strncmp( s, "SHA1", s2-s ) )
240             found |= 2;
241         else if( !strncmp( s, "MD5", s2-s ) )
242             found |= 4;
243         else if( !strncmp( s, "TIGER", s2-s ) )
244             found |= 8;
245         else
246             return 0;
247         for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ )
248             ;
249         if( *s2 && *s2 != ',' )
250             return 0;
251         if( *s2 )
252             s2++;
253     }
254     return found;
255 }
256
257
258
259 /****************
260  * Check whether this is a armor line.
261  * returns: -1 if it is not a armor header or the index number of the
262  * armor header.
263  */
264 static int
265 is_armor_header( byte *line, unsigned len )
266 {
267     const char *s;
268     byte *save_p, *p;
269     int save_c;
270     int i;
271
272     if( len < 15 )
273         return -1; /* too short */
274     if( memcmp( line, "-----", 5 ) )
275         return -1; /* no */
276     p = strstr( line+5, "-----");
277     if( !p )
278         return -1;
279     save_p = p;
280     p += 5;
281     if( *p == '\r' )
282         p++;
283     if( *p == '\n' )
284         p++;
285     if( *p )
286         return -1; /* garbage after dashes */
287     save_c = *save_p; *save_p = 0;
288     p = line+5;
289     for(i=0; (s=head_strings[i]); i++ )
290         if( !strcmp(s, p) )
291             break;
292     *save_p = save_c;
293     if( !s )
294         return -1; /* unknown armor line */
295
296     if( opt.verbose > 1 )
297         log_info(_("armor: %s\n"), head_strings[i]);
298     return i;
299 }
300
301
302
303 /****************
304  * Parse a header lines
305  * Return 0: Empty line (end of header lines)
306  *       -1: invalid header line
307  *       >0: Good header line
308  */
309 static int
310 parse_header_line( armor_filter_context_t *afx, byte *line, unsigned len )
311 {
312     byte *p;
313     int hashes=0;
314
315     if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
316         return 0; /* empty line */
317     len = trim_trailing_ws( line, len );
318     p = strchr( line, ':');
319     if( !p || !p[1] ) {
320         log_error(_("invalid armor header: "));
321         print_string( stderr, line, len, 0 );
322         putc('\n', stderr);
323         return -1;
324     }
325
326     if( opt.verbose ) {
327         log_info(_("armor header: "));
328         print_string( stderr, line, len, 0 );
329         putc('\n', stderr);
330     }
331
332     if( afx->in_cleartext ) {
333         if( (hashes=parse_hash_header( line )) )
334             afx->hashes |= hashes;
335         else if( strlen(line) > 15 && !memcmp( line, "NotDashEscaped:", 15 ) )
336             afx->not_dash_escaped = 1;
337         else {
338             log_error(_("invalid clearsig header\n"));
339             return -1;
340         }
341     }
342     return 1;
343 }
344
345
346
347 /* figure out whether the data is armored or not */
348 static int
349 check_input( armor_filter_context_t *afx, IOBUF a )
350 {
351     int rc = 0;
352     int i;
353     byte *line;
354     unsigned len;
355     unsigned maxlen;
356     int hdr_line = -1;
357
358     /* read the first line to see whether this is armored data */
359     maxlen = MAX_LINELEN;
360     len = afx->buffer_len = iobuf_read_line( a, &afx->buffer,
361                                              &afx->buffer_size, &maxlen );
362     line = afx->buffer;
363     if( !maxlen ) {
364         /* line has been truncated: assume not armored */
365         afx->inp_checked = 1;
366         afx->inp_bypass = 1;
367         return 0;
368     }
369
370     if( !len ) {
371         return -1; /* eof */
372     }
373
374     /* (the line is always a C string but maybe longer) */
375     if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
376         ;
377     else if( !is_armored( line ) ) {
378         afx->inp_checked = 1;
379         afx->inp_bypass = 1;
380         return 0;
381     }
382
383     /* find the armor header */
384     while(len) {
385         i = is_armor_header( line, len );
386         if( i >= 0 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
387             hdr_line = i;
388             if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
389                 if( afx->in_cleartext ) {
390                     log_error(_("nested clear text signatures\n"));
391                     rc = G10ERR_INVALID_ARMOR;
392                 }
393                 afx->in_cleartext = 1;
394             }
395             break;
396         }
397         /* read the next line (skip all truncated lines) */
398         do {
399             maxlen = MAX_LINELEN;
400             afx->buffer_len = iobuf_read_line( a, &afx->buffer,
401                                                &afx->buffer_size, &maxlen );
402             line = afx->buffer;
403             len = afx->buffer_len;
404         } while( !maxlen );
405     }
406
407     /* parse the header lines */
408     while(len) {
409         /* read the next line (skip all truncated lines) */
410         do {
411             maxlen = MAX_LINELEN;
412             afx->buffer_len = iobuf_read_line( a, &afx->buffer,
413                                                &afx->buffer_size, &maxlen );
414             line = afx->buffer;
415             len = afx->buffer_len;
416         } while( !maxlen );
417
418         i = parse_header_line( afx, line, len );
419         if( i <= 0 ) {
420             if( i )
421                 rc = G10ERR_INVALID_ARMOR;
422             break;
423         }
424     }
425
426
427     if( rc )
428         invalid_armor();
429     else if( afx->in_cleartext ) {
430         afx->faked = 1;
431     }
432     else {
433         afx->inp_checked = 1;
434         afx->crc = CRCINIT;
435         afx->idx = 0;
436         afx->radbuf[0] = 0;
437     }
438
439     return rc;
440 }
441
442
443
444 /****************
445  * Fake a literal data packet and wait for the next armor line
446  * fixme: empty line handling and null length clear text signature are
447  *        not implemented/checked.
448  */
449 static int
450 fake_packet( armor_filter_context_t *afx, IOBUF a,
451              size_t *retn, byte *buf, size_t size  )
452 {
453     int rc = 0;
454     size_t len = 0;
455     int lastline = 0;
456     unsigned maxlen, n;
457     byte *p;
458
459     len = 2;    /* reserve 2 bytes for the length header */
460     size -= 2;  /* and 2 for the terminating header */
461     while( !rc && len < size ) {
462         /* copy what we have in the line buffer */
463         if( afx->faked == 1 )
464             afx->faked++; /* skip the first (empty) line */
465         else {
466             while( len < size && afx->buffer_pos < afx->buffer_len )
467                 buf[len++] = afx->buffer[afx->buffer_pos++];
468             if( len >= size )
469                 continue;
470         }
471
472         /* read the next line */
473         maxlen = MAX_LINELEN;
474         afx->buffer_pos = 0;
475         afx->buffer_len = iobuf_read_line( a, &afx->buffer,
476                                            &afx->buffer_size, &maxlen );
477         if( !afx->buffer_len ) {
478             rc = -1; /* eof (should not happen) */
479             continue;
480         }
481         if( !maxlen )
482             afx->truncated++;
483         if( !afx->not_dash_escaped ) {
484             afx->buffer_len = trim_trailing_ws( afx->buffer, afx->buffer_len );
485             /* the buffer is always allocated with enough space to append
486              * a CR, LF, Nul */
487             afx->buffer[afx->buffer_len++] = '\r';
488             afx->buffer[afx->buffer_len++] = '\n';
489             afx->buffer[afx->buffer_len] = 0;
490         }
491         p = afx->buffer;
492         n = afx->buffer_len;
493
494         if( n > 2 && *p == '-' ) {
495             /* check for dash escaped or armor header */
496             if( p[1] == ' ' && !afx->not_dash_escaped ) {
497                 /* issue a warning if it is not regular encoded */
498                 if( p[2] != '-' && !( n > 6 && !memcmp(p+2, "From ", 5))) {
499                     log_info(_("invalid dash escaped line: "));
500                     print_string( stderr, p, n, 0 );
501                     putc('\n', stderr);
502                 }
503                 afx->buffer_pos = 2; /* skip */
504             }
505             else if( n >= 15 &&  p[1] == '-' && p[2] == '-' && p[3] == '-' ) {
506                 if( is_armor_header( p, n ) != BEGIN_SIGNATURE ) {
507                     log_info(_("unexpected armor:"));
508                     print_string( stderr, p, n, 0 );
509                     putc('\n', stderr);
510                 }
511                 lastline = 1;
512                 rc = -1;
513             }
514         }
515     }
516
517     buf[0] = (len-2) >> 8;
518     buf[1] = (len-2);
519     if( lastline ) { /* write last (ending) length header */
520         if( buf[0] || buf[1] ) { /* only if we have some text */
521             buf[len++] = 0;
522             buf[len++] = 0;
523         }
524         rc = 0;
525         afx->faked = 0;
526         afx->in_cleartext = 0;
527         /* and now read the header lines */
528         afx->buffer_pos = 0;
529         for(;;) {
530             int i;
531
532             /* read the next line (skip all truncated lines) */
533             do {
534                 maxlen = MAX_LINELEN;
535                 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
536                                                  &afx->buffer_size, &maxlen );
537             } while( !maxlen );
538             p = afx->buffer;
539             n = afx->buffer_len;
540             if( !n ) {
541                 rc = -1;
542                 break; /* eof */
543             }
544             i = parse_header_line( afx, p , n );
545             if( i <= 0 ) {
546                 if( i )
547                     invalid_armor();
548                 break;
549             }
550         }
551         afx->inp_checked = 1;
552         afx->crc = CRCINIT;
553         afx->idx = 0;
554         afx->radbuf[0] = 0;
555     }
556
557     *retn = len;
558     return rc;
559 }
560
561
562
563 static int
564 radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
565               byte *buf, size_t size )
566 {
567     byte val;
568     int c=0, c2; /*init c because gcc is not clever enough for the continue*/
569     int checkcrc=0;
570     int rc = 0;
571     size_t n = 0;
572     int  idx, i;
573     u32 crc;
574
575     crc = afx->crc;
576     idx = afx->idx;
577     val = afx->radbuf[0];
578     for( n=0; n < size; ) {
579
580         if( afx->buffer_pos < afx->buffer_len )
581             c = afx->buffer[afx->buffer_pos++];
582         else { /* read the next line */
583             unsigned maxlen = MAX_LINELEN;
584             afx->buffer_pos = 0;
585             afx->buffer_len = iobuf_read_line( a, &afx->buffer,
586                                                &afx->buffer_size, &maxlen );
587             if( !maxlen )
588                 afx->truncated++;
589             if( !afx->buffer_len )
590                 break; /* eof */
591             continue;
592         }
593
594       again:
595         if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
596             continue;
597         else if( c == '=' ) { /* pad character: stop */
598             /* some mailers leave quoted-printable encoded characters
599              * so we try to workaround this */
600             if( afx->buffer_pos+2 < afx->buffer_len ) {
601                 int cc1, cc2, cc3;
602                 cc1 = afx->buffer[afx->buffer_pos];
603                 cc2 = afx->buffer[afx->buffer_pos+1];
604                 cc3 = afx->buffer[afx->buffer_pos+2];
605                 if( isxdigit(cc1) && isxdigit(cc2)
606                                   && strchr( "=\n\r\t ", cc3 )) {
607                     /* well it seems to be the case - adjust */
608                     c = isdigit(cc1)? (cc1 - '0'): (toupper(cc1)-'A'+10);
609                     c <<= 4;
610                     c |= isdigit(cc2)? (cc2 - '0'): (toupper(cc2)-'A'+10);
611                     afx->buffer_pos += 2;
612                     afx->qp_detected = 1;
613                     goto again;
614                 }
615             }
616
617             if( idx == 1 )
618                 buf[n++] = val;
619             checkcrc++;
620             break;
621         }
622         else if( (c = asctobin[(c2=c)]) == 255 ) {
623             log_error(_("invalid radix64 character %02x skipped\n"), c2);
624             continue;
625         }
626         switch(idx) {
627           case 0: val =  c << 2; break;
628           case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
629           case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
630           case 3: val |= c&0x3f; buf[n++] = val; break;
631         }
632         idx = (idx+1) % 4;
633     }
634
635     for(i=0; i < n; i++ )
636         crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
637     crc &= 0x00ffffff;
638     afx->crc = crc;
639     afx->idx = idx;
640     afx->radbuf[0] = val;
641
642     if( checkcrc ) {
643         afx->any_data = 1;
644         afx->inp_checked=0;
645         afx->faked = 0;
646         for(;;) { /* skip lf and pad characters */
647             if( afx->buffer_pos < afx->buffer_len )
648                 c = afx->buffer[afx->buffer_pos++];
649             else { /* read the next line */
650                 unsigned maxlen = MAX_LINELEN;
651                 afx->buffer_pos = 0;
652                 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
653                                                    &afx->buffer_size, &maxlen );
654                 if( !maxlen )
655                     afx->truncated++;
656                 if( !afx->buffer_len )
657                     break; /* eof */
658                 continue;
659             }
660             if( c == '\n' || c == ' ' || c == '\r'
661                 || c == '\t' || c == '=' )
662                 continue;
663             break;
664         }
665         if( c == -1 )
666             log_error(_("premature eof (no CRC)\n"));
667         else {
668             u32 mycrc = 0;
669             idx = 0;
670             do {
671                 if( (c = asctobin[c]) == 255 )
672                     break;
673                 switch(idx) {
674                   case 0: val =  c << 2; break;
675                   case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
676                   case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
677                   case 3: val |= c&0x3f; mycrc |= val; break;
678                 }
679                 for(;;) {
680                     if( afx->buffer_pos < afx->buffer_len )
681                         c = afx->buffer[afx->buffer_pos++];
682                     else { /* read the next line */
683                         unsigned maxlen = MAX_LINELEN;
684                         afx->buffer_pos = 0;
685                         afx->buffer_len = iobuf_read_line( a, &afx->buffer,
686                                                            &afx->buffer_size,
687                                                                 &maxlen );
688                         if( !maxlen )
689                             afx->truncated++;
690                         if( !afx->buffer_len )
691                             break; /* eof */
692                         continue;
693                     }
694                     break;
695                 }
696                 if( !afx->buffer_len )
697                     break; /* eof */
698             } while( ++idx < 4 );
699             if( c == -1 ) {
700                 log_error(_("premature eof (in CRC)\n"));
701                 rc = G10ERR_INVALID_ARMOR;
702             }
703             else if( idx != 4 ) {
704                 log_error(_("malformed CRC\n"));
705                 rc = G10ERR_INVALID_ARMOR;
706             }
707             else if( mycrc != afx->crc ) {
708                 log_error(_("CRC error; %06lx - %06lx\n"),
709                                     (ulong)afx->crc, (ulong)mycrc);
710                 rc = G10ERR_INVALID_ARMOR;
711             }
712             else {
713                 rc = 0;
714               #if 0
715                 for(rc=0;!rc;) {
716                     rc = 0 /*check_trailer( &fhdr, c )*/;
717                     if( !rc ) {
718                         if( (c=iobuf_get(a)) == -1 )
719                             rc = 2;
720                     }
721                 }
722                 if( rc == -1 )
723                     rc = 0;
724                 else if( rc == 2 ) {
725                     log_error(_("premature eof (in Trailer)\n"));
726                     rc = G10ERR_INVALID_ARMOR;
727                 }
728                 else {
729                     log_error(_("error in trailer line\n"));
730                     rc = G10ERR_INVALID_ARMOR;
731                 }
732               #endif
733             }
734         }
735     }
736
737     if( !n )
738         rc = -1;
739
740     *retn = n;
741     return rc;
742 }
743
744 /****************
745  * This filter is used to handle the armor stuff
746  */
747 int
748 armor_filter( void *opaque, int control,
749              IOBUF a, byte *buf, size_t *ret_len)
750 {
751     size_t size = *ret_len;
752     armor_filter_context_t *afx = opaque;
753     int rc=0, i, c;
754     byte radbuf[3];
755     int  idx, idx2;
756     size_t n=0;
757     u32 crc;
758   #if 0
759     static FILE *fp ;
760
761     if( !fp ) {
762         fp = fopen("armor.out", "w");
763         assert(fp);
764     }
765   #endif
766
767     if( DBG_FILTER )
768         log_debug("armor-filter: control: %d\n", control );
769     if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
770         n = 0;
771         if( afx->buffer_len ) {
772             for(; n < size && afx->buffer_pos < afx->buffer_len; n++ )
773                 buf[n++] = afx->buffer[afx->buffer_pos++];
774             if( afx->buffer_pos >= afx->buffer_len )
775                 afx->buffer_len = 0;
776         }
777         for(; n < size; n++ ) {
778             if( (c=iobuf_get(a)) == -1 )
779                 break;
780             buf[n] = c & 0xff;
781         }
782         if( !n )
783             rc = -1;
784         *ret_len = n;
785     }
786     else if( control == IOBUFCTRL_UNDERFLOW ) {
787         if( size < 15+(4*15) )  /* need space for up to 4 onepass_sigs */
788             BUG(); /* supplied buffer too short */
789
790         if( afx->faked )
791             rc = fake_packet( afx, a, &n, buf, size );
792         else if( !afx->inp_checked ) {
793             rc = check_input( afx, a );
794             if( afx->inp_bypass ) {
795                 for(n=0; n < size && afx->buffer_pos < afx->buffer_len; n++ )
796                     buf[n++] = afx->buffer[afx->buffer_pos++];
797                 if( afx->buffer_pos >= afx->buffer_len )
798                     afx->buffer_len = 0;
799                 if( !n )
800                     rc = -1;
801             }
802             else if( afx->faked ) {
803                 unsigned hashes = afx->hashes;
804                 /* the buffer is at least 15+n*15 bytes long, so it
805                  * is easy to construct the packets */
806
807                 hashes &= 1|2|4|8;
808                 if( !hashes )
809                     hashes |= 4;  /* default to MD 5 */
810                 n=0;
811                 do {
812                     /* first some onepass signature packets */
813                     buf[n++] = 0x90; /* old format, type 4, 1 length byte */
814                     buf[n++] = 13;   /* length */
815                     buf[n++] = 3;    /* version */
816                     buf[n++] = 0x01; /* sigclass 0x01 (canonical text mode)*/
817                     if( hashes & 1 ) {
818                         hashes &= ~1;
819                         buf[n++] = DIGEST_ALGO_RMD160;
820                     }
821                     else if( hashes & 2 ) {
822                         hashes &= ~2;
823                         buf[n++] = DIGEST_ALGO_SHA1;
824                     }
825                     else if( hashes & 4 ) {
826                         hashes &= ~4;
827                         buf[n++] = DIGEST_ALGO_MD5;
828                     }
829                     else if( hashes & 8 ) {
830                         hashes &= ~8;
831                         buf[n++] = DIGEST_ALGO_TIGER;
832                     }
833                     else
834                         buf[n++] = 0;    /* (don't know) */
835
836                     buf[n++] = 0;    /* public key algo (don't know) */
837                     memset(buf+n, 0, 8); /* don't know the keyid */
838                     n += 8;
839                     buf[n++] = !hashes;   /* last one */
840                 } while( hashes );
841
842                 /* followed by a plaintext packet */
843                 buf[n++] = 0xaf; /* old packet format, type 11, var length */
844                 buf[n++] = 0;    /* set the length header */
845                 buf[n++] = 6;
846                 buf[n++] = 't';  /* canonical text mode */
847                 buf[n++] = 0;    /* namelength */
848                 memset(buf+n, 0, 4); /* timestamp */
849                 n += 4;
850             }
851             else if( !rc )
852                 rc = radix64_read( afx, a, &n, buf, size );
853         }
854         else
855             rc = radix64_read( afx, a, &n, buf, size );
856       #if 0
857         if( n )
858             if( fwrite(buf, n, 1, fp ) != 1 )
859                 BUG();
860       #endif
861         *ret_len = n;
862     }
863     else if( control == IOBUFCTRL_FLUSH ) {
864         if( !afx->status ) { /* write the header line */
865             if( afx->what >= DIM(head_strings) )
866                 log_bug("afx->what=%d", afx->what);
867             iobuf_writestr(a, "-----");
868             iobuf_writestr(a, head_strings[afx->what] );
869             iobuf_writestr(a, "-----\n");
870             if( !opt.no_version )
871                 iobuf_writestr(a, "Version: GnuPG v"  VERSION " ("
872                                               PRINTABLE_OS_NAME ")\n");
873
874             if( opt.comment_string ) {
875                 const char *s = opt.comment_string;
876                 if( *s ) {
877                     iobuf_writestr(a, "Comment: " );
878                     for( ; *s; s++ ) {
879                         if( *s == '\n' )
880                             iobuf_writestr(a, "\\n" );
881                         else if( *s == '\r' )
882                             iobuf_writestr(a, "\\r" );
883                         else if( *s == '\v' )
884                             iobuf_writestr(a, "\\v" );
885                         else
886                             iobuf_put(a, *s );
887                     }
888                     iobuf_put(a, '\n' );
889                 }
890             }
891             else
892                 iobuf_writestr(a,
893                     "Comment: For info see http://www.gnupg.org\n");
894             if( afx->hdrlines )
895                 iobuf_writestr(a, afx->hdrlines);
896             iobuf_put(a, '\n');
897             afx->status++;
898             afx->idx = 0;
899             afx->idx2 = 0;
900             afx->crc = CRCINIT;
901         }
902         crc = afx->crc;
903         idx = afx->idx;
904         idx2 = afx->idx2;
905         for(i=0; i < idx; i++ )
906             radbuf[i] = afx->radbuf[i];
907
908         for(i=0; i < size; i++ )
909             crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
910         crc &= 0x00ffffff;
911
912         for( ; size; buf++, size-- ) {
913             radbuf[idx++] = *buf;
914             if( idx > 2 ) {
915                 idx = 0;
916                 c = bintoasc[(*radbuf >> 2) & 077];
917                 iobuf_put(a, c);
918                 c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
919                 iobuf_put(a, c);
920                 c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
921                 iobuf_put(a, c);
922                 c = bintoasc[radbuf[2]&077];
923                 iobuf_put(a, c);
924                 if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
925                     iobuf_put(a, '\n');
926                     idx2=0;
927                 }
928             }
929         }
930         for(i=0; i < idx; i++ )
931             afx->radbuf[i] = radbuf[i];
932         afx->idx = idx;
933         afx->idx2 = idx2;
934         afx->crc  = crc;
935     }
936     else if( control == IOBUFCTRL_INIT ) {
937         if( !is_initialized )
938             initialize();
939     }
940     else if( control == IOBUFCTRL_FREE ) {
941         if( afx->status ) { /* pad, write cecksum, and bottom line */
942             crc = afx->crc;
943             idx = afx->idx;
944             idx2 = afx->idx2;
945             for(i=0; i < idx; i++ )
946                 radbuf[i] = afx->radbuf[i];
947             if( idx ) {
948                 c = bintoasc[(*radbuf>>2)&077];
949                 iobuf_put(a, c);
950                 if( idx == 1 ) {
951                     c = bintoasc[((*radbuf << 4) & 060) & 077];
952                     iobuf_put(a, c);
953                     iobuf_put(a, '=');
954                     iobuf_put(a, '=');
955                 }
956                 else { /* 2 */
957                     c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
958                     iobuf_put(a, c);
959                     c = bintoasc[((radbuf[1] << 2) & 074) & 077];
960                     iobuf_put(a, c);
961                     iobuf_put(a, '=');
962                 }
963                 if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
964                     iobuf_put(a, '\n');
965                     idx2=0;
966                 }
967             }
968             /* may need a linefeed */
969             if( idx2 )
970                 iobuf_put(a, '\n');
971             /* write the CRC */
972             iobuf_put(a, '=');
973             radbuf[0] = crc >>16;
974             radbuf[1] = crc >> 8;
975             radbuf[2] = crc;
976             c = bintoasc[(*radbuf >> 2) & 077];
977             iobuf_put(a, c);
978             c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
979             iobuf_put(a, c);
980             c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
981             iobuf_put(a, c);
982             c = bintoasc[radbuf[2]&077];
983             iobuf_put(a, c);
984             iobuf_put(a, '\n');
985             /* and the the trailer */
986             if( afx->what >= DIM(tail_strings) )
987                 log_bug("afx->what=%d", afx->what);
988             iobuf_writestr(a, "-----");
989             iobuf_writestr(a, tail_strings[afx->what] );
990             iobuf_writestr(a, "-----\n");
991         }
992         else if( !afx->any_data && !afx->inp_bypass )
993             log_error(_("no valid OpenPGP data found.\n"));
994         if( afx->truncated )
995             log_info(_("invalid armor: line longer than %d characters\n"),
996                       MAX_LINELEN );
997         /* issue an error to enforce dissemination of correct software */
998         if( afx->qp_detected )
999             log_error(_("quoted printable character in armor - "
1000                         "probably a buggy MTA has been used\n") );
1001         m_free( afx->buffer );
1002         afx->buffer = NULL;
1003     }
1004     else if( control == IOBUFCTRL_DESC )
1005         *(char**)buf = "armor_filter";
1006     return rc;
1007 }
1008
1009
1010