1 /* armor.c - Armor flter
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
3 * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
42 #ifdef HAVE_DOSISH_SYSTEM
48 #define MAX_LINELEN 20000
50 #define CRCINIT 0xB704CE
51 #define CRCPOLY 0X864CFB
52 #define CRCUPDATE(a,c) do { \
53 a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \
56 static u32 crc_table
[256];
57 static byte bintoasc
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
58 "abcdefghijklmnopqrstuvwxyz"
60 static byte asctobin
[256]; /* runtime initialized */
61 static int is_initialized
;
81 fhdrCHECKDashEscaped2
,
82 fhdrCHECKDashEscaped3
,
88 fhdrCLEARSIGSimpleNext
,
97 /* if we encounter this armor string with this index, go
98 * into a mode which fakes packets and wait for the next armor */
99 #define BEGIN_SIGNATURE 2
100 #define BEGIN_SIGNED_MSG_IDX 3
101 static char *head_strings
[] = {
103 "BEGIN PGP PUBLIC KEY BLOCK",
104 "BEGIN PGP SIGNATURE",
105 "BEGIN PGP SIGNED MESSAGE",
106 "BEGIN PGP ARMORED FILE", /* gnupg extension */
107 "BEGIN PGP PRIVATE KEY BLOCK",
108 "BEGIN PGP SECRET KEY BLOCK", /* only used by pgp2 */
111 static char *tail_strings
[] = {
113 "END PGP PUBLIC KEY BLOCK",
116 "END PGP ARMORED FILE",
117 "END PGP PRIVATE KEY BLOCK",
118 "END PGP SECRET KEY BLOCK",
131 /* init the crc lookup table */
133 for(i
=j
=0; j
< 128; j
++ ) {
135 if( t
& 0x00800000 ) {
137 crc_table
[i
++] = t
^ CRCPOLY
;
143 crc_table
[i
++] = t
^ CRCPOLY
;
146 /* build the helptable for radix64 to bin conversion */
147 for(i
=0; i
< 256; i
++ )
148 asctobin
[i
] = 255; /* used to detect invalid characters */
149 for(s
=bintoasc
,i
=0; *s
; s
++,i
++ )
156 * Check whether this is an armored file or not See also
157 * parse-packet.c for details on this code For unknown historic
158 * reasons we use a string here but only the first byte will be used.
159 * Returns: True if it seems to be armored
162 is_armored( const byte
*buf
)
168 return 1; /* invalid packet: assume it is armored */
169 pkttype
= ctb
& 0x40 ? (ctb
& 0x3f) : ((ctb
>>2)&0xf);
173 case PKT_ONEPASS_SIG
:
179 case PKT_OLD_COMMENT
:
183 return 0; /* seems to be a regular packet: not armored */
191 * Try to check whether the iobuf is armored
192 * Returns true if this may be the case; the caller should use the
193 * filter to do further processing.
196 use_armor_filter( iobuf_t a
)
201 /* fixme: there might be a problem with iobuf_peek */
202 n
= iobuf_peek(a
, buf
, 1 );
204 return 0; /* EOF, doesn't matter whether armored or not */
206 return 1; /* can't check it: try armored */
207 return is_armored(buf
);
216 write_status(STATUS_BADARMOR
);
217 g10_exit(1); /* stop here */
222 * check whether the armor header is valid on a signed message.
223 * this is for security reasons: the header lines are not included in the
224 * hash and by using some creative formatting rules, Mallory could fake
225 * any text at the beginning of a document; assuming it is read with
226 * a simple viewer. We only allow the Hash Header.
229 parse_hash_header( const char *line
)
234 if( strlen(line
) < 6 || strlen(line
) > 60 )
235 return 0; /* too short or too long */
236 if( memcmp( line
, "Hash:", 5 ) )
237 return 0; /* invalid header */
239 for(s
=line
+5;;s
=s2
) {
240 for(; *s
&& (*s
==' ' || *s
== '\t'); s
++ )
244 for(s2
=s
+1; *s2
&& *s2
!=' ' && *s2
!= '\t' && *s2
!= ','; s2
++ )
246 if( !strncmp( s
, "RIPEMD160", s2
-s
) )
248 else if( !strncmp( s
, "SHA1", s2
-s
) )
250 else if( !strncmp( s
, "MD5", s2
-s
) )
252 else if( !strncmp( s
, "SHA256", s2
-s
) )
254 else if( !strncmp( s
, "SHA384", s2
-s
) )
256 else if( !strncmp( s
, "SHA512", s2
-s
) )
260 for(; *s2
&& (*s2
==' ' || *s2
== '\t'); s2
++ )
262 if( *s2
&& *s2
!= ',' )
273 * Check whether this is a armor line.
274 * returns: -1 if it is not a armor header or the index number of the
278 is_armor_header( byte
*line
, unsigned len
)
286 return -1; /* too short */
287 if( memcmp( line
, "-----", 5 ) )
289 p
= strstr( line
+5, "-----");
295 /* Some mail programs on Windows seem to add spaces to the end of
296 the line. This becomes strict if --openpgp is set. */
307 return -1; /* garbage after dashes */
308 save_c
= *save_p
; *save_p
= 0;
310 for(i
=0; (s
=head_strings
[i
]); i
++ )
315 return -1; /* unknown armor line */
317 if( opt
.verbose
> 1 )
318 log_info(_("armor: %s\n"), head_strings
[i
]);
325 * Parse a header lines
326 * Return 0: Empty line (end of header lines)
327 * -1: invalid header line
328 * >0: Good header line
331 parse_header_line( armor_filter_context_t
*afx
, byte
*line
, unsigned int len
)
337 len2
= length_sans_trailing_ws( line
, len
);
339 afx
->buffer_pos
= len2
; /* (it is not the fine way to do it here) */
340 return 0; /* WS only: same as empty line */
345 p
= strchr( line
, ':');
347 log_error(_("invalid armor header: "));
348 print_string( stderr
, line
, len
, 0 );
354 log_info(_("armor header: "));
355 print_string( stderr
, line
, len
, 0 );
359 if( afx
->in_cleartext
) {
360 if( (hashes
=parse_hash_header( line
)) )
361 afx
->hashes
|= hashes
;
362 else if( strlen(line
) > 15 && !memcmp( line
, "NotDashEscaped:", 15 ) )
363 afx
->not_dash_escaped
= 1;
365 log_error(_("invalid clearsig header\n"));
374 /* figure out whether the data is armored or not */
376 check_input( armor_filter_context_t
*afx
, iobuf_t a
)
385 /* read the first line to see whether this is armored data */
386 maxlen
= MAX_LINELEN
;
387 len
= afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
388 &afx
->buffer_size
, &maxlen
);
391 /* line has been truncated: assume not armored */
392 afx
->inp_checked
= 1;
401 /* (the line is always a C string but maybe longer) */
402 if( *line
== '\n' || ( len
&& (*line
== '\r' && line
[1]=='\n') ) )
404 else if( !is_armored( line
) ) {
405 afx
->inp_checked
= 1;
410 /* find the armor header */
412 i
= is_armor_header( line
, len
);
413 if( i
>= 0 && !(afx
->only_keyblocks
&& i
!= 1 && i
!= 5 && i
!= 6 )) {
415 if( hdr_line
== BEGIN_SIGNED_MSG_IDX
) {
416 if( afx
->in_cleartext
) {
417 log_error(_("nested clear text signatures\n"));
418 rc
= GPG_ERR_INV_ARMOR
;
420 afx
->in_cleartext
= 1;
424 /* read the next line (skip all truncated lines) */
426 maxlen
= MAX_LINELEN
;
427 afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
428 &afx
->buffer_size
, &maxlen
);
430 len
= afx
->buffer_len
;
434 /* parse the header lines */
436 /* read the next line (skip all truncated lines) */
438 maxlen
= MAX_LINELEN
;
439 afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
440 &afx
->buffer_size
, &maxlen
);
442 len
= afx
->buffer_len
;
445 i
= parse_header_line( afx
, line
, len
);
448 rc
= GPG_ERR_INV_ARMOR
;
456 else if( afx
->in_cleartext
)
459 afx
->inp_checked
= 1;
471 * Fake a literal data packet and wait for the next armor line
472 * fixme: empty line handling and null length clear text signature are
473 * not implemented/checked.
476 fake_packet( armor_filter_context_t
*afx
, iobuf_t a
,
477 size_t *retn
, byte
*buf
, size_t size
)
485 len
= 2; /* reserve 2 bytes for the length header */
486 size
-= 2; /* and 2 for the terminating header */
487 while( !rc
&& len
< size
) {
488 /* copy what we have in the line buffer */
489 if( afx
->faked
== 1 )
490 afx
->faked
++; /* skip the first (empty) line */
492 while( len
< size
&& afx
->buffer_pos
< afx
->buffer_len
)
493 buf
[len
++] = afx
->buffer
[afx
->buffer_pos
++];
498 /* read the next line */
499 maxlen
= MAX_LINELEN
;
501 afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
502 &afx
->buffer_size
, &maxlen
);
503 if( !afx
->buffer_len
) {
504 rc
= -1; /* eof (should not happen) */
509 if( !afx
->not_dash_escaped
) {
513 crlf
= n
> 1 && p
[n
-2] == '\r' && p
[n
-1]=='\n';
515 /* PGP2 does not treat a tab as white space character */
516 afx
->buffer_len
= trim_trailing_chars( p
, n
,
517 afx
->pgp2mode
? " \r\n" : " \t\r\n");
518 /* the buffer is always allocated with enough space to append
519 * the removed [CR], LF and a Nul
520 * The reason for this complicated procedure is to keep at least
521 * the original type of lineending - handling of the removed
522 * trailing spaces seems to be impossible in our method
523 * of faking a packet; either we have to use a temporary file
524 * or calculate the hash here in this module and somehow find
525 * a way to send the hash down the processing line (well, a special
526 * faked packet could do the job).
529 afx
->buffer
[afx
->buffer_len
++] = '\r';
530 afx
->buffer
[afx
->buffer_len
++] = '\n';
531 afx
->buffer
[afx
->buffer_len
] = 0;
536 if( n
> 2 && *p
== '-' ) {
537 /* check for dash escaped or armor header */
538 if( p
[1] == ' ' && !afx
->not_dash_escaped
) {
539 /* issue a warning if it is not regular encoded */
540 if( p
[2] != '-' && !( n
> 6 && !memcmp(p
+2, "From ", 5))) {
541 log_info(_("invalid dash escaped line: "));
542 print_string( stderr
, p
, n
, 0 );
545 afx
->buffer_pos
= 2; /* skip */
547 else if( n
>= 15 && p
[1] == '-' && p
[2] == '-' && p
[3] == '-' ) {
548 int type
= is_armor_header( p
, n
);
549 if( afx
->not_dash_escaped
&& type
!= BEGIN_SIGNATURE
)
552 if( type
!= BEGIN_SIGNATURE
) {
553 log_info(_("unexpected armor:"));
554 print_string( stderr
, p
, n
, 0 );
564 buf
[0] = (len
-2) >> 8;
566 if( lastline
) { /* write last (ending) length header */
567 if( buf
[0] || buf
[1] ) { /* only if we have some text */
573 afx
->in_cleartext
= 0;
574 /* and now read the header lines */
579 /* read the next line (skip all truncated lines) */
581 maxlen
= MAX_LINELEN
;
582 afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
583 &afx
->buffer_size
, &maxlen
);
591 i
= parse_header_line( afx
, p
, n
);
598 afx
->inp_checked
= 1;
612 if ( opt
.ignore_crc_error
)
614 log_inc_errorcount();
615 return GPG_ERR_INV_ARMOR
;
620 radix64_read( armor_filter_context_t
*afx
, iobuf_t a
, size_t *retn
,
621 byte
*buf
, size_t size
)
624 int c
=0, c2
; /*init c because gcc is not clever enough for the continue*/
633 val
= afx
->radbuf
[0];
634 for( n
=0; n
< size
; ) {
636 if( afx
->buffer_pos
< afx
->buffer_len
)
637 c
= afx
->buffer
[afx
->buffer_pos
++];
638 else { /* read the next line */
639 unsigned maxlen
= MAX_LINELEN
;
641 afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
642 &afx
->buffer_size
, &maxlen
);
645 if( !afx
->buffer_len
)
651 if( c
== '\n' || c
== ' ' || c
== '\r' || c
== '\t' )
653 else if( c
== '=' ) { /* pad character: stop */
654 /* some mailers leave quoted-printable encoded characters
655 * so we try to workaround this */
656 if( afx
->buffer_pos
+2 < afx
->buffer_len
) {
658 cc1
= afx
->buffer
[afx
->buffer_pos
];
659 cc2
= afx
->buffer
[afx
->buffer_pos
+1];
660 cc3
= afx
->buffer
[afx
->buffer_pos
+2];
661 if( isxdigit(cc1
) && isxdigit(cc2
)
662 && strchr( "=\n\r\t ", cc3
)) {
663 /* well it seems to be the case - adjust */
664 c
= isdigit(cc1
)? (cc1
- '0'): (ascii_toupper(cc1
)-'A'+10);
666 c
|= isdigit(cc2
)? (cc2
- '0'): (ascii_toupper(cc2
)-'A'+10);
667 afx
->buffer_pos
+= 2;
668 afx
->qp_detected
= 1;
678 else if( (c
= asctobin
[(c2
=c
)]) == 255 ) {
679 log_error(_("invalid radix64 character %02x skipped\n"), c2
);
683 case 0: val
= c
<< 2; break;
684 case 1: val
|= (c
>>4)&3; buf
[n
++]=val
;val
=(c
<<4)&0xf0;break;
685 case 2: val
|= (c
>>2)&15; buf
[n
++]=val
;val
=(c
<<6)&0xc0;break;
686 case 3: val
|= c
&0x3f; buf
[n
++] = val
; break;
691 for(i
=0; i
< n
; i
++ )
692 crc
= (crc
<< 8) ^ crc_table
[((crc
>> 16)&0xff) ^ buf
[i
]];
696 afx
->radbuf
[0] = val
;
702 for(;;) { /* skip lf and pad characters */
703 if( afx
->buffer_pos
< afx
->buffer_len
)
704 c
= afx
->buffer
[afx
->buffer_pos
++];
705 else { /* read the next line */
706 unsigned maxlen
= MAX_LINELEN
;
708 afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
709 &afx
->buffer_size
, &maxlen
);
712 if( !afx
->buffer_len
)
716 if( c
== '\n' || c
== ' ' || c
== '\r'
717 || c
== '\t' || c
== '=' )
722 log_error(_("premature eof (no CRC)\n"));
727 if( (c
= asctobin
[c
]) == 255 )
730 case 0: val
= c
<< 2; break;
731 case 1: val
|= (c
>>4)&3; mycrc
|= val
<< 16;val
=(c
<<4)&0xf0;break;
732 case 2: val
|= (c
>>2)&15; mycrc
|= val
<< 8;val
=(c
<<6)&0xc0;break;
733 case 3: val
|= c
&0x3f; mycrc
|= val
; break;
736 if( afx
->buffer_pos
< afx
->buffer_len
)
737 c
= afx
->buffer
[afx
->buffer_pos
++];
738 else { /* read the next line */
739 unsigned maxlen
= MAX_LINELEN
;
741 afx
->buffer_len
= iobuf_read_line( a
, &afx
->buffer
,
746 if( !afx
->buffer_len
)
752 if( !afx
->buffer_len
)
754 } while( ++idx
< 4 );
756 log_info(_("premature eof (in CRC)\n"));
759 else if( idx
!= 4 ) {
760 log_info(_("malformed CRC\n"));
763 else if( mycrc
!= afx
->crc
) {
764 log_info (_("CRC error; %06lx - %06lx\n"),
765 (ulong
)afx
->crc
, (ulong
)mycrc
);
770 /* FIXME: Here we should emit another control packet,
771 * so that we know in mainproc that we are processing
772 * a clearsign message */
775 rc
= 0 /*check_trailer( &fhdr, c )*/;
777 if( (c
=iobuf_get(a
)) == -1 )
784 log_error(_("premature eof (in Trailer)\n"));
785 rc
= GPG_ERR_INV_ARMOR
;
788 log_error(_("error in trailer line\n"));
789 rc
= GPG_ERR_INV_ARMOR
;
804 * This filter is used to handle the armor stuff
807 armor_filter( void *opaque
, int control
,
808 iobuf_t a
, byte
*buf
, size_t *ret_len
)
810 size_t size
= *ret_len
;
811 armor_filter_context_t
*afx
= opaque
;
821 fp
= fopen("armor.out", "w");
827 log_debug("armor-filter: control: %d\n", control
);
828 if( control
== IOBUFCTRL_UNDERFLOW
&& afx
->inp_bypass
) {
830 if( afx
->buffer_len
) {
831 for(; n
< size
&& afx
->buffer_pos
< afx
->buffer_len
; n
++ )
832 buf
[n
++] = afx
->buffer
[afx
->buffer_pos
++];
833 if( afx
->buffer_pos
>= afx
->buffer_len
)
836 for(; n
< size
; n
++ ) {
837 if( (c
=iobuf_get(a
)) == -1 )
845 else if( control
== IOBUFCTRL_UNDERFLOW
) {
846 /* We need some space for the faked packet. The minmum required
847 * size is ~18 + length of the session marker */
849 BUG(); /* supplied buffer too short */
852 rc
= fake_packet( afx
, a
, &n
, buf
, size
);
853 else if( !afx
->inp_checked
) {
854 rc
= check_input( afx
, a
);
855 if( afx
->inp_bypass
) {
856 for(n
=0; n
< size
&& afx
->buffer_pos
< afx
->buffer_len
; )
857 buf
[n
++] = afx
->buffer
[afx
->buffer_pos
++];
858 if( afx
->buffer_pos
>= afx
->buffer_len
)
863 else if( afx
->faked
) {
864 unsigned int hashes
= afx
->hashes
;
868 sesmark
= get_session_marker( &sesmarklen
);
869 if ( sesmarklen
> 20 )
872 /* the buffer is at least 15+n*15 bytes long, so it
873 * is easy to construct the packets */
875 hashes
&= 1|2|4|8|16|32|64;
877 hashes
|= 4; /* default to MD 5 */
878 /* This is non-ideal since PGP 5-8 have the same
879 end-of-line bugs as PGP 2. However, we only
880 enable pgp2mode if there is no Hash: header. */
881 if( opt
.pgp2_workarounds
)
885 /* first a gpg control packet */
886 buf
[n
++] = 0xff; /* new format, type 63, 1 length byte */
888 memcpy(buf
+n
, sesmark
, sesmarklen
); n
+= sesmarklen
;
889 buf
[n
++] = CTRLPKT_CLEARSIGN_START
;
890 buf
[n
++] = afx
->not_dash_escaped
? 0:1; /* sigclass */
892 buf
[n
++] = DIGEST_ALGO_RMD160
;
894 buf
[n
++] = DIGEST_ALGO_SHA1
;
896 buf
[n
++] = DIGEST_ALGO_MD5
;
898 buf
[n
++] = DIGEST_ALGO_SHA256
;
900 buf
[n
++] = DIGEST_ALGO_SHA384
;
902 buf
[n
++] = DIGEST_ALGO_SHA512
;
905 /* followed by a plaintext packet */
906 buf
[n
++] = 0xaf; /* old packet format, type 11, var length */
907 buf
[n
++] = 0; /* set the length header */
909 buf
[n
++] = 't'; /* canonical text mode */
910 buf
[n
++] = 0; /* namelength */
911 memset(buf
+n
, 0, 4); /* timestamp */
915 rc
= radix64_read( afx
, a
, &n
, buf
, size
);
918 rc
= radix64_read( afx
, a
, &n
, buf
, size
);
921 if( fwrite(buf
, n
, 1, fp
) != 1 )
926 else if( control
== IOBUFCTRL_FLUSH
&& !afx
->cancel
) {
927 if( !afx
->status
) { /* write the header line */
929 STRLIST comment
= opt
.comments
;
931 if( afx
->what
>= DIM(head_strings
) )
932 log_bug("afx->what=%d", afx
->what
);
933 iobuf_writestr(a
, "-----");
934 iobuf_writestr(a
, head_strings
[afx
->what
] );
935 iobuf_writestr(a
, "-----" LF
);
936 if( !opt
.no_version
)
937 iobuf_writestr(a
, "Version: GnuPG v" VERSION
" ("
938 PRINTABLE_OS_NAME
")" LF
);
940 /* Write the comment string. */
941 for(s
=comment
? comment
->d
:NULL
; comment
;
942 comment
=comment
->next
,s
=comment
->d
)
944 iobuf_writestr(a
, "Comment: " );
948 iobuf_writestr(a
, "\\n" );
949 else if( *s
== '\r' )
950 iobuf_writestr(a
, "\\r" );
951 else if( *s
== '\v' )
952 iobuf_writestr(a
, "\\v" );
956 iobuf_writestr(a
, LF
);
959 if ( afx
->hdrlines
) {
960 for ( s
= afx
->hdrlines
; *s
; s
++ ) {
961 #ifdef HAVE_DOSISH_SYSTEM
968 iobuf_writestr(a
, LF
);
978 for(i
=0; i
< idx
; i
++ )
979 radbuf
[i
] = afx
->radbuf
[i
];
981 for(i
=0; i
< size
; i
++ )
982 crc
= (crc
<< 8) ^ crc_table
[((crc
>> 16)&0xff) ^ buf
[i
]];
985 for( ; size
; buf
++, size
-- ) {
986 radbuf
[idx
++] = *buf
;
989 c
= bintoasc
[(*radbuf
>> 2) & 077];
991 c
= bintoasc
[(((*radbuf
<<4)&060)|((radbuf
[1] >> 4)&017))&077];
993 c
= bintoasc
[(((radbuf
[1]<<2)&074)|((radbuf
[2]>>6)&03))&077];
995 c
= bintoasc
[radbuf
[2]&077];
997 if( ++idx2
>= (64/4) ) { /* pgp doesn't like 72 here */
998 iobuf_writestr(a
, LF
);
1003 for(i
=0; i
< idx
; i
++ )
1004 afx
->radbuf
[i
] = radbuf
[i
];
1009 else if( control
== IOBUFCTRL_INIT
) {
1010 if( !is_initialized
)
1013 else if( control
== IOBUFCTRL_CANCEL
) {
1016 else if( control
== IOBUFCTRL_FREE
) {
1019 else if( afx
->status
) { /* pad, write cecksum, and bottom line */
1023 for(i
=0; i
< idx
; i
++ )
1024 radbuf
[i
] = afx
->radbuf
[i
];
1026 c
= bintoasc
[(*radbuf
>>2)&077];
1029 c
= bintoasc
[((*radbuf
<< 4) & 060) & 077];
1035 c
= bintoasc
[(((*radbuf
<<4)&060)|((radbuf
[1]>>4)&017))&077];
1037 c
= bintoasc
[((radbuf
[1] << 2) & 074) & 077];
1041 if( ++idx2
>= (64/4) ) { /* pgp doesn't like 72 here */
1042 iobuf_writestr(a
, LF
);
1046 /* may need a linefeed */
1048 iobuf_writestr(a
, LF
);
1051 radbuf
[0] = crc
>>16;
1052 radbuf
[1] = crc
>> 8;
1054 c
= bintoasc
[(*radbuf
>> 2) & 077];
1056 c
= bintoasc
[(((*radbuf
<<4)&060)|((radbuf
[1] >> 4)&017))&077];
1058 c
= bintoasc
[(((radbuf
[1]<<2)&074)|((radbuf
[2]>>6)&03))&077];
1060 c
= bintoasc
[radbuf
[2]&077];
1062 iobuf_writestr(a
, LF
);
1063 /* and the the trailer */
1064 if( afx
->what
>= DIM(tail_strings
) )
1065 log_bug("afx->what=%d", afx
->what
);
1066 iobuf_writestr(a
, "-----");
1067 iobuf_writestr(a
, tail_strings
[afx
->what
] );
1068 iobuf_writestr(a
, "-----" LF
);
1070 else if( !afx
->any_data
&& !afx
->inp_bypass
) {
1071 log_error(_("no valid OpenPGP data found.\n"));
1072 afx
->no_openpgp_data
= 1;
1073 write_status_text( STATUS_NODATA
, "1" );
1075 if( afx
->truncated
)
1076 log_info(_("invalid armor: line longer than %d characters\n"),
1078 /* issue an error to enforce dissemination of correct software */
1079 if( afx
->qp_detected
)
1080 log_error(_("quoted printable character in armor - "
1081 "probably a buggy MTA has been used\n") );
1082 xfree ( afx
->buffer
);
1085 else if( control
== IOBUFCTRL_DESC
)
1086 *(char**)buf
= "armor_filter";
1092 * create a radix64 encoded string.
1095 make_radix64_string( const byte
*data
, size_t len
)
1099 buffer
= p
= xmalloc ( (len
+2)/3*4 + 1 );
1100 for( ; len
>= 3 ; len
-= 3, data
+= 3 ) {
1101 *p
++ = bintoasc
[(data
[0] >> 2) & 077];
1102 *p
++ = bintoasc
[(((data
[0] <<4)&060)|((data
[1] >> 4)&017))&077];
1103 *p
++ = bintoasc
[(((data
[1]<<2)&074)|((data
[2]>>6)&03))&077];
1104 *p
++ = bintoasc
[data
[2]&077];
1107 *p
++ = bintoasc
[(data
[0] >> 2) & 077];
1108 *p
++ = bintoasc
[(((data
[0] <<4)&060)|((data
[1] >> 4)&017))&077];
1109 *p
++ = bintoasc
[((data
[1]<<2)&074)];
1111 else if( len
== 1 ) {
1112 *p
++ = bintoasc
[(data
[0] >> 2) & 077];
1113 *p
++ = bintoasc
[(data
[0] <<4)&060];
1120 /***********************************************
1121 * For the pipemode command we can't use the armor filter for various
1122 * reasons, so we use this new unarmor_pump stuff to remove the armor
1125 enum unarmor_state_e
{
1132 STA_found_header_wait_newline
,
1133 STA_skip_header_lines
,
1134 STA_skip_header_lines_non_ws
,
1141 struct unarmor_pump_s
{
1142 enum unarmor_state_e state
;
1145 int pos
; /* counts from 0..3 */
1147 u32 mycrc
; /* the one store in the data */
1153 unarmor_pump_new (void)
1157 if( !is_initialized
)
1159 x
= xcalloc (1,sizeof *x
);
1164 unarmor_pump_release (UnarmorPump x
)
1170 * Get the next character from the ascii armor taken from the IOBUF
1171 * created earlier by unarmor_pump_new().
1172 * Return: c = Character
1173 * 256 = ignore this value
1174 * -1 = End of current armor
1175 * -2 = Premature EOF (not used)
1176 * -3 = Invalid armor
1179 unarmor_pump (UnarmorPump x
, int c
)
1181 int rval
= 256; /* default is to ignore the return value */
1188 if ( is_armored (tmp
) )
1189 x
->state
= c
== '-'? STA_first_dash
: STA_wait_newline
;
1191 x
->state
= STA_bypass
;
1197 return c
; /* return here to avoid crc calculation */
1198 case STA_wait_newline
:
1200 x
->state
= STA_wait_dash
;
1203 x
->state
= c
== '-'? STA_first_dash
: STA_wait_newline
;
1205 case STA_first_dash
: /* just need for initalization */
1207 x
->state
= STA_compare_header
;
1208 case STA_compare_header
:
1209 if ( "-----BEGIN PGP SIGNATURE-----"[++x
->pos
] == c
) {
1211 x
->state
= STA_found_header_wait_newline
;
1214 x
->state
= c
== '\n'? STA_wait_dash
: STA_wait_newline
;
1216 case STA_found_header_wait_newline
:
1217 /* to make CR,LF issues easier we simply allow for white space
1218 behind the 5 dashes */
1220 x
->state
= STA_skip_header_lines
;
1221 else if ( c
!= '\r' && c
!= ' ' && c
!= '\t' )
1222 x
->state
= STA_wait_dash
; /* garbage after the header line */
1224 case STA_skip_header_lines
:
1225 /* i.e. wait for one empty line */
1227 x
->state
= STA_read_data
;
1232 else if ( c
!= '\r' && c
!= ' ' && c
!= '\t' )
1233 x
->state
= STA_skip_header_lines_non_ws
;
1235 case STA_skip_header_lines_non_ws
:
1236 /* like above but we already encountered non white space */
1238 x
->state
= STA_skip_header_lines
;
1241 /* fixme: we don't check for the trailing dash lines but rely
1242 * on the armor stop characters */
1243 if( c
== '\n' || c
== ' ' || c
== '\r' || c
== '\t' )
1244 break; /* skip all kind of white space */
1246 if( c
== '=' ) { /* pad character: stop */
1247 if( x
->pos
== 1 ) /* in this case val has some value */
1249 x
->state
= STA_wait_crc
;
1255 if( (c
= asctobin
[(c2
=c
)]) == 255 ) {
1256 log_error(_("invalid radix64 character %02x skipped\n"), c2
);
1268 x
->val
= (c
<<4)&0xf0;
1271 x
->val
|= (c
>>2)&15;
1273 x
->val
= (c
<<6)&0xc0;
1280 x
->pos
= (x
->pos
+1) % 4;
1283 if( c
== '\n' || c
== ' ' || c
== '\r' || c
== '\t' || c
== '=' )
1284 break; /* skip ws and pad characters */
1285 /* assume that we are at the next line */
1286 x
->state
= STA_read_crc
;
1290 if( (c
= asctobin
[c
]) == 255 ) {
1291 rval
= -1; /* ready */
1292 if( x
->crc
!= x
->mycrc
) {
1293 log_info (_("CRC error; %06lx - %06lx\n"),
1294 (ulong
)x
->crc
, (ulong
)x
->mycrc
);
1295 if ( invalid_crc() )
1298 x
->state
= STA_ready
; /* not sure whether this is correct */
1308 x
->mycrc
|= x
->val
<< 16;
1309 x
->val
= (c
<<4)&0xf0;
1312 x
->val
|= (c
>>2)&15;
1313 x
->mycrc
|= x
->val
<< 8;
1314 x
->val
= (c
<<6)&0xc0;
1321 x
->pos
= (x
->pos
+1) % 4;
1328 if ( !(rval
& ~255) ) { /* compute the CRC */
1329 x
->crc
= (x
->crc
<< 8) ^ crc_table
[((x
->crc
>> 16)&0xff) ^ rval
];
1330 x
->crc
&= 0x00ffffff;