/[winpt]/trunk/Gnupg/armor.c
ViewVC logotype

Annotation of /trunk/Gnupg/armor.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 46 - (hide annotations)
Fri Oct 28 12:57:05 2005 UTC (19 years, 4 months ago) by werner
File MIME type: text/plain
File size: 32583 byte(s)
Second set of changes to use autotools for building.
1 werner 46 /* armor.c - Armor filter
2     * Copyright (C) 1998, 1999, 2000, 2001, 2002 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     #ifdef HAVE_CONFIG_H
22     #include <config.h>
23     #endif
24    
25     #include <stdio.h>
26     #include <stdio.h>
27     #include <stdlib.h>
28     #include <string.h>
29     #include <errno.h>
30     #include <ctype.h>
31     #include <windows.h>
32     #include <sys/types.h>
33    
34     #include "openpgp.h"
35     #include "packet.h"
36    
37     #define LF "\r\n"
38    
39     #define MAX_LINELEN 20000
40    
41     #define CRCINIT 0xB704CE
42     #define CRCPOLY 0X864CFB
43     #define CRCUPDATE(a,c) do { \
44     a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \
45     a &= 0x00ffffff; \
46     } while(0)
47     static u32 crc_table[256];
48     static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
49     "abcdefghijklmnopqrstuvwxyz"
50     "0123456789+/";
51     static byte asctobin[256]; /* runtime initialized */
52     static int is_initialized;
53     static int armor_errno = 0;
54     static char armor_error[256];
55    
56     typedef enum {
57     fhdrHASArmor = 0,
58     fhdrNOArmor,
59     fhdrINIT,
60     fhdrINITCont,
61     fhdrINITSkip,
62     fhdrCHECKBegin,
63     fhdrWAITHeader,
64     fhdrWAITClearsig,
65     fhdrSKIPHeader,
66     fhdrCLEARSIG,
67     fhdrREADClearsig,
68     fhdrNullClearsig,
69     fhdrEMPTYClearsig,
70     fhdrCHECKClearsig,
71     fhdrCHECKClearsig2,
72     fhdrCHECKDashEscaped,
73     fhdrCHECKDashEscaped2,
74     fhdrCHECKDashEscaped3,
75     fhdrREADClearsigNext,
76     fhdrENDClearsig,
77     fhdrENDClearsigHelp,
78     fhdrTESTSpaces,
79     fhdrCLEARSIGSimple,
80     fhdrCLEARSIGSimpleNext,
81     fhdrTEXT,
82     fhdrTEXTSimple,
83     fhdrERROR,
84     fhdrERRORShow,
85     fhdrEOF
86     } fhdr_state_t;
87    
88    
89     /* if we encounter this armor string with this index, go
90     * into a mode which fakes packets and wait for the next armor */
91     #define BEGIN_SIGNATURE 2
92     #define BEGIN_SIGNED_MSG_IDX 3
93     static char *head_strings[] = {
94     "BEGIN PGP MESSAGE",
95     "BEGIN PGP PUBLIC KEY BLOCK",
96     "BEGIN PGP SIGNATURE",
97     "BEGIN PGP SIGNED MESSAGE",
98     "BEGIN PGP ARMORED FILE", /* gnupg extension */
99     "BEGIN PGP PRIVATE KEY BLOCK",
100     "BEGIN PGP SECRET KEY BLOCK", /* only used by pgp2 */
101     NULL
102     };
103     static char *tail_strings[] = {
104     "END PGP MESSAGE",
105     "END PGP PUBLIC KEY BLOCK",
106     "END PGP SIGNATURE",
107     "END dummy",
108     "END PGP ARMORED FILE",
109     "END PGP PRIVATE KEY BLOCK",
110     "END PGP SECRET KEY BLOCK",
111     NULL
112     };
113    
114     static void
115     set_armor_error( const char *msg )
116     {
117     armor_errno = 1;
118     strcpy( armor_error, msg );
119     }
120    
121     const char*
122     get_armor_error( void )
123     {
124     if( armor_errno )
125     return armor_error;
126     return NULL;
127     }
128    
129    
130     static unsigned int
131     check_trailing_chars( const byte *line, unsigned int len,
132     const char *trimchars )
133     {
134     const byte *p, *mark;
135     unsigned int n;
136    
137     for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
138     if( strchr(trimchars, *p ) ) {
139     if( !mark )
140     mark = p;
141     }
142     else
143     mark = NULL;
144     }
145    
146     if( mark ) {
147     return mark - line;
148     }
149     return len;
150     }
151    
152     /****************
153     * remove trailing white spaces and return the length of the buffer
154     */
155     static unsigned int
156     check_trailing_ws( const byte *line, unsigned int len )
157     {
158     return check_trailing_chars( line, len, " \t\r\n" );
159     }
160    
161     static unsigned int
162     trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
163     {
164     byte *p, *mark;
165     unsigned n;
166    
167     for( mark=NULL, p=line, n=0; n < len; n++, p++ ) {
168     if( strchr(trimchars, *p ) ) {
169     if( !mark )
170     mark = p;
171     }
172     else
173     mark = NULL;
174     }
175    
176     if( mark ) {
177     *mark = 0;
178     return mark - line;
179     }
180     return len;
181     }
182    
183     static void
184     initialize(void)
185     {
186     int i, j;
187     u32 t;
188     byte *s;
189    
190     /* init the crc lookup table */
191     crc_table[0] = 0;
192     for( i=j=0; j < 128; j++ ) {
193     t = crc_table[j];
194     if( t & 0x00800000 ) {
195     t <<= 1;
196     crc_table[i++] = t ^ CRCPOLY;
197     crc_table[i++] = t;
198     }
199     else {
200     t <<= 1;
201     crc_table[i++] = t;
202     crc_table[i++] = t ^ CRCPOLY;
203     }
204     }
205     /* build the helptable for radix64 to bin conversion */
206     for( i = 0; i < 256; i++ )
207     asctobin[i] = 255; /* used to detect invalid characters */
208     for( s = bintoasc, i = 0; *s; s++,i++ )
209     asctobin[*s] = i;
210    
211     is_initialized=1;
212     }
213    
214     /****************
215     * Check whether this is an armored file or not See also
216     * parse-packet.c for details on this code For unknown historic
217     * reasons we use a string here but only the first byte will be used.
218     * Returns: True if it seems to be armored
219     */
220     static int
221     is_armored( const byte *buf )
222     {
223     int ctb, pkttype;
224    
225     ctb = *buf;
226     if( !(ctb & 0x80) )
227     return 1; /* invalid packet: assume it is armored */
228     pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
229     switch( pkttype ) {
230     case PKT_MARKER:
231     case PKT_SYMKEY_ENC:
232     case PKT_ONEPASS_SIG:
233     case PKT_PUBLIC_KEY:
234     case PKT_SECRET_KEY:
235     case PKT_PUBKEY_ENC:
236     case PKT_SIGNATURE:
237     case PKT_COMMENT:
238     case PKT_OLD_COMMENT:
239     case PKT_PLAINTEXT:
240     case PKT_COMPRESSED:
241     case PKT_ENCRYPTED:
242     return 0; /* seems to be a regular packet: not armored */
243     }
244    
245     return 1;
246     }
247    
248    
249     /****************
250     * Try to check whether the iobuf is armored
251     * Returns true if this may be the case; the caller should use the
252     * filter to do further processing.
253     */
254     int
255     gpg_use_armor_filter( gpg_iobuf_t a )
256     {
257     byte buf[1];
258     int n;
259    
260     /* fixme: there might be a problem with iobuf_peek */
261     n = gpg_iobuf_peek(a, buf, 1 );
262     if( n == -1 )
263     return 0; /* EOF, doesn't matter whether armored or not */
264     if( !n )
265     return 1; /* can't check it: try armored */
266     return is_armored(buf);
267     }
268    
269     /****************
270     * check whether the armor header is valid on a signed message.
271     * this is for security reasons: the header lines are not included in the
272     * hash and by using some creative formatting rules, Mallory could fake
273     * any text at the beginning of a document; assuming it is read with
274     * a simple viewer. We only allow the Hash Header.
275     */
276     static int
277     parse_hash_header( const char *line )
278     {
279     const char *s, *s2;
280     unsigned found = 0;
281    
282     if( strlen(line) < 6 || strlen(line) > 60 )
283     return 0; /* too short or too long */
284     if( memcmp( line, "Hash:", 5 ) )
285     return 0; /* invalid header */
286     s = line+5;
287     for( s = line + 5; ; s=s2 ) {
288     for(; *s && (*s==' ' || *s == '\t'); s++ )
289     ;
290     if( !*s )
291     break;
292     for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ )
293     ;
294     if( !strncmp( s, "RIPEMD160", s2-s ) )
295     found |= 1;
296     else if( !strncmp( s, "SHA1", s2-s ) )
297     found |= 2;
298     else if( !strncmp( s, "MD5", s2-s ) )
299     found |= 4;
300     else if( !strncmp( s, "TIGER192", s2-s ) )
301     found |= 8;
302     else if( !strncmp( s, "TIGER", s2-s ) ) /* used by old versions */
303     found |= 8;
304     else
305     return 0;
306     for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ )
307     ;
308     if( *s2 && *s2 != ',' )
309     return 0;
310     if( *s2 )
311     s2++;
312     }
313     return found;
314     }
315    
316    
317    
318     /****************
319     * Check whether this is a armor line.
320     * returns: -1 if it is not a armor header or the index number of the
321     * armor header.
322     */
323     static int
324     is_armor_header( byte *line, unsigned len )
325     {
326     const char *s;
327     byte *save_p, *p;
328     int save_c;
329     int i;
330    
331     if( len < 15 )
332     return -1; /* too short */
333     if( memcmp( line, "-----", 5 ) )
334     return -1; /* no */
335     p = strstr( line+5, "-----");
336     if( !p )
337     return -1;
338     save_p = p;
339     p += 5;
340    
341     /* Some mail programs on Windows seem to add spaces to the end of
342     the line. This becomes strict if --openpgp is set. */
343    
344     #if 0
345     if(!opt.rfc2440)
346     while(*p==' ')
347     p++;
348     #endif
349    
350     if( *p == '\r' )
351     p++;
352     if( *p == '\n' )
353     p++;
354     if( *p )
355     return -1; /* garbage after dashes */
356     save_c = *save_p; *save_p = 0;
357     p = line+5;
358     for(i=0; (s=head_strings[i]); i++ )
359     if( !strcmp(s, p) )
360     break;
361     *save_p = save_c;
362     if( !s )
363     return -1; /* unknown armor line */
364    
365     return i;
366     }
367    
368     void
369     print_string( FILE *fp, const byte *p, size_t n, int delim )
370     {
371     for( ; n; n--, p++ )
372     if( *p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim ||
373     (delim && *p=='\\')) {
374     putc('\\', fp);
375     if( *p == '\n' )
376     putc('n', fp);
377     else if( *p == '\r' )
378     putc('r', fp);
379     else if( *p == '\f' )
380     putc('f', fp);
381     else if( *p == '\v' )
382     putc('v', fp);
383     else if( *p == '\b' )
384     putc('b', fp);
385     else if( !*p )
386     putc('0', fp);
387     else
388     fprintf(fp, "x%02x", *p );
389     }
390     else
391     putc(*p, fp);
392     }
393    
394     /****************
395     * Parse a header lines
396     * Return 0: Empty line (end of header lines)
397     * -1: invalid header line
398     * >0: Good header line
399     */
400     static int
401     parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len )
402     {
403     byte *p;
404     int hashes=0;
405     unsigned int len2;
406    
407     len2 = check_trailing_ws( line, len );
408     if( !len2 ) {
409     afx->buffer_pos = len2; /* (it is not the fine way to do it here) */
410     return 0; /* WS only: same as empty line */
411     }
412     len = len2;
413     line[len2] = 0;
414    
415     p = strchr( line, ':');
416     if( !p || !p[1] ) {
417     set_armor_error("invalid armor header: ");
418     print_string( stderr, line, len, 0 );
419     putc('\n', stderr);
420     return -1;
421     }
422    
423     if( afx->in_cleartext ) {
424     if( (hashes=parse_hash_header( line )) )
425     afx->hashes |= hashes;
426     else if( strlen(line) > 15 && !memcmp( line, "NotDashEscaped:", 15 ) )
427     afx->not_dash_escaped = 1;
428     else {
429     set_armor_error("invalid clearsig header\n");
430     return -1;
431     }
432     }
433     return 1;
434     }
435    
436    
437    
438     /* figure out whether the data is armored or not */
439     static int
440     check_input( armor_filter_context_t *afx, gpg_iobuf_t a )
441     {
442     int rc = 0;
443     int i;
444     byte *line;
445     unsigned len;
446     unsigned maxlen;
447     int hdr_line = -1;
448    
449     /* read the first line to see whether this is armored data */
450     maxlen = MAX_LINELEN;
451     len = afx->buffer_len = gpg_iobuf_read_line( a, &afx->buffer,
452     &afx->buffer_size, &maxlen );
453     line = afx->buffer;
454     if( !maxlen ) {
455     /* line has been truncated: assume not armored */
456     afx->inp_checked = 1;
457     afx->inp_bypass = 1;
458     return 0;
459     }
460    
461     if( !len ) {
462     return -1; /* eof */
463     }
464    
465     /* (the line is always a C string but maybe longer) */
466     if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
467     ;
468     else if( !is_armored( line ) ) {
469     afx->inp_checked = 1;
470     afx->inp_bypass = 1;
471     return 0;
472     }
473    
474     /* find the armor header */
475     while(len) {
476     i = is_armor_header( line, len );
477     if( i >= 0 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
478     hdr_line = i;
479     if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
480     if( afx->in_cleartext ) {
481     set_armor_error("nested clear text signatures\n");
482     rc = G10ERR_INVALID_ARMOR;
483     }
484     afx->in_cleartext = 1;
485     }
486     break;
487     }
488     /* read the next line (skip all truncated lines) */
489     do {
490     maxlen = MAX_LINELEN;
491     afx->buffer_len = gpg_iobuf_read_line( a, &afx->buffer,
492     &afx->buffer_size, &maxlen );
493     line = afx->buffer;
494     len = afx->buffer_len;
495     } while( !maxlen );
496     }
497    
498     /* parse the header lines */
499     while(len) {
500     /* read the next line (skip all truncated lines) */
501     do {
502     maxlen = MAX_LINELEN;
503     afx->buffer_len = gpg_iobuf_read_line( a, &afx->buffer,
504     &afx->buffer_size, &maxlen );
505     line = afx->buffer;
506     len = afx->buffer_len;
507     } while( !maxlen );
508    
509     i = parse_header_line( afx, line, len );
510     if( i <= 0 ) {
511     if( i )
512     rc = G10ERR_INVALID_ARMOR;
513     break;
514     }
515     }
516    
517     if( afx->in_cleartext )
518     afx->faked = 1;
519     else {
520     afx->inp_checked = 1;
521     afx->crc = CRCINIT;
522     afx->idx = 0;
523     afx->radbuf[0] = 0;
524     }
525    
526     return rc;
527     }
528    
529    
530    
531     /****************
532     * Fake a literal data packet and wait for the next armor line
533     * fixme: empty line handling and null length clear text signature are
534     * not implemented/checked.
535     */
536     static int
537     fake_packet( armor_filter_context_t *afx, gpg_iobuf_t a,
538     size_t *retn, byte *buf, size_t size )
539     {
540     int rc = 0;
541     size_t len = 0;
542     int lastline = 0;
543     unsigned maxlen, n;
544     byte *p;
545    
546     len = 2; /* reserve 2 bytes for the length header */
547     size -= 2; /* and 2 for the terminating header */
548     while( !rc && len < size ) {
549     /* copy what we have in the line buffer */
550     if( afx->faked == 1 )
551     afx->faked++; /* skip the first (empty) line */
552     else {
553     while( len < size && afx->buffer_pos < afx->buffer_len )
554     buf[len++] = afx->buffer[afx->buffer_pos++];
555     if( len >= size )
556     continue;
557     }
558    
559     /* read the next line */
560     maxlen = MAX_LINELEN;
561     afx->buffer_pos = 0;
562     afx->buffer_len = gpg_iobuf_read_line( a, &afx->buffer,
563     &afx->buffer_size, &maxlen );
564     if( !afx->buffer_len ) {
565     rc = -1; /* eof (should not happen) */
566     continue;
567     }
568     if( !maxlen )
569     afx->truncated++;
570     if( !afx->not_dash_escaped ) {
571     int crlf;
572     p = afx->buffer;
573     n = afx->buffer_len;
574     crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n';
575    
576     /* PGP2 does not treat a tab as white space character */
577     afx->buffer_len = trim_trailing_chars( p, n,
578     afx->pgp2mode ? " \r\n" : " \t\r\n");
579     /* the buffer is always allocated with enough space to append
580     * the removed [CR], LF and a Nul
581     * The reason for this complicated procedure is to keep at least
582     * the original type of lineending - handling of the removed
583     * trailing spaces seems to be impossible in our method
584     * of faking a packet; either we have to use a temporary file
585     * or calculate the hash here in this module and somehow find
586     * a way to send the hash down the processing line (well, a special
587     * faked packet could do the job).
588     */
589     if( crlf )
590     afx->buffer[afx->buffer_len++] = '\r';
591     afx->buffer[afx->buffer_len++] = '\n';
592     afx->buffer[afx->buffer_len] = 0;
593     }
594     p = afx->buffer;
595     n = afx->buffer_len;
596    
597     if( n > 2 && *p == '-' ) {
598     /* check for dash escaped or armor header */
599     if( p[1] == ' ' && !afx->not_dash_escaped ) {
600     /* issue a warning if it is not regular encoded */
601     if( p[2] != '-' && !( n > 6 && !memcmp(p+2, "From ", 5))) {
602     set_armor_error("invalid dash escaped line: ");
603     print_string( stderr, p, n, 0 );
604     putc('\n', stderr);
605     }
606     afx->buffer_pos = 2; /* skip */
607     }
608     else if( n >= 15 && p[1] == '-' && p[2] == '-' && p[3] == '-' ) {
609     int type = is_armor_header( p, n );
610     if( afx->not_dash_escaped && type != BEGIN_SIGNATURE )
611     ; /* this is okay */
612     else {
613     if( type != BEGIN_SIGNATURE ) {
614     set_armor_error("unexpected armor:");
615     print_string( stderr, p, n, 0 );
616     putc('\n', stderr);
617     }
618     lastline = 1;
619     rc = -1;
620     }
621     }
622     }
623     }
624    
625     buf[0] = (len-2) >> 8;
626     buf[1] = (len-2);
627     if( lastline ) { /* write last (ending) length header */
628     if( buf[0] || buf[1] ) { /* only if we have some text */
629     buf[len++] = 0;
630     buf[len++] = 0;
631     }
632     rc = 0;
633     afx->faked = 0;
634     afx->in_cleartext = 0;
635     /* and now read the header lines */
636     afx->buffer_pos = 0;
637     for(;;) {
638     int i;
639    
640     /* read the next line (skip all truncated lines) */
641     do {
642     maxlen = MAX_LINELEN;
643     afx->buffer_len = gpg_iobuf_read_line( a, &afx->buffer,
644     &afx->buffer_size, &maxlen );
645     } while( !maxlen );
646     p = afx->buffer;
647     n = afx->buffer_len;
648     if( !n ) {
649     rc = -1;
650     break; /* eof */
651     }
652     i = parse_header_line( afx, p , n );
653     if( i <= 0 ) {
654     if( i )
655     MessageBox( NULL, "Invalid ARMOR detected", "Error", MB_OK );
656     break;
657     }
658     }
659     afx->inp_checked = 1;
660     afx->crc = CRCINIT;
661     afx->idx = 0;
662     afx->radbuf[0] = 0;
663     }
664    
665     *retn = len;
666     return rc;
667     }
668    
669    
670     static int
671     invalid_crc(void)
672     {
673     return G10ERR_INVALID_ARMOR;
674     }
675    
676    
677     static int
678     radix64_read( armor_filter_context_t *afx, gpg_iobuf_t a, size_t *retn,
679     byte *buf, size_t size )
680     {
681     byte val;
682     int c=0, c2; /*init c because gcc is not clever enough for the continue*/
683     int checkcrc=0;
684     int rc = 0;
685     size_t n = 0;
686     int idx, i;
687     u32 crc;
688    
689     crc = afx->crc;
690     idx = afx->idx;
691     val = afx->radbuf[0];
692     for( n=0; n < size; ) {
693    
694     if( afx->buffer_pos < afx->buffer_len )
695     c = afx->buffer[afx->buffer_pos++];
696     else { /* read the next line */
697     unsigned maxlen = MAX_LINELEN;
698     afx->buffer_pos = 0;
699     afx->buffer_len = gpg_iobuf_read_line( a, &afx->buffer,
700     &afx->buffer_size, &maxlen );
701     if( !maxlen )
702     afx->truncated++;
703     if( !afx->buffer_len )
704     break; /* eof */
705     continue;
706     }
707    
708     again:
709     if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
710     continue;
711     else if( c == '=' ) { /* pad character: stop */
712     /* some mailers leave quoted-printable encoded characters
713     * so we try to workaround this */
714     if( afx->buffer_pos+2 < afx->buffer_len ) {
715     int cc1, cc2, cc3;
716     cc1 = afx->buffer[afx->buffer_pos];
717     cc2 = afx->buffer[afx->buffer_pos+1];
718     cc3 = afx->buffer[afx->buffer_pos+2];
719     if( isxdigit(cc1) && isxdigit(cc2)
720     && strchr( "=\n\r\t ", cc3 )) {
721     /* well it seems to be the case - adjust */
722     c = isdigit(cc1)? (cc1 - '0'): (toupper(cc1)-'A'+10);
723     c <<= 4;
724     c |= isdigit(cc2)? (cc2 - '0'): (toupper(cc2)-'A'+10);
725     afx->buffer_pos += 2;
726     afx->qp_detected = 1;
727     goto again;
728     }
729     }
730    
731     if( idx == 1 )
732     buf[n++] = val;
733     checkcrc++;
734     break;
735     }
736     else if( (c = asctobin[(c2=c)]) == 255 ) {
737     char msg[128];
738     _snprintf( msg, sizeof msg-1, "invalid radix64 character %02x skipped\n", c2);
739     set_armor_error( msg );
740     continue;
741     }
742     switch(idx) {
743     case 0: val = c << 2; break;
744     case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
745     case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
746     case 3: val |= c&0x3f; buf[n++] = val; break;
747     }
748     idx = (idx+1) % 4;
749     }
750    
751     for(i=0; i < n; i++ )
752     crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
753     crc &= 0x00ffffff;
754     afx->crc = crc;
755     afx->idx = idx;
756     afx->radbuf[0] = val;
757    
758     if( checkcrc ) {
759     afx->any_data = 1;
760     afx->inp_checked=0;
761     afx->faked = 0;
762     for(;;) { /* skip lf and pad characters */
763     if( afx->buffer_pos < afx->buffer_len )
764     c = afx->buffer[afx->buffer_pos++];
765     else { /* read the next line */
766     unsigned maxlen = MAX_LINELEN;
767     afx->buffer_pos = 0;
768     afx->buffer_len = gpg_iobuf_read_line( a, &afx->buffer,
769     &afx->buffer_size, &maxlen );
770     if( !maxlen )
771     afx->truncated++;
772     if( !afx->buffer_len )
773     break; /* eof */
774     continue;
775     }
776     if( c == '\n' || c == ' ' || c == '\r'
777     || c == '\t' || c == '=' )
778     continue;
779     break;
780     }
781     if( c == -1 )
782     set_armor_error("premature eof (no CRC)\n");
783     else {
784     u32 mycrc = 0;
785     idx = 0;
786     do {
787     if( (c = asctobin[c]) == 255 )
788     break;
789     switch(idx) {
790     case 0: val = c << 2; break;
791     case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
792     case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
793     case 3: val |= c&0x3f; mycrc |= val; break;
794     }
795     for(;;) {
796     if( afx->buffer_pos < afx->buffer_len )
797     c = afx->buffer[afx->buffer_pos++];
798     else { /* read the next line */
799     unsigned maxlen = MAX_LINELEN;
800     afx->buffer_pos = 0;
801     afx->buffer_len = gpg_iobuf_read_line( a, &afx->buffer,
802     &afx->buffer_size,
803     &maxlen );
804     if( !maxlen )
805     afx->truncated++;
806     if( !afx->buffer_len )
807     break; /* eof */
808     continue;
809     }
810     break;
811     }
812     if( !afx->buffer_len )
813     break; /* eof */
814     } while( ++idx < 4 );
815     if( c == -1 ) {
816     set_armor_error("premature eof (in CRC)\n");
817     rc = invalid_crc();
818     }
819     else if( idx != 4 ) {
820     set_armor_error("malformed CRC\n");
821     rc = invalid_crc();
822     }
823     else if( mycrc != afx->crc ) {
824     char msg[128];
825     _snprintf( msg, sizeof msg-1,
826     "CRC error; %06lx - %06lx\n",
827     (ulong)afx->crc, (ulong)mycrc);
828     set_armor_error( msg );
829     rc = invalid_crc();
830     }
831     else {
832     rc = 0;
833     }
834     }
835     }
836    
837     if( !n )
838     rc = -1;
839    
840     *retn = n;
841     return rc;
842     }
843    
844     /****************
845     * This filter is used to handle the armor stuff
846     */
847     int
848     gpg_armor_filter( void *opaque, int control,
849     gpg_iobuf_t a, byte *buf, size_t *ret_len)
850     {
851     size_t size = *ret_len;
852     armor_filter_context_t *afx = opaque;
853     int rc=0, i, c;
854     byte radbuf[3];
855     int idx, idx2;
856     size_t n=0;
857     u32 crc;
858    
859     if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
860     n = 0;
861     if( afx->buffer_len ) {
862     for(; n < size && afx->buffer_pos < afx->buffer_len; n++ )
863     buf[n++] = afx->buffer[afx->buffer_pos++];
864     if( afx->buffer_pos >= afx->buffer_len )
865     afx->buffer_len = 0;
866     }
867     for(; n < size; n++ ) {
868     if( (c=gpg_iobuf_get(a)) == -1 )
869     break;
870     buf[n] = c & 0xff;
871     }
872     if( !n )
873     rc = -1;
874     *ret_len = n;
875     }
876     else if( control == IOBUFCTRL_UNDERFLOW ) {
877     /* We need some space for the faked packet. The minmum required
878     * size is ~18 + length of the session marker */
879     if( size < 50 ) {
880     printf( "This is a BUG.\n%s:%d\n", __FILE__, __LINE__ );
881     exit( -1 ); /* supplied buffer too short */
882     }
883     if( afx->faked )
884     rc = fake_packet( afx, a, &n, buf, size );
885     else if( !afx->inp_checked ) {
886     rc = check_input( afx, a );
887     if( afx->inp_bypass ) {
888     for(n=0; n < size && afx->buffer_pos < afx->buffer_len; )
889     buf[n++] = afx->buffer[afx->buffer_pos++];
890     if( afx->buffer_pos >= afx->buffer_len )
891     afx->buffer_len = 0;
892     if( !n )
893     rc = -1;
894     }
895     else if( afx->faked ) {
896     unsigned int hashes = afx->hashes;
897     const byte *sesmark;
898     size_t sesmarklen;
899    
900     sesmark = get_session_marker( &sesmarklen );
901     if ( sesmarklen > 20 ) {
902     printf( "This is a BUG.\n%s:%d\n", __FILE__, __LINE__ );
903     exit( -1 );
904     }
905     /* the buffer is at least 15+n*15 bytes long, so it
906     * is easy to construct the packets */
907    
908     hashes &= 1|2|4|8;
909     if( !hashes ) {
910     hashes |= 4; /* default to MD 5 */
911     afx->pgp2mode = 1;
912     }
913     n=0;
914     /* first a gpg control packet */
915     buf[n++] = 0xff; /* new format, type 63, 1 length byte */
916     n++; /* see below */
917     memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
918     buf[n++] = CTRLPKT_CLEARSIGN_START;
919     buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
920     if( hashes & 1 )
921     buf[n++] = DIGEST_ALGO_RMD160;
922     if( hashes & 2 )
923     buf[n++] = DIGEST_ALGO_SHA1;
924     if( hashes & 4 )
925     buf[n++] = DIGEST_ALGO_MD5;
926     buf[1] = n - 2;
927    
928     /* followed by a plaintext packet */
929     buf[n++] = 0xaf; /* old packet format, type 11, var length */
930     buf[n++] = 0; /* set the length header */
931     buf[n++] = 6;
932     buf[n++] = 't'; /* canonical text mode */
933     buf[n++] = 0; /* namelength */
934     memset(buf+n, 0, 4); /* timestamp */
935     n += 4;
936     }
937     else if( !rc )
938     rc = radix64_read( afx, a, &n, buf, size );
939     }
940     else
941     rc = radix64_read( afx, a, &n, buf, size );
942     *ret_len = n;
943     }
944     else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) {
945     /* we don't need this ;-) */
946     }
947     else if( control == IOBUFCTRL_INIT ) {
948     if( !is_initialized )
949     initialize();
950     }
951     else if( control == IOBUFCTRL_CANCEL ) {
952     afx->cancel = 1;
953     }
954     else if( control == IOBUFCTRL_FREE ) {
955     if( afx->cancel )
956     ;
957     else if( afx->status ) { /* pad, write cecksum, and bottom line */
958     crc = afx->crc;
959     idx = afx->idx;
960     idx2 = afx->idx2;
961     for(i=0; i < idx; i++ )
962     radbuf[i] = afx->radbuf[i];
963     if( idx ) {
964     c = bintoasc[(*radbuf>>2)&077];
965     gpg_iobuf_put(a, c);
966     if( idx == 1 ) {
967     c = bintoasc[((*radbuf << 4) & 060) & 077];
968     gpg_iobuf_put(a, c);
969     gpg_iobuf_put(a, '=');
970     gpg_iobuf_put(a, '=');
971     }
972     else { /* 2 */
973     c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
974     gpg_iobuf_put(a, c);
975     c = bintoasc[((radbuf[1] << 2) & 074) & 077];
976     gpg_iobuf_put(a, c);
977     gpg_iobuf_put(a, '=');
978     }
979     if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
980     gpg_iobuf_writestr(a, LF );
981     idx2=0;
982     }
983     }
984     /* may need a linefeed */
985     if( idx2 )
986     gpg_iobuf_writestr(a, LF );
987     /* write the CRC */
988     gpg_iobuf_put(a, '=');
989     radbuf[0] = crc >>16;
990     radbuf[1] = crc >> 8;
991     radbuf[2] = crc;
992     c = bintoasc[(*radbuf >> 2) & 077];
993     gpg_iobuf_put(a, c);
994     c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
995     gpg_iobuf_put(a, c);
996     c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
997     gpg_iobuf_put(a, c);
998     c = bintoasc[radbuf[2]&077];
999     gpg_iobuf_put(a, c);
1000     gpg_iobuf_writestr(a, LF );
1001     /* and the the trailer */
1002     if( afx->what >= DIM(tail_strings) )
1003     printf("afx->what=%d", afx->what);
1004     gpg_iobuf_writestr(a, "-----");
1005     gpg_iobuf_writestr(a, tail_strings[afx->what] );
1006     gpg_iobuf_writestr(a, "-----" LF );
1007     }
1008     else if( !afx->any_data && !afx->inp_bypass ) {
1009     set_armor_error("no valid OpenPGP data found.\n");
1010     afx->no_openpgp_data = 1;
1011     printf( "[GNUPG:] NODATA 1" );
1012     }
1013     if( afx->truncated ) {
1014     char msg[128];
1015     _snprintf( msg, sizeof msg-1, "invalid armor: line longer than %d characters\n", MAX_LINELEN );
1016     set_armor_error( msg );
1017     }
1018     /* issue an error to enforce dissemination of correct software */
1019     if( afx->qp_detected )
1020     set_armor_error("quoted printable character in armor - "
1021     "probably a buggy MTA has been used\n" );
1022     safe_free( afx->buffer );
1023     afx->buffer = NULL;
1024     }
1025     else if( control == IOBUFCTRL_DESC )
1026     *(char**)buf = "armor_filter";
1027     return rc;
1028     }
1029    
1030     /***********************************************
1031     * For the pipemode command we can't use the armor filter for various
1032     * reasons, so we use this new unarmor_pump stuff to remove the armor
1033     */
1034    
1035     enum unarmor_state_e {
1036     STA_init = 0,
1037     STA_bypass,
1038     STA_wait_newline,
1039     STA_wait_dash,
1040     STA_first_dash,
1041     STA_compare_header,
1042     STA_found_header_wait_newline,
1043     STA_skip_header_lines,
1044     STA_skip_header_lines_non_ws,
1045     STA_read_data,
1046     STA_wait_crc,
1047     STA_read_crc,
1048     STA_ready
1049     };
1050    
1051     struct unarmor_pump_s {
1052     enum unarmor_state_e state;
1053     byte val;
1054     int checkcrc;
1055     int pos; /* counts from 0..3 */
1056     u32 crc;
1057     u32 mycrc; /* the one store in the data */
1058     };
1059    
1060    
1061    
1062     UnarmorPump
1063     unarmor_pump_new (void)
1064     {
1065     UnarmorPump x;
1066    
1067     if( !is_initialized )
1068     initialize();
1069     x = calloc (1, sizeof *x);
1070     return x;
1071     }
1072    
1073     void
1074     unarmor_pump_release (UnarmorPump x)
1075     {
1076     safe_free (x);
1077     }
1078    
1079     /*
1080     * Get the next character from the ascii armor taken from the gpg_iobuf_t
1081     * created earlier by unarmor_pump_new().
1082     * Return: c = Character
1083     * 256 = ignore this value
1084     * -1 = End of current armor
1085     * -2 = Premature EOF (not used)
1086     * -3 = Invalid armor
1087     */
1088     int
1089     unarmor_pump (UnarmorPump x, int c)
1090     {
1091     int rval = 256; /* default is to ignore the return value */
1092    
1093     switch (x->state) {
1094     case STA_init:
1095     {
1096     byte tmp[1];
1097     tmp[0] = c;
1098     if ( is_armored (tmp) )
1099     x->state = c == '-'? STA_first_dash : STA_wait_newline;
1100     else {
1101     x->state = STA_bypass;
1102     return c;
1103     }
1104     }
1105     break;
1106     case STA_bypass:
1107     return c; /* return here to avoid crc calculation */
1108     case STA_wait_newline:
1109     if (c == '\n')
1110     x->state = STA_wait_dash;
1111     break;
1112     case STA_wait_dash:
1113     x->state = c == '-'? STA_first_dash : STA_wait_newline;
1114     break;
1115     case STA_first_dash: /* just need for initalization */
1116     x->pos = 0;
1117     x->state = STA_compare_header;
1118     case STA_compare_header:
1119     if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) {
1120     if ( x->pos == 28 )
1121     x->state = STA_found_header_wait_newline;
1122     }
1123     else
1124     x->state = c == '\n'? STA_wait_dash : STA_wait_newline;
1125     break;
1126     case STA_found_header_wait_newline:
1127     /* to make CR,LF issues easier we simply allow for white space
1128     behind the 5 dashes */
1129     if ( c == '\n' )
1130     x->state = STA_skip_header_lines;
1131     else if ( c != '\r' && c != ' ' && c != '\t' )
1132     x->state = STA_wait_dash; /* garbage after the header line */
1133     break;
1134     case STA_skip_header_lines:
1135     /* i.e. wait for one empty line */
1136     if ( c == '\n' ) {
1137     x->state = STA_read_data;
1138     x->crc = CRCINIT;
1139     x->val = 0;
1140     x->pos = 0;
1141     }
1142     else if ( c != '\r' && c != ' ' && c != '\t' )
1143     x->state = STA_skip_header_lines_non_ws;
1144     break;
1145     case STA_skip_header_lines_non_ws:
1146     /* like above but we already encountered non white space */
1147     if ( c == '\n' )
1148     x->state = STA_skip_header_lines;
1149     break;
1150     case STA_read_data:
1151     /* fixme: we don't check for the trailing dash lines but rely
1152     * on the armor stop characters */
1153     if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
1154     break; /* skip all kind of white space */
1155    
1156     if( c == '=' ) { /* pad character: stop */
1157     if( x->pos == 1 ) /* in this case val has some value */
1158     rval = x->val;
1159     x->state = STA_wait_crc;
1160     break;
1161     }
1162    
1163     {
1164     int c2;
1165     if( (c = asctobin[(c2=c)]) == 255 ) {
1166     char msg[128];
1167     _snprintf( msg, sizeof msg-1, "invalid radix64 character %02x skipped\n", c2);
1168     set_armor_error( msg );
1169     break;
1170     }
1171     }
1172    
1173     switch(x->pos) {
1174     case 0:
1175     x->val = c << 2;
1176     break;
1177     case 1:
1178     x->val |= (c>>4)&3;
1179     rval = x->val;
1180     x->val = (c<<4)&0xf0;
1181     break;
1182     case 2:
1183     x->val |= (c>>2)&15;
1184     rval = x->val;
1185     x->val = (c<<6)&0xc0;
1186     break;
1187     case 3:
1188     x->val |= c&0x3f;
1189     rval = x->val;
1190     break;
1191     }
1192     x->pos = (x->pos+1) % 4;
1193     break;
1194     case STA_wait_crc:
1195     if( c == '\n' || c == ' ' || c == '\r' || c == '\t' || c == '=' )
1196     break; /* skip ws and pad characters */
1197     /* assume that we are at the next line */
1198     x->state = STA_read_crc;
1199     x->pos = 0;
1200     x->mycrc = 0;
1201     case STA_read_crc:
1202     if( (c = asctobin[c]) == 255 ) {
1203     rval = -1; /* ready */
1204     if( x->crc != x->mycrc ) {
1205     char msg[128];
1206     _snprintf( msg, sizeof msg-1, "CRC error; %06lx - %06lx\n",
1207     (ulong)x->crc, (ulong)x->mycrc);
1208     set_armor_error( msg );
1209     if ( invalid_crc() )
1210     rval = -3;
1211     }
1212     x->state = STA_ready; /* not sure whether this is correct */
1213     break;
1214     }
1215    
1216     switch(x->pos) {
1217     case 0:
1218     x->val = c << 2;
1219     break;
1220     case 1:
1221     x->val |= (c>>4)&3;
1222     x->mycrc |= x->val << 16;
1223     x->val = (c<<4)&0xf0;
1224     break;
1225     case 2:
1226     x->val |= (c>>2)&15;
1227     x->mycrc |= x->val << 8;
1228     x->val = (c<<6)&0xc0;
1229     break;
1230     case 3:
1231     x->val |= c&0x3f;
1232     x->mycrc |= x->val;
1233     break;
1234     }
1235     x->pos = (x->pos+1) % 4;
1236     break;
1237     case STA_ready:
1238     rval = -1;
1239     break;
1240     }
1241    
1242     if ( !(rval & ~255) ) { /* compute the CRC */
1243     x->crc = (x->crc << 8) ^ crc_table[((x->crc >> 16)&0xff) ^ rval];
1244     x->crc &= 0x00ffffff;
1245     }
1246    
1247     return rval;
1248     }
1249    
1250    

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26