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