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

Contents of /trunk/Gnupg/armor.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 256 - (show annotations)
Sat Aug 5 10:31:06 2006 UTC (18 years, 6 months ago) by twoaday
File MIME type: text/plain
File size: 32482 byte(s)
1.0.0pre3 release.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26