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

Generated by: LCOV version 1.11