Exemple #1
0
/* Add the human-readable notation data with name NAME and value VALUE
   to the context CTX, using the flags FLAGS.  If NAME is NULL, then
   VALUE should be a policy URL.  The flag
   GPGME_SIG_NOTATION_HUMAN_READABLE is forced to be true for notation
   data, and false for policy URLs.  */
gpgme_error_t
gpgme_sig_notation_add (gpgme_ctx_t ctx, const char *name,
			const char *value, gpgme_sig_notation_flags_t flags)
{
  gpgme_error_t err;
  gpgme_sig_notation_t notation;
  gpgme_sig_notation_t *lastp;

  TRACE_BEG3 (DEBUG_CTX, "gpgme_sig_notation_add", ctx,
	      "name=%s, value=%s, flags=0x%x",
	      name ? name : "(null)", value ? value : "(null)",
	      flags);

  if (!ctx)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  if (name)
    flags |= GPGME_SIG_NOTATION_HUMAN_READABLE;
  else
    flags &= ~GPGME_SIG_NOTATION_HUMAN_READABLE;

  err = _gpgme_sig_notation_create (&notation, name, name ? strlen (name) : 0,
				    value, value ? strlen (value) : 0, flags);
  if (err)
    return TRACE_ERR (err);

  lastp = &ctx->sig_notations;
  while (*lastp)
    lastp = &(*lastp)->next;

  *lastp = notation;
  return TRACE_ERR (0);
}
Exemple #2
0
/* 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;
}
Exemple #3
0
static gpgme_error_t
parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
{
  gpgme_error_t err;
  gpgme_sig_notation_t *lastp = &sig->notations;
  gpgme_sig_notation_t notation = sig->notations;
  char *p;

  if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL)
    {
      p = strchr (args, ' ');
      if (p)
        *p = '\0';

      /* FIXME: We could keep a pointer to the last notation in the list.  */
      while (notation && notation->value)
	{
	  lastp = &notation->next;
	  notation = notation->next;
	}

      if (notation)
	/* There is another notation name without data for the
	   previous one.  The crypto backend misbehaves.  */
	return trace_gpg_error (GPG_ERR_INV_ENGINE);

      err = _gpgme_sig_notation_create (&notation, NULL, 0, NULL, 0, 0);
      if (err)
	return err;

      if (code == GPGME_STATUS_NOTATION_NAME)
	{
	  err = _gpgme_decode_percent_string (args, &notation->name, 0, 0);
	  if (err)
	    {
	      _gpgme_sig_notation_free (notation);
	      return err;
	    }

	  notation->name_len = strlen (notation->name);

	  /* Set default flags for use with older gpg versions which
           * do not emit a NOTATIONS_FLAG line.  */
	  notation->flags = GPGME_SIG_NOTATION_HUMAN_READABLE;
	  notation->human_readable = 1;
	}
      else
	{
	  /* This is a policy URL.  */

	  err = _gpgme_decode_percent_string (args, &notation->value, 0, 0);
	  if (err)
	    {
	      _gpgme_sig_notation_free (notation);
	      return err;
	    }

	  notation->value_len = strlen (notation->value);
	}
      *lastp = notation;
    }
  else if (code == GPGME_STATUS_NOTATION_FLAGS)
    {
      char *field[2];

      while (notation && notation->next)
	{
	  lastp = &notation->next;
	  notation = notation->next;
	}

      if (!notation || !notation->name)
        { /* There are notation flags without a previous notation name.
           * The crypto backend misbehaves.  */
          return trace_gpg_error (GPG_ERR_INV_ENGINE);
        }
      if (_gpgme_split_fields (args, field, DIM (field)) < 2)
        { /* Required args missing.  */
          return trace_gpg_error (GPG_ERR_INV_ENGINE);
        }
      notation->flags = 0;
      if (atoi (field[0]))
        {
          notation->flags |= GPGME_SIG_NOTATION_CRITICAL;
          notation->critical = 1;
        }
      if (atoi (field[1]))
        {
          notation->flags |= GPGME_SIG_NOTATION_HUMAN_READABLE;
          notation->human_readable = 1;
        }
    }
  else if (code == GPGME_STATUS_NOTATION_DATA)
    {
      int len = strlen (args) + 1;
      char *dest;

      /* FIXME: We could keep a pointer to the last notation in the list.  */
      while (notation && notation->next)
	{
	  lastp = &notation->next;
	  notation = notation->next;
	}

      if (!notation || !notation->name)
	/* There is notation data without a previous notation
	   name.  The crypto backend misbehaves.  */
	return trace_gpg_error (GPG_ERR_INV_ENGINE);

      if (!notation->value)
	{
	  dest = notation->value = malloc (len);
	  if (!dest)
	    return gpg_error_from_syserror ();
	}
      else
	{
	  int cur_len = strlen (notation->value);
	  dest = realloc (notation->value, len + strlen (notation->value));
	  if (!dest)
	    return gpg_error_from_syserror ();
	  notation->value = dest;
	  dest += cur_len;
	}

      err = _gpgme_decode_percent_string (args, &dest, len, 0);
      if (err)
	return err;

      notation->value_len += strlen (dest);
    }
  else
    return trace_gpg_error (GPG_ERR_INV_ENGINE);
  return 0;
}
Exemple #4
0
static gpgme_error_t
parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
{
  gpgme_error_t err;
  gpgme_sig_notation_t *lastp = &sig->notations;
  gpgme_sig_notation_t notation = sig->notations;
  char *end = strchr (args, ' ');

  if (end)
    *end = '\0';

  if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL)
    {
      /* FIXME: We could keep a pointer to the last notation in the list.  */
      while (notation && notation->value)
	{
	  lastp = &notation->next;
	  notation = notation->next;
	}

      if (notation)
	/* There is another notation name without data for the
	   previous one.  The crypto backend misbehaves.  */
	return gpg_error (GPG_ERR_INV_ENGINE);

      err = _gpgme_sig_notation_create (&notation, NULL, 0, NULL, 0, 0);
      if (err)
	return err;

      if (code == GPGME_STATUS_NOTATION_NAME)
	{
	  err = _gpgme_decode_percent_string (args, &notation->name, 0, 0);
	  if (err)
	    {
	      _gpgme_sig_notation_free (notation);
	      return err;
	    }

	  notation->name_len = strlen (notation->name);

	  /* FIXME: For now we fake the human-readable flag.  The
	     critical flag can not be reported as it is not
	     provided.  */
	  notation->flags = GPGME_SIG_NOTATION_HUMAN_READABLE;
	  notation->human_readable = 1;
	}
      else
	{
	  /* This is a policy URL.  */

	  err = _gpgme_decode_percent_string (args, &notation->value, 0, 0);
	  if (err)
	    {
	      _gpgme_sig_notation_free (notation);
	      return err;
	    }

	  notation->value_len = strlen (notation->value);
	}
      *lastp = notation;
    }
  else if (code == GPGME_STATUS_NOTATION_DATA)
    {
      int len = strlen (args) + 1;
      char *dest;

      /* FIXME: We could keep a pointer to the last notation in the list.  */
      while (notation && notation->next)
	{
	  lastp = &notation->next;
	  notation = notation->next;
	}

      if (!notation || !notation->name)
	/* There is notation data without a previous notation
	   name.  The crypto backend misbehaves.  */
	return gpg_error (GPG_ERR_INV_ENGINE);
      
      if (!notation->value)
	{
	  dest = notation->value = malloc (len);
	  if (!dest)
	    return gpg_error_from_errno (errno);
	}
      else
	{
	  int cur_len = strlen (notation->value);
	  dest = realloc (notation->value, len + strlen (notation->value));
	  if (!dest)
	    return gpg_error_from_errno (errno);
	  notation->value = dest;
	  dest += cur_len;
	}
      
      err = _gpgme_decode_percent_string (args, &dest, len, 0);
      if (err)
	return err;

      notation->value_len += strlen (dest);
    }
  else
    return gpg_error (GPG_ERR_INV_ENGINE);
  return 0;
}