doc/
2005-10-02 Marcus Brinkmann <marcus@g10code.de> * gpgme.texi (Key Management): Add the new member notations of gpgme_sig_key_t. (Key Listing Mode): Document GPGME_KEYLIST_MODE_SIG_NOTATIONS. gpgme/ 2005-10-02 Marcus Brinkmann <marcus@g10code.de> * util.h (_gpgme_decode_percent_string): Add new argument BINARY to prototype. * verify.c (parse_notation): Likewise for invocation. * conversion.c (_gpgme_decode_percent_string): Likewise to declaration. If set, do not replace '\0' characters with a printable string. * gpgme.h (struct _gpgme_key_sig): New field notations. * ops.h (_gpgme_parse_notation): New prototype. * sig-notation.c (_gpgme_parse_notation): New function. * key.c (gpgme_key_unref): Free all signature notations. * keylist.c (op_data_t): New member tmp_keysig. (finish_key): Clear OPD->tmp_keysig. * gpgme.c (gpgme_set_keylist_mode): Remove check. * rungpg.c (gpg_keylist): Support listing signature notations. (gpg_keylist_ext): Likewise.
This commit is contained in:
parent
ceb26145c7
commit
5f5faeafa1
8
NEWS
8
NEWS
@ -1,11 +1,15 @@
|
|||||||
Noteworthy changes in version 1.x.y (unreleased)
|
Noteworthy changes in version 1.x.y (unreleased)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
* bla bla bla ...
|
* Reading signature notations and policy URLs on key signatures is
|
||||||
|
supported. They can be found in the new field notations of the
|
||||||
|
gpgme_key_sig_t structure. This has to be enabled with the keylist
|
||||||
|
mode flag GPGME_KEYLIST_MODE_SIG_NOTATIONS.
|
||||||
|
|
||||||
* Interface changes relative to the 1.0.3 release:
|
* Interface changes relative to the 1.0.3 release:
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
something changed
|
gpgme_key_sig_t EXTENDED: New field notations.
|
||||||
|
GPGME_KEYLIST_MODE_SIG_NOTATIONS NEW
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
2005-10-02 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* gpgme.texi (Key Management): Add the new member notations of
|
||||||
|
gpgme_sig_key_t.
|
||||||
|
(Key Listing Mode): Document GPGME_KEYLIST_MODE_SIG_NOTATIONS.
|
||||||
|
|
||||||
2005-10-01 Marcus Brinkmann <marcus@g10code.de>
|
2005-10-01 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* gpgme.texi: Enclose all return parameters of deftypefuns in
|
* gpgme.texi: Enclose all return parameters of deftypefuns in
|
||||||
|
@ -2136,6 +2136,12 @@ certificate server.
|
|||||||
The @code{GPGME_KEYLIST_MODE_SIGS} symbol specifies that the key
|
The @code{GPGME_KEYLIST_MODE_SIGS} symbol specifies that the key
|
||||||
signatures should be included in the listed keys.
|
signatures should be included in the listed keys.
|
||||||
|
|
||||||
|
@item GPGME_KEYLIST_MODE_SIG_NOTATIONS
|
||||||
|
The @code{GPGME_KEYLIST_MODE_SIG_NOTATIONS} symbol specifies that the
|
||||||
|
signature notations on key signatures should be included in the listed
|
||||||
|
keys. This only works if @code{GPGME_KEYLIST_MODE_SIGS} is also
|
||||||
|
enabled.
|
||||||
|
|
||||||
@item GPGME_KEYLIST_MODE_VALIDATE
|
@item GPGME_KEYLIST_MODE_VALIDATE
|
||||||
The @code{GPGME_KEYLIST_MODE_VALIDATE} symbol specifies that the
|
The @code{GPGME_KEYLIST_MODE_VALIDATE} symbol specifies that the
|
||||||
backend should do key or certificate validation and not just get the
|
backend should do key or certificate validation and not just get the
|
||||||
@ -2403,7 +2409,13 @@ validate user IDs on the key.
|
|||||||
|
|
||||||
The signatures on a key are only available if the key was retrieved
|
The signatures on a key are only available if the key was retrieved
|
||||||
via a listing operation with the @code{GPGME_KEYLIST_MODE_SIGS} mode
|
via a listing operation with the @code{GPGME_KEYLIST_MODE_SIGS} mode
|
||||||
enabled, because it is expensive to retrieve all signatures of a key.
|
enabled, because it can be expensive to retrieve all signatures of a
|
||||||
|
key.
|
||||||
|
|
||||||
|
The signature notations on a key signature are only available if the
|
||||||
|
key was retrieved via a listing operation with the
|
||||||
|
@code{GPGME_KEYLIST_MODE_SIG_NOTATIONS} mode enabled, because it can
|
||||||
|
be expensive to retrieve all signature notations.
|
||||||
|
|
||||||
The key signature structure has the following members:
|
The key signature structure has the following members:
|
||||||
|
|
||||||
@ -2458,6 +2470,9 @@ This is the comment component of @code{uid}, if available.
|
|||||||
|
|
||||||
@item char *email
|
@item char *email
|
||||||
This is the email component of @code{uid}, if available.
|
This is the email component of @code{uid}, if available.
|
||||||
|
|
||||||
|
@item gpgme_sig_notation_t notations
|
||||||
|
This is a linked list with the notation data and policy URLs.
|
||||||
@end table
|
@end table
|
||||||
@end deftp
|
@end deftp
|
||||||
|
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
2005-10-02 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* util.h (_gpgme_decode_percent_string): Add new argument BINARY
|
||||||
|
to prototype.
|
||||||
|
* verify.c (parse_notation): Likewise for invocation.
|
||||||
|
* conversion.c (_gpgme_decode_percent_string): Likewise to
|
||||||
|
declaration. If set, do not replace '\0' characters with a
|
||||||
|
printable string.
|
||||||
|
* gpgme.h (struct _gpgme_key_sig): New field notations.
|
||||||
|
* ops.h (_gpgme_parse_notation): New prototype.
|
||||||
|
* sig-notation.c (_gpgme_parse_notation): New function.
|
||||||
|
* key.c (gpgme_key_unref): Free all signature notations.
|
||||||
|
* keylist.c (op_data_t): New member tmp_keysig.
|
||||||
|
(finish_key): Clear OPD->tmp_keysig.
|
||||||
|
* gpgme.c (gpgme_set_keylist_mode): Remove check.
|
||||||
|
* rungpg.c (gpg_keylist): Support listing signature notations.
|
||||||
|
(gpg_keylist_ext): Likewise.
|
||||||
|
|
||||||
2005-10-01 Marcus Brinkmann <marcus@g10code.de>
|
2005-10-01 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* engine.h (_gpgme_set_engine_info): Add prototype.
|
* engine.h (_gpgme_set_engine_info): Add prototype.
|
||||||
|
@ -174,9 +174,11 @@ _gpgme_decode_c_string (const char *src, char **destp, size_t len)
|
|||||||
large enough buffer is allocated with malloc and *DESTP is set to
|
large enough buffer is allocated with malloc and *DESTP is set to
|
||||||
the result. Currently, LEN is only used to specify if allocation
|
the result. Currently, LEN is only used to specify if allocation
|
||||||
is desired or not, the caller is expected to make sure that *DESTP
|
is desired or not, the caller is expected to make sure that *DESTP
|
||||||
is large enough if LEN is not zero. */
|
is large enough if LEN is not zero. If BINARY is 1, then '\0'
|
||||||
|
characters are allowed in the output. */
|
||||||
gpgme_error_t
|
gpgme_error_t
|
||||||
_gpgme_decode_percent_string (const char *src, char **destp, size_t len)
|
_gpgme_decode_percent_string (const char *src, char **destp, size_t len,
|
||||||
|
int binary)
|
||||||
{
|
{
|
||||||
char *dest;
|
char *dest;
|
||||||
|
|
||||||
@ -222,7 +224,7 @@ _gpgme_decode_percent_string (const char *src, char **destp, size_t len)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!val)
|
if (!val && !binary)
|
||||||
{
|
{
|
||||||
/* A binary zero is not representable in a C
|
/* A binary zero is not representable in a C
|
||||||
string. */
|
string. */
|
||||||
|
@ -251,11 +251,6 @@ gpgme_get_include_certs (gpgme_ctx_t ctx)
|
|||||||
gpgme_error_t
|
gpgme_error_t
|
||||||
gpgme_set_keylist_mode (gpgme_ctx_t ctx, gpgme_keylist_mode_t mode)
|
gpgme_set_keylist_mode (gpgme_ctx_t ctx, gpgme_keylist_mode_t mode)
|
||||||
{
|
{
|
||||||
if (!((mode & GPGME_KEYLIST_MODE_LOCAL)
|
|
||||||
|| (mode & GPGME_KEYLIST_MODE_EXTERN)
|
|
||||||
|| (mode & GPGME_KEYLIST_MODE_SIGS)))
|
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
|
||||||
|
|
||||||
ctx->keylist_mode = mode;
|
ctx->keylist_mode = mode;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -308,6 +308,7 @@ gpgme_protocol_t;
|
|||||||
#define GPGME_KEYLIST_MODE_LOCAL 1
|
#define GPGME_KEYLIST_MODE_LOCAL 1
|
||||||
#define GPGME_KEYLIST_MODE_EXTERN 2
|
#define GPGME_KEYLIST_MODE_EXTERN 2
|
||||||
#define GPGME_KEYLIST_MODE_SIGS 4
|
#define GPGME_KEYLIST_MODE_SIGS 4
|
||||||
|
#define GPGME_KEYLIST_MODE_SIG_NOTATIONS 8
|
||||||
#define GPGME_KEYLIST_MODE_VALIDATE 256
|
#define GPGME_KEYLIST_MODE_VALIDATE 256
|
||||||
|
|
||||||
typedef unsigned int gpgme_keylist_mode_t;
|
typedef unsigned int gpgme_keylist_mode_t;
|
||||||
@ -594,6 +595,12 @@ struct _gpgme_key_sig
|
|||||||
|
|
||||||
/* Crypto backend specific signature class. */
|
/* Crypto backend specific signature class. */
|
||||||
unsigned int sig_class;
|
unsigned int sig_class;
|
||||||
|
|
||||||
|
/* Notation data and policy URLs. */
|
||||||
|
gpgme_sig_notation_t notations;
|
||||||
|
|
||||||
|
/* Internal to GPGME, do not use. */
|
||||||
|
gpgme_sig_notation_t _last_notation;
|
||||||
};
|
};
|
||||||
typedef struct _gpgme_key_sig *gpgme_key_sig_t;
|
typedef struct _gpgme_key_sig *gpgme_key_sig_t;
|
||||||
|
|
||||||
|
14
gpgme/key.c
14
gpgme/key.c
@ -337,9 +337,19 @@ gpgme_key_unref (gpgme_key_t key)
|
|||||||
|
|
||||||
while (keysig)
|
while (keysig)
|
||||||
{
|
{
|
||||||
gpgme_key_sig_t next = keysig->next;
|
gpgme_key_sig_t next_keysig = keysig->next;
|
||||||
|
gpgme_sig_notation_t notation = keysig->notations;
|
||||||
|
|
||||||
|
while (notation)
|
||||||
|
{
|
||||||
|
gpgme_sig_notation_t next_notation = notation->next;
|
||||||
|
|
||||||
|
_gpgme_sig_notation_free (notation);
|
||||||
|
notation = next_notation;
|
||||||
|
}
|
||||||
|
|
||||||
free (keysig);
|
free (keysig);
|
||||||
keysig = next;
|
keysig = next_keysig;
|
||||||
}
|
}
|
||||||
free (uid);
|
free (uid);
|
||||||
uid = next_uid;
|
uid = next_uid;
|
||||||
|
@ -48,8 +48,13 @@ typedef struct
|
|||||||
struct _gpgme_op_keylist_result result;
|
struct _gpgme_op_keylist_result result;
|
||||||
|
|
||||||
gpgme_key_t tmp_key;
|
gpgme_key_t tmp_key;
|
||||||
|
|
||||||
/* This points to the last uid in tmp_key. */
|
/* This points to the last uid in tmp_key. */
|
||||||
gpgme_user_id_t tmp_uid;
|
gpgme_user_id_t tmp_uid;
|
||||||
|
|
||||||
|
/* This points to the last sig in tmp_uid. */
|
||||||
|
gpgme_key_sig_t tmp_keysig;
|
||||||
|
|
||||||
/* Something new is available. */
|
/* Something new is available. */
|
||||||
int key_cond;
|
int key_cond;
|
||||||
struct key_queue_item_s *key_queue;
|
struct key_queue_item_s *key_queue;
|
||||||
@ -64,8 +69,9 @@ release_op_data (void *hook)
|
|||||||
|
|
||||||
if (opd->tmp_key)
|
if (opd->tmp_key)
|
||||||
gpgme_key_unref (opd->tmp_key);
|
gpgme_key_unref (opd->tmp_key);
|
||||||
/* opd->tmp_uid is actually part of opd->tmp_key, so we do not need
|
|
||||||
to release it here. */
|
/* opd->tmp_uid and opd->tmp_keysig are actually part of opd->tmp_key,
|
||||||
|
so we do not need to release them here. */
|
||||||
|
|
||||||
while (key)
|
while (key)
|
||||||
{
|
{
|
||||||
@ -351,6 +357,7 @@ finish_key (gpgme_ctx_t ctx, op_data_t opd)
|
|||||||
|
|
||||||
opd->tmp_key = NULL;
|
opd->tmp_key = NULL;
|
||||||
opd->tmp_uid = NULL;
|
opd->tmp_uid = NULL;
|
||||||
|
opd->tmp_keysig = NULL;
|
||||||
|
|
||||||
if (key)
|
if (key)
|
||||||
_gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
|
_gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
|
||||||
@ -365,7 +372,7 @@ keylist_colon_handler (void *priv, char *line)
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR,
|
RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR,
|
||||||
RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV
|
RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK
|
||||||
}
|
}
|
||||||
rectype = RT_NONE;
|
rectype = RT_NONE;
|
||||||
#define NR_FIELDS 13
|
#define NR_FIELDS 13
|
||||||
@ -423,6 +430,8 @@ keylist_colon_handler (void *priv, char *line)
|
|||||||
rectype = RT_SUB;
|
rectype = RT_SUB;
|
||||||
else if (!strcmp (field[0], "ssb") && key)
|
else if (!strcmp (field[0], "ssb") && key)
|
||||||
rectype = RT_SSB;
|
rectype = RT_SSB;
|
||||||
|
else if (!strcmp (field[0], "spk") && key)
|
||||||
|
rectype = RT_SPK;
|
||||||
else
|
else
|
||||||
rectype = RT_NONE;
|
rectype = RT_NONE;
|
||||||
|
|
||||||
@ -432,6 +441,12 @@ keylist_colon_handler (void *priv, char *line)
|
|||||||
if (rectype != RT_SIG && rectype != RT_REV)
|
if (rectype != RT_SIG && rectype != RT_REV)
|
||||||
opd->tmp_uid = NULL;
|
opd->tmp_uid = NULL;
|
||||||
|
|
||||||
|
/* Only look at subpackets immediately following a signature. For
|
||||||
|
this, clear the signature pointer when encountering anything but
|
||||||
|
a subpacket. */
|
||||||
|
if (rectype != RT_SPK)
|
||||||
|
opd->tmp_keysig = NULL;
|
||||||
|
|
||||||
switch (rectype)
|
switch (rectype)
|
||||||
{
|
{
|
||||||
case RT_PUB:
|
case RT_PUB:
|
||||||
@ -673,8 +688,51 @@ keylist_colon_handler (void *priv, char *line)
|
|||||||
if (field[10][2] == 'x')
|
if (field[10][2] == 'x')
|
||||||
keysig->exportable = 1;
|
keysig->exportable = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opd->tmp_keysig = keysig;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case RT_SPK:
|
||||||
|
if (!opd->tmp_keysig)
|
||||||
|
return 0;
|
||||||
|
assert (opd->tmp_keysig == key->_last_uid->_last_keysig);
|
||||||
|
|
||||||
|
if (fields >= 4)
|
||||||
|
{
|
||||||
|
/* Field 2 has the subpacket type. */
|
||||||
|
int type = atoi (field[1]);
|
||||||
|
|
||||||
|
/* Field 3 has the flags. */
|
||||||
|
int flags = atoi (field[2]);
|
||||||
|
|
||||||
|
/* Field 4 has the length. */
|
||||||
|
int len = atoi (field[3]);
|
||||||
|
|
||||||
|
/* Field 5 has the data. */
|
||||||
|
char *data = field[4];
|
||||||
|
|
||||||
|
/* Type 20: Notation data. */
|
||||||
|
/* Type 26: Policy URL. */
|
||||||
|
if (type == 20 || type == 26)
|
||||||
|
{
|
||||||
|
gpgme_sig_notation_t notation;
|
||||||
|
|
||||||
|
keysig = opd->tmp_keysig;
|
||||||
|
|
||||||
|
/* At this time, any error is serious. */
|
||||||
|
err = _gpgme_parse_notation (¬ation, type, flags, len, data);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* Add a new notation. FIXME: Could be factored out. */
|
||||||
|
if (!keysig->notations)
|
||||||
|
keysig->notations = notation;
|
||||||
|
if (keysig->_last_notation)
|
||||||
|
keysig->_last_notation->next = notation;
|
||||||
|
keysig->_last_notation = notation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case RT_NONE:
|
case RT_NONE:
|
||||||
/* Unknown record. */
|
/* Unknown record. */
|
||||||
break;
|
break;
|
||||||
|
@ -160,4 +160,10 @@ gpgme_error_t _gpgme_sig_notation_create (gpgme_sig_notation_t *notationp,
|
|||||||
pointer is ignored. */
|
pointer is ignored. */
|
||||||
void _gpgme_sig_notation_free (gpgme_sig_notation_t notation);
|
void _gpgme_sig_notation_free (gpgme_sig_notation_t notation);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
#endif /* OPS_H */
|
#endif /* OPS_H */
|
||||||
|
@ -1617,6 +1617,13 @@ gpg_keylist (void *engine, const char *pattern, int secret_only,
|
|||||||
err = add_arg (gpg, "--with-fingerprint");
|
err = add_arg (gpg, "--with-fingerprint");
|
||||||
if (!err)
|
if (!err)
|
||||||
err = add_arg (gpg, "--with-fingerprint");
|
err = add_arg (gpg, "--with-fingerprint");
|
||||||
|
if (!err && (mode & GPGME_KEYLIST_MODE_SIGS)
|
||||||
|
&& (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
|
||||||
|
{
|
||||||
|
err = add_arg (gpg, "--list-options");
|
||||||
|
if (!err)
|
||||||
|
err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
|
||||||
|
}
|
||||||
if (!err)
|
if (!err)
|
||||||
err = add_arg (gpg, secret_only ? "--list-secret-keys"
|
err = add_arg (gpg, secret_only ? "--list-secret-keys"
|
||||||
: ((mode & GPGME_KEYLIST_MODE_SIGS)
|
: ((mode & GPGME_KEYLIST_MODE_SIGS)
|
||||||
@ -1652,6 +1659,13 @@ gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
|
|||||||
err = add_arg (gpg, "--with-fingerprint");
|
err = add_arg (gpg, "--with-fingerprint");
|
||||||
if (!err)
|
if (!err)
|
||||||
err = add_arg (gpg, "--with-fingerprint");
|
err = add_arg (gpg, "--with-fingerprint");
|
||||||
|
if (!err && (mode & GPGME_KEYLIST_MODE_SIGS)
|
||||||
|
&& (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
|
||||||
|
{
|
||||||
|
err = add_arg (gpg, "--list-options");
|
||||||
|
if (!err)
|
||||||
|
err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
|
||||||
|
}
|
||||||
if (!err)
|
if (!err)
|
||||||
err = add_arg (gpg, secret_only ? "--list-secret-keys"
|
err = add_arg (gpg, secret_only ? "--list-secret-keys"
|
||||||
: ((mode & GPGME_KEYLIST_MODE_SIGS)
|
: ((mode & GPGME_KEYLIST_MODE_SIGS)
|
||||||
|
@ -80,7 +80,10 @@ _gpgme_sig_notation_create (gpgme_sig_notation_t *notationp,
|
|||||||
if (!notation)
|
if (!notation)
|
||||||
return gpg_error_from_errno (errno);
|
return gpg_error_from_errno (errno);
|
||||||
|
|
||||||
if (name_len)
|
/* 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
|
/* We add a trailing '\0' for stringification in the good
|
||||||
case. */
|
case. */
|
||||||
@ -96,7 +99,7 @@ _gpgme_sig_notation_create (gpgme_sig_notation_t *notationp,
|
|||||||
notation->name_len = name_len;
|
notation->name_len = name_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value_len)
|
if (value)
|
||||||
{
|
{
|
||||||
/* We add a trailing '\0' for stringification in the good
|
/* We add a trailing '\0' for stringification in the good
|
||||||
case. */
|
case. */
|
||||||
@ -121,3 +124,137 @@ _gpgme_sig_notation_create (gpgme_sig_notation_t *notationp,
|
|||||||
_gpgme_sig_notation_free (notation);
|
_gpgme_sig_notation_free (notation);
|
||||||
return err;
|
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;
|
||||||
|
}
|
||||||
|
@ -80,9 +80,10 @@ gpgme_error_t _gpgme_decode_c_string (const char *src, char **destp,
|
|||||||
large enough buffer is allocated with malloc and *DESTP is set to
|
large enough buffer is allocated with malloc and *DESTP is set to
|
||||||
the result. Currently, LEN is only used to specify if allocation
|
the result. Currently, LEN is only used to specify if allocation
|
||||||
is desired or not, the caller is expected to make sure that *DESTP
|
is desired or not, the caller is expected to make sure that *DESTP
|
||||||
is large enough if LEN is not zero. */
|
is large enough if LEN is not zero. If BINARY is 1, then '\0'
|
||||||
|
characters are allowed in the output. */
|
||||||
gpgme_error_t _gpgme_decode_percent_string (const char *src, char **destp,
|
gpgme_error_t _gpgme_decode_percent_string (const char *src, char **destp,
|
||||||
size_t len);
|
size_t len, int binary);
|
||||||
|
|
||||||
|
|
||||||
/* Parse the string TIMESTAMP into a time_t. The string may either be
|
/* Parse the string TIMESTAMP into a time_t. The string may either be
|
||||||
|
@ -434,7 +434,7 @@ parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
|
|||||||
|
|
||||||
if (code == GPGME_STATUS_NOTATION_NAME)
|
if (code == GPGME_STATUS_NOTATION_NAME)
|
||||||
{
|
{
|
||||||
err = _gpgme_decode_percent_string (args, ¬ation->name, 0);
|
err = _gpgme_decode_percent_string (args, ¬ation->name, 0, 0);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
_gpgme_sig_notation_free (notation);
|
_gpgme_sig_notation_free (notation);
|
||||||
@ -453,7 +453,7 @@ parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
|
|||||||
{
|
{
|
||||||
/* This is a policy URL. */
|
/* This is a policy URL. */
|
||||||
|
|
||||||
err = _gpgme_decode_percent_string (args, ¬ation->value, 0);
|
err = _gpgme_decode_percent_string (args, ¬ation->value, 0, 0);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
_gpgme_sig_notation_free (notation);
|
_gpgme_sig_notation_free (notation);
|
||||||
@ -497,7 +497,7 @@ parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
|
|||||||
dest += cur_len;
|
dest += cur_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = _gpgme_decode_percent_string (args, &dest, len);
|
err = _gpgme_decode_percent_string (args, &dest, len, 0);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user