LCOV - code coverage report
Current view: top level - g10 - armor.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 497 744 66.8 %
Date: 2015-11-05 17:10:59 Functions: 15 20 75.0 %

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

Generated by: LCOV version 1.11