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