Line data Source code
1 : /* armor.c - Armor flter
2 : * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3 : * 2007 Free Software Foundation, Inc.
4 : *
5 : * This file is part of GnuPG.
6 : *
7 : * GnuPG is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * GnuPG is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with this program; if not, see <https://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <config.h>
22 : #include <stdio.h>
23 : #include <stdlib.h>
24 : #include <string.h>
25 : #include <errno.h>
26 : #include <ctype.h>
27 :
28 : #include "gpg.h"
29 : #include "status.h"
30 : #include "iobuf.h"
31 : #include "util.h"
32 : #include "filter.h"
33 : #include "packet.h"
34 : #include "options.h"
35 : #include "main.h"
36 : #include "status.h"
37 : #include "i18n.h"
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 :
54 :
55 : typedef enum {
56 : fhdrHASArmor = 0,
57 : fhdrNOArmor,
58 : fhdrINIT,
59 : fhdrINITCont,
60 : fhdrINITSkip,
61 : fhdrCHECKBegin,
62 : fhdrWAITHeader,
63 : fhdrWAITClearsig,
64 : fhdrSKIPHeader,
65 : fhdrCLEARSIG,
66 : fhdrREADClearsig,
67 : fhdrNullClearsig,
68 : fhdrEMPTYClearsig,
69 : fhdrCHECKClearsig,
70 : fhdrCHECKClearsig2,
71 : fhdrCHECKDashEscaped,
72 : fhdrCHECKDashEscaped2,
73 : fhdrCHECKDashEscaped3,
74 : fhdrREADClearsigNext,
75 : fhdrENDClearsig,
76 : fhdrENDClearsigHelp,
77 : fhdrTESTSpaces,
78 : fhdrCLEARSIGSimple,
79 : fhdrCLEARSIGSimpleNext,
80 : fhdrTEXT,
81 : fhdrTEXTSimple,
82 : fhdrERROR,
83 : fhdrERRORShow,
84 : fhdrEOF
85 : } fhdr_state_t;
86 :
87 :
88 : /* if we encounter this armor string with this index, go
89 : * into a mode which fakes packets and wait for the next armor */
90 : #define BEGIN_SIGNATURE 2
91 : #define BEGIN_SIGNED_MSG_IDX 3
92 : static char *head_strings[] = {
93 : "BEGIN PGP MESSAGE",
94 : "BEGIN PGP PUBLIC KEY BLOCK",
95 : "BEGIN PGP SIGNATURE",
96 : "BEGIN PGP SIGNED MESSAGE",
97 : "BEGIN PGP ARMORED FILE", /* gnupg extension */
98 : "BEGIN PGP PRIVATE KEY BLOCK",
99 : "BEGIN PGP SECRET KEY BLOCK", /* only used by pgp2 */
100 : NULL
101 : };
102 : static char *tail_strings[] = {
103 : "END PGP MESSAGE",
104 : "END PGP PUBLIC KEY BLOCK",
105 : "END PGP SIGNATURE",
106 : "END dummy",
107 : "END PGP ARMORED FILE",
108 : "END PGP PRIVATE KEY BLOCK",
109 : "END PGP SECRET KEY BLOCK",
110 : NULL
111 : };
112 :
113 :
114 : static int armor_filter ( void *opaque, int control,
115 : iobuf_t chain, byte *buf, size_t *ret_len);
116 :
117 :
118 :
119 :
120 : /* Create a new context for armor filters. */
121 : armor_filter_context_t *
122 397 : new_armor_context (void)
123 : {
124 : armor_filter_context_t *afx;
125 :
126 397 : afx = xcalloc (1, sizeof *afx);
127 397 : afx->refcount = 1;
128 :
129 397 : return afx;
130 : }
131 :
132 : /* Release an armor filter context. Passing NULL is explicitly
133 : allowed and a no-op. */
134 : void
135 2124 : release_armor_context (armor_filter_context_t *afx)
136 : {
137 2124 : if (!afx)
138 1431 : return;
139 693 : log_assert (afx->refcount);
140 693 : if ( --afx->refcount )
141 299 : return;
142 394 : xfree (afx);
143 : }
144 :
145 : /* Push the armor filter onto the iobuf stream IOBUF. */
146 : int
147 299 : push_armor_filter (armor_filter_context_t *afx, iobuf_t iobuf)
148 : {
149 : int rc;
150 :
151 299 : afx->refcount++;
152 299 : rc = iobuf_push_filter (iobuf, armor_filter, afx);
153 299 : if (rc)
154 0 : afx->refcount--;
155 299 : return rc;
156 : }
157 :
158 :
159 :
160 :
161 :
162 : static void
163 245 : initialize(void)
164 : {
165 : int i, j;
166 : u32 t;
167 : byte *s;
168 :
169 : /* init the crc lookup table */
170 245 : crc_table[0] = 0;
171 31605 : for(i=j=0; j < 128; j++ ) {
172 31360 : t = crc_table[j];
173 31360 : if( t & 0x00800000 ) {
174 15680 : t <<= 1;
175 15680 : crc_table[i++] = t ^ CRCPOLY;
176 15680 : crc_table[i++] = t;
177 : }
178 : else {
179 15680 : t <<= 1;
180 15680 : crc_table[i++] = t;
181 15680 : crc_table[i++] = t ^ CRCPOLY;
182 : }
183 : }
184 : /* build the helptable for radix64 to bin conversion */
185 62965 : for(i=0; i < 256; i++ )
186 62720 : asctobin[i] = 255; /* used to detect invalid characters */
187 15925 : for(s=bintoasc,i=0; *s; s++,i++ )
188 15680 : asctobin[*s] = i;
189 :
190 245 : is_initialized=1;
191 245 : }
192 :
193 :
194 : /*
195 : * Check whether this is an armored file. See also
196 : * parse-packet.c for details on this code.
197 : *
198 : * Note that the buffer BUF needs to be at least 2 bytes long. If in
199 : * doubt that the second byte to 0.
200 : *
201 : * Returns: True if it seems to be armored
202 : */
203 : static int
204 939 : is_armored (const byte *buf)
205 : {
206 : int ctb, pkttype;
207 : int indeterminate_length_allowed;
208 :
209 939 : ctb = *buf;
210 939 : if( !(ctb & 0x80) )
211 : /* The most significant bit of the CTB must be set. Since it is
212 : cleared, this is not a binary OpenPGP message. Assume it is
213 : armored. */
214 531 : return 1;
215 :
216 408 : pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
217 408 : switch( pkttype ) {
218 : case PKT_PUBKEY_ENC:
219 : case PKT_SIGNATURE:
220 : case PKT_SYMKEY_ENC:
221 : case PKT_ONEPASS_SIG:
222 : case PKT_SECRET_KEY:
223 : case PKT_PUBLIC_KEY:
224 : case PKT_SECRET_SUBKEY:
225 : case PKT_MARKER:
226 : case PKT_RING_TRUST:
227 : case PKT_USER_ID:
228 : case PKT_PUBLIC_SUBKEY:
229 : case PKT_ATTRIBUTE:
230 : case PKT_MDC:
231 315 : indeterminate_length_allowed = 0;
232 315 : break;
233 :
234 : case PKT_COMPRESSED:
235 : case PKT_ENCRYPTED:
236 : case PKT_ENCRYPTED_MDC:
237 : case PKT_PLAINTEXT:
238 : case PKT_OLD_COMMENT:
239 : case PKT_COMMENT:
240 : case PKT_GPG_CONTROL:
241 93 : indeterminate_length_allowed = 1;
242 93 : break;
243 :
244 : default:
245 : /* Invalid packet type. */
246 0 : return 1;
247 : }
248 :
249 408 : if (! indeterminate_length_allowed)
250 : /* It is only legal to use an indeterminate length with a few
251 : packet types. If a packet uses an indeterminate length, but
252 : that is not allowed, then the data is not valid binary
253 : OpenPGP data. */
254 : {
255 : int new_format;
256 : int indeterminate_length;
257 :
258 315 : new_format = !! (ctb & (1 << 6));
259 315 : if (new_format)
260 1 : indeterminate_length = (buf[1] >= 224 && buf[1] < 255);
261 : else
262 314 : indeterminate_length = (ctb & 3) == 3;
263 :
264 315 : if (indeterminate_length)
265 0 : return 1;
266 : }
267 :
268 : /* The first CTB seems legit. It is probably not armored
269 : data. */
270 408 : return 0;
271 : }
272 :
273 :
274 : /****************
275 : * Try to check whether the iobuf is armored
276 : * Returns true if this may be the case; the caller should use the
277 : * filter to do further processing.
278 : */
279 : int
280 482 : use_armor_filter( IOBUF a )
281 : {
282 : byte buf[2];
283 : int n;
284 :
285 : /* fixme: there might be a problem with iobuf_peek */
286 482 : n = iobuf_peek (a, buf, 2);
287 482 : if( n == -1 )
288 0 : return 0; /* EOF, doesn't matter whether armored or not */
289 482 : if( !n )
290 0 : return 1; /* can't check it: try armored */
291 482 : if (n != 2)
292 1 : return 0; /* short buffer */
293 481 : return is_armored(buf);
294 : }
295 :
296 :
297 :
298 :
299 : static void
300 0 : invalid_armor(void)
301 : {
302 0 : write_status(STATUS_BADARMOR);
303 0 : g10_exit(1); /* stop here */
304 : }
305 :
306 :
307 : /****************
308 : * check whether the armor header is valid on a signed message.
309 : * this is for security reasons: the header lines are not included in the
310 : * hash and by using some creative formatting rules, Mallory could fake
311 : * any text at the beginning of a document; assuming it is read with
312 : * a simple viewer. We only allow the Hash Header.
313 : */
314 : static int
315 18 : parse_hash_header( const char *line )
316 : {
317 : const char *s, *s2;
318 18 : unsigned found = 0;
319 :
320 18 : if( strlen(line) < 6 || strlen(line) > 60 )
321 0 : return 0; /* too short or too long */
322 18 : if( memcmp( line, "Hash:", 5 ) )
323 1 : return 0; /* invalid header */
324 :
325 34 : for(s=line+5;;s=s2) {
326 34 : for(; *s && (*s==' ' || *s == '\t'); s++ )
327 : ;
328 34 : if( !*s )
329 17 : break;
330 17 : for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ )
331 : ;
332 17 : if( !strncmp( s, "RIPEMD160", s2-s ) )
333 0 : found |= 1;
334 17 : else if( !strncmp( s, "SHA1", s2-s ) )
335 14 : found |= 2;
336 3 : else if( !strncmp( s, "SHA224", s2-s ) )
337 0 : found |= 8;
338 3 : else if( !strncmp( s, "SHA256", s2-s ) )
339 3 : found |= 16;
340 0 : else if( !strncmp( s, "SHA384", s2-s ) )
341 0 : found |= 32;
342 0 : else if( !strncmp( s, "SHA512", s2-s ) )
343 0 : found |= 64;
344 : else
345 0 : return 0;
346 17 : for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ )
347 : ;
348 17 : if( *s2 && *s2 != ',' )
349 0 : return 0;
350 17 : if( *s2 )
351 0 : s2++;
352 17 : }
353 17 : return found;
354 : }
355 :
356 : /* Returns true if this is a valid armor tag as per RFC-2440bis-21. */
357 : static int
358 112 : is_armor_tag(const char *line)
359 : {
360 112 : if(strncmp(line,"Version",7)==0
361 33 : || strncmp(line,"Comment",7)==0
362 0 : || strncmp(line,"MessageID",9)==0
363 0 : || strncmp(line,"Hash",4)==0
364 0 : || strncmp(line,"Charset",7)==0)
365 112 : return 1;
366 :
367 0 : return 0;
368 : }
369 :
370 : /****************
371 : * Check whether this is a armor line.
372 : * returns: -1 if it is not a armor header or the index number of the
373 : * armor header.
374 : */
375 : static int
376 738 : is_armor_header( byte *line, unsigned len )
377 : {
378 : const char *s;
379 : byte *save_p, *p;
380 : int save_c;
381 : int i;
382 :
383 738 : if( len < 15 )
384 67 : return -1; /* too short */
385 671 : if( memcmp( line, "-----", 5 ) )
386 187 : return -1; /* no */
387 484 : p = strstr( line+5, "-----");
388 484 : if( !p )
389 2 : return -1;
390 482 : save_p = p;
391 482 : p += 5;
392 :
393 : /* Some Windows environments seem to add whitespace to the end of
394 : the line, so we strip it here. This becomes strict if
395 : --rfc2440 is set since 2440 reads "The header lines, therefore,
396 : MUST start at the beginning of a line, and MUST NOT have text
397 : following them on the same line." It is unclear whether "text"
398 : refers to all text or just non-whitespace text. 4880 clarified
399 : this was only non-whitespace text. */
400 :
401 482 : if(RFC2440)
402 : {
403 0 : if( *p == '\r' )
404 0 : p++;
405 0 : if( *p == '\n' )
406 0 : p++;
407 : }
408 : else
409 1438 : while(*p==' ' || *p=='\r' || *p=='\n' || *p=='\t')
410 474 : p++;
411 :
412 482 : if( *p )
413 1 : return -1; /* garbage after dashes */
414 481 : save_c = *save_p; *save_p = 0;
415 481 : p = line+5;
416 2492 : for(i=0; (s=head_strings[i]); i++ )
417 2261 : if( !strcmp(s, p) )
418 250 : break;
419 481 : *save_p = save_c;
420 481 : if( !s )
421 231 : return -1; /* unknown armor line */
422 :
423 250 : if( opt.verbose > 1 )
424 0 : log_info(_("armor: %s\n"), head_strings[i]);
425 250 : return i;
426 : }
427 :
428 :
429 :
430 : /****************
431 : * Parse a header lines
432 : * Return 0: Empty line (end of header lines)
433 : * -1: invalid header line
434 : * >0: Good header line
435 : */
436 : static int
437 380 : parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len )
438 : {
439 : byte *p;
440 380 : int hashes=0;
441 : unsigned int len2;
442 :
443 380 : len2 = length_sans_trailing_ws ( line, len );
444 380 : if( !len2 ) {
445 250 : afx->buffer_pos = len2; /* (it is not the fine way to do it here) */
446 250 : return 0; /* WS only: same as empty line */
447 : }
448 :
449 : /*
450 : This is fussy. The spec says that a header line is delimited
451 : with a colon-space pair. This means that a line such as
452 : "Comment: " (with nothing else) is actually legal as an empty
453 : string comment. However, email and cut-and-paste being what it
454 : is, that trailing space may go away. Therefore, we accept empty
455 : headers delimited with only a colon. --rfc2440, as always,
456 : makes this strict and enforces the colon-space pair. -dms
457 : */
458 :
459 130 : p = strchr( line, ':');
460 130 : if( !p || (RFC2440 && p[1]!=' ')
461 130 : || (!RFC2440 && p[1]!=' ' && p[1]!='\n' && p[1]!='\r'))
462 : {
463 0 : log_error (_("invalid armor header: "));
464 0 : es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
465 0 : log_printf ("\n");
466 0 : return -1;
467 : }
468 :
469 : /* Chop off the whitespace we detected before */
470 130 : len=len2;
471 130 : line[len2]='\0';
472 :
473 130 : if( opt.verbose ) {
474 6 : log_info(_("armor header: "));
475 6 : es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
476 6 : log_printf ("\n");
477 : }
478 :
479 130 : if( afx->in_cleartext )
480 : {
481 18 : if( (hashes=parse_hash_header( line )) )
482 17 : afx->hashes |= hashes;
483 1 : else if( strlen(line) > 15 && !memcmp( line, "NotDashEscaped:", 15 ) )
484 1 : afx->not_dash_escaped = 1;
485 : else
486 : {
487 0 : log_error(_("invalid clearsig header\n"));
488 0 : return -1;
489 : }
490 : }
491 112 : else if(!is_armor_tag(line))
492 : {
493 : /* Section 6.2: "Unknown keys should be reported to the user,
494 : but OpenPGP should continue to process the message." Note
495 : that in a clearsigned message this applies to the signature
496 : part (i.e. "BEGIN PGP SIGNATURE") and not the signed data
497 : ("BEGIN PGP SIGNED MESSAGE"). The only key allowed in the
498 : signed data section is "Hash". */
499 :
500 0 : log_info(_("unknown armor header: "));
501 0 : es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
502 0 : log_printf ("\n");
503 : }
504 :
505 130 : return 1;
506 : }
507 :
508 :
509 :
510 : /* figure out whether the data is armored or not */
511 : static int
512 480 : check_input( armor_filter_context_t *afx, IOBUF a )
513 : {
514 480 : int rc = 0;
515 : int i;
516 : byte *line;
517 : unsigned len;
518 : unsigned maxlen;
519 480 : int hdr_line = -1;
520 :
521 : /* read the first line to see whether this is armored data */
522 480 : maxlen = MAX_LINELEN;
523 480 : len = afx->buffer_len = iobuf_read_line( a, &afx->buffer,
524 : &afx->buffer_size, &maxlen );
525 480 : line = afx->buffer;
526 480 : if( !maxlen ) {
527 : /* line has been truncated: assume not armored */
528 0 : afx->inp_checked = 1;
529 0 : afx->inp_bypass = 1;
530 0 : return 0;
531 : }
532 :
533 480 : if( !len ) {
534 0 : return -1; /* eof */
535 : }
536 :
537 : /* (the line is always a C string but maybe longer) */
538 480 : if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
539 : ;
540 458 : else if (len >= 2 && !is_armored (line)) {
541 13 : afx->inp_checked = 1;
542 13 : afx->inp_bypass = 1;
543 13 : return 0;
544 : }
545 :
546 : /* find the armor header */
547 1422 : while(len) {
548 721 : i = is_armor_header( line, len );
549 721 : if( i >= 0 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
550 233 : hdr_line = i;
551 233 : if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
552 17 : if( afx->in_cleartext ) {
553 0 : log_error(_("nested clear text signatures\n"));
554 0 : rc = gpg_error (GPG_ERR_INV_ARMOR);
555 : }
556 17 : afx->in_cleartext = 1;
557 : }
558 233 : break;
559 : }
560 : /* read the next line (skip all truncated lines) */
561 : do {
562 488 : maxlen = MAX_LINELEN;
563 488 : afx->buffer_len = iobuf_read_line( a, &afx->buffer,
564 : &afx->buffer_size, &maxlen );
565 488 : line = afx->buffer;
566 488 : len = afx->buffer_len;
567 488 : } while( !maxlen );
568 : }
569 :
570 : /* Parse the header lines. */
571 1063 : while(len) {
572 : /* Read the next line (skip all truncated lines). */
573 : do {
574 362 : maxlen = MAX_LINELEN;
575 362 : afx->buffer_len = iobuf_read_line( a, &afx->buffer,
576 : &afx->buffer_size, &maxlen );
577 362 : line = afx->buffer;
578 362 : len = afx->buffer_len;
579 362 : } while( !maxlen );
580 :
581 362 : i = parse_header_line( afx, line, len );
582 362 : if( i <= 0 ) {
583 233 : if (i && RFC2440)
584 0 : rc = GPG_ERR_INV_ARMOR;
585 233 : break;
586 : }
587 : }
588 :
589 :
590 467 : if( rc )
591 0 : invalid_armor();
592 467 : else if( afx->in_cleartext )
593 17 : afx->faked = 1;
594 : else {
595 450 : afx->inp_checked = 1;
596 450 : afx->crc = CRCINIT;
597 450 : afx->idx = 0;
598 450 : afx->radbuf[0] = 0;
599 : }
600 :
601 467 : return rc;
602 : }
603 :
604 : #define PARTIAL_CHUNK 512
605 : #define PARTIAL_POW 9
606 :
607 : /****************
608 : * Fake a literal data packet and wait for the next armor line
609 : * fixme: empty line handling and null length clear text signature are
610 : * not implemented/checked.
611 : */
612 : static int
613 43 : fake_packet( armor_filter_context_t *afx, IOBUF a,
614 : size_t *retn, byte *buf, size_t size )
615 : {
616 43 : int rc = 0;
617 43 : size_t len = 0;
618 43 : int lastline = 0;
619 : unsigned maxlen, n;
620 : byte *p;
621 : byte tempbuf[PARTIAL_CHUNK];
622 43 : size_t tempbuf_len=0;
623 :
624 6243 : while( !rc && size-len>=(PARTIAL_CHUNK+1)) {
625 : /* copy what we have in the line buffer */
626 6157 : if( afx->faked == 1 )
627 17 : afx->faked++; /* skip the first (empty) line */
628 : else
629 : {
630 : /* It's full, so write this partial chunk */
631 6140 : if(tempbuf_len==PARTIAL_CHUNK)
632 : {
633 400 : buf[len++]=0xE0+PARTIAL_POW;
634 400 : memcpy(&buf[len],tempbuf,PARTIAL_CHUNK);
635 400 : len+=PARTIAL_CHUNK;
636 400 : tempbuf_len=0;
637 400 : continue;
638 : }
639 :
640 219325 : while( tempbuf_len < PARTIAL_CHUNK
641 213185 : && afx->buffer_pos < afx->buffer_len )
642 207845 : tempbuf[tempbuf_len++] = afx->buffer[afx->buffer_pos++];
643 5740 : if( tempbuf_len==PARTIAL_CHUNK )
644 400 : continue;
645 : }
646 :
647 : /* read the next line */
648 5357 : maxlen = MAX_LINELEN;
649 5357 : afx->buffer_pos = 0;
650 5357 : afx->buffer_len = iobuf_read_line( a, &afx->buffer,
651 : &afx->buffer_size, &maxlen );
652 5357 : if( !afx->buffer_len ) {
653 0 : rc = -1; /* eof (should not happen) */
654 0 : continue;
655 : }
656 5357 : if( !maxlen )
657 0 : afx->truncated++;
658 :
659 5357 : p = afx->buffer;
660 5357 : n = afx->buffer_len;
661 :
662 : /* Armor header or dash-escaped line? */
663 5357 : if(p[0]=='-')
664 : {
665 : /* 2440bis-10: When reversing dash-escaping, an
666 : implementation MUST strip the string "- " if it occurs
667 : at the beginning of a line, and SHOULD warn on "-" and
668 : any character other than a space at the beginning of a
669 : line. */
670 :
671 29 : if(p[1]==' ' && !afx->not_dash_escaped)
672 : {
673 : /* It's a dash-escaped line, so skip over the
674 : escape. */
675 10 : afx->buffer_pos = 2;
676 : }
677 19 : else if(p[1]=='-' && p[2]=='-' && p[3]=='-' && p[4]=='-')
678 17 : {
679 : /* Five dashes in a row mean it's probably armor
680 : header. */
681 17 : int type = is_armor_header( p, n );
682 17 : if( afx->not_dash_escaped && type != BEGIN_SIGNATURE )
683 : ; /* this is okay */
684 : else
685 : {
686 17 : if( type != BEGIN_SIGNATURE )
687 : {
688 0 : log_info(_("unexpected armor: "));
689 0 : es_write_sanitized (log_get_stream (), p, n,
690 : NULL, NULL);
691 0 : log_printf ("\n");
692 : }
693 :
694 17 : lastline = 1;
695 17 : rc = -1;
696 : }
697 : }
698 2 : else if(!afx->not_dash_escaped)
699 : {
700 : /* Bad dash-escaping. */
701 0 : log_info (_("invalid dash escaped line: "));
702 0 : es_write_sanitized (log_get_stream (), p, n, NULL, NULL);
703 0 : log_printf ("\n");
704 : }
705 : }
706 :
707 : /* Now handle the end-of-line canonicalization */
708 5357 : if( !afx->not_dash_escaped )
709 : {
710 5345 : int crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n';
711 :
712 5345 : afx->buffer_len=
713 5345 : trim_trailing_chars( &p[afx->buffer_pos], n-afx->buffer_pos,
714 : " \t\r\n");
715 5345 : afx->buffer_len+=afx->buffer_pos;
716 : /* the buffer is always allocated with enough space to append
717 : * the removed [CR], LF and a Nul
718 : * The reason for this complicated procedure is to keep at least
719 : * the original type of lineending - handling of the removed
720 : * trailing spaces seems to be impossible in our method
721 : * of faking a packet; either we have to use a temporary file
722 : * or calculate the hash here in this module and somehow find
723 : * a way to send the hash down the processing line (well, a special
724 : * faked packet could do the job).
725 : */
726 5345 : if( crlf )
727 0 : afx->buffer[afx->buffer_len++] = '\r';
728 5345 : afx->buffer[afx->buffer_len++] = '\n';
729 5345 : afx->buffer[afx->buffer_len] = '\0';
730 : }
731 : }
732 :
733 43 : if( lastline ) { /* write last (ending) length header */
734 17 : if(tempbuf_len<192)
735 11 : buf[len++]=tempbuf_len;
736 : else
737 : {
738 6 : buf[len++]=((tempbuf_len-192)/256) + 192;
739 6 : buf[len++]=(tempbuf_len-192) % 256;
740 : }
741 17 : memcpy(&buf[len],tempbuf,tempbuf_len);
742 17 : len+=tempbuf_len;
743 :
744 17 : rc = 0;
745 17 : afx->faked = 0;
746 17 : afx->in_cleartext = 0;
747 : /* and now read the header lines */
748 17 : afx->buffer_pos = 0;
749 : for(;;) {
750 : int i;
751 :
752 : /* read the next line (skip all truncated lines) */
753 : do {
754 18 : maxlen = MAX_LINELEN;
755 18 : afx->buffer_len = iobuf_read_line( a, &afx->buffer,
756 : &afx->buffer_size, &maxlen );
757 18 : } while( !maxlen );
758 18 : p = afx->buffer;
759 18 : n = afx->buffer_len;
760 18 : if( !n ) {
761 0 : rc = -1;
762 0 : break; /* eof */
763 : }
764 18 : i = parse_header_line( afx, p , n );
765 18 : if( i <= 0 ) {
766 17 : if( i )
767 0 : invalid_armor();
768 17 : break;
769 : }
770 1 : }
771 17 : afx->inp_checked = 1;
772 17 : afx->crc = CRCINIT;
773 17 : afx->idx = 0;
774 17 : afx->radbuf[0] = 0;
775 : }
776 :
777 43 : *retn = len;
778 43 : return rc;
779 : }
780 :
781 :
782 : static int
783 0 : invalid_crc(void)
784 : {
785 0 : if ( opt.ignore_crc_error )
786 0 : return 0;
787 0 : log_inc_errorcount();
788 0 : return gpg_error (GPG_ERR_INV_ARMOR);
789 : }
790 :
791 :
792 : static int
793 565 : radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
794 : byte *buf, size_t size )
795 : {
796 : byte val;
797 565 : int c=0, c2; /*init c because gcc is not clever enough for the continue*/
798 565 : int checkcrc=0;
799 565 : int rc = 0;
800 565 : size_t n = 0;
801 565 : int idx, i, onlypad=0;
802 : u32 crc;
803 :
804 565 : crc = afx->crc;
805 565 : idx = afx->idx;
806 565 : val = afx->radbuf[0];
807 1486877 : for( n=0; n < size; ) {
808 :
809 1486214 : if( afx->buffer_pos < afx->buffer_len )
810 1463368 : c = afx->buffer[afx->buffer_pos++];
811 : else { /* read the next line */
812 22846 : unsigned maxlen = MAX_LINELEN;
813 22846 : afx->buffer_pos = 0;
814 22846 : afx->buffer_len = iobuf_read_line( a, &afx->buffer,
815 : &afx->buffer_size, &maxlen );
816 22846 : if( !maxlen )
817 0 : afx->truncated++;
818 22846 : if( !afx->buffer_len )
819 234 : break; /* eof */
820 22612 : continue;
821 : }
822 :
823 : again:
824 1463368 : if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
825 22612 : continue;
826 1440756 : else if( c == '=' ) { /* pad character: stop */
827 : /* some mailers leave quoted-printable encoded characters
828 : * so we try to workaround this */
829 233 : if( afx->buffer_pos+2 < afx->buffer_len ) {
830 : int cc1, cc2, cc3;
831 40 : cc1 = afx->buffer[afx->buffer_pos];
832 40 : cc2 = afx->buffer[afx->buffer_pos+1];
833 40 : cc3 = afx->buffer[afx->buffer_pos+2];
834 40 : if( isxdigit(cc1) && isxdigit(cc2)
835 7 : && strchr( "=\n\r\t ", cc3 )) {
836 : /* well it seems to be the case - adjust */
837 0 : c = isdigit(cc1)? (cc1 - '0'): (ascii_toupper(cc1)-'A'+10);
838 0 : c <<= 4;
839 0 : c |= isdigit(cc2)? (cc2 - '0'): (ascii_toupper(cc2)-'A'+10);
840 0 : afx->buffer_pos += 2;
841 0 : afx->qp_detected = 1;
842 0 : goto again;
843 : }
844 : }
845 :
846 : /* Occasionally a bug MTA will leave the = escaped as
847 : =3D. If the 4 characters following that are valid
848 : Radix64 characters and they are following by a new
849 : line, assume that this is the case and skip the
850 : 3D. */
851 233 : if (afx->buffer_pos + 6 < afx->buffer_len
852 0 : && afx->buffer[afx->buffer_pos + 0] == '3'
853 0 : && afx->buffer[afx->buffer_pos + 1] == 'D'
854 0 : && asctobin[afx->buffer[afx->buffer_pos + 2]] != 255
855 0 : && asctobin[afx->buffer[afx->buffer_pos + 3]] != 255
856 0 : && asctobin[afx->buffer[afx->buffer_pos + 4]] != 255
857 0 : && asctobin[afx->buffer[afx->buffer_pos + 5]] != 255
858 0 : && afx->buffer[afx->buffer_pos + 6] == '\n')
859 : {
860 0 : afx->buffer_pos += 2;
861 0 : afx->qp_detected = 1;
862 : }
863 :
864 233 : if (!n)
865 2 : onlypad = 1;
866 :
867 233 : if( idx == 1 )
868 0 : buf[n++] = val;
869 233 : checkcrc++;
870 233 : break;
871 : }
872 1440523 : else if( (c = asctobin[(c2=c)]) == 255 ) {
873 0 : log_error(_("invalid radix64 character %02X skipped\n"), c2);
874 0 : continue;
875 : }
876 1440523 : switch(idx) {
877 360210 : case 0: val = c << 2; break;
878 360210 : case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
879 360086 : case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
880 360017 : case 3: val |= c&0x3f; buf[n++] = val; break;
881 : }
882 1440523 : idx = (idx+1) % 4;
883 : }
884 :
885 1080878 : for(i=0; i < n; i++ )
886 1080313 : crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
887 565 : crc &= 0x00ffffff;
888 565 : afx->crc = crc;
889 565 : afx->idx = idx;
890 565 : afx->radbuf[0] = val;
891 :
892 565 : if( checkcrc ) {
893 233 : afx->any_data = 1;
894 233 : afx->inp_checked=0;
895 233 : afx->faked = 0;
896 : for(;;) { /* skip lf and pad characters */
897 936 : if( afx->buffer_pos < afx->buffer_len )
898 743 : c = afx->buffer[afx->buffer_pos++];
899 : else { /* read the next line */
900 193 : unsigned maxlen = MAX_LINELEN;
901 193 : afx->buffer_pos = 0;
902 193 : afx->buffer_len = iobuf_read_line( a, &afx->buffer,
903 : &afx->buffer_size, &maxlen );
904 193 : if( !maxlen )
905 0 : afx->truncated++;
906 193 : if( !afx->buffer_len )
907 0 : break; /* eof */
908 193 : continue;
909 : }
910 743 : if( c == '\n' || c == ' ' || c == '\r'
911 550 : || c == '\t' || c == '=' )
912 510 : continue;
913 233 : break;
914 703 : }
915 233 : if( c == -1 )
916 0 : log_error(_("premature eof (no CRC)\n"));
917 : else {
918 233 : u32 mycrc = 0;
919 233 : idx = 0;
920 : do {
921 932 : if( (c = asctobin[c]) == 255 )
922 0 : break;
923 932 : switch(idx) {
924 233 : case 0: val = c << 2; break;
925 233 : case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
926 233 : case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
927 233 : case 3: val |= c&0x3f; mycrc |= val; break;
928 : }
929 : for(;;) {
930 932 : if( afx->buffer_pos < afx->buffer_len )
931 932 : c = afx->buffer[afx->buffer_pos++];
932 : else { /* read the next line */
933 0 : unsigned maxlen = MAX_LINELEN;
934 0 : afx->buffer_pos = 0;
935 0 : afx->buffer_len = iobuf_read_line( a, &afx->buffer,
936 : &afx->buffer_size,
937 : &maxlen );
938 0 : if( !maxlen )
939 0 : afx->truncated++;
940 0 : if( !afx->buffer_len )
941 0 : break; /* eof */
942 0 : continue;
943 : }
944 932 : break;
945 0 : }
946 932 : if( !afx->buffer_len )
947 0 : break; /* eof */
948 932 : } while( ++idx < 4 );
949 233 : if( c == -1 ) {
950 0 : log_info(_("premature eof (in CRC)\n"));
951 0 : rc = invalid_crc();
952 : }
953 233 : else if( idx == 0 ) {
954 : /* No CRC at all is legal ("MAY") */
955 0 : rc=0;
956 : }
957 233 : else if( idx != 4 ) {
958 0 : log_info(_("malformed CRC\n"));
959 0 : rc = invalid_crc();
960 : }
961 233 : else if( mycrc != afx->crc ) {
962 0 : log_info (_("CRC error; %06lX - %06lX\n"),
963 0 : (ulong)afx->crc, (ulong)mycrc);
964 0 : rc = invalid_crc();
965 : }
966 : else {
967 233 : rc = 0;
968 : /* FIXME: Here we should emit another control packet,
969 : * so that we know in mainproc that we are processing
970 : * a clearsign message */
971 : #if 0
972 : for(rc=0;!rc;) {
973 : rc = 0 /*check_trailer( &fhdr, c )*/;
974 : if( !rc ) {
975 : if( (c=iobuf_get(a)) == -1 )
976 : rc = 2;
977 : }
978 : }
979 : if( rc == -1 )
980 : rc = 0;
981 : else if( rc == 2 ) {
982 : log_error(_("premature eof (in trailer)\n"));
983 : rc = GPG_ERR_INVALID_ARMOR;
984 : }
985 : else {
986 : log_error(_("error in trailer line\n"));
987 : rc = GPG_ERR_INVALID_ARMOR;
988 : }
989 : #endif
990 : }
991 : }
992 : }
993 :
994 565 : if( !n && !onlypad )
995 234 : rc = -1;
996 :
997 565 : *retn = n;
998 565 : return rc;
999 : }
1000 :
1001 : /****************
1002 : * This filter is used to handle the armor stuff
1003 : */
1004 : static int
1005 1431 : armor_filter( void *opaque, int control,
1006 : IOBUF a, byte *buf, size_t *ret_len)
1007 : {
1008 1431 : size_t size = *ret_len;
1009 1431 : armor_filter_context_t *afx = opaque;
1010 1431 : int rc=0, i, c;
1011 : byte radbuf[3];
1012 : int idx, idx2;
1013 1431 : size_t n=0;
1014 : u32 crc;
1015 : #if 0
1016 : static FILE *fp ;
1017 :
1018 : if( !fp ) {
1019 : fp = fopen("armor.out", "w");
1020 : assert(fp);
1021 : }
1022 : #endif
1023 :
1024 1431 : if( DBG_FILTER )
1025 0 : log_debug("armor-filter: control: %d\n", control );
1026 1431 : if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
1027 26 : n = 0;
1028 26 : if( afx->buffer_len ) {
1029 : /* Copy the data from AFX->BUFFER to BUF. */
1030 0 : for(; n < size && afx->buffer_pos < afx->buffer_len; n++ )
1031 0 : buf[n++] = afx->buffer[afx->buffer_pos++];
1032 0 : if( afx->buffer_pos >= afx->buffer_len )
1033 0 : afx->buffer_len = 0;
1034 : }
1035 : /* If there is still space in BUF, read directly into it. */
1036 14757 : for(; n < size; n++ ) {
1037 14757 : if( (c=iobuf_get(a)) == -1 )
1038 26 : break;
1039 14731 : buf[n] = c & 0xff;
1040 : }
1041 26 : if( !n )
1042 : /* We didn't get any data. EOF. */
1043 13 : rc = -1;
1044 26 : *ret_len = n;
1045 : }
1046 1405 : else if( control == IOBUFCTRL_UNDERFLOW ) {
1047 : /* We need some space for the faked packet. The minmum
1048 : * required size is the PARTIAL_CHUNK size plus a byte for the
1049 : * length itself */
1050 638 : if( size < PARTIAL_CHUNK+1 )
1051 0 : BUG(); /* supplied buffer too short */
1052 :
1053 638 : if( afx->faked )
1054 43 : rc = fake_packet( afx, a, &n, buf, size );
1055 595 : else if( !afx->inp_checked ) {
1056 480 : rc = check_input( afx, a );
1057 480 : if( afx->inp_bypass ) {
1058 4312 : for(n=0; n < size && afx->buffer_pos < afx->buffer_len; )
1059 4286 : buf[n++] = afx->buffer[afx->buffer_pos++];
1060 13 : if( afx->buffer_pos >= afx->buffer_len )
1061 13 : afx->buffer_len = 0;
1062 13 : if( !n )
1063 0 : rc = -1;
1064 : }
1065 467 : else if( afx->faked ) {
1066 17 : unsigned int hashes = afx->hashes;
1067 : const byte *sesmark;
1068 : size_t sesmarklen;
1069 :
1070 17 : sesmark = get_session_marker( &sesmarklen );
1071 17 : if ( sesmarklen > 20 )
1072 0 : BUG();
1073 :
1074 : /* the buffer is at least 15+n*15 bytes long, so it
1075 : * is easy to construct the packets */
1076 :
1077 17 : hashes &= 1|2|8|16|32|64;
1078 17 : if( !hashes ) {
1079 0 : hashes |= 2; /* Default to SHA-1. */
1080 : }
1081 17 : n=0;
1082 : /* First a gpg control packet... */
1083 17 : buf[n++] = 0xff; /* new format, type 63, 1 length byte */
1084 17 : n++; /* see below */
1085 17 : memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
1086 17 : buf[n++] = CTRLPKT_CLEARSIGN_START;
1087 17 : buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
1088 17 : if( hashes & 1 )
1089 0 : buf[n++] = DIGEST_ALGO_RMD160;
1090 17 : if( hashes & 2 )
1091 14 : buf[n++] = DIGEST_ALGO_SHA1;
1092 17 : if( hashes & 8 )
1093 0 : buf[n++] = DIGEST_ALGO_SHA224;
1094 17 : if( hashes & 16 )
1095 3 : buf[n++] = DIGEST_ALGO_SHA256;
1096 17 : if( hashes & 32 )
1097 0 : buf[n++] = DIGEST_ALGO_SHA384;
1098 17 : if( hashes & 64 )
1099 0 : buf[n++] = DIGEST_ALGO_SHA512;
1100 17 : buf[1] = n - 2;
1101 :
1102 : /* ...followed by an invented plaintext packet.
1103 : Amusingly enough, this packet is not compliant with
1104 : 2440 as the initial partial length is less than 512
1105 : bytes. Of course, we'll accept it anyway ;) */
1106 :
1107 17 : buf[n++] = 0xCB; /* new packet format, type 11 */
1108 17 : buf[n++] = 0xE1; /* 2^1 == 2 bytes */
1109 17 : buf[n++] = 't'; /* canonical text mode */
1110 17 : buf[n++] = 0; /* namelength */
1111 17 : buf[n++] = 0xE2; /* 2^2 == 4 more bytes */
1112 17 : memset(buf+n, 0, 4); /* timestamp */
1113 17 : n += 4;
1114 : }
1115 450 : else if( !rc )
1116 450 : rc = radix64_read( afx, a, &n, buf, size );
1117 : }
1118 : else
1119 115 : rc = radix64_read( afx, a, &n, buf, size );
1120 : #if 0
1121 : if( n )
1122 : if( fwrite(buf, n, 1, fp ) != 1 )
1123 : BUG();
1124 : #endif
1125 638 : *ret_len = n;
1126 : }
1127 767 : else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) {
1128 169 : if( !afx->status ) { /* write the header line */
1129 : const char *s;
1130 52 : strlist_t comment=opt.comments;
1131 :
1132 52 : if( afx->what >= DIM(head_strings) )
1133 0 : log_bug("afx->what=%d", afx->what);
1134 52 : iobuf_writestr(a, "-----");
1135 52 : iobuf_writestr(a, head_strings[afx->what] );
1136 52 : iobuf_writestr(a, "-----" );
1137 52 : iobuf_writestr(a,afx->eol);
1138 52 : if (opt.emit_version)
1139 : {
1140 0 : iobuf_writestr (a, "Version: "GNUPG_NAME" v");
1141 0 : for (s=VERSION; *s && *s != '.'; s++)
1142 0 : iobuf_writebyte (a, *s);
1143 0 : if (opt.emit_version > 1 && *s)
1144 : {
1145 0 : iobuf_writebyte (a, *s++);
1146 0 : for (; *s && *s != '.'; s++)
1147 0 : iobuf_writebyte (a, *s);
1148 0 : if (opt.emit_version > 2)
1149 : {
1150 0 : for (; *s && *s != '-' && !spacep (s); s++)
1151 0 : iobuf_writebyte (a, *s);
1152 0 : if (opt.emit_version > 3)
1153 0 : iobuf_writestr (a, " (" PRINTABLE_OS_NAME ")");
1154 : }
1155 : }
1156 0 : iobuf_writestr(a,afx->eol);
1157 : }
1158 :
1159 : /* write the comment strings */
1160 52 : for(s=comment->d;comment;comment=comment->next,s=comment->d)
1161 : {
1162 0 : iobuf_writestr(a, "Comment: " );
1163 0 : for( ; *s; s++ )
1164 : {
1165 0 : if( *s == '\n' )
1166 0 : iobuf_writestr(a, "\\n" );
1167 0 : else if( *s == '\r' )
1168 0 : iobuf_writestr(a, "\\r" );
1169 0 : else if( *s == '\v' )
1170 0 : iobuf_writestr(a, "\\v" );
1171 : else
1172 0 : iobuf_put(a, *s );
1173 : }
1174 :
1175 0 : iobuf_writestr(a,afx->eol);
1176 : }
1177 :
1178 52 : if ( afx->hdrlines ) {
1179 129 : for ( s = afx->hdrlines; *s; s++ ) {
1180 : #ifdef HAVE_DOSISH_SYSTEM
1181 : if ( *s == '\n' )
1182 : iobuf_put( a, '\r');
1183 : #endif
1184 126 : iobuf_put(a, *s );
1185 : }
1186 : }
1187 :
1188 52 : iobuf_writestr(a,afx->eol);
1189 52 : afx->status++;
1190 52 : afx->idx = 0;
1191 52 : afx->idx2 = 0;
1192 52 : afx->crc = CRCINIT;
1193 :
1194 : }
1195 169 : crc = afx->crc;
1196 169 : idx = afx->idx;
1197 169 : idx2 = afx->idx2;
1198 246 : for(i=0; i < idx; i++ )
1199 77 : radbuf[i] = afx->radbuf[i];
1200 :
1201 507309 : for(i=0; i < size; i++ )
1202 507140 : crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
1203 169 : crc &= 0x00ffffff;
1204 :
1205 507309 : for( ; size; buf++, size-- ) {
1206 507140 : radbuf[idx++] = *buf;
1207 507140 : if( idx > 2 ) {
1208 169024 : idx = 0;
1209 169024 : c = bintoasc[(*radbuf >> 2) & 077];
1210 169024 : iobuf_put(a, c);
1211 169024 : c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1212 169024 : iobuf_put(a, c);
1213 169024 : c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1214 169024 : iobuf_put(a, c);
1215 169024 : c = bintoasc[radbuf[2]&077];
1216 169024 : iobuf_put(a, c);
1217 169024 : if( ++idx2 >= (64/4) )
1218 : { /* pgp doesn't like 72 here */
1219 10532 : iobuf_writestr(a,afx->eol);
1220 10532 : idx2=0;
1221 : }
1222 : }
1223 : }
1224 314 : for(i=0; i < idx; i++ )
1225 145 : afx->radbuf[i] = radbuf[i];
1226 169 : afx->idx = idx;
1227 169 : afx->idx2 = idx2;
1228 169 : afx->crc = crc;
1229 : }
1230 598 : else if( control == IOBUFCTRL_INIT )
1231 : {
1232 299 : if( !is_initialized )
1233 245 : initialize();
1234 :
1235 : /* Figure out what we're using for line endings if the caller
1236 : didn't specify. */
1237 299 : if(afx->eol[0]==0)
1238 : {
1239 : #ifdef HAVE_DOSISH_SYSTEM
1240 : afx->eol[0]='\r';
1241 : afx->eol[1]='\n';
1242 : #else
1243 299 : afx->eol[0]='\n';
1244 : #endif
1245 : }
1246 : }
1247 299 : else if( control == IOBUFCTRL_CANCEL ) {
1248 0 : afx->cancel = 1;
1249 : }
1250 299 : else if( control == IOBUFCTRL_FREE ) {
1251 299 : if( afx->cancel )
1252 : ;
1253 299 : else if( afx->status ) { /* pad, write cecksum, and bottom line */
1254 52 : crc = afx->crc;
1255 52 : idx = afx->idx;
1256 52 : idx2 = afx->idx2;
1257 52 : if( idx ) {
1258 43 : c = bintoasc[(afx->radbuf[0]>>2)&077];
1259 43 : iobuf_put(a, c);
1260 43 : if( idx == 1 ) {
1261 18 : c = bintoasc[((afx->radbuf[0] << 4) & 060) & 077];
1262 18 : iobuf_put(a, c);
1263 18 : iobuf_put(a, '=');
1264 18 : iobuf_put(a, '=');
1265 : }
1266 : else { /* 2 */
1267 50 : c = bintoasc[(((afx->radbuf[0]<<4)&060)
1268 25 : |((afx->radbuf[1]>>4)&017))&077];
1269 25 : iobuf_put(a, c);
1270 25 : c = bintoasc[((afx->radbuf[1] << 2) & 074) & 077];
1271 25 : iobuf_put(a, c);
1272 25 : iobuf_put(a, '=');
1273 : }
1274 43 : if( ++idx2 >= (64/4) )
1275 : { /* pgp doesn't like 72 here */
1276 20 : iobuf_writestr(a,afx->eol);
1277 20 : idx2=0;
1278 : }
1279 : }
1280 : /* may need a linefeed */
1281 52 : if( idx2 )
1282 32 : iobuf_writestr(a,afx->eol);
1283 : /* write the CRC */
1284 52 : iobuf_put(a, '=');
1285 52 : radbuf[0] = crc >>16;
1286 52 : radbuf[1] = crc >> 8;
1287 52 : radbuf[2] = crc;
1288 52 : c = bintoasc[(*radbuf >> 2) & 077];
1289 52 : iobuf_put(a, c);
1290 52 : c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1291 52 : iobuf_put(a, c);
1292 52 : c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1293 52 : iobuf_put(a, c);
1294 52 : c = bintoasc[radbuf[2]&077];
1295 52 : iobuf_put(a, c);
1296 52 : iobuf_writestr(a,afx->eol);
1297 : /* and the the trailer */
1298 52 : if( afx->what >= DIM(tail_strings) )
1299 0 : log_bug("afx->what=%d", afx->what);
1300 52 : iobuf_writestr(a, "-----");
1301 52 : iobuf_writestr(a, tail_strings[afx->what] );
1302 52 : iobuf_writestr(a, "-----" );
1303 52 : iobuf_writestr(a,afx->eol);
1304 : }
1305 247 : else if( !afx->any_data && !afx->inp_bypass ) {
1306 3 : log_error(_("no valid OpenPGP data found.\n"));
1307 3 : afx->no_openpgp_data = 1;
1308 3 : write_status_text( STATUS_NODATA, "1" );
1309 : }
1310 299 : if( afx->truncated )
1311 0 : log_info(_("invalid armor: line longer than %d characters\n"),
1312 : MAX_LINELEN );
1313 : /* issue an error to enforce dissemination of correct software */
1314 299 : if( afx->qp_detected )
1315 0 : log_error(_("quoted printable character in armor - "
1316 : "probably a buggy MTA has been used\n") );
1317 299 : xfree( afx->buffer );
1318 299 : afx->buffer = NULL;
1319 299 : release_armor_context (afx);
1320 : }
1321 0 : else if( control == IOBUFCTRL_DESC )
1322 0 : mem2str (buf, "armor_filter", *ret_len);
1323 1431 : return rc;
1324 : }
1325 :
1326 :
1327 : /****************
1328 : * create a radix64 encoded string.
1329 : */
1330 : char *
1331 39 : make_radix64_string( const byte *data, size_t len )
1332 : {
1333 : char *buffer, *p;
1334 :
1335 39 : buffer = p = xmalloc( (len+2)/3*4 + 1 );
1336 377 : for( ; len >= 3 ; len -= 3, data += 3 ) {
1337 338 : *p++ = bintoasc[(data[0] >> 2) & 077];
1338 338 : *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1339 338 : *p++ = bintoasc[(((data[1]<<2)&074)|((data[2]>>6)&03))&077];
1340 338 : *p++ = bintoasc[data[2]&077];
1341 : }
1342 39 : if( len == 2 ) {
1343 39 : *p++ = bintoasc[(data[0] >> 2) & 077];
1344 39 : *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1345 39 : *p++ = bintoasc[((data[1]<<2)&074)];
1346 : }
1347 0 : else if( len == 1 ) {
1348 0 : *p++ = bintoasc[(data[0] >> 2) & 077];
1349 0 : *p++ = bintoasc[(data[0] <<4)&060];
1350 : }
1351 39 : *p = 0;
1352 39 : return buffer;
1353 : }
1354 :
1355 :
1356 : /***********************************************
1357 : * For the pipemode command we can't use the armor filter for various
1358 : * reasons, so we use this new unarmor_pump stuff to remove the armor
1359 : */
1360 :
1361 : enum unarmor_state_e {
1362 : STA_init = 0,
1363 : STA_bypass,
1364 : STA_wait_newline,
1365 : STA_wait_dash,
1366 : STA_first_dash,
1367 : STA_compare_header,
1368 : STA_found_header_wait_newline,
1369 : STA_skip_header_lines,
1370 : STA_skip_header_lines_non_ws,
1371 : STA_read_data,
1372 : STA_wait_crc,
1373 : STA_read_crc,
1374 : STA_ready
1375 : };
1376 :
1377 : struct unarmor_pump_s {
1378 : enum unarmor_state_e state;
1379 : byte val;
1380 : int checkcrc;
1381 : int pos; /* counts from 0..3 */
1382 : u32 crc;
1383 : u32 mycrc; /* the one store in the data */
1384 : };
1385 :
1386 :
1387 :
1388 : UnarmorPump
1389 0 : unarmor_pump_new (void)
1390 : {
1391 : UnarmorPump x;
1392 :
1393 0 : if( !is_initialized )
1394 0 : initialize();
1395 0 : x = xmalloc_clear (sizeof *x);
1396 0 : return x;
1397 : }
1398 :
1399 : void
1400 0 : unarmor_pump_release (UnarmorPump x)
1401 : {
1402 0 : xfree (x);
1403 0 : }
1404 :
1405 : /*
1406 : * Get the next character from the ascii armor taken from the IOBUF
1407 : * created earlier by unarmor_pump_new().
1408 : * Return: c = Character
1409 : * 256 = ignore this value
1410 : * -1 = End of current armor
1411 : * -2 = Premature EOF (not used)
1412 : * -3 = Invalid armor
1413 : */
1414 : int
1415 0 : unarmor_pump (UnarmorPump x, int c)
1416 : {
1417 0 : int rval = 256; /* default is to ignore the return value */
1418 :
1419 0 : switch (x->state) {
1420 : case STA_init:
1421 : {
1422 : byte tmp[2];
1423 0 : tmp[0] = c;
1424 0 : tmp[1] = 0;
1425 0 : if ( is_armored (tmp) )
1426 0 : x->state = c == '-'? STA_first_dash : STA_wait_newline;
1427 : else {
1428 0 : x->state = STA_bypass;
1429 0 : return c;
1430 : }
1431 : }
1432 0 : break;
1433 : case STA_bypass:
1434 0 : return c; /* return here to avoid crc calculation */
1435 : case STA_wait_newline:
1436 0 : if (c == '\n')
1437 0 : x->state = STA_wait_dash;
1438 0 : break;
1439 : case STA_wait_dash:
1440 0 : x->state = c == '-'? STA_first_dash : STA_wait_newline;
1441 0 : break;
1442 : case STA_first_dash: /* just need for initialization */
1443 0 : x->pos = 0;
1444 0 : x->state = STA_compare_header;
1445 : case STA_compare_header:
1446 0 : if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) {
1447 0 : if ( x->pos == 28 )
1448 0 : x->state = STA_found_header_wait_newline;
1449 : }
1450 : else
1451 0 : x->state = c == '\n'? STA_wait_dash : STA_wait_newline;
1452 0 : break;
1453 : case STA_found_header_wait_newline:
1454 : /* to make CR,LF issues easier we simply allow for white space
1455 : behind the 5 dashes */
1456 0 : if ( c == '\n' )
1457 0 : x->state = STA_skip_header_lines;
1458 0 : else if ( c != '\r' && c != ' ' && c != '\t' )
1459 0 : x->state = STA_wait_dash; /* garbage after the header line */
1460 0 : break;
1461 : case STA_skip_header_lines:
1462 : /* i.e. wait for one empty line */
1463 0 : if ( c == '\n' ) {
1464 0 : x->state = STA_read_data;
1465 0 : x->crc = CRCINIT;
1466 0 : x->val = 0;
1467 0 : x->pos = 0;
1468 : }
1469 0 : else if ( c != '\r' && c != ' ' && c != '\t' )
1470 0 : x->state = STA_skip_header_lines_non_ws;
1471 0 : break;
1472 : case STA_skip_header_lines_non_ws:
1473 : /* like above but we already encountered non white space */
1474 0 : if ( c == '\n' )
1475 0 : x->state = STA_skip_header_lines;
1476 0 : break;
1477 : case STA_read_data:
1478 : /* fixme: we don't check for the trailing dash lines but rely
1479 : * on the armor stop characters */
1480 0 : if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
1481 : break; /* skip all kind of white space */
1482 :
1483 0 : if( c == '=' ) { /* pad character: stop */
1484 0 : if( x->pos == 1 ) /* in this case val has some value */
1485 0 : rval = x->val;
1486 0 : x->state = STA_wait_crc;
1487 0 : break;
1488 : }
1489 :
1490 : {
1491 : int c2;
1492 0 : if( (c = asctobin[(c2=c)]) == 255 ) {
1493 0 : log_error(_("invalid radix64 character %02X skipped\n"), c2);
1494 0 : break;
1495 : }
1496 : }
1497 :
1498 0 : switch(x->pos) {
1499 : case 0:
1500 0 : x->val = c << 2;
1501 0 : break;
1502 : case 1:
1503 0 : x->val |= (c>>4)&3;
1504 0 : rval = x->val;
1505 0 : x->val = (c<<4)&0xf0;
1506 0 : break;
1507 : case 2:
1508 0 : x->val |= (c>>2)&15;
1509 0 : rval = x->val;
1510 0 : x->val = (c<<6)&0xc0;
1511 0 : break;
1512 : case 3:
1513 0 : x->val |= c&0x3f;
1514 0 : rval = x->val;
1515 0 : break;
1516 : }
1517 0 : x->pos = (x->pos+1) % 4;
1518 0 : break;
1519 : case STA_wait_crc:
1520 0 : if( c == '\n' || c == ' ' || c == '\r' || c == '\t' || c == '=' )
1521 : break; /* skip ws and pad characters */
1522 : /* assume that we are at the next line */
1523 0 : x->state = STA_read_crc;
1524 0 : x->pos = 0;
1525 0 : x->mycrc = 0;
1526 : case STA_read_crc:
1527 0 : if( (c = asctobin[c]) == 255 ) {
1528 0 : rval = -1; /* ready */
1529 0 : if( x->crc != x->mycrc ) {
1530 0 : log_info (_("CRC error; %06lX - %06lX\n"),
1531 0 : (ulong)x->crc, (ulong)x->mycrc);
1532 0 : if ( invalid_crc() )
1533 0 : rval = -3;
1534 : }
1535 0 : x->state = STA_ready; /* not sure whether this is correct */
1536 0 : break;
1537 : }
1538 :
1539 0 : switch(x->pos) {
1540 : case 0:
1541 0 : x->val = c << 2;
1542 0 : break;
1543 : case 1:
1544 0 : x->val |= (c>>4)&3;
1545 0 : x->mycrc |= x->val << 16;
1546 0 : x->val = (c<<4)&0xf0;
1547 0 : break;
1548 : case 2:
1549 0 : x->val |= (c>>2)&15;
1550 0 : x->mycrc |= x->val << 8;
1551 0 : x->val = (c<<6)&0xc0;
1552 0 : break;
1553 : case 3:
1554 0 : x->val |= c&0x3f;
1555 0 : x->mycrc |= x->val;
1556 0 : break;
1557 : }
1558 0 : x->pos = (x->pos+1) % 4;
1559 0 : break;
1560 : case STA_ready:
1561 0 : rval = -1;
1562 0 : break;
1563 : }
1564 :
1565 0 : if ( !(rval & ~255) ) { /* compute the CRC */
1566 0 : x->crc = (x->crc << 8) ^ crc_table[((x->crc >> 16)&0xff) ^ rval];
1567 0 : x->crc &= 0x00ffffff;
1568 : }
1569 :
1570 0 : return rval;
1571 : }
|