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

Contents of /trunk/Gnupg/armor.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 46 - (show 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 /* 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