diff options
| author | Marcus Brinkmann <[email protected]> | 2008-11-03 17:24:09 +0000 | 
|---|---|---|
| committer | Marcus Brinkmann <[email protected]> | 2008-11-03 17:24:09 +0000 | 
| commit | 66d0fa1973e5e1a1bff619de8b595673d1b76cc5 (patch) | |
| tree | 4b1f8e470fa455cbe3d9b5c4ab6fb4fa77f20ba3 /src/sig-notation.c | |
| parent | assuan/ (diff) | |
| download | gpgme-66d0fa1973e5e1a1bff619de8b595673d1b76cc5.tar.gz gpgme-66d0fa1973e5e1a1bff619de8b595673d1b76cc5.zip | |
008-11-03  Marcus Brinkmann  <[email protected]>
        * configure.ac: Replace gpgme paths with src.
        * gpgme: Move to ...
        * src: ... this new directory.
assuan/
2008-11-03  Marcus Brinkmann  <[email protected]>
	* Makefile.am (INCLUDES): Replace gpgme path with src.
tests/
2008-11-03  Marcus Brinkmann  <[email protected]>
        * gpgsm/Makefile.am (INCLUDES, LDADD): Replace gpgme path with src.
        * gpg/Makefile.am (INCLUDES, LDADD, t_thread1_LDADD): Likewise.
	* Makefile.am (LDADD): Likewise.
Diffstat (limited to 'src/sig-notation.c')
| -rw-r--r-- | src/sig-notation.c | 260 | 
1 files changed, 260 insertions, 0 deletions
| diff --git a/src/sig-notation.c b/src/sig-notation.c new file mode 100644 index 00000000..5800c378 --- /dev/null +++ b/src/sig-notation.c @@ -0,0 +1,260 @@ +/* sig-notation.c - Signature notation data support. +   Copyright (C) 2005 g10 Code GmbH + +   This file is part of GPGME. +  +   GPGME is free software; you can redistribute it and/or modify it +   under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of +   the License, or (at your option) any later version. +    +   GPGME is distributed in the hope that it will be useful, but +   WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. +    +   You should have received a copy of the GNU Lesser General Public +   License along with this program; if not, write to the Free Software +   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +   02111-1307, USA.  */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include "gpgme.h" +#include "util.h" +#include "context.h" +#include "ops.h" + + +/* Free the signature notation object and all associated resources. +   The object must already be removed from any linked list as the next +   pointer is ignored.  */ +void +_gpgme_sig_notation_free (gpgme_sig_notation_t notation) +{ +  if (notation->name) +    free (notation->name); + +  if (notation->value) +    free (notation->value); + +  free (notation); +} + + +/* Set the flags of NOTATION to FLAGS.  */ +static void +sig_notation_set_flags (gpgme_sig_notation_t notation, +			gpgme_sig_notation_flags_t flags) +{ +  /* We copy the flags into individual bits to make them easier +     accessible individually for the user.  */ +  notation->human_readable = flags & GPGME_SIG_NOTATION_HUMAN_READABLE ? 1 : 0; +  notation->critical = flags & GPGME_SIG_NOTATION_CRITICAL ? 1 : 0;  + +  notation->flags = flags; +} + + +/* Create a new, empty signature notation data object.  */ +gpgme_error_t +_gpgme_sig_notation_create (gpgme_sig_notation_t *notationp, +			    const char *name, int name_len, +			    const char *value, int value_len, +			    gpgme_sig_notation_flags_t flags) +{ +  gpgme_error_t err = 0; +  gpgme_sig_notation_t notation; + +  /* Currently, we require all notations to be human-readable.  */ +  if (name && !(flags & GPGME_SIG_NOTATION_HUMAN_READABLE)) +    return gpg_error (GPG_ERR_INV_VALUE); + +  notation = calloc (1, sizeof (*notation)); +  if (!notation) +    return gpg_error_from_errno (errno); + +  /* This is critical.  We want to reliably identify policy URLs by +     using a NULL pointer for NAME.  So all notations must have a NAME +     string, even if it is empty.  */ +  if (name) +    { +      /* We add a trailing '\0' for stringification in the good +	 case.  */ +      notation->name = malloc (name_len + 1); +      if (!notation->name) +	{ +	  err = gpg_error_from_errno (errno); +	  goto err; +	} + +      memcpy (notation->name, name, name_len); +      notation->name[name_len] = '\0'; +      notation->name_len = name_len; +    } + +  if (value) +    { +      /* We add a trailing '\0' for stringification in the good +	 case.  */ +      notation->value = malloc (value_len + 1); +      if (!notation->value) +	{ +	  err = gpg_error_from_errno (errno); +	  goto err; +	} + +      memcpy (notation->value, value, value_len); +      notation->value[value_len] = '\0'; +      notation->value_len = value_len; +    } + +  sig_notation_set_flags (notation, flags); + +  *notationp = notation; +  return 0; + + err: +  _gpgme_sig_notation_free (notation); +  return err; +} + + +/* GnuPG subpacket flags.  */ + +/* This subpacket data is part of the hashed data.  */ +#define GNUPG_SPK_HASHED	0x01 + +/* This subpacket is marked critical.  */ +#define GNUPG_SPK_CRITICAL	0x02 + +/* Parse a notation or policy URL subpacket.  If the packet type is +   not known, return no error but NULL in NOTATION.  */ +gpgme_error_t +_gpgme_parse_notation (gpgme_sig_notation_t *notationp, +		       int type, int pkflags, int len, char *data) +{ +  gpgme_error_t err; +  char *name = NULL; +  int name_len = 0; +  char *value = NULL; +  int value_len = 0; +  gpgme_sig_notation_flags_t flags = 0; +  char *decoded_data; +  unsigned char *bdata; + +  /* Type 20: Notation data.  */ +  /* Type 26: Policy URL.  */ +  if (type != 20 && type != 26) +    { +      *notationp = NULL; +      return 0; +    } + +  /* A few simple sanity checks.  */ +  if (len > strlen (data)) +    return gpg_error (GPG_ERR_INV_ENGINE); + +  /* See below for the format of a notation subpacket.  It has at +     least four octets of flags and two times two octets of length +     information.  */ +  if (type == 20 && len < 4 + 2 + 2) +    return gpg_error (GPG_ERR_INV_ENGINE); + +  err = _gpgme_decode_percent_string (data, &decoded_data, 0, 1); +  if (err) +    return err; +  bdata = (unsigned char *) decoded_data; + +  /* Flags common to notation data and policy URL.  */ +  if (pkflags & GNUPG_SPK_CRITICAL) +    flags |= GPGME_SIG_NOTATION_CRITICAL; + +  /* This information is relevant in parsing multi-octet numbers below: + +     3.1. Scalar numbers + +     Scalar numbers are unsigned, and are always stored in big-endian +     format.  Using n[k] to refer to the kth octet being interpreted, +     the value of a two-octet scalar is ((n[0] << 8) + n[1]).  The +     value of a four-octet scalar is ((n[0] << 24) + (n[1] << 16) + +     (n[2] << 8) + n[3]). + +     From RFC2440: OpenPGP Message Format.  Copyright (C) The Internet +     Society (1998).  All Rights Reserved.  */ +#define RFC2440_GET_WORD(chr) ((((int)((unsigned char *)(chr))[0]) << 8) \ +			       + ((int)((unsigned char *)(chr))[1])) + +  if (type == 20) +    { +      /* 5.2.3.15. Notation Data + +	 (4 octets of flags, 2 octets of name length (M), +	 2 octets of value length (N), M octets of name data, +	 N octets of value data) + +	 [...] The "flags" field holds four octets of flags. +	 All undefined flags MUST be zero. Defined flags are: + +	 First octet: 0x80 = human-readable. [...] +	 Other octets:  none. + +	 From RFC2440: OpenPGP Message Format.  Copyright (C) The +	 Internet Society (1998).  All Rights Reserved.  */ + +      int chr; + +      /* First octet of flags.  */ +#define RFC2440_SPK20_FLAG1_HUMAN_READABLE 0x80 + +      chr = *bdata; +      bdata++; + +      if (chr & RFC2440_SPK20_FLAG1_HUMAN_READABLE) +	flags |= GPGME_SIG_NOTATION_HUMAN_READABLE; + +      /* The second, third and four octet of flags are unused.  */ +      bdata++; +      bdata++; +      bdata++; + +      name_len = RFC2440_GET_WORD (bdata); +      bdata += 2; + +      value_len = RFC2440_GET_WORD (bdata); +      bdata += 2; + +      /* Small sanity check.  */ +      if (4 + 2 + 2 + name_len + value_len > len) +	{ +	  free (decoded_data); +	  return gpg_error (GPG_ERR_INV_ENGINE); +	} + +      name = (char *) bdata; +      bdata += name_len; + +      value = (char *) bdata; +    } +  else +    { +      /* Type is 26.  */ + +      /* NAME is NULL, name_len is 0.  */ + +      value = (char *) bdata; +      value_len = strlen (value); +    } + +  err = _gpgme_sig_notation_create (notationp, name, name_len, +				    value, value_len, flags); + +  free (decoded_data); +  return err; +} | 
