diff options
Diffstat (limited to '')
| -rw-r--r-- | NEWS | 11 | ||||
| -rw-r--r-- | TODO | 2 | ||||
| -rw-r--r-- | doc/ChangeLog | 5 | ||||
| -rw-r--r-- | doc/gpgme.texi | 92 | ||||
| -rw-r--r-- | gpgme/ChangeLog | 23 | ||||
| -rw-r--r-- | gpgme/Makefile.am | 2 | ||||
| -rw-r--r-- | gpgme/context.h | 5 | ||||
| -rw-r--r-- | gpgme/data.h | 2 | ||||
| -rw-r--r-- | gpgme/gpgme.c | 65 | ||||
| -rw-r--r-- | gpgme/gpgme.def | 7 | ||||
| -rw-r--r-- | gpgme/gpgme.h | 68 | ||||
| -rw-r--r-- | gpgme/libgpgme.vers | 6 | ||||
| -rw-r--r-- | gpgme/ops.h | 19 | ||||
| -rw-r--r-- | gpgme/rungpg.c | 89 | ||||
| -rw-r--r-- | gpgme/sig-notation.c | 123 | ||||
| -rw-r--r-- | gpgme/verify.c | 55 | ||||
| -rw-r--r-- | tests/ChangeLog | 8 | ||||
| -rw-r--r-- | tests/gpg/Makefile.am | 2 | ||||
| -rw-r--r-- | tests/gpg/gpg.conf | 27 | ||||
| -rw-r--r-- | tests/gpg/t-sig-notation.c | 166 | ||||
| -rw-r--r-- | tests/gpg/t-verify.c | 10 | 
21 files changed, 731 insertions, 56 deletions
@@ -33,10 +33,13 @@ Noteworthy changes in version 1.1.0 (unreleased)     to local government regulations.   * You can associate a filename with a data object using the new -   gpgme_data_set_filename() function.  This filename will be stored +   function gpgme_data_set_filename().  This filename will be stored     in the output when encrypting or signing the data and will be     returned when decrypting or verifying the output data. + * You can now set notation data at signature creation with the new +   function gpgme_sig_notation_add(). +   * Interface changes relative to the 1.0.3 release:  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  gpgme_set_engine_info		NEW @@ -51,6 +54,12 @@ GPGME_STATUS_PLAINTEXT		NEW  gpgme_key_t			EXTENDED: New field is_qualified.  gpgme_subkey_t			EXTENDED: New field is_qualified.  gpgme_data_set_filename		NEW +gpgme_sig_notation_flags_t	NEW +GPGME_SIG_NOTATION_HUMAN_READABLE NEW +GPGME_SIG_NOTATAION_CRITICAL	NEW +gpgme_sig_notation_clear	NEW +gpgme_sig_notation_add		NEW +gpgme_sig_notation_get		NEW  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -37,6 +37,8 @@ Hey Emacs, this is -*- outline -*- mode!     There is a configure time warning, though.  * New features: +** Extended notation support.  When gpg supports arbitrary binary +   notation data, provide a user interface for that.  ** notification system     We need a simple notification system, probably a simple callback     with a string and some optional arguments.  This is for example diff --git a/doc/ChangeLog b/doc/ChangeLog index 681ed9b2..4d227f83 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2005-10-01  Marcus Brinkmann  <[email protected]> + +	* gpgme.texi (Signature Notation Data): New section. +	(Verify): Added more about the notation data structure. +  2005-09-30  Marcus Brinkmann  <[email protected]>  	* gpgme.texi (Data Buffer I/O Operations, Data Buffer Meta-Data): diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 44cdcbb1..1ddf9a07 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -209,6 +209,7 @@ Sign  * Selecting Signers::             How to choose the keys to sign with.  * Creating a Signature::          How to create a signature. +* Signature Notation Data::       How to add notation data to a signature.  Encrypt @@ -3753,6 +3754,8 @@ the context.  @cindex signature, verification  @cindex cryptographic operation, verification  @cindex cryptographic operation, signature check +@cindex signature notation data +@cindex notation data  @deftypefun gpgme_error_t gpgme_op_verify (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{sig}}, @w{gpgme_data_t @var{signed_text}}, @w{gpgme_data_t @var{plain}})  The function @code{gpgme_op_verify} verifies that the signature in the @@ -3801,9 +3804,45 @@ linked list, or @code{NULL} if this is the last element.  The name of the notation field.  If this is @code{NULL}, then the  member @code{value} will contain a policy URL. +@item int name_len +The length of the @code{name} field.  For strings the length is +counted without the trailing binary zero. +  @item char *value  The value of the notation field.  If @code{name} is @code{NULL}, then  this is a policy URL. + +@item int value_len +The length of the @code{value} field.  For strings the length is +counted without the trailing binary zero. + +@item gpgme_sig_notation_flags_t flags +The accumulated flags field.  This field contains the flags associated +with the notation data in an accumulated form which can be used as an +argument to the function @code{gpgme_sig_notation_add}.  The value +@code{flags} is a bitwise-or combination of one or multiple of the +following bit values: + +@table @code +@item GPGME_SIG_NOTATION_HUMAN_READABLE +The @code{GPGME_SIG_NOTATION_HUMAN_READABLE} symbol specifies that the +notation data is in human readable form + +@item GPGME_SIG_NOTATION_CRITICAL +The @code{GPGME_SIG_NOTATION_CRITICAL} symbol specifies that the +notation data is critical. + +@end table + +@item unsigned int human_readable : 1 +This is true if the @code{GPGME_SIG_NOTATION_HUMAN_READABLE} flag is +set and false otherwise.  This flag is only valid for notation data, +not for policy URLs. + +@item unsigned int critical : 1 +This is true if the @code{GPGME_SIG_NOTATION_CRITICAL} flag is set and +false otherwise.  This flag is valid for notation data and policy URLs. +  @end table  @end deftp @@ -4258,6 +4297,7 @@ set is changed).  @menu  * Selecting Signers::             How to choose the keys to sign with.  * Creating a Signature::          How to create a signature. +* Signature Notation Data::       How to add notation data to a signature.  @end menu @@ -4406,6 +4446,58 @@ context.  @end deftypefun +@node Signature Notation Data +@subsubsection Signature Notation Data +@cindex notation data +@cindex signature notation data +@cindex policy URL + +Using the following functions, you can attach arbitrary notation data +to a signature.  This information is then available to the user when +the signature is verified. + +@deftypefun void gpgme_sig_notation_clear (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_sig_notation_clear} removes the notation data +from the context @var{ctx}.  Subsequent signing operations from this +context will not include any notation data. + +Every context starts with an empty notation data list. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_sig_notation_add (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{name}}, @w{const char *@var{value}}, @w{gpgme_sig_notation_flags_t @var{flags}}) +The function @code{gpgme_sig_notation_add} adds the notation data with +the name @var{name} and the value @var{value} to the context +@var{ctx}. + +Subsequent signing operations will include this notation data, as well +as any other notation data that was added since the creation of the +context or the last @code{gpgme_sig_notation_clear} operation. + +The arguments @var{name} and @var{value} must be @code{NUL}-terminated +strings in human-readable form.  The flag +@code{GPGME_SIG_NOTATION_HUMAN_READABLE} is implied +(non-human-readable notation data is currently not supported).  The +strings must be in UTF-8 encoding. + +If @var{name} is @code{NULL}, then @var{value} should be a policy URL. + +The function @code{gpgme_sig_notation_add} returns the error code +@code{GPG_ERR_NO_ERROR} if the notation data could be added +successfully, @code{GPG_ERR_INV_VALUE} if @var{ctx} is not a valid +pointer, or if @var{name}, @var{value} and @var{flags} are an invalid +combination.  The function also passes through any errors that are +reported by the crypto engine support routines. +@end deftypefun + +@deftypefun gpgme_sig_notation_t gpgme_sig_notation_get (@w{const gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_sig_notation_get} returns the linked list of +notation data structures that are contained in the context @var{ctx}. + +If @var{ctx} is not a valid pointer, or there is no notation data +added for this context, @code{NULL} is returned. +@end deftypefun + +  @node Encrypt  @subsection Encrypt  @cindex encryption diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 6ec0bfd2..4150db02 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,26 @@ +2005-10-01  Marcus Brinkmann  <[email protected]> + +	* gpgme.def: Add gpgme_data_set_file_name, +	gpgme_data_get_file_name, gpgme_sig_notation_clear, +	gpgme_sig_notation_add and gpgme_sig_notation_get. +	* libgpgme.vers: Add gpgme_sig_notation_clear, +	gpgme_sig_notation_add and gpgme_sig_notation_get. +	* Makefile.am (libgpgme_real_la_SOURCES): Add sig-notation.c. +	* context.h (struct gpgme_context): New field sig_notations. +	* gpgme.h (struct _gpgme_sig_notation): New member value_len and +	critical. +	(GPGME_SIG_NOTATION_CRITICAL): New symbol. +	(gpgme_sig_notation_flags_t): New type. +	(gpgme_sig_notation_add, gpgme_sig_notation_clear, +	gpgme_sig_notation_get): New prototypes. +	* ops.h (_gpgme_sig_notation_create, _gpgme_sig_notation_free): +	New prototypes. +	* sig-notation.c (_gpgme_sig_notation_free): New file. +	* verify.c (parse_notation): Use support functions. +	(release_op_data): Likewise. +	* rungpg.c (append_args_from_sig_notations): New function. +	(gpg_encrypt_sign, gpg_sign): Call it. +  2005-09-30  Marcus Brinkmann  <[email protected]>  	* data.h (struct gpgme_data): New member file_name. diff --git a/gpgme/Makefile.am b/gpgme/Makefile.am index b8f27f97..994d5761 100644 --- a/gpgme/Makefile.am +++ b/gpgme/Makefile.am @@ -72,7 +72,7 @@ libgpgme_real_la_SOURCES =						\  	gpgme.h util.h conversion.c get-env.c context.h ops.h		\  	data.h data.c data-fd.c data-stream.c data-mem.c data-user.c	\  	data-compat.c							\ -	signers.c							\ +	signers.c sig-notation.c					\  	wait.c wait-global.c wait-private.c wait-user.c wait.h		\  	op-support.c							\  	encrypt.c encrypt-sign.c decrypt.c decrypt-verify.c verify.c	\ diff --git a/gpgme/context.h b/gpgme/context.h index 3afd61bd..e7e2afa4 100644 --- a/gpgme/context.h +++ b/gpgme/context.h @@ -1,6 +1,6 @@  /* context.h - Definitions for a GPGME context.     Copyright (C) 2000 Werner Koch (dd9jn) -   Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH +   Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH     This file is part of GPGME. @@ -91,6 +91,9 @@ struct gpgme_context    unsigned int signers_size;    gpgme_key_t *signers; +  /* The signature notations for this context.  */ +  gpgme_sig_notation_t sig_notations; +    /* The locale for the pinentry.  */    char *lc_ctype;    char *lc_messages; diff --git a/gpgme/data.h b/gpgme/data.h index 80eeae8b..80a86e69 100644 --- a/gpgme/data.h +++ b/gpgme/data.h @@ -1,5 +1,5 @@  /* data.h - Internal data object abstraction interface. -   Copyright (C) 2002, 2004 g10 Code GmbH +   Copyright (C) 2002, 2004, 2005 g10 Code GmbH     This file is part of GPGME. diff --git a/gpgme/gpgme.c b/gpgme/gpgme.c index 85eaf3a0..da598339 100644 --- a/gpgme/gpgme.c +++ b/gpgme/gpgme.c @@ -430,6 +430,71 @@ gpgme_ctx_set_engine_info (gpgme_ctx_t ctx, gpgme_protocol_t proto,  } +/* Clear all notation data from the context.  */ +void +gpgme_sig_notation_clear (gpgme_ctx_t ctx) +{ +  gpgme_sig_notation_t notation; + +  if (!ctx) +    return; + +  notation = ctx->sig_notations; +  while (notation) +    { +      gpgme_sig_notation_t next_notation = notation->next; +      _gpgme_sig_notation_free (notation); +      notation = next_notation; +    } +} + + +/* 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; + +  if (!ctx) +     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 (¬ation, name, name ? strlen (name) : 0, +				    value, value ? strlen (value) : 0, flags); +  if (err) +    return err; + +  lastp = &ctx->sig_notations; +  while (*lastp) +    lastp = &(*lastp)->next; + +  *lastp = notation; +  return 0; +} + + +/* Get the sig notations for this context.  */ +gpgme_sig_notation_t +gpgme_sig_notation_get (gpgme_ctx_t ctx) +{ +  if (!ctx) +    return NULL; + +  return ctx->sig_notations; +} +   +  const char *  gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo)  { diff --git a/gpgme/gpgme.def b/gpgme/gpgme.def index f7117e06..07a72ebb 100644 --- a/gpgme/gpgme.def +++ b/gpgme/gpgme.def @@ -144,5 +144,12 @@ EXPORTS      gpgme_ctx_get_engine_info             @113       gpgme_ctx_set_engine_info             @114 +    gpgme_data_set_file_name		  @115 +    gpgme_data_get_file_name		  @116 + +    gpgme_sig_notation_clear		  @117 +    gpgme_sig_notation_add		  @118 +    gpgme_sig_notation_get		  @119 +  ; END diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index f0f27d9b..28d89574 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.h @@ -1,6 +1,6 @@  /* gpgme.h - Public interface to GnuPG Made Easy.     Copyright (C) 2000 Werner Koch (dd9jn) -   Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH +   Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH     This file is part of GPGME. @@ -313,6 +313,46 @@ gpgme_protocol_t;  typedef unsigned int gpgme_keylist_mode_t; +/* Signature notations.  */ + +/* The available signature notation flags.  */ +#define GPGME_SIG_NOTATION_HUMAN_READABLE	1 +#define GPGME_SIG_NOTATION_CRITICAL		2 + +typedef unsigned int gpgme_sig_notation_flags_t; + +struct _gpgme_sig_notation +{ +  struct _gpgme_sig_notation *next; + +  /* If NAME is a null pointer, then VALUE contains a policy URL +     rather than a notation.  */ +  char *name; + +  /* The value of the notation data.  */ +  char *value; + +  /* The length of the name of the notation data.  */ +  int name_len; + +  /* The length of the value of the notation data.  */ +  int value_len; + +  /* The accumulated flags.  */ +  gpgme_sig_notation_flags_t flags; + +  /* Notation data is human-readable.  */ +  unsigned int human_readable : 1; + +  /* Notation data is critical.  */ +  unsigned int critical : 1; + +  /* Internal to GPGME, do not use.  */ +  int _unused : 30; +}; +typedef struct _gpgme_sig_notation *gpgme_sig_notation_t; + +  /* The possible stati for the edit operation.  */  typedef enum    { @@ -819,6 +859,22 @@ gpgme_error_t gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)       _GPGME_DEPRECATED; +/* Clear all notation data from the context.  */ +void gpgme_sig_notation_clear (gpgme_ctx_t ctx); + +/* 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); + +/* Get the sig notations for this context.  */ +gpgme_sig_notation_t gpgme_sig_notation_get (gpgme_ctx_t ctx); + +  /* Run control.  */  /* The type of an I/O callback function.  */ @@ -1209,16 +1265,6 @@ gpgme_error_t gpgme_op_sign (gpgme_ctx_t ctx,  /* Verify.  */ -struct _gpgme_sig_notation -{ -  struct _gpgme_sig_notation *next; - -  /* If NAME is a null pointer, then VALUE contains a policy URL -     rather than a notation.  */ -  char *name; -  char *value; -}; -typedef struct _gpgme_sig_notation *gpgme_sig_notation_t;  /* Flags used for the SUMMARY field in a gpgme_signature_t.  */  typedef enum diff --git a/gpgme/libgpgme.vers b/gpgme/libgpgme.vers index 4735f49b..20073039 100644 --- a/gpgme/libgpgme.vers +++ b/gpgme/libgpgme.vers @@ -1,5 +1,5 @@  # libgpgme.vers - List of symbols to export. -# Copyright (C) 2002, 2004 g10 Code GmbH +# Copyright (C) 2002, 2004, 2005 g10 Code GmbH  #  # This file is part of GPGME.  # @@ -30,6 +30,10 @@ GPGME_1.1 {      gpgme_data_set_file_name;      gpgme_data_get_file_name; + +    gpgme_sig_notation_clear; +    gpgme_sig_notation_add; +    gpgme_sig_notation_get;  }; diff --git a/gpgme/ops.h b/gpgme/ops.h index 79fb3b47..9525e7c9 100644 --- a/gpgme/ops.h +++ b/gpgme/ops.h @@ -1,6 +1,6 @@  /* ops.h - Internal operation support.     Copyright (C) 2000 Werner Koch (dd9jn) -   Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH +   Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH     This file is part of GPGME. @@ -138,11 +138,26 @@ void _gpgme_op_trustlist_event_cb (void *data, gpgme_event_io_t type,  				   void *type_data); -/*-- version.c --*/ +/* From version.c.  */ +  /* Return true if MY_VERSION is at least REQ_VERSION, and false     otherwise.  */  int _gpgme_compare_versions (const char *my_version,  			     const char *req_version);  char *_gpgme_get_program_version (const char *const path); + +/* From sig-notation.c.  */ + +/* 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); + +/* 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); +  #endif /* OPS_H */ diff --git a/gpgme/rungpg.c b/gpgme/rungpg.c index 86710a0d..e5ef0306 100644 --- a/gpgme/rungpg.c +++ b/gpgme/rungpg.c @@ -1256,6 +1256,91 @@ append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)  static gpgme_error_t +append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */) +{ +  gpgme_error_t err = 0; +  gpgme_sig_notation_t notation; + +  notation = gpgme_sig_notation_get (ctx); + +  while (!err && notation) +    { +      if (notation->name +	  && !(notation->flags & GPGME_SIG_NOTATION_HUMAN_READABLE)) +	err = gpg_error (GPG_ERR_INV_VALUE); +      else if (notation->name) +	{ +	  char *arg; + +	  /* Maximum space needed is one byte for the "critical" flag, +	     the name, one byte for '=', the value, and a terminating +	     '\0'.  */ + +	  arg = malloc (1 + notation->name_len + 1 + notation->value_len + 1); +	  if (!arg) +	    err = gpg_error_from_errno (errno); + +	  if (!err) +	    { +	      char *argp = arg; + +	      if (notation->critical) +		*(argp++) = '!'; + +	      memcpy (argp, notation->name, notation->name_len); +	      argp += notation->name_len; + +	      *(argp++) = '='; + +	      /* We know that notation->name is '\0' terminated.  */ +	      strcpy (argp, notation->value); +	    } + +	  if (!err) +	    err = add_arg (gpg, "--sig-notation"); +	  if (!err) +	    err = add_arg (gpg, arg); + +	  if (arg) +	    free (arg); +	} +      else +	{ +	  /* This is a policy URL.  */ + +	  char *value; + +	  if (notation->critical) +	    { +	      value = malloc (1 + notation->value_len + 1); +	      if (!value) +		err = gpg_error_from_errno (errno); +	      else +		{ +		  value[0] = '!'; +		  /* We know that notation->value is '\0' terminated.  */ +		  strcpy (&value[1], notation->value); +		} +	    } +	  else +	    value = notation->value; + +	  if (!err) +	    err = add_arg (gpg, "--sig-policy-url"); +	  if (!err) +	    err = add_arg (gpg, value); + +	  if (value != notation->value) +	    free (value); +      	} + +      notation = notation->next; +    } +  return err; +} + + +static gpgme_error_t  gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,  	  gpgme_ctx_t ctx /* FIXME */)  { @@ -1383,6 +1468,8 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[],    if (!err)      err = append_args_from_signers (gpg, ctx); +  if (!err) +    err = append_args_from_sig_notations (gpg, ctx);    /* Tell the gpg object about the data.  */    if (!err) @@ -1608,6 +1695,8 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,    if (!err)      err = append_args_from_signers (gpg, ctx); +  if (!err) +    err = append_args_from_sig_notations (gpg, ctx);    if (gpgme_data_get_file_name (in))      { diff --git a/gpgme/sig-notation.c b/gpgme/sig-notation.c new file mode 100644 index 00000000..6a04fd03 --- /dev/null +++ b/gpgme/sig-notation.c @@ -0,0 +1,123 @@ +/* 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); + +  if (name_len) +    { +      /* 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_len) +    { +      /* 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; +} diff --git a/gpgme/verify.c b/gpgme/verify.c index 90b4cf89..d7c32169 100644 --- a/gpgme/verify.c +++ b/gpgme/verify.c @@ -1,6 +1,6 @@  /* verify.c - Signature verification.     Copyright (C) 2000 Werner Koch (dd9jn) -   Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH +   Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH     This file is part of GPGME. @@ -58,10 +58,7 @@ release_op_data (void *hook)  	{  	  gpgme_sig_notation_t next_nota = notation->next; -	  if (notation->name) -	    free (notation->name); -	  if (notation->value) -	    free (notation->value); +	  _gpgme_sig_notation_free (notation);  	  notation = next_nota;  	} @@ -431,51 +428,39 @@ parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)  	   previous one.  The crypto backend misbehaves.  */  	return gpg_error (GPG_ERR_INV_ENGINE); -      notation = malloc (sizeof (*sig)); -      if (!notation) -	return gpg_error_from_errno (errno); -      notation->next = NULL; +      err = _gpgme_sig_notation_create (¬ation, NULL, 0, NULL, 0, 0); +      if (err) +	return err;        if (code == GPGME_STATUS_NOTATION_NAME)  	{ -	  int len = strlen (args) + 1; - -	  notation->name = malloc (len); -	  if (!notation->name) -	    { -	      int saved_errno = errno; -	      free (notation); -	      return gpg_error_from_errno (saved_errno); -	    } -	  err = _gpgme_decode_percent_string (args, ¬ation->name, len); +	  err = _gpgme_decode_percent_string (args, ¬ation->name, 0);  	  if (err)  	    { -	      free (notation->name); -	      free (notation); +	      _gpgme_sig_notation_free (notation);  	      return err;  	    } -	  notation->value = NULL; +	  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  	{ -	  int len = strlen (args) + 1; +	  /* This is a policy URL.  */ -	  notation->name = NULL; -	  notation->value = malloc (len); -	  if (!notation->value) -	    { -	      int saved_errno = errno; -	      free (notation); -	      return gpg_error_from_errno (saved_errno); -	    } -	  err = _gpgme_decode_percent_string (args, ¬ation->value, len); +	  err = _gpgme_decode_percent_string (args, ¬ation->value, 0);  	  if (err)  	    { -	      free (notation->value); -	      free (notation); +	      _gpgme_sig_notation_free (notation);  	      return err;  	    } + +	  notation->value_len = strlen (notation->value);  	}        *lastp = notation;      } @@ -515,6 +500,8 @@ parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)        err = _gpgme_decode_percent_string (args, &dest, len);        if (err)  	return err; + +      notation->value_len += strlen (dest);      }    else      return gpg_error (GPG_ERR_INV_ENGINE); diff --git a/tests/ChangeLog b/tests/ChangeLog index 94645929..42d9e144 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,11 @@ +2005-10-01  Marcus Brinkmann  <[email protected]> + +	* gpg/Makefile.am (TESTS): Add t-sig-notation. +	* gpg/t-sig-notation.c (check_result): New file. +	* gpg/t-verify.c (check_result): Also check the length of the +	notation data. +	* gpg/gpg.conf: New file. +  2005-09-30  Marcus Brinkmann  <[email protected]>  	* gpg/Makefile.am (TESTS): Add t-filename. diff --git a/tests/gpg/Makefile.am b/tests/gpg/Makefile.am index 0fa03492..e946eafd 100644 --- a/tests/gpg/Makefile.am +++ b/tests/gpg/Makefile.am @@ -26,7 +26,7 @@ TESTS_ENVIRONMENT = GNUPGHOME=. GPG_AGENT_INFO=  # The keylist tests must come after the import and the edit test.  noinst_HEADERS = t-support.h  TESTS = t-encrypt t-encrypt-sym t-encrypt-sign t-sign t-signers	\ -	t-decrypt t-verify t-decrypt-verify \ +	t-decrypt t-verify t-decrypt-verify t-sig-notation \  	t-export t-import t-trustlist t-eventloop t-edit \  	t-keylist t-keylist-sig t-thread1 t-wait t-encrypt-large \  	t-file-name diff --git a/tests/gpg/gpg.conf b/tests/gpg/gpg.conf new file mode 100644 index 00000000..f1196a1e --- /dev/null +++ b/tests/gpg/gpg.conf @@ -0,0 +1,27 @@ +# Options for GnuPG +# Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Unless you specify which option file to use (with the command line +# option "--options filename"), GnuPG uses the file ~/.gnupg/gpg.conf +# by default. +# +# An options file can contain any long options which are available in +# GnuPG. If the first non white space character of a line is a '#', +# this line is ignored.  Empty lines are also ignored. +# +# See the man page for a list of options. + +# By default GnuPG creates version 3 signatures for data files.  This +# is not strictly OpenPGP compliant but PGP 6 and most versions of PGP +# 7 require them.  To disable this behavior, you may use this option +# or --openpgp. + +no-force-v3-sigs diff --git a/tests/gpg/t-sig-notation.c b/tests/gpg/t-sig-notation.c new file mode 100644 index 00000000..a9014733 --- /dev/null +++ b/tests/gpg/t-sig-notation.c @@ -0,0 +1,166 @@ +/* t-sig-notation.c - Regression test. +   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.  */ + +/* We need to include config.h so that we know whether we are building +   with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <gpgme.h> + +#include "t-support.h" + + +static struct { +  const char *name; +  const char *value; +  gpgme_sig_notation_flags_t flags; +  int seen; +} expected_notations[] = {  +  { "laughing@me", +    "Just Squeeze Me", +    GPGME_SIG_NOTATION_HUMAN_READABLE }, +  { "leave@home", +    "Right Now", +    GPGME_SIG_NOTATION_HUMAN_READABLE | GPGME_SIG_NOTATION_CRITICAL }, +  { NULL,  +    "http://www.gnu.org/policy/", +    0 } +}; + +static void +check_result (gpgme_verify_result_t result) +{ +  int i; +  gpgme_sig_notation_t r; +   +  gpgme_signature_t sig; + +  sig = result->signatures; +  if (!sig || sig->next) +    { +      fprintf (stderr, "%s:%i: Unexpected number of signatures\n", +	       __FILE__, __LINE__); +      exit (1); +    } + +  for (i=0; i < DIM(expected_notations); i++ ) +    expected_notations[i].seen = 0; +   +  for (r = result->signatures->notations; r; r = r->next) +    { +      int any = 0; +      for (i=0; i < DIM(expected_notations); i++) +	{ +	  if ( ((r->name && expected_notations[i].name +		 && !strcmp (r->name, expected_notations[i].name) +		 && r->name_len +		 == strlen (expected_notations[i].name)) +		|| (!r->name && !expected_notations[i].name +		    && r->name_len == 0)) +	       && r->value +	       && !strcmp (r->value, expected_notations[i].value) +	       && r->value_len == strlen (expected_notations[i].value) +	       && r->flags +	       == (expected_notations[i].flags & ~GPGME_SIG_NOTATION_CRITICAL) +	       && r->human_readable +	       == !!(r->flags & GPGME_SIG_NOTATION_HUMAN_READABLE) +	       && r->critical == 0) +	    { +	      expected_notations[i].seen++; +	      any++; +	    } +	} +      if (!any) +	{ +	  fprintf (stderr, "%s:%i: Unexpected notation data\n", +		   __FILE__, __LINE__); +	  exit (1); +	} +    } +  for (i=0; i < DIM(expected_notations); i++ ) +    { +      if (expected_notations[i].seen != 1) +	{ +	  fprintf (stderr, "%s:%i: Missing or duplicate notation data\n", +		   __FILE__, __LINE__); +	  exit (1); +	} +    } +} + + +int  +main (int argc, char *argv[]) +{ +  gpgme_ctx_t ctx; +  gpgme_error_t err; +  gpgme_data_t in, out; +  gpgme_verify_result_t result; +  char *agent_info; +  int i; + +  init_gpgme (GPGME_PROTOCOL_OpenPGP); + +  err = gpgme_new (&ctx); +  fail_if_err (err); + +  agent_info = getenv ("GPG_AGENT_INFO"); +  if (!(agent_info && strchr (agent_info, ':'))) +    gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL); + +  err = gpgme_data_new_from_mem (&in, "Hallo Leute\n", 12, 0); +  fail_if_err (err); +  err = gpgme_data_new (&out); +  fail_if_err (err); + +  for (i = 0; i < sizeof (expected_notations) / sizeof (expected_notations[0]); +       i++) +    { +      err = gpgme_sig_notation_add (ctx, expected_notations[i].name, +				    expected_notations[i].value, +				    expected_notations[i].flags); +      fail_if_err (err); +    } +   +  err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_NORMAL); +  fail_if_err (err); + +  gpgme_data_release (in); +  err = gpgme_data_new (&in); +  fail_if_err (err); + +  gpgme_data_seek (out, 0, SEEK_SET); + +  err = gpgme_op_verify (ctx, out, NULL, in); +  fail_if_err (err); +  result = gpgme_op_verify_result (ctx); +  check_result (result); + +  gpgme_data_release (in); +  gpgme_data_release (out); +  gpgme_release (ctx); +  return 0; +} diff --git a/tests/gpg/t-verify.c b/tests/gpg/t-verify.c index 1b63829c..22f04773 100644 --- a/tests/gpg/t-verify.c +++ b/tests/gpg/t-verify.c @@ -136,10 +136,14 @@ check_result (gpgme_verify_result_t result, unsigned int summary, char *fpr,            for (i=0; i < DIM(expected_notations); i++)              {                if ( ((r->name && expected_notations[i].name -                     && !strcmp (r->name, expected_notations[i].name)) -                    || (!r->name && !expected_notations[i].name)) +                     && !strcmp (r->name, expected_notations[i].name) +		     && r->name_len +		     == strlen (expected_notations[i].name)) +                    || (!r->name && !expected_notations[i].name +			&& r->name_len == 0))                     && r->value -                   && !strcmp (r->value, expected_notations[i].value)) +                   && !strcmp (r->value, expected_notations[i].value) +		   && r->value_len == strlen (expected_notations[i].value))                  {                    expected_notations[i].seen++;                    any++;  | 
