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 <http://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 301 : new_armor_context (void)
123 : {
124 : armor_filter_context_t *afx;
125 :
126 301 : afx = xcalloc (1, sizeof *afx);
127 301 : afx->refcount = 1;
128 :
129 301 : return afx;
130 : }
131 :
132 : /* Release an armor filter context. Passing NULL is explicitly
133 : allowed and a no-op. */
134 : void
135 2598 : release_armor_context (armor_filter_context_t *afx)
136 : {
137 2598 : if (!afx)
138 2095 : return;
139 503 : log_assert (afx->refcount);
140 503 : if ( --afx->refcount )
141 203 : return;
142 300 : xfree (afx);
143 : }
144 :
145 : /* Push the armor filter onto the iobuf stream IOBUF. */
146 : int
147 203 : push_armor_filter (armor_filter_context_t *afx, iobuf_t iobuf)
148 : {
149 : int rc;
150 :
151 203 : afx->refcount++;
152 203 : rc = iobuf_push_filter (iobuf, armor_filter, afx);
153 203 : if (rc)
154 0 : afx->refcount--;
155 203 : return rc;
156 : }
157 :
158 :
159 :
160 :
161 :
162 : static void
163 198 : initialize(void)
164 : {
165 : int i, j;
166 : u32 t;
167 : byte *s;
168 :
169 : /* init the crc lookup table */
170 198 : crc_table[0] = 0;
171 25542 : for(i=j=0; j < 128; j++ ) {
172 25344 : t = crc_table[j];
173 25344 : if( t & 0x00800000 ) {
174 12672 : t <<= 1;
175 12672 : crc_table[i++] = t ^ CRCPOLY;
176 12672 : crc_table[i++] = t;
177 : }
178 : else {
179 12672 : t <<= 1;
180 12672 : crc_table[i++] = t;
181 12672 : crc_table[i++] = t ^ CRCPOLY;
182 : }
183 : }
184 : /* build the helptable for radix64 to bin conversion */
185 50886 : for(i=0; i < 256; i++ )
186 50688 : asctobin[i] = 255; /* used to detect invalid characters */
187 12870 : for(s=bintoasc,i=0; *s; s++,i++ )
188 12672 : asctobin[*s] = i;
189 :
190 198 : is_initialized=1;
191 198 : }
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 899 : is_armored (const byte *buf)
205 : {
206 : int ctb, pkttype;
207 : int indeterminate_length_allowed;
208 :
209 899 : ctb = *buf;
210 899 : 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 361 : return 1;
215 :
216 538 : pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
217 538 : 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 469 : indeterminate_length_allowed = 0;
232 469 : 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 69 : indeterminate_length_allowed = 1;
242 69 : break;
243 :
244 : default:
245 : /* Invalid packet type. */
246 0 : return 1;
247 : }
248 :
249 538 : 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 469 : new_format = !! (ctb & (1 << 6));
259 469 : if (new_format)
260 1 : indeterminate_length = (buf[1] >= 224 && buf[1] < 255);
261 : else
262 468 : indeterminate_length = (ctb & 3) == 3;
263 :
264 469 : if (indeterminate_length)
265 0 : return 1;
266 : }
267 :
268 : /* The first CTB seems legit. It is probably not armored
269 : data. */
270 538 : 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 621 : 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 621 : n = iobuf_peek (a, buf, 2);
287 621 : if( n == -1 )
288 0 : return 0; /* EOF, doesn't matter whether armored or not */
289 621 : if( !n )
290 0 : return 1; /* can't check it: try armored */
291 621 : if (n != 2)
292 1 : return 0; /* short buffer */
293 620 : 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 109 : is_armor_tag(const char *line)
359 : {
360 109 : 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 109 : 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 562 : 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 562 : if( len < 15 )
384 66 : return -1; /* too short */
385 496 : if( memcmp( line, "-----", 5 ) )
386 180 : return -1; /* no */
387 316 : p = strstr( line+5, "-----");
388 316 : if( !p )
389 2 : return -1;
390 314 : save_p = p;
391 314 : 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 314 : if(RFC2440)
402 : {
403 0 : if( *p == '\r' )
404 0 : p++;
405 0 : if( *p == '\n' )
406 0 : p++;
407 : }
408 : else
409 934 : while(*p==' ' || *p=='\r' || *p=='\n' || *p=='\t')
410 306 : p++;
411 :
412 314 : if( *p )
413 1 : return -1; /* garbage after dashes */
414 313 : save_c = *save_p; *save_p = 0;
415 313 : p = line+5;
416 1650 : for(i=0; (s=head_strings[i]); i++ )
417 1503 : if( !strcmp(s, p) )
418 166 : break;
419 313 : *save_p = save_c;
420 313 : if( !s )
421 147 : return -1; /* unknown armor line */
422 :
423 166 : if( opt.verbose > 1 )
424 0 : log_info(_("armor: %s\n"), head_strings[i]);
425 166 : 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 293 : parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len )
438 : {
439 : byte *p;
440 293 : int hashes=0;
441 : unsigned int len2;
442 :
443 293 : len2 = length_sans_trailing_ws ( line, len );
444 293 : if( !len2 ) {
445 166 : afx->buffer_pos = len2; /* (it is not the fine way to do it here) */
446 166 : 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 127 : p = strchr( line, ':');
460 127 : if( !p || (RFC2440 && p[1]!=' ')
461 127 : || (!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 127 : len=len2;
471 127 : line[len2]='\0';
472 :
473 127 : 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 127 : 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 109 : 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 127 : return 1;
506 : }
507 :
508 :
509 :
510 : /* figure out whether the data is armored or not */
511 : static int
512 301 : check_input( armor_filter_context_t *afx, IOBUF a )
513 : {
514 301 : int rc = 0;
515 : int i;
516 : byte *line;
517 : unsigned len;
518 : unsigned maxlen;
519 301 : int hdr_line = -1;
520 :
521 : /* read the first line to see whether this is armored data */
522 301 : maxlen = MAX_LINELEN;
523 301 : len = afx->buffer_len = iobuf_read_line( a, &afx->buffer,
524 : &afx->buffer_size, &maxlen );
525 301 : line = afx->buffer;
526 301 : 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 301 : if( !len ) {
534 0 : return -1; /* eof */
535 : }
536 :
537 : /* (the line is always a C string but maybe longer) */
538 301 : if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
539 : ;
540 279 : else if (len >= 2 && !is_armored (line)) {
541 2 : afx->inp_checked = 1;
542 2 : afx->inp_bypass = 1;
543 2 : return 0;
544 : }
545 :
546 : /* find the armor header */
547 994 : while(len) {
548 545 : i = is_armor_header( line, len );
549 545 : if( i >= 0 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
550 149 : hdr_line = i;
551 149 : 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 149 : break;
559 : }
560 : /* read the next line (skip all truncated lines) */
561 : do {
562 396 : maxlen = MAX_LINELEN;
563 396 : afx->buffer_len = iobuf_read_line( a, &afx->buffer,
564 : &afx->buffer_size, &maxlen );
565 396 : line = afx->buffer;
566 396 : len = afx->buffer_len;
567 396 : } while( !maxlen );
568 : }
569 :
570 : /* Parse the header lines. */
571 724 : while(len) {
572 : /* Read the next line (skip all truncated lines). */
573 : do {
574 275 : maxlen = MAX_LINELEN;
575 275 : afx->buffer_len = iobuf_read_line( a, &afx->buffer,
576 : &afx->buffer_size, &maxlen );
577 275 : line = afx->buffer;
578 275 : len = afx->buffer_len;
579 275 : } while( !maxlen );
580 :
581 275 : i = parse_header_line( afx, line, len );
582 275 : if( i <= 0 ) {
583 149 : if (i && RFC2440)
584 0 : rc = GPG_ERR_INV_ARMOR;
585 149 : break;
586 : }
587 : }
588 :
589 :
590 299 : if( rc )
591 0 : invalid_armor();
592 299 : else if( afx->in_cleartext )
593 17 : afx->faked = 1;
594 : else {
595 282 : afx->inp_checked = 1;
596 282 : afx->crc = CRCINIT;
597 282 : afx->idx = 0;
598 282 : afx->radbuf[0] = 0;
599 : }
600 :
601 299 : 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 397 : radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
794 : byte *buf, size_t size )
795 : {
796 : byte val;
797 397 : int c=0, c2; /*init c because gcc is not clever enough for the continue*/
798 397 : int checkcrc=0;
799 397 : int rc = 0;
800 397 : size_t n = 0;
801 397 : int idx, i, onlypad=0;
802 : u32 crc;
803 :
804 397 : crc = afx->crc;
805 397 : idx = afx->idx;
806 397 : val = afx->radbuf[0];
807 1340058 : for( n=0; n < size; ) {
808 :
809 1339563 : if( afx->buffer_pos < afx->buffer_len )
810 1319024 : c = afx->buffer[afx->buffer_pos++];
811 : else { /* read the next line */
812 20539 : unsigned maxlen = MAX_LINELEN;
813 20539 : afx->buffer_pos = 0;
814 20539 : afx->buffer_len = iobuf_read_line( a, &afx->buffer,
815 : &afx->buffer_size, &maxlen );
816 20539 : if( !maxlen )
817 0 : afx->truncated++;
818 20539 : if( !afx->buffer_len )
819 150 : break; /* eof */
820 20389 : continue;
821 : }
822 :
823 : again:
824 1319024 : if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
825 20389 : continue;
826 1298635 : else if( c == '=' ) { /* pad character: stop */
827 : /* some mailers leave quoted-printable encoded characters
828 : * so we try to workaround this */
829 149 : if( afx->buffer_pos+2 < afx->buffer_len ) {
830 : int cc1, cc2, cc3;
831 57 : cc1 = afx->buffer[afx->buffer_pos];
832 57 : cc2 = afx->buffer[afx->buffer_pos+1];
833 57 : cc3 = afx->buffer[afx->buffer_pos+2];
834 57 : if( isxdigit(cc1) && isxdigit(cc2)
835 10 : && 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 149 : 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 149 : if (!n)
865 2 : onlypad = 1;
866 :
867 149 : if( idx == 1 )
868 0 : buf[n++] = val;
869 149 : checkcrc++;
870 149 : break;
871 : }
872 1298486 : else if( (c = asctobin[(c2=c)]) == 255 ) {
873 0 : log_error(_("invalid radix64 character %02X skipped\n"), c2);
874 0 : continue;
875 : }
876 1298486 : switch(idx) {
877 324654 : case 0: val = c << 2; break;
878 324654 : case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
879 324616 : case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
880 324562 : case 3: val |= c&0x3f; buf[n++] = val; break;
881 : }
882 1298486 : idx = (idx+1) % 4;
883 : }
884 :
885 974229 : for(i=0; i < n; i++ )
886 973832 : crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
887 397 : crc &= 0x00ffffff;
888 397 : afx->crc = crc;
889 397 : afx->idx = idx;
890 397 : afx->radbuf[0] = val;
891 :
892 397 : if( checkcrc ) {
893 149 : afx->any_data = 1;
894 149 : afx->inp_checked=0;
895 149 : afx->faked = 0;
896 : for(;;) { /* skip lf and pad characters */
897 463 : if( afx->buffer_pos < afx->buffer_len )
898 371 : c = afx->buffer[afx->buffer_pos++];
899 : else { /* read the next line */
900 92 : unsigned maxlen = MAX_LINELEN;
901 92 : afx->buffer_pos = 0;
902 92 : afx->buffer_len = iobuf_read_line( a, &afx->buffer,
903 : &afx->buffer_size, &maxlen );
904 92 : if( !maxlen )
905 0 : afx->truncated++;
906 92 : if( !afx->buffer_len )
907 0 : break; /* eof */
908 92 : continue;
909 : }
910 371 : if( c == '\n' || c == ' ' || c == '\r'
911 279 : || c == '\t' || c == '=' )
912 222 : continue;
913 149 : break;
914 314 : }
915 149 : if( c == -1 )
916 0 : log_error(_("premature eof (no CRC)\n"));
917 : else {
918 149 : u32 mycrc = 0;
919 149 : idx = 0;
920 : do {
921 596 : if( (c = asctobin[c]) == 255 )
922 0 : break;
923 596 : switch(idx) {
924 149 : case 0: val = c << 2; break;
925 149 : case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
926 149 : case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
927 149 : case 3: val |= c&0x3f; mycrc |= val; break;
928 : }
929 : for(;;) {
930 596 : if( afx->buffer_pos < afx->buffer_len )
931 596 : 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 596 : break;
945 0 : }
946 596 : if( !afx->buffer_len )
947 0 : break; /* eof */
948 596 : } while( ++idx < 4 );
949 149 : if( c == -1 ) {
950 0 : log_info(_("premature eof (in CRC)\n"));
951 0 : rc = invalid_crc();
952 : }
953 149 : else if( idx == 0 ) {
954 : /* No CRC at all is legal ("MAY") */
955 0 : rc=0;
956 : }
957 149 : else if( idx != 4 ) {
958 0 : log_info(_("malformed CRC\n"));
959 0 : rc = invalid_crc();
960 : }
961 149 : 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 149 : 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 397 : if( !n && !onlypad )
995 150 : rc = -1;
996 :
997 397 : *retn = n;
998 397 : return rc;
999 : }
1000 :
1001 : /****************
1002 : * This filter is used to handle the armor stuff
1003 : */
1004 : static int
1005 1037 : armor_filter( void *opaque, int control,
1006 : IOBUF a, byte *buf, size_t *ret_len)
1007 : {
1008 1037 : size_t size = *ret_len;
1009 1037 : armor_filter_context_t *afx = opaque;
1010 1037 : int rc=0, i, c;
1011 : byte radbuf[3];
1012 : int idx, idx2;
1013 1037 : 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 1037 : if( DBG_FILTER )
1025 0 : log_debug("armor-filter: control: %d\n", control );
1026 1037 : if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
1027 4 : n = 0;
1028 4 : if( afx->buffer_len ) {
1029 0 : for(; n < size && afx->buffer_pos < afx->buffer_len; n++ )
1030 0 : buf[n++] = afx->buffer[afx->buffer_pos++];
1031 0 : if( afx->buffer_pos >= afx->buffer_len )
1032 0 : afx->buffer_len = 0;
1033 : }
1034 1072 : for(; n < size; n++ ) {
1035 1072 : if( (c=iobuf_get(a)) == -1 )
1036 4 : break;
1037 1068 : buf[n] = c & 0xff;
1038 : }
1039 4 : if( !n )
1040 2 : rc = -1;
1041 4 : *ret_len = n;
1042 : }
1043 1033 : else if( control == IOBUFCTRL_UNDERFLOW ) {
1044 : /* We need some space for the faked packet. The minmum
1045 : * required size is the PARTIAL_CHUNK size plus a byte for the
1046 : * length itself */
1047 459 : if( size < PARTIAL_CHUNK+1 )
1048 0 : BUG(); /* supplied buffer too short */
1049 :
1050 459 : if( afx->faked )
1051 43 : rc = fake_packet( afx, a, &n, buf, size );
1052 416 : else if( !afx->inp_checked ) {
1053 301 : rc = check_input( afx, a );
1054 301 : if( afx->inp_bypass ) {
1055 783 : for(n=0; n < size && afx->buffer_pos < afx->buffer_len; )
1056 779 : buf[n++] = afx->buffer[afx->buffer_pos++];
1057 2 : if( afx->buffer_pos >= afx->buffer_len )
1058 2 : afx->buffer_len = 0;
1059 2 : if( !n )
1060 0 : rc = -1;
1061 : }
1062 299 : else if( afx->faked ) {
1063 17 : unsigned int hashes = afx->hashes;
1064 : const byte *sesmark;
1065 : size_t sesmarklen;
1066 :
1067 17 : sesmark = get_session_marker( &sesmarklen );
1068 17 : if ( sesmarklen > 20 )
1069 0 : BUG();
1070 :
1071 : /* the buffer is at least 15+n*15 bytes long, so it
1072 : * is easy to construct the packets */
1073 :
1074 17 : hashes &= 1|2|8|16|32|64;
1075 17 : if( !hashes ) {
1076 0 : hashes |= 2; /* Default to SHA-1. */
1077 : }
1078 17 : n=0;
1079 : /* First a gpg control packet... */
1080 17 : buf[n++] = 0xff; /* new format, type 63, 1 length byte */
1081 17 : n++; /* see below */
1082 17 : memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
1083 17 : buf[n++] = CTRLPKT_CLEARSIGN_START;
1084 17 : buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
1085 17 : if( hashes & 1 )
1086 0 : buf[n++] = DIGEST_ALGO_RMD160;
1087 17 : if( hashes & 2 )
1088 14 : buf[n++] = DIGEST_ALGO_SHA1;
1089 17 : if( hashes & 8 )
1090 0 : buf[n++] = DIGEST_ALGO_SHA224;
1091 17 : if( hashes & 16 )
1092 3 : buf[n++] = DIGEST_ALGO_SHA256;
1093 17 : if( hashes & 32 )
1094 0 : buf[n++] = DIGEST_ALGO_SHA384;
1095 17 : if( hashes & 64 )
1096 0 : buf[n++] = DIGEST_ALGO_SHA512;
1097 17 : buf[1] = n - 2;
1098 :
1099 : /* ...followed by an invented plaintext packet.
1100 : Amusingly enough, this packet is not compliant with
1101 : 2440 as the initial partial length is less than 512
1102 : bytes. Of course, we'll accept it anyway ;) */
1103 :
1104 17 : buf[n++] = 0xCB; /* new packet format, type 11 */
1105 17 : buf[n++] = 0xE1; /* 2^1 == 2 bytes */
1106 17 : buf[n++] = 't'; /* canonical text mode */
1107 17 : buf[n++] = 0; /* namelength */
1108 17 : buf[n++] = 0xE2; /* 2^2 == 4 more bytes */
1109 17 : memset(buf+n, 0, 4); /* timestamp */
1110 17 : n += 4;
1111 : }
1112 282 : else if( !rc )
1113 282 : rc = radix64_read( afx, a, &n, buf, size );
1114 : }
1115 : else
1116 115 : rc = radix64_read( afx, a, &n, buf, size );
1117 : #if 0
1118 : if( n )
1119 : if( fwrite(buf, n, 1, fp ) != 1 )
1120 : BUG();
1121 : #endif
1122 459 : *ret_len = n;
1123 : }
1124 574 : else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) {
1125 168 : if( !afx->status ) { /* write the header line */
1126 : const char *s;
1127 51 : strlist_t comment=opt.comments;
1128 :
1129 51 : if( afx->what >= DIM(head_strings) )
1130 0 : log_bug("afx->what=%d", afx->what);
1131 51 : iobuf_writestr(a, "-----");
1132 51 : iobuf_writestr(a, head_strings[afx->what] );
1133 51 : iobuf_writestr(a, "-----" );
1134 51 : iobuf_writestr(a,afx->eol);
1135 51 : if (opt.emit_version)
1136 : {
1137 0 : iobuf_writestr (a, "Version: "GNUPG_NAME" v");
1138 0 : for (s=VERSION; *s && *s != '.'; s++)
1139 0 : iobuf_writebyte (a, *s);
1140 0 : if (opt.emit_version > 1 && *s)
1141 : {
1142 0 : iobuf_writebyte (a, *s++);
1143 0 : for (; *s && *s != '.'; s++)
1144 0 : iobuf_writebyte (a, *s);
1145 0 : if (opt.emit_version > 2)
1146 : {
1147 0 : for (; *s && *s != '-' && !spacep (s); s++)
1148 0 : iobuf_writebyte (a, *s);
1149 0 : if (opt.emit_version > 3)
1150 0 : iobuf_writestr (a, " (" PRINTABLE_OS_NAME ")");
1151 : }
1152 : }
1153 0 : iobuf_writestr(a,afx->eol);
1154 : }
1155 :
1156 : /* write the comment strings */
1157 51 : for(s=comment->d;comment;comment=comment->next,s=comment->d)
1158 : {
1159 0 : iobuf_writestr(a, "Comment: " );
1160 0 : for( ; *s; s++ )
1161 : {
1162 0 : if( *s == '\n' )
1163 0 : iobuf_writestr(a, "\\n" );
1164 0 : else if( *s == '\r' )
1165 0 : iobuf_writestr(a, "\\r" );
1166 0 : else if( *s == '\v' )
1167 0 : iobuf_writestr(a, "\\v" );
1168 : else
1169 0 : iobuf_put(a, *s );
1170 : }
1171 :
1172 0 : iobuf_writestr(a,afx->eol);
1173 : }
1174 :
1175 51 : if ( afx->hdrlines ) {
1176 86 : for ( s = afx->hdrlines; *s; s++ ) {
1177 : #ifdef HAVE_DOSISH_SYSTEM
1178 : if ( *s == '\n' )
1179 : iobuf_put( a, '\r');
1180 : #endif
1181 84 : iobuf_put(a, *s );
1182 : }
1183 : }
1184 :
1185 51 : iobuf_writestr(a,afx->eol);
1186 51 : afx->status++;
1187 51 : afx->idx = 0;
1188 51 : afx->idx2 = 0;
1189 51 : afx->crc = CRCINIT;
1190 :
1191 : }
1192 168 : crc = afx->crc;
1193 168 : idx = afx->idx;
1194 168 : idx2 = afx->idx2;
1195 242 : for(i=0; i < idx; i++ )
1196 74 : radbuf[i] = afx->radbuf[i];
1197 :
1198 506144 : for(i=0; i < size; i++ )
1199 505976 : crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
1200 168 : crc &= 0x00ffffff;
1201 :
1202 506144 : for( ; size; buf++, size-- ) {
1203 505976 : radbuf[idx++] = *buf;
1204 505976 : if( idx > 2 ) {
1205 168646 : idx = 0;
1206 168646 : c = bintoasc[(*radbuf >> 2) & 077];
1207 168646 : iobuf_put(a, c);
1208 168646 : c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1209 168646 : iobuf_put(a, c);
1210 168646 : c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1211 168646 : iobuf_put(a, c);
1212 168646 : c = bintoasc[radbuf[2]&077];
1213 168646 : iobuf_put(a, c);
1214 168646 : if( ++idx2 >= (64/4) )
1215 : { /* pgp doesn't like 72 here */
1216 10513 : iobuf_writestr(a,afx->eol);
1217 10513 : idx2=0;
1218 : }
1219 : }
1220 : }
1221 280 : for(i=0; i < idx; i++ )
1222 112 : afx->radbuf[i] = radbuf[i];
1223 168 : afx->idx = idx;
1224 168 : afx->idx2 = idx2;
1225 168 : afx->crc = crc;
1226 : }
1227 406 : else if( control == IOBUFCTRL_INIT )
1228 : {
1229 203 : if( !is_initialized )
1230 198 : initialize();
1231 :
1232 : /* Figure out what we're using for line endings if the caller
1233 : didn't specify. */
1234 203 : if(afx->eol[0]==0)
1235 : {
1236 : #ifdef HAVE_DOSISH_SYSTEM
1237 : afx->eol[0]='\r';
1238 : afx->eol[1]='\n';
1239 : #else
1240 203 : afx->eol[0]='\n';
1241 : #endif
1242 : }
1243 : }
1244 203 : else if( control == IOBUFCTRL_CANCEL ) {
1245 0 : afx->cancel = 1;
1246 : }
1247 203 : else if( control == IOBUFCTRL_FREE ) {
1248 203 : if( afx->cancel )
1249 : ;
1250 203 : else if( afx->status ) { /* pad, write cecksum, and bottom line */
1251 51 : crc = afx->crc;
1252 51 : idx = afx->idx;
1253 51 : idx2 = afx->idx2;
1254 51 : if( idx ) {
1255 24 : c = bintoasc[(afx->radbuf[0]>>2)&077];
1256 24 : iobuf_put(a, c);
1257 24 : if( idx == 1 ) {
1258 10 : c = bintoasc[((afx->radbuf[0] << 4) & 060) & 077];
1259 10 : iobuf_put(a, c);
1260 10 : iobuf_put(a, '=');
1261 10 : iobuf_put(a, '=');
1262 : }
1263 : else { /* 2 */
1264 28 : c = bintoasc[(((afx->radbuf[0]<<4)&060)
1265 14 : |((afx->radbuf[1]>>4)&017))&077];
1266 14 : iobuf_put(a, c);
1267 14 : c = bintoasc[((afx->radbuf[1] << 2) & 074) & 077];
1268 14 : iobuf_put(a, c);
1269 14 : iobuf_put(a, '=');
1270 : }
1271 24 : if( ++idx2 >= (64/4) )
1272 : { /* pgp doesn't like 72 here */
1273 3 : iobuf_writestr(a,afx->eol);
1274 3 : idx2=0;
1275 : }
1276 : }
1277 : /* may need a linefeed */
1278 51 : if( idx2 )
1279 48 : iobuf_writestr(a,afx->eol);
1280 : /* write the CRC */
1281 51 : iobuf_put(a, '=');
1282 51 : radbuf[0] = crc >>16;
1283 51 : radbuf[1] = crc >> 8;
1284 51 : radbuf[2] = crc;
1285 51 : c = bintoasc[(*radbuf >> 2) & 077];
1286 51 : iobuf_put(a, c);
1287 51 : c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1288 51 : iobuf_put(a, c);
1289 51 : c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1290 51 : iobuf_put(a, c);
1291 51 : c = bintoasc[radbuf[2]&077];
1292 51 : iobuf_put(a, c);
1293 51 : iobuf_writestr(a,afx->eol);
1294 : /* and the the trailer */
1295 51 : if( afx->what >= DIM(tail_strings) )
1296 0 : log_bug("afx->what=%d", afx->what);
1297 51 : iobuf_writestr(a, "-----");
1298 51 : iobuf_writestr(a, tail_strings[afx->what] );
1299 51 : iobuf_writestr(a, "-----" );
1300 51 : iobuf_writestr(a,afx->eol);
1301 : }
1302 152 : else if( !afx->any_data && !afx->inp_bypass ) {
1303 3 : log_error(_("no valid OpenPGP data found.\n"));
1304 3 : afx->no_openpgp_data = 1;
1305 3 : write_status_text( STATUS_NODATA, "1" );
1306 : }
1307 203 : if( afx->truncated )
1308 0 : log_info(_("invalid armor: line longer than %d characters\n"),
1309 : MAX_LINELEN );
1310 : /* issue an error to enforce dissemination of correct software */
1311 203 : if( afx->qp_detected )
1312 0 : log_error(_("quoted printable character in armor - "
1313 : "probably a buggy MTA has been used\n") );
1314 203 : xfree( afx->buffer );
1315 203 : afx->buffer = NULL;
1316 203 : release_armor_context (afx);
1317 : }
1318 0 : else if( control == IOBUFCTRL_DESC )
1319 0 : mem2str (buf, "armor_filter", *ret_len);
1320 1037 : return rc;
1321 : }
1322 :
1323 :
1324 : /****************
1325 : * create a radix64 encoded string.
1326 : */
1327 : char *
1328 19 : make_radix64_string( const byte *data, size_t len )
1329 : {
1330 : char *buffer, *p;
1331 :
1332 19 : buffer = p = xmalloc( (len+2)/3*4 + 1 );
1333 157 : for( ; len >= 3 ; len -= 3, data += 3 ) {
1334 138 : *p++ = bintoasc[(data[0] >> 2) & 077];
1335 138 : *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1336 138 : *p++ = bintoasc[(((data[1]<<2)&074)|((data[2]>>6)&03))&077];
1337 138 : *p++ = bintoasc[data[2]&077];
1338 : }
1339 19 : if( len == 2 ) {
1340 19 : *p++ = bintoasc[(data[0] >> 2) & 077];
1341 19 : *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1342 19 : *p++ = bintoasc[((data[1]<<2)&074)];
1343 : }
1344 0 : else if( len == 1 ) {
1345 0 : *p++ = bintoasc[(data[0] >> 2) & 077];
1346 0 : *p++ = bintoasc[(data[0] <<4)&060];
1347 : }
1348 19 : *p = 0;
1349 19 : return buffer;
1350 : }
1351 :
1352 :
1353 : /***********************************************
1354 : * For the pipemode command we can't use the armor filter for various
1355 : * reasons, so we use this new unarmor_pump stuff to remove the armor
1356 : */
1357 :
1358 : enum unarmor_state_e {
1359 : STA_init = 0,
1360 : STA_bypass,
1361 : STA_wait_newline,
1362 : STA_wait_dash,
1363 : STA_first_dash,
1364 : STA_compare_header,
1365 : STA_found_header_wait_newline,
1366 : STA_skip_header_lines,
1367 : STA_skip_header_lines_non_ws,
1368 : STA_read_data,
1369 : STA_wait_crc,
1370 : STA_read_crc,
1371 : STA_ready
1372 : };
1373 :
1374 : struct unarmor_pump_s {
1375 : enum unarmor_state_e state;
1376 : byte val;
1377 : int checkcrc;
1378 : int pos; /* counts from 0..3 */
1379 : u32 crc;
1380 : u32 mycrc; /* the one store in the data */
1381 : };
1382 :
1383 :
1384 :
1385 : UnarmorPump
1386 0 : unarmor_pump_new (void)
1387 : {
1388 : UnarmorPump x;
1389 :
1390 0 : if( !is_initialized )
1391 0 : initialize();
1392 0 : x = xmalloc_clear (sizeof *x);
1393 0 : return x;
1394 : }
1395 :
1396 : void
1397 0 : unarmor_pump_release (UnarmorPump x)
1398 : {
1399 0 : xfree (x);
1400 0 : }
1401 :
1402 : /*
1403 : * Get the next character from the ascii armor taken from the IOBUF
1404 : * created earlier by unarmor_pump_new().
1405 : * Return: c = Character
1406 : * 256 = ignore this value
1407 : * -1 = End of current armor
1408 : * -2 = Premature EOF (not used)
1409 : * -3 = Invalid armor
1410 : */
1411 : int
1412 0 : unarmor_pump (UnarmorPump x, int c)
1413 : {
1414 0 : int rval = 256; /* default is to ignore the return value */
1415 :
1416 0 : switch (x->state) {
1417 : case STA_init:
1418 : {
1419 : byte tmp[2];
1420 0 : tmp[0] = c;
1421 0 : tmp[1] = 0;
1422 0 : if ( is_armored (tmp) )
1423 0 : x->state = c == '-'? STA_first_dash : STA_wait_newline;
1424 : else {
1425 0 : x->state = STA_bypass;
1426 0 : return c;
1427 : }
1428 : }
1429 0 : break;
1430 : case STA_bypass:
1431 0 : return c; /* return here to avoid crc calculation */
1432 : case STA_wait_newline:
1433 0 : if (c == '\n')
1434 0 : x->state = STA_wait_dash;
1435 0 : break;
1436 : case STA_wait_dash:
1437 0 : x->state = c == '-'? STA_first_dash : STA_wait_newline;
1438 0 : break;
1439 : case STA_first_dash: /* just need for initalization */
1440 0 : x->pos = 0;
1441 0 : x->state = STA_compare_header;
1442 : case STA_compare_header:
1443 0 : if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) {
1444 0 : if ( x->pos == 28 )
1445 0 : x->state = STA_found_header_wait_newline;
1446 : }
1447 : else
1448 0 : x->state = c == '\n'? STA_wait_dash : STA_wait_newline;
1449 0 : break;
1450 : case STA_found_header_wait_newline:
1451 : /* to make CR,LF issues easier we simply allow for white space
1452 : behind the 5 dashes */
1453 0 : if ( c == '\n' )
1454 0 : x->state = STA_skip_header_lines;
1455 0 : else if ( c != '\r' && c != ' ' && c != '\t' )
1456 0 : x->state = STA_wait_dash; /* garbage after the header line */
1457 0 : break;
1458 : case STA_skip_header_lines:
1459 : /* i.e. wait for one empty line */
1460 0 : if ( c == '\n' ) {
1461 0 : x->state = STA_read_data;
1462 0 : x->crc = CRCINIT;
1463 0 : x->val = 0;
1464 0 : x->pos = 0;
1465 : }
1466 0 : else if ( c != '\r' && c != ' ' && c != '\t' )
1467 0 : x->state = STA_skip_header_lines_non_ws;
1468 0 : break;
1469 : case STA_skip_header_lines_non_ws:
1470 : /* like above but we already encountered non white space */
1471 0 : if ( c == '\n' )
1472 0 : x->state = STA_skip_header_lines;
1473 0 : break;
1474 : case STA_read_data:
1475 : /* fixme: we don't check for the trailing dash lines but rely
1476 : * on the armor stop characters */
1477 0 : if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
1478 : break; /* skip all kind of white space */
1479 :
1480 0 : if( c == '=' ) { /* pad character: stop */
1481 0 : if( x->pos == 1 ) /* in this case val has some value */
1482 0 : rval = x->val;
1483 0 : x->state = STA_wait_crc;
1484 0 : break;
1485 : }
1486 :
1487 : {
1488 : int c2;
1489 0 : if( (c = asctobin[(c2=c)]) == 255 ) {
1490 0 : log_error(_("invalid radix64 character %02X skipped\n"), c2);
1491 0 : break;
1492 : }
1493 : }
1494 :
1495 0 : switch(x->pos) {
1496 : case 0:
1497 0 : x->val = c << 2;
1498 0 : break;
1499 : case 1:
1500 0 : x->val |= (c>>4)&3;
1501 0 : rval = x->val;
1502 0 : x->val = (c<<4)&0xf0;
1503 0 : break;
1504 : case 2:
1505 0 : x->val |= (c>>2)&15;
1506 0 : rval = x->val;
1507 0 : x->val = (c<<6)&0xc0;
1508 0 : break;
1509 : case 3:
1510 0 : x->val |= c&0x3f;
1511 0 : rval = x->val;
1512 0 : break;
1513 : }
1514 0 : x->pos = (x->pos+1) % 4;
1515 0 : break;
1516 : case STA_wait_crc:
1517 0 : if( c == '\n' || c == ' ' || c == '\r' || c == '\t' || c == '=' )
1518 : break; /* skip ws and pad characters */
1519 : /* assume that we are at the next line */
1520 0 : x->state = STA_read_crc;
1521 0 : x->pos = 0;
1522 0 : x->mycrc = 0;
1523 : case STA_read_crc:
1524 0 : if( (c = asctobin[c]) == 255 ) {
1525 0 : rval = -1; /* ready */
1526 0 : if( x->crc != x->mycrc ) {
1527 0 : log_info (_("CRC error; %06lX - %06lX\n"),
1528 0 : (ulong)x->crc, (ulong)x->mycrc);
1529 0 : if ( invalid_crc() )
1530 0 : rval = -3;
1531 : }
1532 0 : x->state = STA_ready; /* not sure whether this is correct */
1533 0 : break;
1534 : }
1535 :
1536 0 : switch(x->pos) {
1537 : case 0:
1538 0 : x->val = c << 2;
1539 0 : break;
1540 : case 1:
1541 0 : x->val |= (c>>4)&3;
1542 0 : x->mycrc |= x->val << 16;
1543 0 : x->val = (c<<4)&0xf0;
1544 0 : break;
1545 : case 2:
1546 0 : x->val |= (c>>2)&15;
1547 0 : x->mycrc |= x->val << 8;
1548 0 : x->val = (c<<6)&0xc0;
1549 0 : break;
1550 : case 3:
1551 0 : x->val |= c&0x3f;
1552 0 : x->mycrc |= x->val;
1553 0 : break;
1554 : }
1555 0 : x->pos = (x->pos+1) % 4;
1556 0 : break;
1557 : case STA_ready:
1558 0 : rval = -1;
1559 0 : break;
1560 : }
1561 :
1562 0 : if ( !(rval & ~255) ) { /* compute the CRC */
1563 0 : x->crc = (x->crc << 8) ^ crc_table[((x->crc >> 16)&0xff) ^ rval];
1564 0 : x->crc &= 0x00ffffff;
1565 : }
1566 :
1567 0 : return rval;
1568 : }
|