See ChangeLog: Tue Feb 16 14:10:02 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     unsigned emplines = afx->empty;
456     int lastline = 0;
457     unsigned maxlen, n;
458     byte *p;
459
460     len = 2;    /* reserve 2 bytes for the length header */
461     size -= 3;  /* and 1 for empline handling and 2 for the term header */
462                 /* or the appended CR,LF */
463     while( !rc && len < size ) {
464         if( emplines ) {
465             while( emplines && len < size ) {
466                 buf[len++] = '\r';
467                 buf[len++] = '\n';
468                 emplines--;
469             }
470             continue;
471         }
472
473         if( afx->faked == 1 )
474             afx->faked++;  /* skip the first (empty) line */
475         else {
476             while( len < size && afx->buffer_pos < afx->buffer_len )
477                 buf[len++] = afx->buffer[afx->buffer_pos++];
478             if( afx->buffer_pos >= afx->buffer_len
479                 && !afx->not_dash_escaped ) {
480                 buf[len++] = '\r';
481                 buf[len++] = '\n';
482             }
483             if( len >= size )
484                 continue;
485         }
486
487         /* read the next line */
488         maxlen = MAX_LINELEN;
489         afx->buffer_pos = 0;
490         afx->buffer_len = iobuf_read_line( a, &afx->buffer,
491                                            &afx->buffer_size, &maxlen );
492         if( !afx->buffer_len ) {
493             rc = -1; /* eof */
494             continue;
495         }
496         if( !maxlen )
497             afx->truncated++;
498         if( !afx->not_dash_escaped )
499             afx->buffer_len = trim_trailing_ws( afx->buffer, afx->buffer_len );
500         p = afx->buffer;
501         n = afx->buffer_len;
502
503         if( n > 2 && *p == '-' ) {
504             /* check for dash escaped or armor header */
505             if( p[1] == ' ' && !afx->not_dash_escaped ) {
506                 /* issue a warning if it is not regular encoded */
507                 if( p[2] != '-' && !( n > 6 && !memcmp(p+2, "From ", 5))) {
508                     log_info(_("invalid dash escaped line: "));
509                     print_string( stderr, p, n, 0 );
510                     putc('\n', stderr);
511                 }
512                 afx->buffer_pos = 2; /* skip */
513             }
514             else if( n >= 15 &&  p[1] == '-' && p[2] == '-' && p[3] == '-' ) {
515                 if( is_armor_header( p, n ) != BEGIN_SIGNATURE ) {
516                     log_info(_("unexpected armor:"));
517                     print_string( stderr, p, n, 0 );
518                     putc('\n', stderr);
519                 }
520                 lastline = 1;
521                 rc = -1;
522             }
523         }
524     }
525
526     buf[0] = (len-2) >> 8;
527     buf[1] = (len-2);
528     if( lastline ) { /* write last (ending) length header */
529         if( buf[0] || buf[1] ) { /* only if we have some text */
530             buf[len++] = 0;
531             buf[len++] = 0;
532         }
533         rc = 0;
534         afx->faked = 0;
535         afx->in_cleartext = 0;
536         /* and now read the header lines */
537         afx->buffer_pos = 0;
538         for(;;) {
539             int i;
540
541             /* read the next line (skip all truncated lines) */
542             do {
543                 maxlen = MAX_LINELEN;
544                 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
545                                                  &afx->buffer_size, &maxlen );
546             } while( !maxlen );
547             p = afx->buffer;
548             n = afx->buffer_len;
549             if( !n ) {
550                 rc = -1;
551                 break; /* eof */
552             }
553             i = parse_header_line( afx, p , n );
554             if( i <= 0 ) {
555                 if( i )
556                     invalid_armor();
557                 break;
558             }
559         }
560         afx->inp_checked = 1;
561         afx->crc = CRCINIT;
562         afx->idx = 0;
563         afx->radbuf[0] = 0;
564     }
565
566     afx->empty = emplines;
567     *retn = len;
568     return rc;
569 }
570
571
572
573 static int
574 radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
575               byte *buf, size_t size )
576 {
577     byte val;
578     int c=0, c2; /*init c because gcc is not clever enough for the continue*/
579     int checkcrc=0;
580     int rc = 0;
581     size_t n = 0;
582     int  idx, i;
583     u32 crc;
584
585     crc = afx->crc;
586     idx = afx->idx;
587     val = afx->radbuf[0];
588     for( n=0; n < size; ) {
589
590         if( afx->buffer_pos < afx->buffer_len )
591             c = afx->buffer[afx->buffer_pos++];
592         else { /* read the next line */
593             unsigned maxlen = MAX_LINELEN;
594             afx->buffer_pos = 0;
595             afx->buffer_len = iobuf_read_line( a, &afx->buffer,
596                                                &afx->buffer_size, &maxlen );
597             if( !maxlen )
598                 afx->truncated++;
599             if( !afx->buffer_len )
600                 break; /* eof */
601             continue;
602         }
603
604       again:
605         if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
606             continue;
607         else if( c == '=' ) { /* pad character: stop */
608             /* some mailers leave quoted-printable encoded characters
609              * so we try to workaround this */
610             if( afx->buffer_pos+2 < afx->buffer_len ) {
611                 int cc1, cc2, cc3;
612                 cc1 = afx->buffer[afx->buffer_pos];
613                 cc2 = afx->buffer[afx->buffer_pos+1];
614                 cc3 = afx->buffer[afx->buffer_pos+2];
615                 if( isxdigit(cc1) && isxdigit(cc2)
616                                   && strchr( "=\n\r\t ", cc3 )) {
617                     /* well it seems to be the case - adjust */
618                     c = isdigit(cc1)? (cc1 - '0'): (toupper(cc1)-'A'+10);
619                     c <<= 4;
620                     c |= isdigit(cc2)? (cc2 - '0'): (toupper(cc2)-'A'+10);
621                     afx->buffer_pos += 2;
622                     afx->qp_detected = 1;
623                     goto again;
624                 }
625             }
626
627             if( idx == 1 )
628                 buf[n++] = val;
629             checkcrc++;
630             break;
631         }
632         else if( (c = asctobin[(c2=c)]) == 255 ) {
633             log_error(_("invalid radix64 character %02x skipped\n"), c2);
634             continue;
635         }
636         switch(idx) {
637           case 0: val =  c << 2; break;
638           case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
639           case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
640           case 3: val |= c&0x3f; buf[n++] = val; break;
641         }
642         idx = (idx+1) % 4;
643     }
644
645     for(i=0; i < n; i++ )
646         crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
647     crc &= 0x00ffffff;
648     afx->crc = crc;
649     afx->idx = idx;
650     afx->radbuf[0] = val;
651
652     if( checkcrc ) {
653         afx->any_data = 1;
654         afx->inp_checked=0;
655         afx->faked = 0;
656         for(;;) { /* skip lf and pad characters */
657             if( afx->buffer_pos < afx->buffer_len )
658                 c = afx->buffer[afx->buffer_pos++];
659             else { /* read the next line */
660                 unsigned maxlen = MAX_LINELEN;
661                 afx->buffer_pos = 0;
662                 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
663                                                    &afx->buffer_size, &maxlen );
664                 if( !maxlen )
665                     afx->truncated++;
666                 if( !afx->buffer_len )
667                     break; /* eof */
668                 continue;
669             }
670             if( c == '\n' || c == ' ' || c == '\r'
671                 || c == '\t' || c == '=' )
672                 continue;
673             break;
674         }
675         if( c == -1 )
676             log_error(_("premature eof (no CRC)\n"));
677         else {
678             u32 mycrc = 0;
679             idx = 0;
680             do {
681                 if( (c = asctobin[c]) == 255 )
682                     break;
683                 switch(idx) {
684                   case 0: val =  c << 2; break;
685                   case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
686                   case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
687                   case 3: val |= c&0x3f; mycrc |= val; break;
688                 }
689                 for(;;) {
690                     if( afx->buffer_pos < afx->buffer_len )
691                         c = afx->buffer[afx->buffer_pos++];
692                     else { /* read the next line */
693                         unsigned maxlen = MAX_LINELEN;
694                         afx->buffer_pos = 0;
695                         afx->buffer_len = iobuf_read_line( a, &afx->buffer,
696                                                            &afx->buffer_size,
697                                                                 &maxlen );
698                         if( !maxlen )
699                             afx->truncated++;
700                         if( !afx->buffer_len )
701                             break; /* eof */
702                         continue;
703                     }
704                     break;
705                 }
706                 if( !afx->buffer_len )
707                     break; /* eof */
708             } while( ++idx < 4 );
709             if( c == -1 ) {
710                 log_error(_("premature eof (in CRC)\n"));
711                 rc = G10ERR_INVALID_ARMOR;
712             }
713             else if( idx != 4 ) {
714                 log_error(_("malformed CRC\n"));
715                 rc = G10ERR_INVALID_ARMOR;
716             }
717             else if( mycrc != afx->crc ) {
718                 log_error(_("CRC error; %06lx - %06lx\n"),
719                                     (ulong)afx->crc, (ulong)mycrc);
720                 rc = G10ERR_INVALID_ARMOR;
721             }
722             else {
723                 rc = 0;
724               #if 0
725                 for(rc=0;!rc;) {
726                     rc = 0 /*check_trailer( &fhdr, c )*/;
727                     if( !rc ) {
728                         if( (c=iobuf_get(a)) == -1 )
729                             rc = 2;
730                     }
731                 }
732                 if( rc == -1 )
733                     rc = 0;
734                 else if( rc == 2 ) {
735                     log_error(_("premature eof (in Trailer)\n"));
736                     rc = G10ERR_INVALID_ARMOR;
737                 }
738                 else {
739                     log_error(_("error in trailer line\n"));
740                     rc = G10ERR_INVALID_ARMOR;
741                 }
742               #endif
743             }
744         }
745     }
746
747     if( !n )
748         rc = -1;
749
750     *retn = n;
751     return rc;
752 }
753
754 /****************
755  * This filter is used to handle the armor stuff
756  */
757 int
758 armor_filter( void *opaque, int control,
759              IOBUF a, byte *buf, size_t *ret_len)
760 {
761     size_t size = *ret_len;
762     armor_filter_context_t *afx = opaque;
763     int rc=0, i, c;
764     byte radbuf[3];
765     int  idx, idx2;
766     size_t n=0;
767     u32 crc;
768   #if 0
769     static FILE *fp ;
770
771     if( !fp ) {
772         fp = fopen("armor.out", "w");
773         assert(fp);
774     }
775   #endif
776
777     if( DBG_FILTER )
778         log_debug("armor-filter: control: %d\n", control );
779     if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
780         n = 0;
781         if( afx->buffer_len ) {
782             for(; n < size && afx->buffer_pos < afx->buffer_len; n++ )
783                 buf[n++] = afx->buffer[afx->buffer_pos++];
784             if( afx->buffer_pos >= afx->buffer_len )
785                 afx->buffer_len = 0;
786         }
787         for(; n < size; n++ ) {
788             if( (c=iobuf_get(a)) == -1 )
789                 break;
790             buf[n] = c & 0xff;
791         }
792         if( !n )
793             rc = -1;
794         *ret_len = n;
795     }
796     else if( control == IOBUFCTRL_UNDERFLOW ) {
797         if( size < 15+(4*15) )  /* need space for up to 4 onepass_sigs */
798             BUG(); /* supplied buffer too short */
799
800         if( afx->faked )
801             rc = fake_packet( afx, a, &n, buf, size );
802         else if( !afx->inp_checked ) {
803             rc = check_input( afx, a );
804             if( afx->inp_bypass ) {
805                 for(n=0; n < size && afx->buffer_pos < afx->buffer_len; n++ )
806                     buf[n++] = afx->buffer[afx->buffer_pos++];
807                 if( afx->buffer_pos >= afx->buffer_len )
808                     afx->buffer_len = 0;
809                 if( !n )
810                     rc = -1;
811             }
812             else if( afx->faked ) {
813                 unsigned hashes = afx->hashes;
814                 /* the buffer is at least 15+n*15 bytes long, so it
815                  * is easy to construct the packets */
816
817                 hashes &= 1|2|4|8;
818                 if( !hashes )
819                     hashes |= 4;  /* default to MD 5 */
820                 n=0;
821                 do {
822                     /* first some onepass signature packets */
823                     buf[n++] = 0x90; /* old format, type 4, 1 length byte */
824                     buf[n++] = 13;   /* length */
825                     buf[n++] = 3;    /* version */
826                     buf[n++] = 0x01; /* sigclass 0x01 (canonical text mode)*/
827                     if( hashes & 1 ) {
828                         hashes &= ~1;
829                         buf[n++] = DIGEST_ALGO_RMD160;
830                     }
831                     else if( hashes & 2 ) {
832                         hashes &= ~2;
833                         buf[n++] = DIGEST_ALGO_SHA1;
834                     }
835                     else if( hashes & 4 ) {
836                         hashes &= ~4;
837                         buf[n++] = DIGEST_ALGO_MD5;
838                     }
839                     else if( hashes & 8 ) {
840                         hashes &= ~8;
841                         buf[n++] = DIGEST_ALGO_TIGER;
842                     }
843                     else
844                         buf[n++] = 0;    /* (don't know) */
845
846                     buf[n++] = 0;    /* public key algo (don't know) */
847                     memset(buf+n, 0, 8); /* don't know the keyid */
848                     n += 8;
849                     buf[n++] = !hashes;   /* last one */
850                 } while( hashes );
851
852                 /* followed by a plaintext packet */
853                 buf[n++] = 0xaf; /* old packet format, type 11, var length */
854                 buf[n++] = 0;    /* set the length header */
855                 buf[n++] = 6;
856                 buf[n++] = 't';  /* canonical text mode */
857                 buf[n++] = 0;    /* namelength */
858                 memset(buf+n, 0, 4); /* timestamp */
859                 n += 4;
860             }
861             else if( !rc )
862                 rc = radix64_read( afx, a, &n, buf, size );
863         }
864         else
865             rc = radix64_read( afx, a, &n, buf, size );
866       #if 0
867         if( n )
868             if( fwrite(buf, n, 1, fp ) != 1 )
869                 BUG();
870       #endif
871         *ret_len = n;
872     }
873     else if( control == IOBUFCTRL_FLUSH ) {
874         if( !afx->status ) { /* write the header line */
875             if( afx->what >= DIM(head_strings) )
876                 log_bug("afx->what=%d", afx->what);
877             iobuf_writestr(a, "-----");
878             iobuf_writestr(a, head_strings[afx->what] );
879             iobuf_writestr(a, "-----\n");
880             if( !opt.no_version )
881                 iobuf_writestr(a, "Version: GnuPG v"  VERSION " ("
882                                               PRINTABLE_OS_NAME ")\n");
883
884             if( opt.comment_string ) {
885                 const char *s = opt.comment_string;
886                 if( *s ) {
887                     iobuf_writestr(a, "Comment: " );
888                     for( ; *s; s++ ) {
889                         if( *s == '\n' )
890                             iobuf_writestr(a, "\\n" );
891                         else if( *s == '\r' )
892                             iobuf_writestr(a, "\\r" );
893                         else if( *s == '\v' )
894                             iobuf_writestr(a, "\\v" );
895                         else
896                             iobuf_put(a, *s );
897                     }
898                     iobuf_put(a, '\n' );
899                 }
900             }
901             else
902                 iobuf_writestr(a,
903                     "Comment: For info see http://www.gnupg.org\n");
904             if( afx->hdrlines )
905                 iobuf_writestr(a, afx->hdrlines);
906             iobuf_put(a, '\n');
907             afx->status++;
908             afx->idx = 0;
909             afx->idx2 = 0;
910             afx->crc = CRCINIT;
911         }
912         crc = afx->crc;
913         idx = afx->idx;
914         idx2 = afx->idx2;
915         for(i=0; i < idx; i++ )
916             radbuf[i] = afx->radbuf[i];
917
918         for(i=0; i < size; i++ )
919             crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
920         crc &= 0x00ffffff;
921
922         for( ; size; buf++, size-- ) {
923             radbuf[idx++] = *buf;
924             if( idx > 2 ) {
925                 idx = 0;
926                 c = bintoasc[(*radbuf >> 2) & 077];
927                 iobuf_put(a, c);
928                 c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
929                 iobuf_put(a, c);
930                 c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
931                 iobuf_put(a, c);
932                 c = bintoasc[radbuf[2]&077];
933                 iobuf_put(a, c);
934                 if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
935                     iobuf_put(a, '\n');
936                     idx2=0;
937                 }
938             }
939         }
940         for(i=0; i < idx; i++ )
941             afx->radbuf[i] = radbuf[i];
942         afx->idx = idx;
943         afx->idx2 = idx2;
944         afx->crc  = crc;
945     }
946     else if( control == IOBUFCTRL_INIT ) {
947         if( !is_initialized )
948             initialize();
949     }
950     else if( control == IOBUFCTRL_FREE ) {
951         if( afx->status ) { /* pad, write cecksum, and bottom line */
952             crc = afx->crc;
953             idx = afx->idx;
954             idx2 = afx->idx2;
955             for(i=0; i < idx; i++ )
956                 radbuf[i] = afx->radbuf[i];
957             if( idx ) {
958                 c = bintoasc[(*radbuf>>2)&077];
959                 iobuf_put(a, c);
960                 if( idx == 1 ) {
961                     c = bintoasc[((*radbuf << 4) & 060) & 077];
962                     iobuf_put(a, c);
963                     iobuf_put(a, '=');
964                     iobuf_put(a, '=');
965                 }
966                 else { /* 2 */
967                     c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
968                     iobuf_put(a, c);
969                     c = bintoasc[((radbuf[1] << 2) & 074) & 077];
970                     iobuf_put(a, c);
971                     iobuf_put(a, '=');
972                 }
973                 if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
974                     iobuf_put(a, '\n');
975                     idx2=0;
976                 }
977             }
978             /* may need a linefeed */
979             if( idx2 )
980                 iobuf_put(a, '\n');
981             /* write the CRC */
982             iobuf_put(a, '=');
983             radbuf[0] = crc >>16;
984             radbuf[1] = crc >> 8;
985             radbuf[2] = crc;
986             c = bintoasc[(*radbuf >> 2) & 077];
987             iobuf_put(a, c);
988             c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
989             iobuf_put(a, c);
990             c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
991             iobuf_put(a, c);
992             c = bintoasc[radbuf[2]&077];
993             iobuf_put(a, c);
994             iobuf_put(a, '\n');
995             /* and the the trailer */
996             if( afx->what >= DIM(tail_strings) )
997                 log_bug("afx->what=%d", afx->what);
998             iobuf_writestr(a, "-----");
999             iobuf_writestr(a, tail_strings[afx->what] );
1000             iobuf_writestr(a, "-----\n");
1001         }
1002         else if( !afx->any_data && !afx->inp_bypass )
1003             log_error(_("no valid OpenPGP data found.\n"));
1004         if( afx->truncated )
1005             log_info(_("invalid armor: line longer than %d characters\n"),
1006                       MAX_LINELEN );
1007         /* issue an error to enforce dissemination of correct software */
1008         if( afx->qp_detected )
1009             log_error(_("quoted printable character in armor - "
1010                         "probably a buggy MTA has been used\n") );
1011         m_free( afx->buffer );
1012         afx->buffer = NULL;
1013     }
1014     else if( control == IOBUFCTRL_DESC )
1015         *(char**)buf = "armor_filter";
1016     return rc;
1017 }
1018
1019
1020