LCOV - code coverage report
Current view: top level - src - sig-notation.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 32 82 39.0 %
Date: 2016-11-29 15:07:43 Functions: 3 4 75.0 %

          Line data    Source code
       1             : /* sig-notation.c - Signature notation data support.
       2             :    Copyright (C) 2005 g10 Code GmbH
       3             : 
       4             :    This file is part of GPGME.
       5             : 
       6             :    GPGME is free software; you can redistribute it and/or modify it
       7             :    under the terms of the GNU Lesser General Public License as
       8             :    published by the Free Software Foundation; either version 2.1 of
       9             :    the License, or (at your option) any later version.
      10             : 
      11             :    GPGME is distributed in the hope that it will be useful, but
      12             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :    Lesser General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU Lesser General Public
      17             :    License along with this program; if not, write to the Free Software
      18             :    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      19             :    02111-1307, USA.  */
      20             : 
      21             : #if HAVE_CONFIG_H
      22             : #include <config.h>
      23             : #endif
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : #include <errno.h>
      27             : #include <assert.h>
      28             : 
      29             : #include "gpgme.h"
      30             : #include "util.h"
      31             : #include "context.h"
      32             : #include "ops.h"
      33             : #include "debug.h"
      34             : 
      35             : 
      36             : /* Free the signature notation object and all associated resources.
      37             :    The object must already be removed from any linked list as the next
      38             :    pointer is ignored.  */
      39             : void
      40         324 : _gpgme_sig_notation_free (gpgme_sig_notation_t notation)
      41             : {
      42         324 :   if (notation->name)
      43         216 :     free (notation->name);
      44             : 
      45         324 :   if (notation->value)
      46         324 :     free (notation->value);
      47             : 
      48         324 :   free (notation);
      49         324 : }
      50             : 
      51             : 
      52             : /* Set the flags of NOTATION to FLAGS.  */
      53             : static void
      54         324 : sig_notation_set_flags (gpgme_sig_notation_t notation,
      55             :                         gpgme_sig_notation_flags_t flags)
      56             : {
      57             :   /* We copy the flags into individual bits to make them easier
      58             :      accessible individually for the user.  */
      59         324 :   notation->human_readable = flags & GPGME_SIG_NOTATION_HUMAN_READABLE ? 1 : 0;
      60         324 :   notation->critical = flags & GPGME_SIG_NOTATION_CRITICAL ? 1 : 0;
      61             : 
      62         324 :   notation->flags = flags;
      63         324 : }
      64             : 
      65             : 
      66             : /* Create a new, empty signature notation data object.  */
      67             : gpgme_error_t
      68         324 : _gpgme_sig_notation_create (gpgme_sig_notation_t *notationp,
      69             :                             const char *name, int name_len,
      70             :                             const char *value, int value_len,
      71             :                             gpgme_sig_notation_flags_t flags)
      72             : {
      73         324 :   gpgme_error_t err = 0;
      74             :   gpgme_sig_notation_t notation;
      75             : 
      76             :   /* Currently, we require all notations to be human-readable.  */
      77         324 :   if (name && !(flags & GPGME_SIG_NOTATION_HUMAN_READABLE))
      78           0 :     return gpg_error (GPG_ERR_INV_VALUE);
      79             : 
      80         324 :   notation = calloc (1, sizeof (*notation));
      81         324 :   if (!notation)
      82           0 :     return gpg_error_from_syserror ();
      83             : 
      84             :   /* This is critical.  We want to reliably identify policy URLs by
      85             :      using a NULL pointer for NAME.  So all notations must have a NAME
      86             :      string, even if it is empty.  */
      87         324 :   if (name)
      88             :     {
      89             :       /* We add a trailing '\0' for stringification in the good
      90             :          case.  */
      91           6 :       notation->name = malloc (name_len + 1);
      92           6 :       if (!notation->name)
      93             :         {
      94           0 :           err = gpg_error_from_syserror ();
      95           0 :           goto err;
      96             :         }
      97             : 
      98           6 :       memcpy (notation->name, name, name_len);
      99           6 :       notation->name[name_len] = '\0';
     100           6 :       notation->name_len = name_len;
     101             :     }
     102             : 
     103         324 :   if (value)
     104             :     {
     105             :       /* We add a trailing '\0' for stringification in the good
     106             :          case.  */
     107           9 :       notation->value = malloc (value_len + 1);
     108           9 :       if (!notation->value)
     109             :         {
     110           0 :           err = gpg_error_from_syserror ();
     111           0 :           goto err;
     112             :         }
     113             : 
     114           9 :       memcpy (notation->value, value, value_len);
     115           9 :       notation->value[value_len] = '\0';
     116           9 :       notation->value_len = value_len;
     117             :     }
     118             : 
     119         324 :   sig_notation_set_flags (notation, flags);
     120             : 
     121         324 :   *notationp = notation;
     122         324 :   return 0;
     123             : 
     124             :  err:
     125           0 :   _gpgme_sig_notation_free (notation);
     126           0 :   return err;
     127             : }
     128             : 
     129             : 
     130             : /* GnuPG subpacket flags.  */
     131             : 
     132             : /* This subpacket data is part of the hashed data.  */
     133             : #define GNUPG_SPK_HASHED        0x01
     134             : 
     135             : /* This subpacket is marked critical.  */
     136             : #define GNUPG_SPK_CRITICAL      0x02
     137             : 
     138             : /* Parse a notation or policy URL subpacket.  If the packet type is
     139             :    not known, return no error but NULL in NOTATION.  */
     140             : gpgme_error_t
     141           0 : _gpgme_parse_notation (gpgme_sig_notation_t *notationp,
     142             :                        int type, int pkflags, int len, char *data)
     143             : {
     144             :   gpgme_error_t err;
     145           0 :   char *name = NULL;
     146           0 :   int name_len = 0;
     147           0 :   char *value = NULL;
     148           0 :   int value_len = 0;
     149           0 :   gpgme_sig_notation_flags_t flags = 0;
     150             :   char *decoded_data;
     151             :   unsigned char *bdata;
     152             : 
     153             :   /* Type 20: Notation data.  */
     154             :   /* Type 26: Policy URL.  */
     155           0 :   if (type != 20 && type != 26)
     156             :     {
     157           0 :       *notationp = NULL;
     158           0 :       return 0;
     159             :     }
     160             : 
     161             :   /* A few simple sanity checks.  */
     162           0 :   if (len > strlen (data))
     163           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     164             : 
     165             :   /* See below for the format of a notation subpacket.  It has at
     166             :      least four octets of flags and two times two octets of length
     167             :      information.  */
     168           0 :   if (type == 20 && len < 4 + 2 + 2)
     169           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     170             : 
     171           0 :   err = _gpgme_decode_percent_string (data, &decoded_data, 0, 1);
     172           0 :   if (err)
     173           0 :     return err;
     174           0 :   bdata = (unsigned char *) decoded_data;
     175             : 
     176             :   /* Flags common to notation data and policy URL.  */
     177           0 :   if (pkflags & GNUPG_SPK_CRITICAL)
     178           0 :     flags |= GPGME_SIG_NOTATION_CRITICAL;
     179             : 
     180             :   /* This information is relevant in parsing multi-octet numbers below:
     181             : 
     182             :      3.1. Scalar numbers
     183             : 
     184             :      Scalar numbers are unsigned, and are always stored in big-endian
     185             :      format.  Using n[k] to refer to the kth octet being interpreted,
     186             :      the value of a two-octet scalar is ((n[0] << 8) + n[1]).  The
     187             :      value of a four-octet scalar is ((n[0] << 24) + (n[1] << 16) +
     188             :      (n[2] << 8) + n[3]).
     189             : 
     190             :      From RFC2440: OpenPGP Message Format.  Copyright (C) The Internet
     191             :      Society (1998).  All Rights Reserved.  */
     192             : #define RFC2440_GET_WORD(chr) ((((int)((unsigned char *)(chr))[0]) << 8) \
     193             :                                + ((int)((unsigned char *)(chr))[1]))
     194             : 
     195           0 :   if (type == 20)
     196             :     {
     197             :       /* 5.2.3.15. Notation Data
     198             : 
     199             :          (4 octets of flags, 2 octets of name length (M),
     200             :          2 octets of value length (N), M octets of name data,
     201             :          N octets of value data)
     202             : 
     203             :          [...] The "flags" field holds four octets of flags.
     204             :          All undefined flags MUST be zero. Defined flags are:
     205             : 
     206             :          First octet: 0x80 = human-readable. [...]
     207             :          Other octets:  none.
     208             : 
     209             :          From RFC2440: OpenPGP Message Format.  Copyright (C) The
     210             :          Internet Society (1998).  All Rights Reserved.  */
     211             : 
     212             :       int chr;
     213             : 
     214             :       /* First octet of flags.  */
     215             : #define RFC2440_SPK20_FLAG1_HUMAN_READABLE 0x80
     216             : 
     217           0 :       chr = *bdata;
     218           0 :       bdata++;
     219             : 
     220           0 :       if (chr & RFC2440_SPK20_FLAG1_HUMAN_READABLE)
     221           0 :         flags |= GPGME_SIG_NOTATION_HUMAN_READABLE;
     222             : 
     223             :       /* The second, third and four octet of flags are unused.  */
     224           0 :       bdata++;
     225           0 :       bdata++;
     226           0 :       bdata++;
     227             : 
     228           0 :       name_len = RFC2440_GET_WORD (bdata);
     229           0 :       bdata += 2;
     230             : 
     231           0 :       value_len = RFC2440_GET_WORD (bdata);
     232           0 :       bdata += 2;
     233             : 
     234             :       /* Small sanity check.  */
     235           0 :       if (4 + 2 + 2 + name_len + value_len > len)
     236             :         {
     237           0 :           free (decoded_data);
     238           0 :           return trace_gpg_error (GPG_ERR_INV_ENGINE);
     239             :         }
     240             : 
     241           0 :       name = (char *) bdata;
     242           0 :       bdata += name_len;
     243             : 
     244           0 :       value = (char *) bdata;
     245             :     }
     246             :   else
     247             :     {
     248             :       /* Type is 26.  */
     249             : 
     250             :       /* NAME is NULL, name_len is 0.  */
     251             : 
     252           0 :       value = (char *) bdata;
     253           0 :       value_len = strlen (value);
     254             :     }
     255             : 
     256           0 :   err = _gpgme_sig_notation_create (notationp, name, name_len,
     257             :                                     value, value_len, flags);
     258             : 
     259           0 :   free (decoded_data);
     260           0 :   return err;
     261             : }

Generated by: LCOV version 1.11