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