See ChangeLog: Wed Jan 13 14:10: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 static unsigned
261 trim_trailing_spaces( byte *line, unsigned len )
262 {
263     byte *p, *mark;
264     unsigned n;
265
266     for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
267         if( strchr(" \t\r\n", *p ) ) {
268             if( !mark )
269                 mark = p;
270         }
271         else
272             mark = NULL;
273     }
274
275     if( mark ) {
276         *mark = 0;
277         return mark - line;
278     }
279     return len;
280 }
281
282
283
284 /****************
285  * Check whether this is a armor line.
286  * returns: -1 if it is not a armor header or the index number of the
287  * armor header.
288  */
289 static int
290 is_armor_header( byte *line, unsigned len )
291 {
292     const char *s;
293     byte *save_p, *p;
294     int save_c;
295     int i;
296
297     if( len < 15 )
298         return -1; /* too short */
299     if( memcmp( line, "-----", 5 ) )
300         return -1; /* no */
301     p = strstr( line+5, "-----");
302     if( !p )
303         return -1;
304     save_p = p;
305     p += 5;
306     if( *p == '\r' )
307         p++;
308     if( *p == '\n' )
309         p++;
310     if( *p )
311         return -1; /* garbage after dashes */
312     save_c = *save_p; *save_p = 0;
313     p = line+5;
314     for(i=0; (s=head_strings[i]); i++ )
315         if( !strcmp(s, p) )
316             break;
317     *save_p = save_c;
318     if( !s )
319         return -1; /* unknown armor line */
320
321     if( opt.verbose > 1 )
322         log_info(_("armor: %s\n"), head_strings[i]);
323     return i;
324 }
325
326
327
328 /****************
329  * Parse a header lines
330  * Return 0: Empty line (end of header lines)
331  *       -1: invalid header line
332  *       >0: Good header line
333  */
334 static int
335 parse_header_line( armor_filter_context_t *afx, byte *line, unsigned len )
336 {
337     byte *p;
338     int hashes=0;
339
340     if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
341         return 0; /* empty line */
342     len = trim_trailing_spaces( line, len );
343     p = strchr( line, ':');
344     if( !p || !p[1] ) {
345         log_error(_("invalid armor header: "));
346         print_string( stderr, line, len, 0 );
347         putc('\n', stderr);
348         return -1;
349     }
350
351     if( opt.verbose ) {
352         log_info(_("armor header: "));
353         print_string( stderr, line, len, 0 );
354         putc('\n', stderr);
355     }
356
357     if( afx->in_cleartext ) {
358         if( (hashes=parse_hash_header( line )) )
359             afx->hashes |= hashes;
360         else if( strlen(line) > 15 && !memcmp( line, "NotDashEscaped:", 15 ) )
361             afx->not_dash_escaped = 1;
362         else {
363             log_error(_("invalid clearsig header\n"));
364             return -1;
365         }
366     }
367     return 1;
368 }
369
370
371
372 /* figure out whether the data is armored or not */
373 static int
374 check_input( armor_filter_context_t *afx, IOBUF a )
375 {
376     int rc = 0;
377     int i;
378     byte *line;
379     unsigned len;
380     unsigned maxlen;
381     int hdr_line = -1;
382
383     /* read the first line to see whether this is armored data */
384     maxlen = MAX_LINELEN;
385     len = afx->buffer_len = iobuf_read_line( a, &afx->buffer,
386                                              &afx->buffer_size, &maxlen );
387     line = afx->buffer;
388     if( !maxlen ) {
389         /* line has been truncated: assume not armored */
390         afx->inp_checked = 1;
391         afx->inp_bypass = 1;
392         return 0;
393     }
394
395     if( !len ) {
396         return -1; /* eof */
397     }
398
399     /* (the line is always a C string but maybe longer) */
400     if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
401         ;
402     else if( !is_armored( line ) ) {
403         afx->inp_checked = 1;
404         afx->inp_bypass = 1;
405         return 0;
406     }
407
408     /* find the armor header */
409     while(len) {
410         i = is_armor_header( line, len );
411         if( i >= 0 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
412             hdr_line = i;
413             if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
414                 if( afx->in_cleartext ) {
415                     log_error(_("nested clear text signatures\n"));
416                     rc = G10ERR_INVALID_ARMOR;
417                 }
418                 afx->in_cleartext = 1;
419             }
420             break;
421         }
422         /* read the next line (skip all truncated lines) */
423         do {
424             maxlen = MAX_LINELEN;
425             afx->buffer_len = iobuf_read_line( a, &afx->buffer,
426                                                &afx->buffer_size, &maxlen );
427             line = afx->buffer;
428             len = afx->buffer_len;
429         } while( !maxlen );
430     }
431
432     /* parse the header lines */
433     while(len) {
434         /* read the next line (skip all truncated lines) */
435         do {
436             maxlen = MAX_LINELEN;
437             afx->buffer_len = iobuf_read_line( a, &afx->buffer,
438                                                &afx->buffer_size, &maxlen );
439             line = afx->buffer;
440             len = afx->buffer_len;
441         } while( !maxlen );
442
443         i = parse_header_line( afx, line, len );
444         if( i <= 0 ) {
445             if( i )
446                 rc = G10ERR_INVALID_ARMOR;
447             break;
448         }
449     }
450
451
452     if( rc )
453         invalid_armor();
454     else if( afx->in_cleartext ) {
455         afx->faked = 1;
456     }
457     else {
458         afx->inp_checked = 1;
459         afx->crc = CRCINIT;
460         afx->idx = 0;
461         afx->radbuf[0] = 0;
462     }
463
464     return rc;
465 }
466
467
468
469 /****************
470  * Fake a literal data packet and wait for the next armor line
471  * fixme: empty line handling and null length clear text signature are
472  *        not implemented/checked.
473  */
474 static int
475 fake_packet( armor_filter_context_t *afx, IOBUF a,
476              size_t *retn, byte *buf, size_t size  )
477 {
478     int rc = 0;
479     size_t len = 0;
480     unsigned emplines = afx->empty;
481     int lastline = 0;
482     unsigned maxlen, n;
483     byte *p;
484
485     len = 2;    /* reserve 2 bytes for the length header */
486     size -= 3;  /* and 1 for empline handling and 2 for the term header */
487                 /* or the appended CR,LF */
488     while( !rc && len < size ) {
489         if( emplines ) {
490             while( emplines && len < size ) {
491                 buf[len++] = '\r';
492                 buf[len++] = '\n';
493                 emplines--;
494             }
495             continue;
496         }
497
498         if( afx->faked == 1 )
499             afx->faked++;  /* skip the first (empty) line */
500         else {
501             while( len < size && afx->buffer_pos < afx->buffer_len )
502                 buf[len++] = afx->buffer[afx->buffer_pos++];
503             if( afx->buffer_pos >= afx->buffer_len
504                 && !afx->not_dash_escaped ) {
505                 buf[len++] = '\r';
506                 buf[len++] = '\n';
507             }
508             if( len >= size )
509                 continue;
510         }
511
512         /* read the next line */
513         maxlen = MAX_LINELEN;
514         afx->buffer_pos = 0;
515         afx->buffer_len = iobuf_read_line( a, &afx->buffer,
516                                            &afx->buffer_size, &maxlen );
517         if( !afx->buffer_len ) {
518             rc = -1; /* eof */
519             continue;
520         }
521         if( !maxlen )
522             afx->truncated++;
523         if( !afx->not_dash_escaped )
524             afx->buffer_len = trim_trailing_spaces( afx->buffer,
525                                                     afx->buffer_len );
526         p = afx->buffer;
527         n = afx->buffer_len;
528
529         if( n > 2 && *p == '-' ) {
530             /* check for dash escaped or armor header */
531             if( p[1] == ' ' && !afx->not_dash_escaped ) {
532                 /* issue a warning if it is not regular encoded */
533                 if( p[2] != '-' && !( n > 6 && !memcmp(p+2, "From ", 5))) {
534                     log_info(_("invalid dash escaped line: "));
535                     print_string( stderr, p, n, 0 );
536                     putc('\n', stderr);
537                 }
538                 afx->buffer_pos = 2; /* skip */
539             }
540             else if( n >= 15 &&  p[1] == '-' && p[2] == '-' && p[3] == '-' ) {
541                 if( is_armor_header( p, n ) != BEGIN_SIGNATURE ) {
542                     log_info(_("unexpected armor:"));
543                     print_string( stderr, p, n, 0 );
544                     putc('\n', stderr);
545                 }
546                 lastline = 1;
547                 if( len >= 2 && !afx->not_dash_escaped )
548                     len -= 2; /* remove the last CR,LF */
549                 rc = -1;
550             }
551         }
552     }
553
554     buf[0] = (len-2) >> 8;
555     buf[1] = (len-2);
556     if( lastline ) { /* write last (ending) length header */
557         if( buf[0] || buf[1] ) { /* only if we have some text */
558             buf[len++] = 0;
559             buf[len++] = 0;
560         }
561         rc = 0;
562         afx->faked = 0;
563         afx->in_cleartext = 0;
564         /* and now read the header lines */
565         afx->buffer_pos = 0;
566         for(;;) {
567             int i;
568
569             /* read the next line (skip all truncated lines) */
570             do {
571                 maxlen = MAX_LINELEN;
572                 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
573                                                  &afx->buffer_size, &maxlen );
574             } while( !maxlen );
575             p = afx->buffer;
576             n = afx->buffer_len;
577             if( !n ) {
578                 rc = -1;
579                 break; /* eof */
580             }
581             i = parse_header_line( afx, p , n );
582             if( i <= 0 ) {
583                 if( i )
584                     invalid_armor();
585                 break;
586             }
587         }
588         afx->inp_checked = 1;
589         afx->crc = CRCINIT;
590         afx->idx = 0;
591         afx->radbuf[0] = 0;
592     }
593
594     afx->empty = emplines;
595     *retn = len;
596     return rc;
597 }
598
599
600
601 static int
602 radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
603               byte *buf, size_t size )
604 {
605     byte val;
606     int c, c2;
607     int checkcrc=0;
608     int rc = 0;
609     size_t n = 0;
610     int  idx, i;
611     u32 crc;
612
613     crc = afx->crc;
614     idx = afx->idx;
615     val = afx->radbuf[0];
616     for( n=0; n < size; ) {
617
618         if( afx->buffer_pos < afx->buffer_len )
619             c = afx->buffer[afx->buffer_pos++];
620         else { /* read the next line */
621             unsigned maxlen = MAX_LINELEN;
622             afx->buffer_pos = 0;
623             afx->buffer_len = iobuf_read_line( a, &afx->buffer,
624                                                &afx->buffer_size, &maxlen );
625             if( !maxlen )
626                 afx->truncated++;
627             if( !afx->buffer_len )
628                 break; /* eof */
629             continue;
630         }
631
632       again:
633         if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
634             continue;
635         else if( c == '=' ) { /* pad character: stop */
636             /* some mailers leave quoted-printable encoded characters
637              * so we try to workaround this */
638             if( afx->buffer_pos+2 < afx->buffer_len ) {
639                 int c1, c2, c3;
640                 c1 = afx->buffer[afx->buffer_pos];
641                 c2 = afx->buffer[afx->buffer_pos+1];
642                 c3 = afx->buffer[afx->buffer_pos+2];
643                 if( isxdigit(c1) && isxdigit(c2) && strchr( "=\n\r\t ", c3 )) {
644                     /* well it seems to be the case - adjust */
645                     c = isdigit(c1)? (c1 - '0'): (toupper(c1)-'A'+10);
646                     c <<= 4;
647                     c |= isdigit(c2)? (c2 - '0'): (toupper(c2)-'A'+10);
648                     afx->buffer_pos += 2;
649                     afx->qp_detected = 1;
650                     goto again;
651                 }
652             }
653
654             if( idx == 1 )
655                 buf[n++] = val;
656             checkcrc++;
657             break;
658         }
659         else if( (c = asctobin[(c2=c)]) == 255 ) {
660             log_error(_("invalid radix64 character %02x skipped\n"), c2);
661             continue;
662         }
663         switch(idx) {
664           case 0: val =  c << 2; break;
665           case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
666           case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
667           case 3: val |= c&0x3f; buf[n++] = val; break;
668         }
669         idx = (idx+1) % 4;
670     }
671
672     for(i=0; i < n; i++ )
673         crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
674     crc &= 0x00ffffff;
675     afx->crc = crc;
676     afx->idx = idx;
677     afx->radbuf[0] = val;
678
679     if( checkcrc ) {
680         afx->any_data = 1;
681         afx->inp_checked=0;
682         afx->faked = 0;
683         for(;;) { /* skip lf and pad characters */
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, &maxlen );
691                 if( !maxlen )
692                     afx->truncated++;
693                 if( !afx->buffer_len )
694                     break; /* eof */
695                 continue;
696             }
697             if( c == '\n' || c == ' ' || c == '\r'
698                 || c == '\t' || c == '=' )
699                 continue;
700             break;
701         }
702         if( c == -1 )
703             log_error(_("premature eof (no CRC)\n"));
704         else {
705             u32 mycrc = 0;
706             idx = 0;
707             do {
708                 if( (c = asctobin[c]) == 255 )
709                     break;
710                 switch(idx) {
711                   case 0: val =  c << 2; break;
712                   case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
713                   case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
714                   case 3: val |= c&0x3f; mycrc |= val; break;
715                 }
716                 for(;;) {
717                     if( afx->buffer_pos < afx->buffer_len )
718                         c = afx->buffer[afx->buffer_pos++];
719                     else { /* read the next line */
720                         unsigned maxlen = MAX_LINELEN;
721                         afx->buffer_pos = 0;
722                         afx->buffer_len = iobuf_read_line( a, &afx->buffer,
723                                                            &afx->buffer_size,
724                                                                 &maxlen );
725                         if( !maxlen )
726                             afx->truncated++;
727                         if( !afx->buffer_len )
728                             break; /* eof */
729                         continue;
730                     }
731                     break;
732                 }
733                 if( !afx->buffer_len )
734                     break; /* eof */
735             } while( ++idx < 4 );
736             if( c == -1 ) {
737                 log_error(_("premature eof (in CRC)\n"));
738                 rc = G10ERR_INVALID_ARMOR;
739             }
740             else if( idx != 4 ) {
741                 log_error(_("malformed CRC\n"));
742                 rc = G10ERR_INVALID_ARMOR;
743             }
744             else if( mycrc != afx->crc ) {
745                 log_error(_("CRC error; %06lx - %06lx\n"),
746                                     (ulong)afx->crc, (ulong)mycrc);
747                 rc = G10ERR_INVALID_ARMOR;
748             }
749             else {
750                 rc = 0;
751               #if 0
752                 for(rc=0;!rc;) {
753                     rc = 0 /*check_trailer( &fhdr, c )*/;
754                     if( !rc ) {
755                         if( (c=iobuf_get(a)) == -1 )
756                             rc = 2;
757                     }
758                 }
759                 if( rc == -1 )
760                     rc = 0;
761                 else if( rc == 2 ) {
762                     log_error(_("premature eof (in Trailer)\n"));
763                     rc = G10ERR_INVALID_ARMOR;
764                 }
765                 else {
766                     log_error(_("error in trailer line\n"));
767                     rc = G10ERR_INVALID_ARMOR;
768                 }
769               #endif
770             }
771         }
772     }
773
774     if( !n )
775         rc = -1;
776
777     *retn = n;
778     return rc;
779 }
780
781 /****************
782  * This filter is used to handle the armor stuff
783  */
784 int
785 armor_filter( void *opaque, int control,
786              IOBUF a, byte *buf, size_t *ret_len)
787 {
788     size_t size = *ret_len;
789     armor_filter_context_t *afx = opaque;
790     int rc=0, i, c;
791     byte radbuf[3];
792     int  idx, idx2;
793     size_t n=0;
794     u32 crc;
795   #if 0
796     static FILE *fp ;
797
798     if( !fp ) {
799         fp = fopen("armor.out", "w");
800         assert(fp);
801     }
802   #endif
803
804     if( DBG_FILTER )
805         log_debug("armor-filter: control: %d\n", control );
806     if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
807         n = 0;
808         if( afx->buffer_len ) {
809             for(; n < size && afx->buffer_pos < afx->buffer_len; n++ )
810                 buf[n++] = afx->buffer[afx->buffer_pos++];
811             if( afx->buffer_pos >= afx->buffer_len )
812                 afx->buffer_len = 0;
813         }
814         for(; n < size; n++ ) {
815             if( (c=iobuf_get(a)) == -1 )
816                 break;
817             buf[n] = c & 0xff;
818         }
819         if( !n )
820             rc = -1;
821         *ret_len = n;
822     }
823     else if( control == IOBUFCTRL_UNDERFLOW ) {
824         if( size < 15+(4*15) )  /* need space for up to 4 onepass_sigs */
825             BUG(); /* supplied buffer too short */
826
827         if( afx->faked )
828             rc = fake_packet( afx, a, &n, buf, size );
829         else if( !afx->inp_checked ) {
830             rc = check_input( afx, a );
831             if( afx->inp_bypass ) {
832                 for(n=0; n < size && afx->buffer_pos < afx->buffer_len; n++ )
833                     buf[n++] = afx->buffer[afx->buffer_pos++];
834                 if( afx->buffer_pos >= afx->buffer_len )
835                     afx->buffer_len = 0;
836                 if( !n )
837                     rc = -1;
838             }
839             else if( afx->faked ) {
840                 unsigned hashes = afx->hashes;
841                 /* the buffer is at least 15+n*15 bytes long, so it
842                  * is easy to construct the packets */
843
844                 hashes &= 1|2|4|8;
845                 if( !hashes )
846                     hashes |= 4;  /* default to MD 5 */
847                 n=0;
848                 do {
849                     /* first some onepass signature packets */
850                     buf[n++] = 0x90; /* old format, type 4, 1 length byte */
851                     buf[n++] = 13;   /* length */
852                     buf[n++] = 3;    /* version */
853                     buf[n++] = 0x01; /* sigclass 0x01 (canonical text mode)*/
854                     if( hashes & 1 ) {
855                         hashes &= ~1;
856                         buf[n++] = DIGEST_ALGO_RMD160;
857                     }
858                     else if( hashes & 2 ) {
859                         hashes &= ~2;
860                         buf[n++] = DIGEST_ALGO_SHA1;
861                     }
862                     else if( hashes & 4 ) {
863                         hashes &= ~4;
864                         buf[n++] = DIGEST_ALGO_MD5;
865                     }
866                     else if( hashes & 8 ) {
867                         hashes &= ~8;
868                         buf[n++] = DIGEST_ALGO_TIGER;
869                     }
870                     else
871                         buf[n++] = 0;    /* (don't know) */
872
873                     buf[n++] = 0;    /* public key algo (don't know) */
874                     memset(buf+n, 0, 8); /* don't know the keyid */
875                     n += 8;
876                     buf[n++] = !hashes;   /* last one */
877                 } while( hashes );
878
879                 /* followed by a plaintext packet */
880                 buf[n++] = 0xaf; /* old packet format, type 11, var length */
881                 buf[n++] = 0;    /* set the length header */
882                 buf[n++] = 6;
883                 buf[n++] = 't';  /* canonical text mode */
884                 buf[n++] = 0;    /* namelength */
885                 memset(buf+n, 0, 4); /* timestamp */
886                 n += 4;
887             }
888             else if( !rc )
889                 rc = radix64_read( afx, a, &n, buf, size );
890         }
891         else
892             rc = radix64_read( afx, a, &n, buf, size );
893       #if 0
894         if( n )
895             if( fwrite(buf, n, 1, fp ) != 1 )
896                 BUG();
897       #endif
898         *ret_len = n;
899     }
900     else if( control == IOBUFCTRL_FLUSH ) {
901         if( !afx->status ) { /* write the header line */
902             if( afx->what >= DIM(head_strings) )
903                 log_bug("afx->what=%d", afx->what);
904             iobuf_writestr(a, "-----");
905             iobuf_writestr(a, head_strings[afx->what] );
906             iobuf_writestr(a, "-----\n");
907             iobuf_writestr(a, "Version: GnuPG v"  VERSION " ("
908                                             PRINTABLE_OS_NAME ")\n");
909
910             if( opt.comment_string ) {
911                 const char *s = opt.comment_string;
912                 iobuf_writestr(a, "Comment: " );
913                 for( ; *s; s++ ) {
914                     if( *s == '\n' )
915                         iobuf_writestr(a, "\\n" );
916                     else if( *s == '\r' )
917                         iobuf_writestr(a, "\\r" );
918                     else if( *s == '\v' )
919                         iobuf_writestr(a, "\\v" );
920                     else
921                         iobuf_put(a, *s );
922                 }
923                 iobuf_put(a, '\n' );
924             }
925             else
926                 iobuf_writestr(a,
927                     "Comment: For info see http://www.gnupg.org\n");
928             if( afx->hdrlines )
929                 iobuf_writestr(a, afx->hdrlines);
930             iobuf_put(a, '\n');
931             afx->status++;
932             afx->idx = 0;
933             afx->idx2 = 0;
934             afx->crc = CRCINIT;
935         }
936         crc = afx->crc;
937         idx = afx->idx;
938         idx2 = afx->idx2;
939         for(i=0; i < idx; i++ )
940             radbuf[i] = afx->radbuf[i];
941
942         for(i=0; i < size; i++ )
943             crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
944         crc &= 0x00ffffff;
945
946         for( ; size; buf++, size-- ) {
947             radbuf[idx++] = *buf;
948             if( idx > 2 ) {
949                 idx = 0;
950                 c = bintoasc[(*radbuf >> 2) & 077];
951                 iobuf_put(a, c);
952                 c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
953                 iobuf_put(a, c);
954                 c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
955                 iobuf_put(a, c);
956                 c = bintoasc[radbuf[2]&077];
957                 iobuf_put(a, c);
958                 if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
959                     iobuf_put(a, '\n');
960                     idx2=0;
961                 }
962             }
963         }
964         for(i=0; i < idx; i++ )
965             afx->radbuf[i] = radbuf[i];
966         afx->idx = idx;
967         afx->idx2 = idx2;
968         afx->crc  = crc;
969     }
970     else if( control == IOBUFCTRL_INIT ) {
971         if( !is_initialized )
972             initialize();
973     }
974     else if( control == IOBUFCTRL_FREE ) {
975         if( afx->status ) { /* pad, write cecksum, and bottom line */
976             crc = afx->crc;
977             idx = afx->idx;
978             idx2 = afx->idx2;
979             for(i=0; i < idx; i++ )
980                 radbuf[i] = afx->radbuf[i];
981             if( idx ) {
982                 c = bintoasc[(*radbuf>>2)&077];
983                 iobuf_put(a, c);
984                 if( idx == 1 ) {
985                     c = bintoasc[((*radbuf << 4) & 060) & 077];
986                     iobuf_put(a, c);
987                     iobuf_put(a, '=');
988                     iobuf_put(a, '=');
989                 }
990                 else { /* 2 */
991                     c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
992                     iobuf_put(a, c);
993                     c = bintoasc[((radbuf[1] << 2) & 074) & 077];
994                     iobuf_put(a, c);
995                     iobuf_put(a, '=');
996                 }
997                 if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
998                     iobuf_put(a, '\n');
999                     idx2=0;
1000                 }
1001             }
1002             /* may need a linefeed */
1003             if( idx2 )
1004                 iobuf_put(a, '\n');
1005             /* write the CRC */
1006             iobuf_put(a, '=');
1007             radbuf[0] = crc >>16;
1008             radbuf[1] = crc >> 8;
1009             radbuf[2] = crc;
1010             c = bintoasc[(*radbuf >> 2) & 077];
1011             iobuf_put(a, c);
1012             c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1013             iobuf_put(a, c);
1014             c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1015             iobuf_put(a, c);
1016             c = bintoasc[radbuf[2]&077];
1017             iobuf_put(a, c);
1018             iobuf_put(a, '\n');
1019             /* and the the trailer */
1020             if( afx->what >= DIM(tail_strings) )
1021                 log_bug("afx->what=%d", afx->what);
1022             iobuf_writestr(a, "-----");
1023             iobuf_writestr(a, tail_strings[afx->what] );
1024             iobuf_writestr(a, "-----\n");
1025         }
1026         else if( !afx->any_data && !afx->inp_bypass )
1027             log_error(_("no valid OpenPGP data found.\n"));
1028         if( afx->truncated )
1029             log_info(_("invalid armor: line longer than %d characters\n"),
1030                       MAX_LINELEN );
1031         /* issue an error to enforce dissemination of correct software */
1032         if( afx->qp_detected )
1033             log_error(_("quoted printable character in armor - "
1034                         "probably a buggy MTA has been used\n") );
1035         m_free( afx->buffer );
1036         afx->buffer = NULL;
1037     }
1038     else if( control == IOBUFCTRL_DESC )
1039         *(char**)buf = "armor_filter";
1040     return rc;
1041 }
1042
1043
1044