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
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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
+2005-10-01 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.texi (Signature Notation Data): New section.
+ (Verify): Added more about the notation data structure.
+
2005-09-30 Marcus Brinkmann <marcus@g10code.de>
* gpgme.texi (Data Buffer I/O Operations, Data Buffer Meta-Data):
* 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
@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
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
@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
@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
+2005-10-01 Marcus Brinkmann <marcus@g10code.de>
+
+ * 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 <marcus@g10code.de>
* data.h (struct gpgme_data): New member file_name.
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 \
/* 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.
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;
/* 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.
file_name, home_dir);
}
+\f
+/* 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;
+}
+
\f
const char *
gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo)
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
/* 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.
typedef unsigned int gpgme_keylist_mode_t;
+\f
+/* 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;
+
\f
/* The possible stati for the edit operation. */
typedef enum
gpgme_error_t gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
_GPGME_DEPRECATED;
+\f
+/* 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);
+
\f
/* Run control. */
\f
/* 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
# 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.
#
gpgme_data_set_file_name;
gpgme_data_get_file_name;
+
+ gpgme_sig_notation_clear;
+ gpgme_sig_notation_add;
+ gpgme_sig_notation_get;
};
/* 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.
void *type_data);
\f
-/*-- 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);
+\f
+/* 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 */
}
+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 */)
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)
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))
{
--- /dev/null
+/* 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"
+
+\f
+/* 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);
+}
+
+\f
+/* 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;
+}
/* 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.
{
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;
}
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;
}
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);
+2005-10-01 Marcus Brinkmann <marcus@g10code.de>
+
+ * 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 <marcus@g10code.de>
* gpg/Makefile.am (TESTS): Add t-filename.
# 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
--- /dev/null
+# 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
--- /dev/null
+/* 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"
+
+\f
+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;
+}
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++;