1 /* armor.c - Armor flter
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3 * 2006 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
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 2 of the License, or
10 * (at your option) any later version.
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.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
42 #define MAX_LINELEN 20000
44 #define CRCINIT 0xB704CE
45 #define CRCPOLY 0X864CFB
46 #define CRCUPDATE(a,c) do { \
47 a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \
50 static u32 crc_table
[256];
51 static byte bintoasc
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
52 "abcdefghijklmnopqrstuvwxyz"
54 static byte asctobin
[256]; /* runtime initialized */
55 static int is_initialized
;
75 fhdrCHECKDashEscaped2
,
76 fhdrCHECKDashEscaped3
,
82 fhdrCLEARSIGSimpleNext
,
91 /* if we encounter this armor string with this index, go
92 * into a mode which fakes packets and wait for the next armor */
93 #define BEGIN_SIGNATURE 2
94 #define BEGIN_SIGNED_MSG_IDX 3
95 static char *head_strings
[] = {
97 "BEGIN PGP PUBLIC KEY BLOCK",
98 "BEGIN PGP SIGNATURE",
99 "BEGIN PGP SIGNED MESSAGE",
100 "BEGIN PGP ARMORED FILE", /* gnupg extension */
101 "BEGIN PGP PRIVATE KEY BLOCK",
102 "BEGIN PGP SECRET KEY BLOCK", /* only used by pgp2 */
105 static char *tail_strings
[] = {
107 "END PGP PUBLIC KEY BLOCK",
110 "END PGP ARMORED FILE",
111 "END PGP PRIVATE KEY BLOCK",
112 "END PGP SECRET KEY BLOCK",
124 /* init the crc lookup table */
126 for(i
=j
=0; j
< 128; j
++ ) {
128 if( t
& 0x00800000 ) {
130 crc_table
[i
++] = t
^ CRCPOLY
;
136 crc_table
[i
++] = t
^ CRCPOLY
;
139 /* build the helptable for radix64 to bin conversion */
140 for(i
=0; i
< 256; i
++ )
141 asctobin
[i
] = 255; /* used to detect invalid characters */
142 for(s
=bintoasc
,i
=0; *s
; s
++,i
++ )
149 * Check whether this is an armored file or not See also
150 * parse-packet.c for details on this code For unknown historic
151 * reasons we use a string here but only the first byte will be used.
152 * Returns: True if it seems to be armored
155 is_armored( const byte
*buf
)
161 return 1; /* invalid packet: assume it is armored */
162 pkttype
= ctb
& 0x40 ? (ctb
& 0x3f) : ((ctb
>>2)&0xf);
166 case PKT_ONEPASS_SIG
:
172 case PKT_OLD_COMMENT
:
176 return 0; /* seems to be a regular packet: not armored */
184 * Try to check whether the iobuf is armored
185 * Returns true if this may be the case; the caller should use the
186 * filter to do further processing.
189 use_armor_filter( IOBUF a
)
194 /* fixme: there might be a problem with iobuf_peek */
195 n
= iobuf_peek(a
, buf
, 1 );
197 return 0; /* EOF, doesn't matter whether armored or not */
199 return 1; /* can't check it: try armored */
200 return is_armored(buf
);
209 write_status(STATUS_BADARMOR
);
210 g10_exit(1); /* stop here */
215 * check whether the armor header is valid on a signed message.
216 * this is for security reasons: the header lines are not included in the
217 * hash and by using some creative formatting rules, Mallory could fake
218 * any text at the beginning of a document; assuming it is read with
219 * a simple viewer. We only allow the Hash Header.
222 parse_hash_header( const char *line
)
227 if( strlen(line
) < 6 || strlen(line
) > 60 )
228 return 0; /* too short or too long */
229 if( memcmp( line
, "Hash:", 5 ) )
230 return 0; /* invalid header */
232 for(s
=line
+5;;s
=s2
) {
233 for(; *s
&& (*s
==' ' || *s
== '\t'); s
++ )
237 for(s2
=s
+1; *s2
&& *s2
!=' ' && *s2
!= '\t' && *s2
!= ','; s2
++ )
239 if( !strncmp( s
, "RIPEMD160", s2
-s
) )
241 else if( !strncmp( s
, "SHA1", s2
-s
) )
243 else if( !strncmp( s
, "MD5", s2
-s
) )
245 else if( !strncmp( s
, "SHA224", s2
-s
) )
247 else if( !strncmp( s
, "SHA256", s2
-s
) )
249 else if( !strncmp( s
, "SHA384", s2
-s
) )
251 else if( !strncmp( s
, "SHA512", s2
-s
) )
255 for(; *s2
&& (*s2
==' ' || *s2
== '\t'); s2
++ )
257 if( *s2
&& *s2
!= ',' )
268 * Check whether this is a armor line.
269 * returns: -1 if it is not a armor header or the index number of the
273 is_armor_header( byte
*line
, unsigned len
)
281 return -1; /* too short */
282 if( memcmp( line
, "-----", 5 ) )
284 p
= strstr( line
+5, "-----");
290 /* Some Windows environments seem to add whitespace to the end of
291 the line, so we strip it here. This becomes strict if
292 --rfc2440 is set since 2440 reads "The header lines, therefore,
293 MUST start at the beginning of a line, and MUST NOT have text
294 following them on the same line." It is unclear whether "text"
295 refers to all text or just non-whitespace text. */
305 while(*p
==' ' || *p
=='\r' || *p
=='\n' || *p
=='\t')
309 return -1; /* garbage after dashes */
310 save_c
= *save_p
; *save_p
= 0;
312 for(i
=0; (s
=head_strings
[i
]); i
++ )
317 return -1; /* unknown armor line */
319 if( opt
.verbose
> 1 )
320 log_info(_("armor: %s\n"), head_strings
[i
]);
327 * Parse a header lines
328 * Return 0: Empty line (end of header lines)
329 * -1: invalid header line
330 * >0: Good header line
333 parse_header_line( armor_filter_context_t
*afx
, byte
*line
, unsigned int len
)
339 len2
= check_trailing_ws( line
, len
);
341 afx
->buffer_pos
= len2
; /* (it is not the fine way to do it here) */
342 return 0; /* WS only: same as empty line */
346 This is fussy. The spec says that a header line is delimited
347 with a colon-space pair. This means that a line such as
348 "Comment: " (with nothing else) is actually legal as an empty
349 string comment. However, email and cut-and-paste being what it
350 is, that trailing space may go away. Therefore, we accept empty
351 headers delimited with only a colon. --rfc2440, as always,
352 makes this strict and enforces the colon-space pair. -dms
355 p
= strchr( line
, ':');
356 if( !p
|| (RFC2440
&& p
[1]!=' ')
357 || (!RFC2440
&& p
[1]!=' ' && p
[1]!='\n' && p
[1]!='\r'))
359 log_error(_("invalid armor header: "));
360 print_string( stderr
, line
, len
, 0 );
365 /* Chop off the whitespace we detected before */
370 log_info(_("armor header: "));
371 print_string( stderr
, line
, len
, 0 );
375 if( afx
->in_cleartext
) {
376 if( (hashes
=parse_hash_header( line
)) )
377 afx
->hashes
|= hashes
;
378 else if( strlen(line
) > 15 && !memcmp( line
, "NotDashEscaped:", 15 ) )
379 afx
->not_dash_escaped
= 1;
381 log_error(_("invalid clearsig header\n"));
390 /* figure out whether the data is armored or not */
392 check_input( armor_filter_context_t
*afx
, IOBUF a
)
401 /* read the first line to see whether this is armored data */
402 maxlen
= MAX_LINELEN
;
403 len
= afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
404 &afx
->buffer_size
, &maxlen
);
407 /* line has been truncated: assume not armored */
408 afx
->inp_checked
= 1;
417 /* (the line is always a C string but maybe longer) */
418 if( *line
== '\n' || ( len
&& (*line
== '\r' && line
[1]=='\n') ) )
420 else if( !is_armored( line
) ) {
421 afx
->inp_checked
= 1;
426 /* find the armor header */
428 i
= is_armor_header( line
, len
);
429 if( i
>= 0 && !(afx
->only_keyblocks
&& i
!= 1 && i
!= 5 && i
!= 6 )) {
431 if( hdr_line
== BEGIN_SIGNED_MSG_IDX
) {
432 if( afx
->in_cleartext
) {
433 log_error(_("nested clear text signatures\n"));
434 rc
= G10ERR_INVALID_ARMOR
;
436 afx
->in_cleartext
= 1;
440 /* read the next line (skip all truncated lines) */
442 maxlen
= MAX_LINELEN
;
443 afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
444 &afx
->buffer_size
, &maxlen
);
446 len
= afx
->buffer_len
;
450 /* Parse the header lines. */
452 /* Read the next line (skip all truncated lines). */
454 maxlen
= MAX_LINELEN
;
455 afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
456 &afx
->buffer_size
, &maxlen
);
458 len
= afx
->buffer_len
;
461 i
= parse_header_line( afx
, line
, len
);
464 rc
= G10ERR_INVALID_ARMOR
;
472 else if( afx
->in_cleartext
)
475 afx
->inp_checked
= 1;
484 #define PARTIAL_CHUNK 512
485 #define PARTIAL_POW 9
488 * Fake a literal data packet and wait for the next armor line
489 * fixme: empty line handling and null length clear text signature are
490 * not implemented/checked.
493 fake_packet( armor_filter_context_t
*afx
, IOBUF a
,
494 size_t *retn
, byte
*buf
, size_t size
)
501 byte tempbuf
[PARTIAL_CHUNK
];
502 size_t tempbuf_len
=0;
504 while( !rc
&& size
-len
>=(PARTIAL_CHUNK
+1)) {
505 /* copy what we have in the line buffer */
506 if( afx
->faked
== 1 )
507 afx
->faked
++; /* skip the first (empty) line */
510 /* It's full, so write this partial chunk */
511 if(tempbuf_len
==PARTIAL_CHUNK
)
513 buf
[len
++]=0xE0+PARTIAL_POW
;
514 memcpy(&buf
[len
],tempbuf
,PARTIAL_CHUNK
);
520 while( tempbuf_len
< PARTIAL_CHUNK
521 && afx
->buffer_pos
< afx
->buffer_len
)
522 tempbuf
[tempbuf_len
++] = afx
->buffer
[afx
->buffer_pos
++];
523 if( tempbuf_len
==PARTIAL_CHUNK
)
527 /* read the next line */
528 maxlen
= MAX_LINELEN
;
530 afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
531 &afx
->buffer_size
, &maxlen
);
532 if( !afx
->buffer_len
) {
533 rc
= -1; /* eof (should not happen) */
542 /* Armor header or dash-escaped line? */
545 /* 2440bis-10: When reversing dash-escaping, an
546 implementation MUST strip the string "- " if it occurs
547 at the beginning of a line, and SHOULD warn on "-" and
548 any character other than a space at the beginning of a
551 if(p
[1]==' ' && !afx
->not_dash_escaped
)
553 /* It's a dash-escaped line, so skip over the
557 else if(p
[1]=='-' && p
[2]=='-' && p
[3]=='-' && p
[4]=='-')
559 /* Five dashes in a row mean it's probably armor
561 int type
= is_armor_header( p
, n
);
562 if( afx
->not_dash_escaped
&& type
!= BEGIN_SIGNATURE
)
566 if( type
!= BEGIN_SIGNATURE
)
568 log_info(_("unexpected armor: "));
569 print_string( stderr
, p
, n
, 0 );
577 else if(!afx
->not_dash_escaped
)
579 /* Bad dash-escaping. */
580 log_info(_("invalid dash escaped line: "));
581 print_string( stderr
, p
, n
, 0 );
586 /* Now handle the end-of-line canonicalization */
587 if( !afx
->not_dash_escaped
)
589 int crlf
= n
> 1 && p
[n
-2] == '\r' && p
[n
-1]=='\n';
591 /* PGP2 does not treat a tab as white space character */
593 trim_trailing_chars( &p
[afx
->buffer_pos
], n
-afx
->buffer_pos
,
594 afx
->pgp2mode
? " \r\n" : " \t\r\n");
595 afx
->buffer_len
+=afx
->buffer_pos
;
596 /* the buffer is always allocated with enough space to append
597 * the removed [CR], LF and a Nul
598 * The reason for this complicated procedure is to keep at least
599 * the original type of lineending - handling of the removed
600 * trailing spaces seems to be impossible in our method
601 * of faking a packet; either we have to use a temporary file
602 * or calculate the hash here in this module and somehow find
603 * a way to send the hash down the processing line (well, a special
604 * faked packet could do the job).
607 afx
->buffer
[afx
->buffer_len
++] = '\r';
608 afx
->buffer
[afx
->buffer_len
++] = '\n';
609 afx
->buffer
[afx
->buffer_len
] = '\0';
613 if( lastline
) { /* write last (ending) length header */
615 buf
[len
++]=tempbuf_len
;
618 buf
[len
++]=((tempbuf_len
-192)/256) + 192;
619 buf
[len
++]=(tempbuf_len
-192) % 256;
621 memcpy(&buf
[len
],tempbuf
,tempbuf_len
);
626 afx
->in_cleartext
= 0;
627 /* and now read the header lines */
632 /* read the next line (skip all truncated lines) */
634 maxlen
= MAX_LINELEN
;
635 afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
636 &afx
->buffer_size
, &maxlen
);
644 i
= parse_header_line( afx
, p
, n
);
651 afx
->inp_checked
= 1;
665 if ( opt
.ignore_crc_error
)
667 log_inc_errorcount();
668 return G10ERR_INVALID_ARMOR
;
673 radix64_read( armor_filter_context_t
*afx
, IOBUF a
, size_t *retn
,
674 byte
*buf
, size_t size
)
677 int c
=0, c2
; /*init c because gcc is not clever enough for the continue*/
681 int idx
, i
, onlypad
=0;
686 val
= afx
->radbuf
[0];
687 for( n
=0; n
< size
; ) {
689 if( afx
->buffer_pos
< afx
->buffer_len
)
690 c
= afx
->buffer
[afx
->buffer_pos
++];
691 else { /* read the next line */
692 unsigned maxlen
= MAX_LINELEN
;
694 afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
695 &afx
->buffer_size
, &maxlen
);
698 if( !afx
->buffer_len
)
704 if( c
== '\n' || c
== ' ' || c
== '\r' || c
== '\t' )
706 else if( c
== '=' ) { /* pad character: stop */
707 /* some mailers leave quoted-printable encoded characters
708 * so we try to workaround this */
709 if( afx
->buffer_pos
+2 < afx
->buffer_len
) {
711 cc1
= afx
->buffer
[afx
->buffer_pos
];
712 cc2
= afx
->buffer
[afx
->buffer_pos
+1];
713 cc3
= afx
->buffer
[afx
->buffer_pos
+2];
714 if( isxdigit(cc1
) && isxdigit(cc2
)
715 && strchr( "=\n\r\t ", cc3
)) {
716 /* well it seems to be the case - adjust */
717 c
= isdigit(cc1
)? (cc1
- '0'): (ascii_toupper(cc1
)-'A'+10);
719 c
|= isdigit(cc2
)? (cc2
- '0'): (ascii_toupper(cc2
)-'A'+10);
720 afx
->buffer_pos
+= 2;
721 afx
->qp_detected
= 1;
733 else if( (c
= asctobin
[(c2
=c
)]) == 255 ) {
734 log_error(_("invalid radix64 character %02X skipped\n"), c2
);
738 case 0: val
= c
<< 2; break;
739 case 1: val
|= (c
>>4)&3; buf
[n
++]=val
;val
=(c
<<4)&0xf0;break;
740 case 2: val
|= (c
>>2)&15; buf
[n
++]=val
;val
=(c
<<6)&0xc0;break;
741 case 3: val
|= c
&0x3f; buf
[n
++] = val
; break;
746 for(i
=0; i
< n
; i
++ )
747 crc
= (crc
<< 8) ^ crc_table
[((crc
>> 16)&0xff) ^ buf
[i
]];
751 afx
->radbuf
[0] = val
;
757 for(;;) { /* skip lf and pad characters */
758 if( afx
->buffer_pos
< afx
->buffer_len
)
759 c
= afx
->buffer
[afx
->buffer_pos
++];
760 else { /* read the next line */
761 unsigned maxlen
= MAX_LINELEN
;
763 afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
764 &afx
->buffer_size
, &maxlen
);
767 if( !afx
->buffer_len
)
771 if( c
== '\n' || c
== ' ' || c
== '\r'
772 || c
== '\t' || c
== '=' )
777 log_error(_("premature eof (no CRC)\n"));
782 if( (c
= asctobin
[c
]) == 255 )
785 case 0: val
= c
<< 2; break;
786 case 1: val
|= (c
>>4)&3; mycrc
|= val
<< 16;val
=(c
<<4)&0xf0;break;
787 case 2: val
|= (c
>>2)&15; mycrc
|= val
<< 8;val
=(c
<<6)&0xc0;break;
788 case 3: val
|= c
&0x3f; mycrc
|= val
; break;
791 if( afx
->buffer_pos
< afx
->buffer_len
)
792 c
= afx
->buffer
[afx
->buffer_pos
++];
793 else { /* read the next line */
794 unsigned maxlen
= MAX_LINELEN
;
796 afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
801 if( !afx
->buffer_len
)
807 if( !afx
->buffer_len
)
809 } while( ++idx
< 4 );
811 log_info(_("premature eof (in CRC)\n"));
814 else if( idx
== 0 ) {
815 /* No CRC at all is legal ("MAY") */
818 else if( idx
!= 4 ) {
819 log_info(_("malformed CRC\n"));
822 else if( mycrc
!= afx
->crc
) {
823 log_info (_("CRC error; %06lX - %06lX\n"),
824 (ulong
)afx
->crc
, (ulong
)mycrc
);
829 /* FIXME: Here we should emit another control packet,
830 * so that we know in mainproc that we are processing
831 * a clearsign message */
834 rc
= 0 /*check_trailer( &fhdr, c )*/;
836 if( (c
=iobuf_get(a
)) == -1 )
843 log_error(_("premature eof (in trailer)\n"));
844 rc
= G10ERR_INVALID_ARMOR
;
847 log_error(_("error in trailer line\n"));
848 rc
= G10ERR_INVALID_ARMOR
;
863 * This filter is used to handle the armor stuff
866 armor_filter( void *opaque
, int control
,
867 IOBUF a
, byte
*buf
, size_t *ret_len
)
869 size_t size
= *ret_len
;
870 armor_filter_context_t
*afx
= opaque
;
880 fp
= fopen("armor.out", "w");
886 log_debug("armor-filter: control: %d\n", control
);
887 if( control
== IOBUFCTRL_UNDERFLOW
&& afx
->inp_bypass
) {
889 if( afx
->buffer_len
) {
890 for(; n
< size
&& afx
->buffer_pos
< afx
->buffer_len
; n
++ )
891 buf
[n
++] = afx
->buffer
[afx
->buffer_pos
++];
892 if( afx
->buffer_pos
>= afx
->buffer_len
)
895 for(; n
< size
; n
++ ) {
896 if( (c
=iobuf_get(a
)) == -1 )
904 else if( control
== IOBUFCTRL_UNDERFLOW
) {
905 /* We need some space for the faked packet. The minmum
906 * required size is the PARTIAL_CHUNK size plus a byte for the
908 if( size
< PARTIAL_CHUNK
+1 )
909 BUG(); /* supplied buffer too short */
912 rc
= fake_packet( afx
, a
, &n
, buf
, size
);
913 else if( !afx
->inp_checked
) {
914 rc
= check_input( afx
, a
);
915 if( afx
->inp_bypass
) {
916 for(n
=0; n
< size
&& afx
->buffer_pos
< afx
->buffer_len
; )
917 buf
[n
++] = afx
->buffer
[afx
->buffer_pos
++];
918 if( afx
->buffer_pos
>= afx
->buffer_len
)
923 else if( afx
->faked
) {
924 unsigned int hashes
= afx
->hashes
;
928 sesmark
= get_session_marker( &sesmarklen
);
929 if ( sesmarklen
> 20 )
932 /* the buffer is at least 15+n*15 bytes long, so it
933 * is easy to construct the packets */
935 hashes
&= 1|2|4|8|16|32|64;
937 hashes
|= 4; /* default to MD 5 */
938 /* This is non-ideal since PGP 5-8 have the same
939 end-of-line bugs as PGP 2. However, we only
940 enable pgp2mode if there is no Hash: header. */
941 if( opt
.pgp2_workarounds
)
945 /* First a gpg control packet... */
946 buf
[n
++] = 0xff; /* new format, type 63, 1 length byte */
948 memcpy(buf
+n
, sesmark
, sesmarklen
); n
+= sesmarklen
;
949 buf
[n
++] = CTRLPKT_CLEARSIGN_START
;
950 buf
[n
++] = afx
->not_dash_escaped
? 0:1; /* sigclass */
952 buf
[n
++] = DIGEST_ALGO_RMD160
;
954 buf
[n
++] = DIGEST_ALGO_SHA1
;
956 buf
[n
++] = DIGEST_ALGO_MD5
;
958 buf
[n
++] = DIGEST_ALGO_SHA224
;
960 buf
[n
++] = DIGEST_ALGO_SHA256
;
962 buf
[n
++] = DIGEST_ALGO_SHA384
;
964 buf
[n
++] = DIGEST_ALGO_SHA512
;
967 /* ...followed by an invented plaintext packet.
968 Amusingly enough, this packet is not compliant with
969 2440 as the initial partial length is less than 512
970 bytes. Of course, we'll accept it anyway ;) */
972 buf
[n
++] = 0xCB; /* new packet format, type 11 */
973 buf
[n
++] = 0xE1; /* 2^1 == 2 bytes */
974 buf
[n
++] = 't'; /* canonical text mode */
975 buf
[n
++] = 0; /* namelength */
976 buf
[n
++] = 0xE2; /* 2^2 == 4 more bytes */
977 memset(buf
+n
, 0, 4); /* timestamp */
981 rc
= radix64_read( afx
, a
, &n
, buf
, size
);
984 rc
= radix64_read( afx
, a
, &n
, buf
, size
);
987 if( fwrite(buf
, n
, 1, fp
) != 1 )
992 else if( control
== IOBUFCTRL_FLUSH
&& !afx
->cancel
) {
993 if( !afx
->status
) { /* write the header line */
995 STRLIST comment
=opt
.comments
;
997 if( afx
->what
>= DIM(head_strings
) )
998 log_bug("afx->what=%d", afx
->what
);
999 iobuf_writestr(a
, "-----");
1000 iobuf_writestr(a
, head_strings
[afx
->what
] );
1001 iobuf_writestr(a
, "-----" );
1002 iobuf_writestr(a
,afx
->eol
);
1003 if( !opt
.no_version
)
1005 iobuf_writestr(a
, "Version: GnuPG v" VERSION
" ("
1006 PRINTABLE_OS_NAME
")" );
1007 iobuf_writestr(a
,afx
->eol
);
1010 /* write the comment strings */
1011 for(s
=comment
->d
;comment
;comment
=comment
->next
,s
=comment
->d
)
1013 iobuf_writestr(a
, "Comment: " );
1017 iobuf_writestr(a
, "\\n" );
1018 else if( *s
== '\r' )
1019 iobuf_writestr(a
, "\\r" );
1020 else if( *s
== '\v' )
1021 iobuf_writestr(a
, "\\v" );
1026 iobuf_writestr(a
,afx
->eol
);
1029 if ( afx
->hdrlines
) {
1030 for ( s
= afx
->hdrlines
; *s
; s
++ ) {
1031 #ifdef HAVE_DOSISH_SYSTEM
1033 iobuf_put( a
, '\r');
1039 iobuf_writestr(a
,afx
->eol
);
1049 for(i
=0; i
< idx
; i
++ )
1050 radbuf
[i
] = afx
->radbuf
[i
];
1052 for(i
=0; i
< size
; i
++ )
1053 crc
= (crc
<< 8) ^ crc_table
[((crc
>> 16)&0xff) ^ buf
[i
]];
1056 for( ; size
; buf
++, size
-- ) {
1057 radbuf
[idx
++] = *buf
;
1060 c
= bintoasc
[(*radbuf
>> 2) & 077];
1062 c
= bintoasc
[(((*radbuf
<<4)&060)|((radbuf
[1] >> 4)&017))&077];
1064 c
= bintoasc
[(((radbuf
[1]<<2)&074)|((radbuf
[2]>>6)&03))&077];
1066 c
= bintoasc
[radbuf
[2]&077];
1068 if( ++idx2
>= (64/4) )
1069 { /* pgp doesn't like 72 here */
1070 iobuf_writestr(a
,afx
->eol
);
1075 for(i
=0; i
< idx
; i
++ )
1076 afx
->radbuf
[i
] = radbuf
[i
];
1081 else if( control
== IOBUFCTRL_INIT
)
1083 if( !is_initialized
)
1086 /* Figure out what we're using for line endings if the caller
1090 #ifdef HAVE_DOSISH_SYSTEM
1098 else if( control
== IOBUFCTRL_CANCEL
) {
1101 else if( control
== IOBUFCTRL_FREE
) {
1104 else if( afx
->status
) { /* pad, write cecksum, and bottom line */
1108 for(i
=0; i
< idx
; i
++ )
1109 radbuf
[i
] = afx
->radbuf
[i
];
1111 c
= bintoasc
[(*radbuf
>>2)&077];
1114 c
= bintoasc
[((*radbuf
<< 4) & 060) & 077];
1120 c
= bintoasc
[(((*radbuf
<<4)&060)|((radbuf
[1]>>4)&017))&077];
1122 c
= bintoasc
[((radbuf
[1] << 2) & 074) & 077];
1126 if( ++idx2
>= (64/4) )
1127 { /* pgp doesn't like 72 here */
1128 iobuf_writestr(a
,afx
->eol
);
1132 /* may need a linefeed */
1134 iobuf_writestr(a
,afx
->eol
);
1137 radbuf
[0] = crc
>>16;
1138 radbuf
[1] = crc
>> 8;
1140 c
= bintoasc
[(*radbuf
>> 2) & 077];
1142 c
= bintoasc
[(((*radbuf
<<4)&060)|((radbuf
[1] >> 4)&017))&077];
1144 c
= bintoasc
[(((radbuf
[1]<<2)&074)|((radbuf
[2]>>6)&03))&077];
1146 c
= bintoasc
[radbuf
[2]&077];
1148 iobuf_writestr(a
,afx
->eol
);
1149 /* and the the trailer */
1150 if( afx
->what
>= DIM(tail_strings
) )
1151 log_bug("afx->what=%d", afx
->what
);
1152 iobuf_writestr(a
, "-----");
1153 iobuf_writestr(a
, tail_strings
[afx
->what
] );
1154 iobuf_writestr(a
, "-----" );
1155 iobuf_writestr(a
,afx
->eol
);
1157 else if( !afx
->any_data
&& !afx
->inp_bypass
) {
1158 log_error(_("no valid OpenPGP data found.\n"));
1159 afx
->no_openpgp_data
= 1;
1160 write_status_text( STATUS_NODATA
, "1" );
1162 if( afx
->truncated
)
1163 log_info(_("invalid armor: line longer than %d characters\n"),
1165 /* issue an error to enforce dissemination of correct software */
1166 if( afx
->qp_detected
)
1167 log_error(_("quoted printable character in armor - "
1168 "probably a buggy MTA has been used\n") );
1169 xfree( afx
->buffer
);
1172 else if( control
== IOBUFCTRL_DESC
)
1173 *(char**)buf
= "armor_filter";
1179 * create a radix64 encoded string.
1182 make_radix64_string( const byte
*data
, size_t len
)
1186 buffer
= p
= xmalloc( (len
+2)/3*4 + 1 );
1187 for( ; len
>= 3 ; len
-= 3, data
+= 3 ) {
1188 *p
++ = bintoasc
[(data
[0] >> 2) & 077];
1189 *p
++ = bintoasc
[(((data
[0] <<4)&060)|((data
[1] >> 4)&017))&077];
1190 *p
++ = bintoasc
[(((data
[1]<<2)&074)|((data
[2]>>6)&03))&077];
1191 *p
++ = bintoasc
[data
[2]&077];
1194 *p
++ = bintoasc
[(data
[0] >> 2) & 077];
1195 *p
++ = bintoasc
[(((data
[0] <<4)&060)|((data
[1] >> 4)&017))&077];
1196 *p
++ = bintoasc
[((data
[1]<<2)&074)];
1198 else if( len
== 1 ) {
1199 *p
++ = bintoasc
[(data
[0] >> 2) & 077];
1200 *p
++ = bintoasc
[(data
[0] <<4)&060];
1207 /***********************************************
1208 * For the pipemode command we can't use the armor filter for various
1209 * reasons, so we use this new unarmor_pump stuff to remove the armor
1212 enum unarmor_state_e
{
1219 STA_found_header_wait_newline
,
1220 STA_skip_header_lines
,
1221 STA_skip_header_lines_non_ws
,
1228 struct unarmor_pump_s
{
1229 enum unarmor_state_e state
;
1232 int pos
; /* counts from 0..3 */
1234 u32 mycrc
; /* the one store in the data */
1240 unarmor_pump_new (void)
1244 if( !is_initialized
)
1246 x
= xmalloc_clear (sizeof *x
);
1251 unarmor_pump_release (UnarmorPump x
)
1257 * Get the next character from the ascii armor taken from the IOBUF
1258 * created earlier by unarmor_pump_new().
1259 * Return: c = Character
1260 * 256 = ignore this value
1261 * -1 = End of current armor
1262 * -2 = Premature EOF (not used)
1263 * -3 = Invalid armor
1266 unarmor_pump (UnarmorPump x
, int c
)
1268 int rval
= 256; /* default is to ignore the return value */
1275 if ( is_armored (tmp
) )
1276 x
->state
= c
== '-'? STA_first_dash
: STA_wait_newline
;
1278 x
->state
= STA_bypass
;
1284 return c
; /* return here to avoid crc calculation */
1285 case STA_wait_newline
:
1287 x
->state
= STA_wait_dash
;
1290 x
->state
= c
== '-'? STA_first_dash
: STA_wait_newline
;
1292 case STA_first_dash
: /* just need for initalization */
1294 x
->state
= STA_compare_header
;
1295 case STA_compare_header
:
1296 if ( "-----BEGIN PGP SIGNATURE-----"[++x
->pos
] == c
) {
1298 x
->state
= STA_found_header_wait_newline
;
1301 x
->state
= c
== '\n'? STA_wait_dash
: STA_wait_newline
;
1303 case STA_found_header_wait_newline
:
1304 /* to make CR,LF issues easier we simply allow for white space
1305 behind the 5 dashes */
1307 x
->state
= STA_skip_header_lines
;
1308 else if ( c
!= '\r' && c
!= ' ' && c
!= '\t' )
1309 x
->state
= STA_wait_dash
; /* garbage after the header line */
1311 case STA_skip_header_lines
:
1312 /* i.e. wait for one empty line */
1314 x
->state
= STA_read_data
;
1319 else if ( c
!= '\r' && c
!= ' ' && c
!= '\t' )
1320 x
->state
= STA_skip_header_lines_non_ws
;
1322 case STA_skip_header_lines_non_ws
:
1323 /* like above but we already encountered non white space */
1325 x
->state
= STA_skip_header_lines
;
1328 /* fixme: we don't check for the trailing dash lines but rely
1329 * on the armor stop characters */
1330 if( c
== '\n' || c
== ' ' || c
== '\r' || c
== '\t' )
1331 break; /* skip all kind of white space */
1333 if( c
== '=' ) { /* pad character: stop */
1334 if( x
->pos
== 1 ) /* in this case val has some value */
1336 x
->state
= STA_wait_crc
;
1342 if( (c
= asctobin
[(c2
=c
)]) == 255 ) {
1343 log_error(_("invalid radix64 character %02X skipped\n"), c2
);
1355 x
->val
= (c
<<4)&0xf0;
1358 x
->val
|= (c
>>2)&15;
1360 x
->val
= (c
<<6)&0xc0;
1367 x
->pos
= (x
->pos
+1) % 4;
1370 if( c
== '\n' || c
== ' ' || c
== '\r' || c
== '\t' || c
== '=' )
1371 break; /* skip ws and pad characters */
1372 /* assume that we are at the next line */
1373 x
->state
= STA_read_crc
;
1377 if( (c
= asctobin
[c
]) == 255 ) {
1378 rval
= -1; /* ready */
1379 if( x
->crc
!= x
->mycrc
) {
1380 log_info (_("CRC error; %06lX - %06lX\n"),
1381 (ulong
)x
->crc
, (ulong
)x
->mycrc
);
1382 if ( invalid_crc() )
1385 x
->state
= STA_ready
; /* not sure whether this is correct */
1395 x
->mycrc
|= x
->val
<< 16;
1396 x
->val
= (c
<<4)&0xf0;
1399 x
->val
|= (c
>>2)&15;
1400 x
->mycrc
|= x
->val
<< 8;
1401 x
->val
= (c
<<6)&0xc0;
1408 x
->pos
= (x
->pos
+1) % 4;
1415 if ( !(rval
& ~255) ) { /* compute the CRC */
1416 x
->crc
= (x
->crc
<< 8) ^ crc_table
[((x
->crc
>> 16)&0xff) ^ rval
];
1417 x
->crc
&= 0x00ffffff;