2003-04-30  Marcus Brinkmann  <marcus@g10code.de>

	* gpgme.texi (Key Listing Mode): Add GPGME_KEYLIST_MODE_SIGS.
	(Manipulating Keys): Add obsoleteness note.
	(Key Signatures): Likewise.
	(Information About Keys): Likewise.
	(Key Management): Add new data types GpgmeSubkey, GpgmeKeySig,
	GpgmeUserID, and all the information about GpgmeKey.

gpgme/
2003-04-30  Marcus Brinkmann  <marcus@g10code.de>

	* gpgme.h (struct _gpgme_key): New structure.
	(GpgmeKey): Define using _gpgme_key.
	(struct _gpgme_subkey): New structure.
	(GpgmeSubKey): New type.
	(struct _gpgme_key_sig): New structure.
	(GpgmeKeySig): New type.
	(struct _gpgme_user_id): New structure.
	(GpgmeUserID): New type.
	(struct _gpgme_op_keylist_result): New structure.
	(GpgmeKeyListResult): New type.
	(gpgme_op_keylist_result): New function.
	(gpgme_key_get_as_xml): Remove prototype.
	* context.h (struct gpgme_context_s): Remove members tmp_key,
	tmp_uid, key_cond and key_queue.
	(struct key_queue_item_s): Remove structure.
	(struct user_id_s): Remove structure.
	(struct gpgme_recipients_s): Replace with simple
	GpgmeUserID list.
	* gpgme.c (gpgme_release): Do not release CTX->tmp_key.
	* ops.h (_gpgme_key_add_subkey, _gpgme_key_append_name,
	_gpgme_key_add_sig, _gpgme_trust_item_new): New prototypes.
	* rungpg.c (command_cb): Return GpgmeError instead int.
	New variable ERR.  Use it to hold return value of cmd handler.
	(gpg_delete): Access fingerprint of key directly.
	(append_args_from_signers): Likewise.
	(gpg_edit): Likewise.
	(append_args_from_recipients): Use GpgmeUserID for recipient list.
	* engine-gpgsm.c: Do not include "key.h".
	(gpgsm_delete): Access fingerprint of key directly.
	(gpgsm_sign): Likewise.
	(set_recipients): Use GpgmeUserID for recipients.  Invert invalid
	user ID flag.
	* key.h: File removed.
	* key.c: Completely reworked to use exposed GpgmeKey data types.
	* keylist.c: Likewise.
	* recipient.c: Completely reworked to use GpgmeUserID.

tests/
2003-04-30  Marcus Brinkmann  <marcus@g10code.de>

	* gpg/t-keylist.c: Rewritten.
	* gpgsm/t-keylist.c (main): Rewritten.
	* gpg/t-edit.c (main): Do not use gpgme_key_get_as_xml.  Use
	gpgme_key_unref instead gpgme_key_release.
	* gpg/t-signers.c (main): Use gpgme_key_unref instead
	gpgme_key_release.
This commit is contained in:
Marcus Brinkmann 2003-04-30 03:02:50 +00:00
parent 18fb96bdcd
commit ba333bf07e
20 changed files with 2109 additions and 1442 deletions

29
NEWS
View File

@ -4,7 +4,8 @@ Noteworthy changes in version 0.4.1 (unreleased)
* GPGME_ATTR_IS_SECRET is not anymore representable as a string.
* gpgme_op_verify and gpgme_op_decrypt_verify don't return a status
summary anymore. Use gpgme_get_sig_status to retrieve the individual stati.
summary anymore. Use gpgme_get_sig_status to retrieve the individual
stati.
* GpgmeIOCb changed from a void function to a function returning a
GpgmeError value. However, it will always return 0, so you can
@ -87,7 +88,7 @@ Noteworthy changes in version 0.4.1 (unreleased)
a GpgmeEncryptResult object.
* The new gpgme_op_decrypt_result function provides detailed
information about the result of an encryption operation in
information about the result of a decryption operation in
a GpgmeDecryptResult object.
* The new gpgme_op_verify_result function provides detailed
@ -106,6 +107,19 @@ Noteworthy changes in version 0.4.1 (unreleased)
* Keys are not cached internally anymore, so the force_update argument
to gpgme_get_key has been removed.
* GpgmeKey objects have now directly accessible data so the
gpgme_key_get_string_attr, gpgme_key_get_ulong_attr,
gpgme_key_sig_get_string_attr and gpgme_key_sig_get_ulong_attr
functions are deprecated. Also, gpgme_key_release is now
deprecated. The gpgme_key_get_as_xml function has been dropped.
* Because all interfaces using attributes are deprecated, the
GpgmeAttr data type is also deprecated.
* The new gpgme_op_keylist_result function provides detailed
information about the result of a key listing operation in
a GpgmeKeyListResult object.
* Interface changes relative to the 0.4.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GpgmeIOCb CHANGED: Return type from void to GpgmeError.
@ -163,6 +177,17 @@ gpgme_trust_item_release DEPRECATED: Use gpgme_trust_item_unref.
gpgme_trust_item_get_string_attr DEPRECATED
gpgme_trust_item_get_ulong_attr DEPRECATED
gpgme_get_key CHANGED: Removed force_update argument.
GpgmeSubKey NEW
GpgmeKeySig NEW
GpgmeUserID NEW
GpgmeKey CHANGED: Now has user accessible data members.
gpgme_key_get_string_attr DEPRECATED
gpgme_key_get_ulong_attr DEPRECATED
gpgme_key_sig_get_string_attr DEPRECATED
gpgme_key_sig_get_ulong_attr DEPRECATED
gpgme_key_get_as_xml REMOVED
GpgmeKeyListResult NEW
gpgme_op_keylist_result NEW
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Noteworthy changes in version 0.4.0 (2002-12-23)

View File

@ -1,3 +1,12 @@
2003-04-30 Marcus Brinkmann <marcus@g10code.de>
* gpgme.texi (Key Listing Mode): Add GPGME_KEYLIST_MODE_SIGS.
(Manipulating Keys): Add obsoleteness note.
(Key Signatures): Likewise.
(Information About Keys): Likewise.
(Key Management): Add new data types GpgmeSubkey, GpgmeKeySig,
GpgmeUserID, and all the information about GpgmeKey.
2003-04-29 Marcus Brinkmann <marcus@g10code.de>
* gpgme.texi (Listing Keys): Remove force_update argument from

View File

@ -1647,6 +1647,10 @@ source should be should be searched for keys in the keylisting
operation. The type of external source is dependant on the crypto
engine used. For example, it can be a remote keyserver or LDAP
certificate server.
@item GPGME_KEYLIST_MODE_SIGS
The @code{GPGME_KEYLIST_MODE_SIGS} symbol specifies that the key
signatures should be included in the listed keys.
@end table
At least one of @code{GPGME_KEYLIST_MODE_LOCAL} and
@ -1785,11 +1789,230 @@ signers are specified. This is always done by specifying the
respective keys that should be used for the operation. The following
section describes how such keys can be selected and manipulated.
@deftp {Data type} GpgmeKey
The @code{GpgmeKey} type is a handle for a public or secret key, and
is used to select the key for operations involving it.
@deftp {Data type} GpgmeSubkey
The @code{GpgmeSubKey} type is a pointer to a subkey structure. Sub
keys are one component of a @code{GpgmeKey} object. In fact, subkeys
are those parts that contains the real information about the
individual cryptographic keys that belong to the same key object. One
@code{GpgmeKey} can contain several subkeys. The first subkey in the
linked list is also called the primary key.
A key can contain several user IDs and sub keys.
The subkey structure has the following members:
@table @code
@item GpgmeSubkey next
This is a pointer to the next subkey structure in the linked list, or
@code{NULL} if this is the last element.
@item unsigned int revoked : 1
This is true if the subkey is revoked.
@item unsigned int expired : 1
This is true if the subkey is expired.
@item unsigned int disabled : 1
This is true if the subkey is disabled.
@item unsigned int invalid : 1
This is true if the subkey is invalid.
@item unsigned int can_encrypt : 1
This is true if the subkey can be used for encryption.
@item unsigned int can_sign : 1
This is true if the subkey can be used for signing.
@item unsigned int can_certify : 1
This is true if the subkey can be used for certification.
@item unsigned int secret : 1
This is true if the subkey is a secret key.
@item GpgmePubKeyAlgo pubkey_algo
This is the public key algorithm supported by this subkey.
@item unsigned int length
This is the length of the subkey (in bits).
@item char *keyid
This is the key ID of the subkey in hexadecimal digits.
@item char *fpr
This is the fingerprint of the subkey in hexadecimal digits, if
available. This is usually only available for the primary key.
@item long int timestamp
This is the creation timestamp of the subkey. This is -1 if the
timestamp is invalid, and 0 if it is not available.
@item long int expires
This is the expiration timestamp of the subkey, or 0 if the subkey
does not expire.
@end table
@end deftp
@deftp {Data type} GpgmeKeySig
The @code{GpgmeKeySig} type is a pointer to a key signature structure.
Key signatures are one component of a @code{GpgmeKey} object, and
validate user IDs on the key.
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
enabled, because it is expensive to retrieve all signatures of a key.
The key signature structure has the following members:
@table @code
@item GpgmeKeySig next
This is a pointer to the next key signature structure in the linked
list, or @code{NULL} if this is the last element.
@item unsigned int revoked : 1
This is true if the key signature is a revocation signature.
@item unsigned int expired : 1
This is true if the key signature is expired.
@item unsigned int invalid : 1
This is true if the key signature is invalid.
@item unsigned int disabled : 1
This is true if the key signature is exportable.
@item GpgmePubKeyAlgo pubkey_algo
This is the public key algorithm used to create the signature.
@item char *keyid
This is the key ID of the key (in hexadecimal digits) used to create
the signature.
@item long int timestamp
This is the creation timestamp of the key signature. This is -1 if
the timestamp is invalid, and 0 if it is not available.
@item long int expires
This is the expiration timestamp of the key signature, or 0 if the key
signature does not expire.
@item GpgmeError status
This is the status of the signature and has the same meaning as the
member of the same name in a @code{GpgmeSignature} object.
@item unsigned int class
This specifies the signature class of the key signature. The meaning
is specific to the crypto engine.
@item char *uid
This is the main user ID of the key used to create the signature.
@item char *name
This is the name component of @code{uid}, if available.
@item char *comment
This is the comment component of @code{uid}, if available.
@item char *email
This is the email component of @code{uid}, if available.
@end table
@end deftp
@deftp {Data type} GpgmeUserID
A user ID is a component of a @code{GpgmeKey} object. One key can
have many user IDs. The first one in the list is the main (or
primary) user ID.
The user ID structure has the following members.
@table @code
@item GpgmeUserID next
This is a pointer to the next user ID structure in the linked list, or
@code{NULL} if this is the last element.
@item unsigned int revoked : 1
This is true if the user ID is revoked.
@item unsigned int invalid : 1
This is true if the user ID is invalid.
@item GpgmeValidity validity
This specifies the validity of the user ID.
@item char *uid
This is the user ID string.
@item char *name
This is the name component of @code{uid}, if available.
@item char *comment
This is the comment component of @code{uid}, if available.
@item char *email
This is the email component of @code{uid}, if available.
@item GpgmeKeySig signatures
This is a linked list with the signatures on this user ID.
@end table
@end deftp
@deftp {Data type} GpgmeKey
The @code{GpgmeKey} type is a pointer to a key object. It has the
following members:
@table @code
@item unsigned int revoked : 1
This is true if the key is revoked.
@item unsigned int expired : 1
This is true if the key is expired.
@item unsigned int disabled : 1
This is true if the key is disabled.
@item unsigned int invalid : 1
This is true if the key is invalid.
@item unsigned int can_encrypt : 1
This is true if the key (ie one of its subkeys) can be used for
encryption.
@item unsigned int can_sign : 1
This is true if the key (ie one of its subkeys) can be used for
signing.
@item unsigned int can_certify : 1
This is true if the key (ie one of its subkeys) can be used for
certification.
@item unsigned int secret : 1
This is true if the key is a secret key.
@item GpgmeProtocol protocol
This is the protocol supported by this key.
@item char *issuer_serial
If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the
issuer serial.
@item char *issuer_name
If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the
issuer name.
@item char *chain_id
If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the
chain ID, which can be used to built the certificate chain.
@item GpgmeValidity owner_trust
If @code{protocol} is @code{GPGME_PROTOCOL_OpenPGP}, then this is the
owner trust.
@item GpgmeSubkey subkeys
This is a linked list with the subkeys of the key. The first subkey
in the list is the primary key and usually available.
@item GpgmeUserID uids
This is a linked list with the user IDs of the key. The first user ID
in the list is the main (or primary) user ID.
@end table
@end deftp
@menu
@ -1880,6 +2103,10 @@ there is not enough memory for the operation.
The function @code{gpgme_op_keylist_next} ends a pending key list
operation in the context @var{ctx}.
After the operation completed successfully, the result of the key
listing operation can be retrieved with
@code{gpgme_op_keylist_result}.
The function returns @code{GPGME_Invalid_Value} if @var{ctx} is not a
valid pointer, and @code{GPGME_Out_Of_Core} if at some time during the
operation there was not enough memory available.
@ -1914,6 +2141,29 @@ if (err)
@}
@end example
@deftp {Data type} {GpgmeKeyListResult}
This is a pointer to a structure used to store the result of a
@code{gpgme_op_keylist_*} operation. After successfully ending a key
listing operation, you can retrieve the pointer to the result with
@code{gpgme_op_keylist_result}. The structure contains the following
member:
@table @code
@item unsigned int truncated : 1
This is true if the crypto backend had to truncate the result, and
less than the desired keys could be listed.
@end table
@end deftp
@deftypefun GpgmeKeyListResult gpgme_op_keylist_result (@w{GpgmeCtx @var{ctx}})
The function @code{gpgme_op_keylist_result} returns a
@code{GpgmeKeyListResult} pointer to a structure holding the result of
a @code{gpgme_op_keylist_*} operation. The pointer is only valid if
the last operation on the context was a key listing operation, and if
this operation finished successfully. The returned pointer is only
valid until the next operation is started on the context.
@end deftypefun
In a simple program, for which a blocking operation is acceptable, the
following function can be used to retrieve a single key.
@ -1939,14 +2189,44 @@ available.
@cindex key, attributes
@cindex attributes, of a key
@deftypefun {char *} gpgme_key_get_as_xml (@w{GpgmeKey @var{key}})
The function @code{gpgme_key_get_as_xml} returns a string in
@acronym{XML} format describing the key @var{key}. The user has to
release the string with @code{free}.
Please see the beginning of this section for more information about
@code{GpgmeKey} objects.
The function returns @code{NULL} if @var{key} is not a valid pointer,
or there is not enough memory available.
@end deftypefun
@deftp {Data type} GpgmeValidity
The @code{GpgmeValidity} type is used to specify the validity of a user ID
in a key. The following validities are defined:
@table @code
@item GPGME_VALIDITY_UNKNOWN
The user ID is of unknown validity. The string representation of this
validity is ``?''.
@item GPGME_VALIDITY_UNDEFINED
The validity of the user ID is undefined. The string representation of this
validity is ``q''.
@item GPGME_VALIDITY_NEVER
The user ID is never valid. The string representation of this
validity is ``n''.
@item GPGME_VALIDITY_MARGINAL
The user ID is marginally valid. The string representation of this
validity is ``m''.
@item GPGME_VALIDITY_FULL
The user ID is fully valid. The string representation of this
validity is ``f''.
@item GPGME_VALIDITY_ULTIMATE
The user ID is ultimately valid. The string representation of this
validity is ``u''.
@end table
@end deftp
The following interfaces are deprecated and only provided for backward
compatibility. Don't use them. They will be removed in a future
version of @acronym{GPGME}.
@deftp {Data type} GpgmeAttr
The @code{GpgmeAttr} type is used to specify a key or trust item
@ -2080,37 +2360,6 @@ is representable as a string.
@end table
@end deftp
@deftp {Data type} GpgmeValidity
The @code{GpgmeValidity} type is used to specify the validity of a user ID
in a key. The following validities are defined:
@table @code
@item GPGME_VALIDITY_UNKNOWN
The user ID is of unknown validity. The string representation of this
validity is ``?''.
@item GPGME_VALIDITY_UNDEFINED
The validity of the user ID is undefined. The string representation of this
validity is ``q''.
@item GPGME_VALIDITY_NEVER
The user ID is never valid. The string representation of this
validity is ``n''.
@item GPGME_VALIDITY_MARGINAL
The user ID is marginally valid. The string representation of this
validity is ``m''.
@item GPGME_VALIDITY_FULL
The user ID is fully valid. The string representation of this
validity is ``f''.
@item GPGME_VALIDITY_ULTIMATE
The user ID is ultimately valid. The string representation of this
validity is ``u''.
@end table
@end deftp
@deftypefun {const char *} gpgme_key_get_string_attr (@w{GpgmeKey @var{key}}, @w{GpgmeAttr @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}})
The function @code{gpgme_key_get_string_attr} returns the value of the
string-representable attribute @var{what} of key @var{key}. If the
@ -2145,6 +2394,10 @@ or @var{reserved} not @code{NULL}.
@cindex key, signatures
@cindex signatures, on a key
The following interfaces are deprecated and only provided for backward
compatibility. Don't use them. They will be removed in a future
version of @acronym{GPGME}.
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
enabled, because it is expensive to retrieve all signatures of a key.
@ -2253,12 +2506,18 @@ the key @var{key}.
@end deftypefun
@deftypefun void gpgme_key_unref (@w{GpgmeKey @var{key}})
@deftypefunx void gpgme_key_release (@w{GpgmeKey @var{key}})
The function @code{gpgme_key_unref} releases a reference for the key
@var{key}. If this was the last reference, the key will be destroyed
and all resources associated to it will be released.
@end deftypefun
The function @code{gpgme_key_release} is an alias for
The following interface is deprecated and only provided for backward
compatibility. Don't use it. It will be removed in a future version
of @acronym{GPGME}.
@deftypefun void gpgme_key_release (@w{GpgmeKey @var{key}})
The function @code{gpgme_key_release} is equivalent to
@code{gpgme_key_unref}.
@end deftypefun
@ -2610,10 +2869,10 @@ value of 2 refers to a user ID.
@item int level
This is the trust level.
@item char *otrust
@item char *owner_trust
The owner trust if @code{type} is 1.
@item char *val
@item char *validity
The calculated validity.
@item char *name

View File

@ -1,3 +1,42 @@
2003-04-30 Marcus Brinkmann <marcus@g10code.de>
* gpgme.h (struct _gpgme_key): New structure.
(GpgmeKey): Define using _gpgme_key.
(struct _gpgme_subkey): New structure.
(GpgmeSubKey): New type.
(struct _gpgme_key_sig): New structure.
(GpgmeKeySig): New type.
(struct _gpgme_user_id): New structure.
(GpgmeUserID): New type.
(struct _gpgme_op_keylist_result): New structure.
(GpgmeKeyListResult): New type.
(gpgme_op_keylist_result): New function.
(gpgme_key_get_as_xml): Remove prototype.
* context.h (struct gpgme_context_s): Remove members tmp_key,
tmp_uid, key_cond and key_queue.
(struct key_queue_item_s): Remove structure.
(struct user_id_s): Remove structure.
(struct gpgme_recipients_s): Replace with simple
GpgmeUserID list.
* gpgme.c (gpgme_release): Do not release CTX->tmp_key.
* ops.h (_gpgme_key_add_subkey, _gpgme_key_append_name,
_gpgme_key_add_sig, _gpgme_trust_item_new): New prototypes.
* rungpg.c (command_cb): Return GpgmeError instead int.
New variable ERR. Use it to hold return value of cmd handler.
(gpg_delete): Access fingerprint of key directly.
(append_args_from_signers): Likewise.
(gpg_edit): Likewise.
(append_args_from_recipients): Use GpgmeUserID for recipient list.
* engine-gpgsm.c: Do not include "key.h".
(gpgsm_delete): Access fingerprint of key directly.
(gpgsm_sign): Likewise.
(set_recipients): Use GpgmeUserID for recipients. Invert invalid
user ID flag.
* key.h: File removed.
* key.c: Completely reworked to use exposed GpgmeKey data types.
* keylist.c: Likewise.
* recipient.c: Completely reworked to use GpgmeUserID.
2003-04-29 Marcus Brinkmann <marcus@g10code.de>
* gpgme.h (gpgme_get_key): Remove force_update argument.

View File

@ -56,15 +56,8 @@ struct ctx_op_data
};
struct key_queue_item_s
{
struct key_queue_item_s *next;
GpgmeKey key;
};
/* Currently we need it at several places, so we put the definition
into this header file. */
/* The context defines an environment in which crypto operations can
be performed (sequentially). */
struct gpgme_context_s
{
/* The protocol used by this context. */
@ -98,13 +91,6 @@ struct gpgme_context_s
/* Last operation info. */
GpgmeData op_info;
/* Used by keylist.c. */
GpgmeKey tmp_key;
struct user_id_s *tmp_uid;
/* Something new is available. */
volatile int key_cond;
struct key_queue_item_s *key_queue;
/* The user provided passphrase callback and its hook value. */
GpgmePassphraseCb passphrase_cb;
void *passphrase_cb_value;
@ -119,31 +105,12 @@ struct gpgme_context_s
struct GpgmeIOCbs io_cbs;
};
/* Forward declaration of a structure to store certification
signatures. */
struct certsig_s;
/* Structure to store user IDs. */
struct user_id_s
{
struct user_id_s *next;
unsigned int revoked : 1;
unsigned int invalid : 1;
GpgmeValidity validity;
struct certsig_s *certsigs;
struct certsig_s *last_certsig;
const char *name_part; /* All 3 point into strings behind name */
const char *email_part; /* or to read-only strings. */
const char *comment_part;
char name[1];
};
/* A recipient is defined by a user ID, but we define it as an opaque
type for the user. */
struct gpgme_recipients_s
{
struct user_id_s *list;
int checked; /* Whether the recipients are all valid. */
GpgmeUserID list;
};
#endif /* CONTEXT_H */

View File

@ -35,7 +35,6 @@
#include "ops.h"
#include "wait.h"
#include "io.h"
#include "key.h"
#include "sema.h"
#include "assuan.h"
@ -873,7 +872,7 @@ gpgsm_delete (void *engine, GpgmeKey key, int allow_secret)
{
GpgsmObject gpgsm = engine;
GpgmeError err;
char *fpr = (char *) gpgme_key_get_string_attr (key, GPGME_ATTR_FPR, NULL, 0);
char *fpr = key->subkeys ? key->subkeys->fpr : NULL;
char *linep = fpr;
char *line;
int length = 8; /* "DELKEYS " */
@ -942,17 +941,17 @@ set_recipients (GpgsmObject gpgsm, GpgmeRecipients recp)
ASSUAN_CONTEXT ctx = gpgsm->assuan_ctx;
char *line;
int linelen;
struct user_id_s *r;
int valid_recipients = 0;
GpgmeUserID uid;
int invalid_recipients = 0;
linelen = 10 + 40 + 1; /* "RECIPIENT " + guess + '\0'. */
line = malloc (10 + 40 + 1);
if (!line)
return GPGME_Out_Of_Core;
strcpy (line, "RECIPIENT ");
for (r = recp->list; r; r = r->next)
for (uid = recp->list; uid; uid = uid->next)
{
int newlen = 11 + strlen (r->name);
int newlen = 11 + strlen (uid->uid);
if (linelen < newlen)
{
char *newline = realloc (line, newlen);
@ -964,22 +963,20 @@ set_recipients (GpgsmObject gpgsm, GpgmeRecipients recp)
line = newline;
linelen = newlen;
}
strcpy (&line[10], r->name);
strcpy (&line[10], uid->uid);
err = gpgsm_assuan_simple_command (ctx, line, gpgsm->status.fnc,
gpgsm->status.fnc_value);
if (!err)
valid_recipients = 1;
else if (err != GPGME_Invalid_Key)
if (err == GPGME_Invalid_Key)
invalid_recipients = 1;
else if (err)
{
free (line);
return err;
}
}
free (line);
if (!valid_recipients && gpgsm->status.fnc)
gpgsm->status.fnc (gpgsm->status.fnc_value, GPGME_STATUS_NO_RECP, "");
return 0;
return invalid_recipients ? GPGME_Invalid_UserID : 0;
}
@ -1302,8 +1299,7 @@ gpgsm_sign (void *engine, GpgmeData in, GpgmeData out, GpgmeSigMode mode,
for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
{
const char *s = gpgme_key_get_string_attr (key, GPGME_ATTR_FPR,
NULL, 0);
const char *s = key->subkeys ? key->subkeys->fpr : NULL;
if (s && strlen (s) < 80)
{
char buf[100];

View File

@ -67,11 +67,9 @@ gpgme_release (GpgmeCtx ctx)
_gpgme_engine_release (ctx->engine);
_gpgme_fd_table_deinit (&ctx->fdt);
_gpgme_release_result (ctx);
gpgme_key_release (ctx->tmp_key);
gpgme_signers_clear (ctx);
if (ctx->signers)
free (ctx->signers);
/* FIXME: Release the key_queue. */
free (ctx);
}

View File

@ -63,10 +63,8 @@ typedef struct gpgme_data_s *GpgmeData;
struct gpgme_recipients_s;
typedef struct gpgme_recipients_s *GpgmeRecipients;
/* A key from the keyring. */
struct gpgme_key_s;
typedef struct gpgme_key_s *GpgmeKey;
/* Public data types provided by GPGME. */
/* The error numbers used by GPGME. */
typedef enum
@ -343,6 +341,7 @@ typedef enum
}
GpgmeStatusCode;
/* The engine information structure. */
struct _gpgme_engine_info
{
@ -362,7 +361,221 @@ struct _gpgme_engine_info
};
typedef struct _gpgme_engine_info *GpgmeEngineInfo;
/* A subkey from a key. */
struct _gpgme_subkey
{
struct _gpgme_subkey *next;
/* True if subkey is revoked. */
unsigned int revoked : 1;
/* True if subkey is expired. */
unsigned int expired : 1;
/* True if subkey is disabled. */
unsigned int disabled : 1;
/* True if subkey is invalid. */
unsigned int invalid : 1;
/* True if subkey can be used for encryption. */
unsigned int can_encrypt : 1;
/* True if subkey can be used for signing. */
unsigned int can_sign : 1;
/* True if subkey can be used for certification. */
unsigned int can_certify : 1;
/* True if subkey is secret. */
unsigned int secret : 1;
/* Internal to GPGME, do not use. */
unsigned int _unused : 24;
/* Public key algorithm supported by this subkey. */
GpgmePubKeyAlgo pubkey_algo;
/* Length of the subkey. */
unsigned int length;
/* The key ID of the subkey. */
char *keyid;
/* Internal to GPGME, do not use. */
char _keyid[16 + 1];
/* The fingerprint of the subkey in hex digit form. */
char *fpr;
/* The creation timestamp, -1 if invalid, 0 if not available. */
long int timestamp;
/* The expiration timestamp, 0 if the subkey does not expire. */
long int expires;
};
typedef struct _gpgme_subkey *GpgmeSubkey;
/* A signature on a user ID. */
struct _gpgme_key_sig
{
struct _gpgme_key_sig *next;
/* True if the signature is revoked. */
unsigned int revoked : 1;
/* True if the signature is expired. */
unsigned int expired : 1;
/* True if the signature is invalid. */
unsigned int invalid : 1;
/* True if the signature should be exported. */
unsigned int exportable : 1;
/* Internal to GPGME, do not use. */
unsigned int _unused : 28;
/* The public key algorithm used to create the signature. */
GpgmePubKeyAlgo pubkey_algo;
/* The key ID of key used to create the signature. */
char *keyid;
/* Internal to GPGME, do not use. */
char _keyid[16 + 1];
/* The creation timestamp, -1 if invalid, 0 if not available. */
long int timestamp;
/* The expiration timestamp, 0 if the subkey does not expire. */
long int expires;
/* Same as in GpgmeSignature. */
GpgmeError status;
/* Crypto backend specific signature class. */
unsigned int class;
/* The user ID string. */
char *uid;
/* The name part of the user ID. */
char *name;
/* The email part of the user ID. */
char *email;
/* The comment part of the user ID. */
char *comment;
};
typedef struct _gpgme_key_sig *GpgmeKeySig;
/* An user ID from a key. */
struct _gpgme_user_id
{
struct _gpgme_user_id *next;
/* True if the user ID is revoked. */
unsigned int revoked : 1;
/* True if the user ID is invalid. */
unsigned int invalid : 1;
/* Internal to GPGME, do not use. */
unsigned int _unused : 30;
/* The validity of the user ID. */
GpgmeValidity validity;
/* The user ID string. */
char *uid;
/* The name part of the user ID. */
char *name;
/* The email part of the user ID. */
char *email;
/* The comment part of the user ID. */
char *comment;
/* The signatures of the user ID. */
GpgmeKeySig signatures;
/* Internal to GPGME, do not use. */
GpgmeKeySig _last_keysig;
};
typedef struct _gpgme_user_id *GpgmeUserID;
/* A key from the keyring. */
struct _gpgme_key
{
/* Internal to GPGME, do not use. */
unsigned int _refs;
/* True if key is revoked. */
unsigned int revoked : 1;
/* True if key is expired. */
unsigned int expired : 1;
/* True if key is disabled. */
unsigned int disabled : 1;
/* True if key is invalid. */
unsigned int invalid : 1;
/* True if key can be used for encryption. */
unsigned int can_encrypt : 1;
/* True if key can be used for signing. */
unsigned int can_sign : 1;
/* True if key can be used for certification. */
unsigned int can_certify : 1;
/* True if key is secret. */
unsigned int secret : 1;
/* Internal to GPGME, do not use. */
unsigned int _unused : 24;
/* This is the protocol supported by this key. */
GpgmeProtocol protocol;
/* If protocol is GPGME_PROTOCOL_CMS, this string contains the
issuer serial. */
char *issuer_serial;
/* If protocol is GPGME_PROTOCOL_CMS, this string contains the
issuer name. */
char *issuer_name;
/* If protocol is GPGME_PROTOCOL_CMS, this string contains the chain
ID. */
char *chain_id;
/* If protocol is GPGME_PROTOCOL_OpenPGP, this field contains the
owner trust. */
GpgmeValidity owner_trust;
/* The subkeys of the key. */
GpgmeSubkey subkeys;
/* The user IDs of the key. */
GpgmeUserID uids;
/* Internal to GPGME, do not use. */
GpgmeSubkey _last_subkey;
/* Internal to GPGME, do not use. */
GpgmeUserID _last_uid;
};
typedef struct _gpgme_key *GpgmeKey;
/* Types for callback functions. */
/* Request a passphrase from the user. */
@ -693,10 +906,6 @@ void gpgme_key_ref (GpgmeKey key);
void gpgme_key_unref (GpgmeKey key);
void gpgme_key_release (GpgmeKey key);
/* Get the data from key KEY in a XML string, which has to be released
with free by the user. */
char *gpgme_key_get_as_xml (GpgmeKey key);
/* Return the value of the attribute WHAT of KEY, which has to be
representable by a string. IDX specifies the sub key or
user ID for attributes related to sub keys or user IDs. */
@ -1045,7 +1254,19 @@ GpgmeError gpgme_op_edit (GpgmeCtx ctx, GpgmeKey key,
GpgmeEditCb fnc, void *fnc_value,
GpgmeData out);
/* Key management functions */
struct _gpgme_op_keylist_result
{
unsigned int truncated : 1;
/* Internal to GPGME, do not use. */
unsigned int _unused : 31;
};
typedef struct _gpgme_op_keylist_result *GpgmeKeyListResult;
/* Retrieve a pointer to the result of the key listing operation. */
GpgmeKeyListResult gpgme_op_keylist_result (GpgmeCtx ctx);
/* Start a keylist operation within CTX, searching for keys which
match PATTERN. If SECRET_ONLY is true, only secret keys are
@ -1082,16 +1303,16 @@ struct _gpgme_trust_item
int level;
/* The owner trust if TYPE is 1. */
char *otrust;
char *owner_trust;
/* Internal to GPGME, do not use. */
char _otrust[2];
char _owner_trust[2];
/* The calculated validity. */
char *val;
char *validity;
/* Internal to GPGME, do not use. */
char _val[2];
char _validity[2];
/* The user name if TYPE is 2. */
char *name;

File diff suppressed because it is too large Load Diff

View File

@ -28,89 +28,80 @@
#include <assert.h>
#include <ctype.h>
#include "gpgme.h"
#include "util.h"
#include "context.h"
#include "ops.h"
#include "key.h"
#include "debug.h"
struct keylist_result
struct key_queue_item_s
{
int truncated;
GpgmeData xmlinfo;
struct key_queue_item_s *next;
GpgmeKey key;
};
typedef struct keylist_result *KeylistResult;
typedef struct
{
struct _gpgme_op_keylist_result result;
GpgmeKey tmp_key;
GpgmeUserID tmp_uid;
/* Something new is available. */
int key_cond;
struct key_queue_item_s *key_queue;
} *op_data_t;
static void
release_keylist_result (void *hook)
release_op_data (void *hook)
{
KeylistResult result = (KeylistResult) hook;
op_data_t opd = (op_data_t) hook;
struct key_queue_item_s *key = opd->key_queue;
if (result->xmlinfo)
gpgme_data_release (result->xmlinfo);
if (opd->tmp_key)
gpgme_key_unref (opd->tmp_key);
if (opd->tmp_uid)
free (opd->tmp_uid);
while (key)
{
struct key_queue_item_s *next = key->next;
gpgme_key_unref (key->key);
key = next;
}
}
/* Append some XML info. args is currently ignore but we might want
to add more information in the future (like source of the
keylisting. With args of NULL the XML structure is closed. */
static void
append_xml_keylistinfo (GpgmeData *rdh, char *args)
{
GpgmeData dh;
if (!*rdh)
{
if (gpgme_data_new (rdh))
return; /* FIXME: We are ignoring out-of-core. */
dh = *rdh;
_gpgme_data_append_string (dh, "<GnupgOperationInfo>\n");
}
else
{
dh = *rdh;
_gpgme_data_append_string (dh, " </keylisting>\n");
}
if (!args)
{
/* Just close the XML containter. */
_gpgme_data_append_string (dh, "</GnupgOperationInfo>\n");
return;
}
_gpgme_data_append_string (dh, " <keylisting>\n <truncated/>\n");
}
static GpgmeError
keylist_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
GpgmeKeyListResult
gpgme_op_keylist_result (GpgmeCtx ctx)
{
op_data_t opd;
GpgmeError err;
KeylistResult result;
err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &result,
sizeof (*result), release_keylist_result);
err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &opd, -1, NULL);
if (err || !opd)
return NULL;
return &opd->result;
}
static GpgmeError
keylist_status_handler (void *priv, GpgmeStatusCode code, char *args)
{
GpgmeCtx ctx = (GpgmeCtx) priv;
GpgmeError err;
op_data_t opd;
err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &opd, -1, NULL);
if (err)
return err;
switch (code)
{
case GPGME_STATUS_TRUNCATED:
result->truncated = 1;
break;
case GPGME_STATUS_EOF:
if (result->truncated)
append_xml_keylistinfo (&result->xmlinfo, "1");
if (result->xmlinfo)
{
append_xml_keylistinfo (&result->xmlinfo, NULL);
_gpgme_set_op_info (ctx, result->xmlinfo);
result->xmlinfo = NULL;
}
opd->result.truncated = 1;
break;
default:
@ -139,21 +130,21 @@ set_mainkey_trust_info (GpgmeKey key, const char *src)
switch (*src)
{
case 'e':
key->keys.flags.expired = 1;
key->subkeys->expired = 1;
break;
case 'r':
key->keys.flags.revoked = 1;
key->subkeys->revoked = 1;
break;
case 'd':
/* Note that gpg 1.3 won't print that anymore but only uses
the capabilities field. */
key->keys.flags.disabled = 1;
key->subkeys->disabled = 1;
break;
case 'i':
key->keys.flags.invalid = 1;
key->subkeys->invalid = 1;
break;
}
src++;
@ -164,7 +155,7 @@ set_mainkey_trust_info (GpgmeKey key, const char *src)
static void
set_userid_flags (GpgmeKey key, const char *src)
{
struct user_id_s *uid = key->last_uid;
GpgmeUserID uid = key->_last_uid;
assert (uid);
/* Look at letters and stop at the first digit. */
@ -202,7 +193,7 @@ set_userid_flags (GpgmeKey key, const char *src)
static void
set_subkey_trust_info (struct subkey_s *subkey, const char *src)
set_subkey_trust_info (GpgmeSubkey subkey, const char *src)
{
/* Look at letters and stop at the first digit. */
while (*src && !isdigit (*src))
@ -210,19 +201,19 @@ set_subkey_trust_info (struct subkey_s *subkey, const char *src)
switch (*src)
{
case 'e':
subkey->flags.expired = 1;
subkey->expired = 1;
break;
case 'r':
subkey->flags.revoked = 1;
subkey->revoked = 1;
break;
case 'd':
subkey->flags.disabled = 1;
subkey->disabled = 1;
break;
case 'i':
subkey->flags.invalid = 1;
subkey->invalid = 1;
break;
}
src++;
@ -238,15 +229,15 @@ set_mainkey_capability (GpgmeKey key, const char *src)
switch (*src)
{
case 'e':
key->keys.flags.can_encrypt = 1;
key->subkeys->can_encrypt = 1;
break;
case 's':
key->keys.flags.can_sign = 1;
key->subkeys->can_sign = 1;
break;
case 'c':
key->keys.flags.can_certify = 1;
key->subkeys->can_certify = 1;
break;
case 'd':
@ -256,19 +247,19 @@ set_mainkey_capability (GpgmeKey key, const char *src)
and D, so that a future gpg version will be able to
disable certain subkeys. Currently it is expected that
gpg sets this for the primary key. */
key->keys.flags.disabled = 1;
key->subkeys->disabled = 1;
break;
case 'E':
key->gloflags.can_encrypt = 1;
key->can_encrypt = 1;
break;
case 'S':
key->gloflags.can_sign = 1;
key->can_sign = 1;
break;
case 'C':
key->gloflags.can_certify = 1;
key->can_certify = 1;
break;
}
src++;
@ -277,22 +268,22 @@ set_mainkey_capability (GpgmeKey key, const char *src)
static void
set_subkey_capability (struct subkey_s *subkey, const char *src)
set_subkey_capability (GpgmeSubkey subkey, const char *src)
{
while (*src)
{
switch (*src)
{
case 'e':
subkey->flags.can_encrypt = 1;
subkey->can_encrypt = 1;
break;
case 's':
subkey->flags.can_sign = 1;
subkey->can_sign = 1;
break;
case 'c':
subkey->flags.can_certify = 1;
subkey->can_certify = 1;
break;
}
src++;
@ -308,23 +299,23 @@ set_ownertrust (GpgmeKey key, const char *src)
switch (*src)
{
case 'n':
key->otrust = GPGME_VALIDITY_NEVER;
key->owner_trust = GPGME_VALIDITY_NEVER;
break;
case 'm':
key->otrust = GPGME_VALIDITY_MARGINAL;
key->owner_trust = GPGME_VALIDITY_MARGINAL;
break;
case 'f':
key->otrust = GPGME_VALIDITY_FULL;
key->owner_trust = GPGME_VALIDITY_FULL;
break;
case 'u':
key->otrust = GPGME_VALIDITY_ULTIMATE;
key->owner_trust = GPGME_VALIDITY_ULTIMATE;
break;
default:
key->otrust = GPGME_VALIDITY_UNKNOWN;
key->owner_trust = GPGME_VALIDITY_UNKNOWN;
break;
}
src++;
@ -332,14 +323,14 @@ set_ownertrust (GpgmeKey key, const char *src)
}
/* We have read an entire key into ctx->tmp_key and should now finish
it. It is assumed that this releases ctx->tmp_key. */
/* We have read an entire key into tmp_key and should now finish it.
It is assumed that this releases tmp_key. */
static void
finish_key (GpgmeCtx ctx)
finish_key (GpgmeCtx ctx, op_data_t opd)
{
GpgmeKey key = ctx->tmp_key;
GpgmeKey key = opd->tmp_key;
ctx->tmp_key = NULL;
opd->tmp_key = NULL;
if (key)
_gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
@ -348,28 +339,37 @@ finish_key (GpgmeCtx ctx)
/* Note: We are allowed to modify LINE. */
static GpgmeError
keylist_colon_handler (GpgmeCtx ctx, char *line)
keylist_colon_handler (void *priv, char *line)
{
GpgmeCtx ctx = (GpgmeCtx) priv;
enum
{
RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR, RT_SSB, RT_SEC,
RT_CRT, RT_CRS, RT_REV
RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR,
RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV
}
rectype = RT_NONE;
#define NR_FIELDS 13
char *field[NR_FIELDS];
int fields = 0;
GpgmeKey key = ctx->tmp_key;
struct subkey_s *subkey = NULL;
struct certsig_s *certsig = NULL;
op_data_t opd;
GpgmeError err;
GpgmeKey key;
GpgmeSubkey subkey = NULL;
GpgmeKeySig keysig = NULL;
DEBUG3 ("keylist_colon_handler ctx = %p, key = %p, line = %s\n",
ctx, key, line ? line : "(null)");
err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &opd, -1, NULL);
if (err)
return err;
key = opd->tmp_key;
if (!line)
{
/* End Of File. */
finish_key (ctx);
finish_key (ctx, opd);
return 0;
}
@ -385,67 +385,22 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
rectype = RT_SIG;
else if (!strcmp (field[0], "rev"))
rectype = RT_REV;
else if (!strcmp (field[0], "pub"))
rectype = RT_PUB;
else if (!strcmp (field[0], "sec"))
rectype = RT_SEC;
else if (!strcmp (field[0], "crt"))
rectype = RT_CRT;
else if (!strcmp (field[0], "crs"))
rectype = RT_CRS;
else if (!strcmp (field[0], "fpr") && key)
rectype = RT_FPR;
else if (!strcmp (field[0], "uid") && key)
rectype = RT_UID;
else if (!strcmp (field[0], "sub") && key)
{
/* Start a new subkey. */
rectype = RT_SUB;
if (!(subkey = _gpgme_key_add_subkey (key)))
return GPGME_Out_Of_Core;
}
rectype = RT_SUB;
else if (!strcmp (field[0], "ssb") && key)
{
/* Start a new secret subkey. */
rectype = RT_SSB;
if (!(subkey = _gpgme_key_add_secret_subkey (key)))
return GPGME_Out_Of_Core;
}
else if (!strcmp (field[0], "pub"))
{
/* Start a new keyblock. */
if (_gpgme_key_new (&key))
/* The only kind of error we can get. */
return GPGME_Out_Of_Core;
rectype = RT_PUB;
finish_key (ctx);
assert (!ctx->tmp_key);
ctx->tmp_key = key;
}
else if (!strcmp (field[0], "sec"))
{
/* Start a new keyblock, */
if (_gpgme_key_new_secret (&key))
return GPGME_Out_Of_Core;
rectype = RT_SEC;
finish_key (ctx);
assert (!ctx->tmp_key);
ctx->tmp_key = key;
}
else if (!strcmp (field[0], "crt"))
{
/* Start a new certificate. */
if (_gpgme_key_new (&key))
return GPGME_Out_Of_Core;
key->x509 = 1;
rectype = RT_CRT;
finish_key (ctx);
assert (!ctx->tmp_key);
ctx->tmp_key = key;
}
else if (!strcmp (field[0], "crs"))
{
/* Start a new certificate. */
if (_gpgme_key_new_secret (&key))
return GPGME_Out_Of_Core;
key->x509 = 1;
rectype = RT_CRS;
finish_key (ctx);
assert (!ctx->tmp_key);
ctx->tmp_key = key;
}
else if (!strcmp (field[0], "fpr") && key)
rectype = RT_FPR;
rectype = RT_SSB;
else
rectype = RT_NONE;
@ -453,29 +408,32 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
this, clear the user ID pointer when encountering anything but a
signature. */
if (rectype != RT_SIG && rectype != RT_REV)
ctx->tmp_uid = NULL;
opd->tmp_uid = NULL;
switch (rectype)
{
case RT_CRT:
case RT_CRS:
/* Field 8 has the X.509 serial number. */
if (fields >= 8)
{
key->issuer_serial = strdup (field[7]);
if (!key->issuer_serial)
return GPGME_Out_Of_Core;
}
/* Field 10 is not used for gpg due to --fixed-list-mode option
but GPGSM stores the issuer name. */
if (fields >= 10 && _gpgme_decode_c_string (field[9],
&key->issuer_name, 0))
return GPGME_Out_Of_Core;
/* Fall through! */
case RT_PUB:
case RT_SEC:
case RT_CRT:
case RT_CRS:
/* Start a new keyblock. */
err = _gpgme_key_new (&key);
if (err)
return err;
err = _gpgme_key_add_subkey (key, &subkey);
if (err)
{
gpgme_key_unref (key);
return err;
}
if (rectype == RT_SEC || rectype == RT_CRS)
key->secret = 1;
if (rectype == RT_CRT || rectype == RT_CRS)
key->protocol = GPGME_PROTOCOL_CMS;
finish_key (ctx, opd);
opd->tmp_key = key;
/* Field 2 has the trust info. */
if (fields >= 2)
set_mainkey_trust_info (key, field[1]);
@ -486,7 +444,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
int i = atoi (field[2]);
/* Ignore invalid values. */
if (i > 1)
key->keys.key_len = i;
subkey->length = i;
}
/* Field 4 has the public key algorithm. */
@ -494,25 +452,39 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
{
int i = atoi (field[3]);
if (i >= 1 && i < 128)
key->keys.key_algo = i;
subkey->pubkey_algo = i;
}
/* Field 5 has the long keyid. */
if (fields >= 5 && strlen (field[4]) == DIM(key->keys.keyid) - 1)
strcpy (key->keys.keyid, field[4]);
if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
strcpy (subkey->_keyid, field[4]);
/* Field 6 has the timestamp (seconds). */
if (fields >= 6)
key->keys.timestamp = parse_timestamp (field[5]);
subkey->timestamp = parse_timestamp (field[5]);
/* Field 7 has the expiration time (seconds). */
if (fields >= 7)
key->keys.expires_at = parse_timestamp (field[6]);
subkey->expires = parse_timestamp (field[6]);
/* Field 8 has the X.509 serial number. */
if (fields >= 8 && (rectype == RT_CRT || rectype == RT_CRS))
{
key->issuer_serial = strdup (field[7]);
if (!key->issuer_serial)
return GPGME_Out_Of_Core;
}
/* Field 9 has the ownertrust. */
if (fields >= 9)
set_ownertrust (key, field[8]);
/* Field 10 is not used for gpg due to --fixed-list-mode option
but GPGSM stores the issuer name. */
if (fields >= 10 && (rectype == RT_CRT || rectype == RT_CRS))
if (_gpgme_decode_c_string (field[9], &key->issuer_name, 0))
return GPGME_Out_Of_Core;
/* Field 11 has the signature class. */
/* Field 12 has the capabilities. */
@ -522,6 +494,14 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
case RT_SUB:
case RT_SSB:
/* Start a new subkey. */
err = _gpgme_key_add_subkey (key, &subkey);
if (err)
return err;
if (rectype == RT_SSB)
subkey->secret = 1;
/* Field 2 has the trust info. */
if (fields >= 2)
set_subkey_trust_info (subkey, field[1]);
@ -532,7 +512,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
int i = atoi (field[2]);
/* Ignore invalid values. */
if (i > 1)
subkey->key_len = i;
subkey->length = i;
}
/* Field 4 has the public key algorithm. */
@ -540,12 +520,12 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
{
int i = atoi (field[3]);
if (i >= 1 && i < 128)
subkey->key_algo = i;
subkey->pubkey_algo = i;
}
/* Field 5 has the long keyid. */
if (fields >= 5 && strlen (field[4]) == DIM(subkey->keyid) - 1)
strcpy (subkey->keyid, field[4]);
if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
strcpy (subkey->_keyid, field[4]);
/* Field 6 has the timestamp (seconds). */
if (fields >= 6)
@ -553,7 +533,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
/* Field 7 has the expiration time (seconds). */
if (fields >= 7)
subkey->expires_at = parse_timestamp (field[6]);
subkey->expires = parse_timestamp (field[6]);
/* Field 8 is reserved (LID). */
/* Field 9 has the ownertrust. */
@ -576,17 +556,17 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
{
if (field[1])
set_userid_flags (key, field[1]);
ctx->tmp_uid = key->last_uid;
opd->tmp_uid = key->_last_uid;
}
}
break;
case RT_FPR:
/* Field 10 has the fingerprint (take only the first one). */
if (fields >= 10 && !key->keys.fingerprint && field[9] && *field[9])
if (fields >= 10 && !key->subkeys->fpr && field[9] && *field[9])
{
key->keys.fingerprint = strdup (field[9]);
if (!key->keys.fingerprint)
key->subkeys->fpr = strdup (field[9]);
if (!key->subkeys->fpr)
return GPGME_Out_Of_Core;
}
@ -601,13 +581,13 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
case RT_SIG:
case RT_REV:
if (!ctx->tmp_uid)
if (!opd->tmp_uid)
return 0;
/* Start a new (revoked) signature. */
assert (ctx->tmp_uid == key->last_uid);
certsig = _gpgme_key_add_certsig (key, (fields >= 10) ? field[9] : NULL);
if (!certsig)
assert (opd->tmp_uid == key->_last_uid);
keysig = _gpgme_key_add_sig (key, (fields >= 10) ? field[9] : NULL);
if (!keysig)
return GPGME_Out_Of_Core;
/* Field 2 has the calculated trust ('!', '-', '?', '%'). */
@ -615,23 +595,23 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
switch (field[1][0])
{
case '!':
certsig->sig_stat = GPGME_SIG_STAT_GOOD;
keysig->status = GPGME_No_Error;
break;
case '-':
certsig->sig_stat = GPGME_SIG_STAT_BAD;
keysig->status = GPGME_Bad_Signature;
break;
case '?':
certsig->sig_stat = GPGME_SIG_STAT_NOKEY;
keysig->status = GPGME_No_Public_Key;
break;
case '%':
certsig->sig_stat = GPGME_SIG_STAT_ERROR;
keysig->status = GPGME_General_Error;
break;
default:
certsig->sig_stat = GPGME_SIG_STAT_NONE;
keysig->status = GPGME_No_Error;
break;
}
@ -640,20 +620,20 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
{
int i = atoi (field[3]);
if (i >= 1 && i < 128)
certsig->algo = i;
keysig->pubkey_algo = i;
}
/* Field 5 has the long keyid. */
if (fields >= 5 && strlen (field[4]) == DIM(certsig->keyid) - 1)
strcpy (certsig->keyid, field[4]);
if (fields >= 5 && strlen (field[4]) == DIM(keysig->_keyid) - 1)
strcpy (keysig->_keyid, field[4]);
/* Field 6 has the timestamp (seconds). */
if (fields >= 6)
certsig->timestamp = parse_timestamp (field[5]);
keysig->timestamp = parse_timestamp (field[5]);
/* Field 7 has the expiration time (seconds). */
if (fields >= 7)
certsig->expires_at = parse_timestamp (field[6]);
keysig->expires = parse_timestamp (field[6]);
/* Field 11 has the signature class (eg, 0x30 means revoked). */
if (fields >= 11)
@ -662,12 +642,12 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
int class = _gpgme_hextobyte (field[10]);
if (class >= 0)
{
certsig->sig_class = class;
keysig->class = class;
if (class == 0x30)
certsig->flags.revoked = 1;
keysig->revoked = 1;
}
if (field[10][2] == 'x')
certsig->flags.exportable = 1;
keysig->exportable = 1;
}
break;
@ -682,162 +662,134 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
void
_gpgme_op_keylist_event_cb (void *data, GpgmeEventIO type, void *type_data)
{
GpgmeError err;
GpgmeCtx ctx = (GpgmeCtx) data;
GpgmeKey key = (GpgmeKey) type_data;
op_data_t opd;
struct key_queue_item_s *q, *q2;
assert (type == GPGME_EVENT_NEXT_KEY);
err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &opd, -1, NULL);
if (err)
return;
q = malloc (sizeof *q);
if (!q)
{
gpgme_key_release (key);
gpgme_key_unref (key);
/* FIXME return GPGME_Out_Of_Core; */
return;
}
q->key = key;
q->next = NULL;
/* FIXME: Lock queue. Use a tail pointer? */
if (!(q2 = ctx->key_queue))
ctx->key_queue = q;
/* FIXME: Use a tail pointer? */
if (!(q2 = opd->key_queue))
opd->key_queue = q;
else
{
for (; q2->next; q2 = q2->next)
;
q2->next = q;
}
ctx->key_cond = 1;
/* FIXME: Unlock queue. */
opd->key_cond = 1;
}
/**
* gpgme_op_keylist_start:
* @c: context
* @pattern: a GnuPG user ID or NULL for all
* @secret_only: List only keys where the secret part is available
*
* Note that this function also cancels a pending key listing
* operaton. To actually retrieve the key, use
* gpgme_op_keylist_next().
*
* Return value: 0 on success or an errorcode.
**/
/* Start a keylist operation within CTX, searching for keys which
match PATTERN. If SECRET_ONLY is true, only secret keys are
returned. */
GpgmeError
gpgme_op_keylist_start (GpgmeCtx ctx, const char *pattern, int secret_only)
{
GpgmeError err = 0;
GpgmeError err;
op_data_t opd;
err = _gpgme_op_reset (ctx, 2);
if (err)
goto leave;
return err;
gpgme_key_release (ctx->tmp_key);
ctx->tmp_key = NULL;
/* Fixme: Release key_queue. */
err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &opd,
sizeof (*opd), release_op_data);
if (err)
return err;
_gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
err = _gpgme_engine_set_colon_line_handler (ctx->engine,
keylist_colon_handler, ctx);
if (err)
goto leave;
return err;
err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
ctx->keylist_mode);
leave:
if (err)
{
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
}
return err;
return _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
ctx->keylist_mode);
}
/**
* gpgme_op_keylist_ext_start:
* @c: context
* @pattern: a NULL terminated array of search patterns
* @secret_only: List only keys where the secret part is available
* @reserved: Should be 0.
*
* Note that this function also cancels a pending key listing
* operaton. To actually retrieve the key, use
* gpgme_op_keylist_next().
*
* Return value: 0 on success or an errorcode.
**/
/* Start a keylist operation within CTX, searching for keys which
match PATTERN. If SECRET_ONLY is true, only secret keys are
returned. */
GpgmeError
gpgme_op_keylist_ext_start (GpgmeCtx ctx, const char *pattern[],
int secret_only, int reserved)
{
GpgmeError err = 0;
GpgmeError err;
op_data_t opd;
err = _gpgme_op_reset (ctx, 2);
if (err)
goto leave;
return err;
gpgme_key_release (ctx->tmp_key);
ctx->tmp_key = NULL;
err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &opd,
sizeof (*opd), release_op_data);
if (err)
return err;
_gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
err = _gpgme_engine_set_colon_line_handler (ctx->engine,
keylist_colon_handler, ctx);
if (err)
goto leave;
return err;
err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
reserved, ctx->keylist_mode);
leave:
if (err)
{
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
}
return err;
return _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
reserved, ctx->keylist_mode);
}
/**
* gpgme_op_keylist_next:
* @c: Context
* @r_key: Returned key object
*
* Return the next key from the key listing started with
* gpgme_op_keylist_start(). The caller must free the key using
* gpgme_key_release(). If the last key has already been returned the
* last time the function was called, %GPGME_EOF is returned and the
* operation is finished.
*
* Return value: 0 on success, %GPGME_EOF or another error code.
**/
/* Return the next key from the keylist in R_KEY. */
GpgmeError
gpgme_op_keylist_next (GpgmeCtx ctx, GpgmeKey *r_key)
{
GpgmeError err;
struct key_queue_item_s *queue_item;
op_data_t opd;
if (!r_key)
if (!ctx || !r_key)
return GPGME_Invalid_Value;
*r_key = NULL;
if (!ctx)
return GPGME_Invalid_Value;
if (!ctx->key_queue)
err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &opd, -1, NULL);
if (err)
return err;
if (!opd->key_queue)
{
GpgmeError err = _gpgme_wait_on_condition (ctx, &ctx->key_cond);
err = _gpgme_wait_on_condition (ctx, &opd->key_cond);
if (err)
return err;
if (!ctx->key_cond)
if (!opd->key_cond)
return GPGME_EOF;
ctx->key_cond = 0;
assert (ctx->key_queue);
opd->key_cond = 0;
assert (opd->key_queue);
}
queue_item = ctx->key_queue;
ctx->key_queue = queue_item->next;
if (!ctx->key_queue)
ctx->key_cond = 0;
queue_item = opd->key_queue;
opd->key_queue = queue_item->next;
if (!opd->key_queue)
opd->key_cond = 0;
*r_key = queue_item->key;
free (queue_item);
@ -845,13 +797,7 @@ gpgme_op_keylist_next (GpgmeCtx ctx, GpgmeKey *r_key)
}
/**
* gpgme_op_keylist_end:
* @c: Context
*
* Ends the keylist operation and allows to use the context for some
* other operation next.
**/
/* Terminate a pending keylist operation within CTX. */
GpgmeError
gpgme_op_keylist_end (GpgmeCtx ctx)
{

View File

@ -53,10 +53,6 @@ GpgmeError _gpgme_data_append_percentstring_for_xml ( GpgmeData dh,
GpgmeError _gpgme_data_inbound_handler (void *opaque, int fd);
GpgmeError _gpgme_data_outbound_handler (void *opaque, int fd);
/*-- key.c --*/
GpgmeError _gpgme_key_new ( GpgmeKey *r_key );
GpgmeError _gpgme_key_new_secret ( GpgmeKey *r_key );
/* From op-support.c. */
@ -119,12 +115,27 @@ GpgmeError _gpgme_progress_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
char *args);
/*-- keylist.c --*/
/* From key.c. */
GpgmeError _gpgme_key_new (GpgmeKey *r_key);
GpgmeError _gpgme_key_add_subkey (GpgmeKey key, GpgmeSubkey *r_subkey);
GpgmeError _gpgme_key_append_name (GpgmeKey key, char *src);
GpgmeKeySig _gpgme_key_add_sig (GpgmeKey key, char *src);
/* From keylist.c. */
void _gpgme_op_keylist_event_cb (void *data, GpgmeEventIO type, void *type_data);
/*-- trustlist.c --*/
/* From trust-item.c. */
/* Create a new trust item. */
GpgmeError _gpgme_trust_item_new (GpgmeTrustItem *r_item);
/* From trustlist.c. */
void _gpgme_op_trustlist_event_cb (void *data, GpgmeEventIO type, void *type_data);
/*-- version.c --*/
const char *_gpgme_compare_versions (const char *my_version,
const char *req_version);

View File

@ -21,220 +21,143 @@
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "util.h"
#include "context.h"
/**
* gpgme_recipients_new:
* @r_rset: Returns the new object.
*
* Create a new uninitialized Reciepient set Object.
*
* Return value: 0 on success or an error code.
**/
/* Create a new uninitialized recipient object and return it in R_RSET. */
GpgmeError
gpgme_recipients_new (GpgmeRecipients *r_rset)
{
GpgmeRecipients rset;
rset = calloc ( 1, sizeof *rset );
if (!rset)
return GPGME_Out_Of_Core;
*r_rset = rset;
return 0;
GpgmeRecipients rset;
rset = calloc (1, sizeof *rset);
if (!rset)
return GPGME_Out_Of_Core;
*r_rset = rset;
return 0;
}
/**
* gpgme_recipients_release:
* @rset: Recipient Set object
*
* Free the given object.
**/
/* Release the recipient object RSET. */
void
gpgme_recipients_release ( GpgmeRecipients rset )
gpgme_recipients_release (GpgmeRecipients rset)
{
if (rset) {
struct user_id_s *u, *u2;
GpgmeUserID uid = rset->list;
for (u = rset->list; u; u = u2) {
u2 = u->next;
free(u);
}
while (uid)
{
GpgmeUserID next_uid = uid->next;
free (uid);
uid = next_uid;
}
free ( rset );
free (rset);
}
/**
* gpgme_recipients_add_name:
* @rset: Recipient Set object
* @name: user name or keyID
*
* Add a name to the recipient Set.
*
* Return value: 0 on success or an error code
**/
GpgmeError
gpgme_recipients_add_name (GpgmeRecipients rset, const char *name )
{
return gpgme_recipients_add_name_with_validity (
rset, name, GPGME_VALIDITY_UNKNOWN
);
}
/**
* gpgme_recipients_add_name_with_validity:
* @rset: Recipient Set object
* @name: user name or keyID
* @val: Validity value
*
* Same as gpgme_recipients_add_name() but with explictly given key
* validity. Use one of the constants
* %GPGME_VALIDITY_UNKNOWN, %GPGME_VALIDITY_UNDEFINED,
* %GPGME_VALIDITY_NEVER, %GPGME_VALIDITY_MARGINAL,
* %GPGME_VALIDITY_FULL, %GPGME_VALIDITY_ULTIMATE
* for the validity. %GPGME_VALIDITY_UNKNOWN is implicitly used by
* gpgme_recipients_add_name().
*
* Return value: o on success or an error value.
**/
/* Add the name NAME to the recipient set RSET with the given key
validity VALIDITY. */
GpgmeError
gpgme_recipients_add_name_with_validity (GpgmeRecipients rset,
const char *name,
GpgmeValidity val )
const char *name,
GpgmeValidity validity)
{
struct user_id_s *r;
GpgmeUserID uid;
if (!name || !rset )
return GPGME_Invalid_Value;
r = malloc ( sizeof *r + strlen (name) );
if (!r)
return GPGME_Out_Of_Core;
r->validity = val;
r->name_part = "";
r->email_part = "";
r->comment_part = "";
strcpy (r->name, name );
r->next = rset->list;
rset->list = r;
return 0;
if (!name || !rset)
return GPGME_Invalid_Value;
uid = malloc (sizeof (*uid) + strlen (name));
if (!uid)
return GPGME_Out_Of_Core;
uid->validity = validity;
uid->name = "";
uid->email = "";
uid->comment = "";
uid->uid = ((char *) uid) + sizeof (*uid);
strcpy (uid->uid, name);
uid->next = rset->list;
rset->list = uid;
return 0;
}
/* Add the name NAME to the recipient set RSET. Same as
gpgme_recipients_add_name_with_validity with validitiy
GPGME_VALIDITY_UNKNOWN. */
GpgmeError
gpgme_recipients_add_name (GpgmeRecipients rset, const char *name)
{
return gpgme_recipients_add_name_with_validity (rset, name,
GPGME_VALIDITY_UNKNOWN);
}
/**
* gpgme_recipients_count:
* @rset: Recipient Set object
*
* Return value: The number of recipients in the set.
**/
/* Return the number of recipients in the set. */
unsigned int
gpgme_recipients_count ( const GpgmeRecipients rset )
gpgme_recipients_count (const GpgmeRecipients rset)
{
struct user_id_s *r;
unsigned int count = 0;
GpgmeUserID uid = rset->list;
unsigned int count = 0;
if ( rset ) {
for (r=rset->list ; r; r = r->next )
count++;
while (uid)
{
count++;
uid = uid->next;
}
return count;
return count;
}
/**
* gpgme_recipients_enum_open:
* @rset: Recipient Set object
* @ctx: Enumerator
*
* Start an enumeration on the Recipient Set object. The caller must pass
* the address of a void pointer which is used as the enumerator object.
*
* Return value: 0 on success or an error code.
*
* See also: gpgme_recipients_enum_read(), gpgme_recipients_enum_close().
**/
/* Start an enumeration on the recipient set RSET. The caller must
pass the address of a void pointer which is used as the iterator
object. */
GpgmeError
gpgme_recipients_enum_open ( const GpgmeRecipients rset, void **ctx )
gpgme_recipients_enum_open (const GpgmeRecipients rset, void **iter)
{
if (!rset || !ctx)
return GPGME_Invalid_Value;
*ctx = rset->list;
return 0;
*iter = rset->list;
return 0;
}
/**
* gpgme_recipients_enum_read:
* @rset: Recipient Set object
* @ctx: Enumerator
*
* Return the name of the next user name from the given recipient
* set. This name is valid as along as the @rset is valid and until
* the next call to this function.
*
* Return value: name or NULL for no more names.
*
* See also: gpgme_recipients_enum_read(), gpgme_recipients_enum_close().
**/
/* Return the name of the next recipient in the set RSET. */
const char *
gpgme_recipients_enum_read ( const GpgmeRecipients rset, void **ctx )
gpgme_recipients_enum_read (const GpgmeRecipients rset, void **iter)
{
struct user_id_s *r;
if (!rset || !ctx)
return NULL; /* oops */
r = *ctx;
if ( r ) {
const char *s = r->name;
r = r->next;
*ctx = r;
return s;
}
GpgmeUserID uid;
uid = *iter;
if (!uid)
return NULL;
*iter = uid->next;
return uid->name;
}
/**
* gpgme_recipients_enum_close:
* @rset: Recipient Set object
* @ctx: Enumerator
*
* Release the enumerator @rset for this object.
*
* Return value: 0 on success or %GPGME_Invalid_Value;
*
* See also: gpgme_recipients_enum_read(), gpgme_recipients_enum_close().
**/
/* Release the iterator for this object. */
GpgmeError
gpgme_recipients_enum_close ( const GpgmeRecipients rset, void **ctx )
gpgme_recipients_enum_close (const GpgmeRecipients rset, void **iter)
{
if (!rset || !ctx)
return GPGME_Invalid_Value;
*ctx = NULL;
return 0;
/* Not really needed, but might catch the occasional mistake. */
*iter = NULL;
return 0;
}
int
_gpgme_recipients_all_valid ( const GpgmeRecipients rset )
_gpgme_recipients_all_valid (const GpgmeRecipients rset)
{
struct user_id_s *r;
GpgmeUserID uid = rset->list;
assert (rset);
for (r=rset->list ; r; r = r->next ) {
if (r->validity != GPGME_VALIDITY_FULL
&& r->validity != GPGME_VALIDITY_ULTIMATE )
return 0; /*no*/
while (uid)
{
if (uid->validity != GPGME_VALIDITY_FULL
&& uid->validity != GPGME_VALIDITY_ULTIMATE )
return 0;
uid = uid->next;
}
return 1; /*yes*/
return 1;
}

View File

@ -437,9 +437,10 @@ gpg_set_colon_line_handler (void *engine, EngineColonLineHandler fnc,
/* Here we handle --command-fd. This works closely together with the
status handler. */
static int
static GpgmeError
command_cb (void *opaque, char *buffer, size_t length, size_t *nread)
{
GpgmeError err;
GpgObject gpg = opaque;
const char *value;
int value_len;
@ -462,8 +463,11 @@ command_cb (void *opaque, char *buffer, size_t length, size_t *nread)
}
/* FIXME catch error */
gpg->cmd.fnc (gpg->cmd.fnc_value,
gpg->cmd.code, gpg->cmd.keyword, &value);
err = gpg->cmd.fnc (gpg->cmd.fnc_value,
gpg->cmd.code, gpg->cmd.keyword, &value);
if (err)
return err;
if (!value)
{
DEBUG0 ("command_cb: no data from user cb\n");
@ -1200,11 +1204,10 @@ gpg_delete (void *engine, GpgmeKey key, int allow_secret)
err = add_arg (gpg, "--");
if (!err)
{
const char *s = gpgme_key_get_string_attr (key, GPGME_ATTR_FPR, NULL, 0);
if (!s)
if (!key->subkeys || !key->subkeys->fpr)
err = GPGME_Invalid_Key;
else
err = add_arg (gpg, s);
err = add_arg (gpg, key->subkeys->fpr);
}
if (!err)
@ -1222,8 +1225,7 @@ append_args_from_signers (GpgObject gpg, GpgmeCtx ctx /* FIXME */)
for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
{
const char *s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID,
NULL, 0);
const char *s = key->subkeys ? key->subkeys->keyid : NULL;
if (s)
{
if (!err)
@ -1255,7 +1257,7 @@ gpg_edit (void *engine, GpgmeKey key, GpgmeData out, GpgmeCtx ctx /* FIXME */)
err = add_arg (gpg, "--");
if (!err)
{
const char *s = gpgme_key_get_string_attr (key, GPGME_ATTR_FPR, NULL, 0);
const char *s = key->subkeys ? key->subkeys->fpr : NULL;
if (!s)
err = GPGME_Invalid_Key;
else
@ -1272,14 +1274,14 @@ static GpgmeError
append_args_from_recipients (GpgObject gpg, const GpgmeRecipients rset)
{
GpgmeError err = 0;
struct user_id_s *r;
GpgmeUserID uid;
assert (rset);
for (r = rset->list; r; r = r->next)
for (uid = rset->list; uid; uid = uid->next)
{
err = add_arg (gpg, "-r");
if (!err)
err = add_arg (gpg, r->name);
err = add_arg (gpg, uid->uid);
if (err)
break;
}

View File

@ -48,10 +48,10 @@ _gpgme_trust_item_new (GpgmeTrustItem *r_item)
item->_refs = 1;
item->keyid = item->_keyid;
item->_keyid[16] = '\0';
item->otrust = item->_otrust;
item->_otrust[1] = '\0';
item->val = item->_val;
item->_val[1] = '\0';
item->owner_trust = item->_owner_trust;
item->_owner_trust[1] = '\0';
item->validity = item->_validity;
item->_validity[1] = '\0';
*r_item = item;
return 0;
}
@ -119,11 +119,11 @@ const char *gpgme_trust_item_get_string_attr (GpgmeTrustItem item,
break;
case GPGME_ATTR_OTRUST:
val = item->otrust;
val = item->owner_trust;
break;
case GPGME_ATTR_VALIDITY:
val = item->val;
val = item->validity;
break;
case GPGME_ATTR_USERID:

View File

@ -99,10 +99,10 @@ trustlist_colon_handler (void *priv, char *line)
item->type = *p == 'K'? 1 : *p == 'U'? 2 : 0;
break;
case 5: /* owner trust */
item->_otrust[0] = *p;
item->_owner_trust[0] = *p;
break;
case 6: /* validity */
item->_val[0] = *p;
item->_validity[0] = *p;
break;
case 9: /* user ID */
item->name = strdup (p);

View File

@ -1,3 +1,12 @@
2003-04-30 Marcus Brinkmann <marcus@g10code.de>
* gpg/t-keylist.c: Rewritten.
* gpgsm/t-keylist.c (main): Rewritten.
* gpg/t-edit.c (main): Do not use gpgme_key_get_as_xml. Use
gpgme_key_unref instead gpgme_key_release.
* gpg/t-signers.c (main): Use gpgme_key_unref instead
gpgme_key_release.
2003-04-29 Marcus Brinkmann <marcus@g10code.de>
* gpg/t-trustlist.c: Rewritten.

View File

@ -150,13 +150,6 @@ main (int argc, char **argv)
err = gpgme_op_keylist_end (ctx);
fail_if_err (err);
p = gpgme_key_get_as_xml (key);
if (p)
{
fputs (p, stdout);
free (p);
}
err = gpgme_op_edit (ctx, key, edit_fnc, out, out);
fail_if_err (err);
@ -164,7 +157,7 @@ main (int argc, char **argv)
flush_data (out);
gpgme_data_release (out);
gpgme_key_release (key);
gpgme_key_unref (key);
gpgme_release (ctx);
}
while (argc > 1 && !strcmp( argv[1], "--loop"));

View File

@ -1,170 +1,537 @@
/* t-keylist.c - regression test
* Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001 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 General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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
*/
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2003 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 General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GPGME; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <gpgme.h>
#define fail_if_err(a) do { if(a) { \
fprintf (stderr, "%s:%d: GpgmeError %s\n", \
__FILE__, __LINE__, gpgme_strerror(a)); \
exit (1); } \
} while(0)
#define fail_if_err(err) \
do \
{ \
if (err) \
{ \
fprintf (stderr, "%s:%d: GpgmeError %s\n", \
__FILE__, __LINE__, gpgme_strerror (err)); \
exit (1); \
} \
} \
while (0)
static void
doit (GpgmeCtx ctx, const char *pattern)
struct
{
GpgmeError err;
GpgmeKey key;
err = gpgme_op_keylist_start (ctx, pattern, 0);
fail_if_err (err);
while (!(err = gpgme_op_keylist_next (ctx, &key)))
{
char *p;
const char *s;
int i;
printf ("<!-- Begin key object (%p) -->\n", key);
p = gpgme_key_get_as_xml (key);
if (p)
{
fputs (p, stdout);
free (p);
}
else
fputs("<!-- Ooops: gpgme_key_get_as_xml failed -->\n", stdout);
for (i = 0; ; i++)
{
s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID, NULL, i);
if (!s)
break;
printf ("<!-- keyid.%d=%s -->\n", i, s);
s = gpgme_key_get_string_attr (key, GPGME_ATTR_ALGO, NULL, i);
printf ("<!-- algo.%d=%s -->\n", i, s);
s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEY_CAPS, NULL, i);
printf ("<!-- caps.%d=%s -->\n", i, s);
}
for (i = 0; ; i++)
{
s = gpgme_key_get_string_attr (key, GPGME_ATTR_NAME, NULL, i);
if (!s)
break;
printf ("<!-- name.%d=%s -->\n", i, s);
s = gpgme_key_get_string_attr (key, GPGME_ATTR_EMAIL, NULL, i);
printf ("<!-- email.%d=%s -->\n", i, s);
s = gpgme_key_get_string_attr (key, GPGME_ATTR_COMMENT, NULL, i);
printf ("<!-- comment.%d=%s -->\n", i, s);
}
fputs ("<!-- usable for:", stdout);
if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_ENCRYPT, NULL, 0))
fputs (" encryption", stdout);
if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_SIGN, NULL, 0))
fputs (" signing", stdout);
if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_CERTIFY, NULL, 0))
fputs (" certification", stdout);
fputs (" -->\n", stdout );
printf ("<!-- End key object (%p) -->\n", key);
gpgme_key_release (key);
}
if (err != GPGME_EOF)
fail_if_err (err);
char *fpr;
char *sec_keyid;
struct
{
char *name;
char *comment;
char *email;
} uid[3];
}
/*
* Check that there are no problems when we are using two context for
* listing keys.
*/
static void
check_two_contexts (void)
{
GpgmeError err;
GpgmeCtx ctx1, ctx2;
GpgmeKey key;
err = gpgme_new(&ctx1); fail_if_err (err);
err = gpgme_op_keylist_start(ctx1, "", 1);
fail_if_err (err);
err = gpgme_new(&ctx2); fail_if_err (err);
err = gpgme_op_keylist_start(ctx2, "", 1);
fail_if_err (err);
while ((err = gpgme_op_keylist_next (ctx2, &key)) != GPGME_EOF)
gpgme_key_release (key);
if (err != GPGME_EOF)
fail_if_err (err);
while ((err=gpgme_op_keylist_next(ctx1, &key)) != GPGME_EOF)
gpgme_key_release (key);
if (err != GPGME_EOF)
fail_if_err (err);
}
keys[] =
{
{ "A0FF4590BB6122EDEF6E3C542D727CC768697734", "6AE6D7EE46A871F8",
{ { "Alpha Test", "demo key", "alpha@example.net" },
{ "Alice", "demo key", NULL },
{ "Alfa Test", "demo key", "alfa@example.net" } } },
{ "61EE841A2A27EB983B3B3C26413F4AF31AFDAB6C", "E71E72ACBC43DA60",
{ { "Charlie Test", "demo key", "charlie@example.net" } } },
{ "3531152DE293E26A07F504BC318C1FAEFAEF6D1B", "B5C79E1A7272144D",
{ { "Echelon", "demo key", NULL },
{ "Echo Test", "demo key", "echo@example.net" },
{ "Eve", "demo key", NULL } } },
{ "C9C07DCC6621B9FB8D071B1D168410A48FC282E6", "247491CC9DCAD354",
{ { "Golf Test", "demo key", "golf@example.net" } } },
{ "CD538D6CC9FB3D745ECDA5201FE8FC6F04259677", "C1C8EFDE61F76C73",
{ { "India Test", "demo key", "india@example.net" } } },
{ "3FD11083779196C2ECDD9594AD1B0FAD43C2D0C7", "86CBB34A9AF64D02",
{ { "Kilo Test", "demo key", "kilo@example.net" } } },
{ "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", "5381EA4EE29BA37F",
{ { "Bob", "demo key", NULL },
{ "Bravo Test", "demo key", "bravo@example.net" } } },
{ "6560C59C43D031C54D7C588EEBA9F240EB9DC9E6", "06F22880B0C45424",
{ { "Delta Test", "demo key", "delta@example.net" } } },
{ "56D33268F7FE693FBB594762D4BF57F37372E243", "0A32EE79EE45198E",
{ { "Foxtrot Test", "demo key", "foxtrot@example.net" } } },
{ "9E91CBB11E4D4135583EF90513DB965534C6E3F1", "76E26537D622AD0A",
{ { "Hotel Test", "demo key", "hotel@example.net" } } },
{ "F8F1EDC73995AB739AD54B380C820C71D2699313", "BD0B108735F8F136",
{ { "Juliet Test", "demo key", "juliet@example.net" } } },
{ "1DDD28CEF714F5B03B8C246937CAB51FB79103F8", "0363B449FE56350C",
{ { "Lima Test", "demo key", "lima@example.net" } } },
{ "2686AA191A278013992C72EBBE794852BE5CF886", "5F600A834F31EAE8",
{ { "Mallory", "demo key", NULL },
{ "Mike Test", "demo key", "mike@example.net" } } },
{ "5AB9D6D7BAA1C95B3BAA3D9425B00FD430CEC684", "4C1D63308B70E472",
{ { "November Test", "demo key", "november@example.net" } } },
{ "43929E89F8F79381678CAE515F6356BA6D9732AC", "FF0785712681619F",
{ { "Oscar Test", "demo key", "oscar@example.net" } } },
{ "6FAA9C201E5E26DCBAEC39FD5D15E01D3FF13206", "2764E18263330D9C",
{ { "Papa test", "demo key", "papa@example.net" } } },
{ "A7969DA1C3297AA96D49843F1C67EC133C661C84", "6CDCFC44A029ACF4",
{ { "Quebec Test", "demo key", "quebec@example.net" } } },
{ "38FBE1E4BF6A5E1242C8F6A13BDBEDB1777FBED3", "9FAB805A11D102EA",
{ { "Romeo Test", "demo key", "romeo@example.net" } } },
{ "045B2334ADD69FC221076841A5E67F7FA3AE3EA1", "93B88B0F0F1B50B4",
{ { "Sierra Test", "demo key", "sierra@example.net" } } },
{ "ECAC774F4EEEB0620767044A58CB9A4C85A81F38", "97B60E01101C0402",
{ { "Tango Test", "demo key", "tango@example.net" } } },
{ "0DBCAD3F08843B9557C6C4D4A94C0F75653244D6", "93079B915522BDB9",
{ { "Uniform Test", "demo key", "uniform@example.net" } } },
{ "E8143C489C8D41124DC40D0B47AF4B6961F04784", "04071FB807287134",
{ { "Victor Test", "demo key", "victor@example.org" } } },
{ "E8D6C90B683B0982BD557A99DEF0F7B8EC67DBDE", "D7FBB421FD6E27F6",
{ { "Whisky Test", "demo key", "whisky@example.net" } } },
{ "04C1DF62EFA0EBB00519B06A8979A6C5567FB34A", "5CC6F87F41E408BE",
{ { "XRay Test", "demo key", "xray@example.net" } } },
{ "ED9B316F78644A58D042655A9EEF34CD4B11B25F", "5ADFD255F7B080AD",
{ { "Yankee Test", "demo key", "yankee@example.net" } } },
{ "23FD347A419429BACCD5E72D6BC4778054ACD246", "EF9DC276A172C881",
{ { "Zulu Test", "demo key", "zulu@example.net" } } },
{ "ADAB7FCC1F4DE2616ECFA402AF82244F9CD9FD55", "087DD7E0381701C4",
{ { "Joe Random Hacker", "test key with passphrase \"x\"",
"joe@setq.org" } } },
{ NULL }
};
int
main (int argc, char **argv)
{
GpgmeCtx ctx;
GpgmeError err;
int loop = 0;
const char *pattern;
if (argc)
{
argc--;
argv++;
}
if (argc && !strcmp( *argv, "--loop"))
{
loop = 1;
argc--; argv++;
}
pattern = argc? *argv : NULL;
GpgmeCtx ctx;
GpgmeKey key;
GpgmeKeyListResult result;
int i = 0;
err = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP);
fail_if_err (err);
err = gpgme_new (&ctx);
fail_if_err (err);
/* No validity calculation. */
gpgme_set_keylist_mode (ctx, 1);
do
err = gpgme_op_keylist_start (ctx, NULL, 0);
fail_if_err (err);
while (!(err = gpgme_op_keylist_next (ctx, &key)))
{
fprintf (stderr, "** pattern=`%s'\n", pattern ? pattern : "(null)");
doit (ctx, pattern);
if (!keys[i].fpr)
{
fprintf (stderr, "More keys returned than expected\n");
exit (1);
}
/* Global key flags. */
if (key->revoked)
{
fprintf (stderr, "Key unexpectedly revoked\n");
exit (1);
}
if (key->expired)
{
fprintf (stderr, "Key unexpectedly expired\n");
exit (1);
}
if (key->disabled)
{
fprintf (stderr, "Key unexpectedly disabled\n");
exit (1);
}
if (key->invalid)
{
fprintf (stderr, "Key unexpectedly invalid\n");
exit (1);
}
if (!key->can_encrypt)
{
fprintf (stderr, "Key unexpectedly unusable for encryption\n");
exit (1);
}
if (!key->can_sign)
{
fprintf (stderr, "Key unexpectedly unusable for signing\n");
exit (1);
}
if (!key->can_certify)
{
fprintf (stderr, "Key unexpectedly unusable for certifications\n");
exit (1);
}
if (key->secret)
{
fprintf (stderr, "Key unexpectedly secret\n");
exit (1);
}
if (key->protocol != GPGME_PROTOCOL_OpenPGP)
{
fprintf (stderr, "Key has unexpected protocol: %s\n",
gpgme_get_protocol_name (key->protocol));
exit (1);
}
if (key->issuer_serial)
{
fprintf (stderr, "Key unexpectedly carries issuer serial: %s\n",
key->issuer_serial);
exit (1);
}
if (key->issuer_name)
{
fprintf (stderr, "Key unexpectedly carries issuer name: %s\n",
key->issuer_name);
exit (1);
}
if (key->chain_id)
{
fprintf (stderr, "Key unexpectedly carries chain ID: %s\n",
key->chain_id);
exit (1);
}
if (key->owner_trust != GPGME_VALIDITY_UNKNOWN)
{
fprintf (stderr, "Key has unexpected owner trust: %i\n",
key->owner_trust);
exit (1);
}
if (!key->subkeys || !key->subkeys->next || key->subkeys->next->next)
{
fprintf (stderr, "Key has unexpected number of subkeys\n");
exit (1);
}
/* Primary key. */
if (key->subkeys->revoked)
{
fprintf (stderr, "Primary key unexpectedly revoked\n");
exit (1);
}
if (key->subkeys->expired)
{
fprintf (stderr, "Primary key unexpectedly expired\n");
exit (1);
}
if (key->subkeys->disabled)
{
fprintf (stderr, "Primary key unexpectedly disabled\n");
exit (1);
}
if (key->subkeys->invalid)
{
fprintf (stderr, "Primary key unexpectedly invalid\n");
exit (1);
}
if (key->subkeys->can_encrypt)
{
fprintf (stderr, "Primary key unexpectedly usable for encryption\n");
exit (1);
}
if (!key->subkeys->can_sign)
{
fprintf (stderr, "Primary key unexpectedly unusable for signing\n");
exit (1);
}
if (!key->subkeys->can_certify)
{
fprintf (stderr, "Primary key unexpectedly unusable for certifications\n");
exit (1);
}
if (key->subkeys->secret)
{
fprintf (stderr, "Primary key unexpectedly secret\n");
exit (1);
}
if (key->subkeys->pubkey_algo != GPGME_PK_DSA)
{
fprintf (stderr, "Primary key has unexpected public key algo: %s\n",
gpgme_pubkey_algo_name (key->subkeys->pubkey_algo));
exit (1);
}
if (key->subkeys->length != 1024)
{
fprintf (stderr, "Primary key has unexpected length: %i\n",
key->subkeys->length);
exit (1);
}
if (strcmp (key->subkeys->keyid, &keys[i].fpr[40 - 16]))
{
fprintf (stderr, "Primary key has unexpected key ID: %s\n",
key->subkeys->keyid);
exit (1);
}
if (strcmp (key->subkeys->fpr, keys[i].fpr))
{
fprintf (stderr, "Primary key has unexpected fingerprint: %s\n",
key->subkeys->fpr);
exit (1);
}
if (key->subkeys->expires)
{
fprintf (stderr, "Primary key unexpectedly expires: %lu\n",
key->subkeys->expires);
exit (1);
}
/* Secondary key. */
if (key->subkeys->next->revoked)
{
fprintf (stderr, "Secondary key unexpectedly revoked\n");
exit (1);
}
if (key->subkeys->next->expired)
{
fprintf (stderr, "Secondary key unexpectedly expired\n");
exit (1);
}
if (key->subkeys->next->disabled)
{
fprintf (stderr, "Secondary key unexpectedly disabled\n");
exit (1);
}
if (key->subkeys->next->invalid)
{
fprintf (stderr, "Secondary key unexpectedly invalid\n");
exit (1);
}
if (!key->subkeys->next->can_encrypt)
{
fprintf (stderr, "Secondary key unexpectedly unusable for encryption\n");
exit (1);
}
if (key->subkeys->next->can_sign)
{
fprintf (stderr, "Secondary key unexpectedly usable for signing\n");
exit (1);
}
if (key->subkeys->next->can_certify)
{
fprintf (stderr, "Secondary key unexpectedly usable for certifications\n");
exit (1);
}
if (key->subkeys->next->secret)
{
fprintf (stderr, "Secondary key unexpectedly secret\n");
exit (1);
}
if (key->subkeys->next->pubkey_algo != GPGME_PK_ELG_E)
{
fprintf (stderr, "Secondary key has unexpected public key algo: %s\n",
gpgme_pubkey_algo_name (key->subkeys->next->pubkey_algo));
exit (1);
}
if (key->subkeys->next->length != 1024)
{
fprintf (stderr, "Secondary key has unexpected length: %i\n",
key->subkeys->next->length);
exit (1);
}
if (strcmp (key->subkeys->next->keyid, keys[i].sec_keyid))
{
fprintf (stderr, "Secondary key has unexpected key ID: %s\n",
key->subkeys->next->keyid);
exit (1);
}
if (key->subkeys->next->fpr)
{
fprintf (stderr, "Secondary key has unexpectedly a fingerprint: %s\n",
key->subkeys->next->fpr);
exit (1);
}
if (key->subkeys->next->expires)
{
fprintf (stderr, "Secondary key unexpectedly expires: %lu\n",
key->subkeys->next->expires);
exit (1);
}
/* FIXME: The below test will crash if we want to check for a
name, comment or email that doesn't exist in the key's user
IDs. */
if (!((!keys[i].uid[0].name && !key->uids)
|| (keys[i].uid[0].name && !keys[i].uid[1].name
&& key->uids && !key->uids->next)
|| (keys[i].uid[0].name && keys[i].uid[1].name
&& !keys[i].uid[2].name
&& key->uids && key->uids->next && !key->uids->next->next)
|| (keys[i].uid[0].name && keys[i].uid[1].name
&& keys[i].uid[2].name
&& key->uids && key->uids->next && key->uids->next->next
&& !key->uids->next->next->next)))
{
fprintf (stderr, "Key has unexpected number of user IDs\n");
exit (1);
}
if (key->uids && key->uids->revoked)
{
fprintf (stderr, "First user ID unexpectedly revoked\n");
exit (1);
}
if (key->uids && key->uids->invalid)
{
fprintf (stderr, "First user ID unexpectedly invalid\n");
exit (1);
}
if (key->uids && key->uids->validity != GPGME_VALIDITY_UNKNOWN)
{
fprintf (stderr, "First user ID has unexpectedly validity: %i\n",
key->uids->validity);
exit (1);
}
if (key->uids && key->uids->signatures)
{
fprintf (stderr, "First user ID unexpectedly signed\n");
exit (1);
}
if (keys[i].uid[0].name
&& strcmp (keys[i].uid[0].name, key->uids->name))
{
fprintf (stderr, "Unexpected name in first user ID: %s\n",
key->uids->name);
exit (1);
}
if (keys[i].uid[0].comment
&& strcmp (keys[i].uid[0].comment, key->uids->comment))
{
fprintf (stderr, "Unexpected comment in first user ID: %s\n",
key->uids->comment);
exit (1);
}
if (keys[i].uid[0].email
&& strcmp (keys[i].uid[0].email, key->uids->email))
{
fprintf (stderr, "Unexpected email in first user ID: %s\n",
key->uids->email);
exit (1);
}
if (key->uids && key->uids->next && key->uids->next->revoked)
{
fprintf (stderr, "Second user ID unexpectedly revoked\n");
exit (1);
}
if (key->uids && key->uids->next && key->uids->next->invalid)
{
fprintf (stderr, "Second user ID unexpectedly invalid\n");
exit (1);
}
if (key->uids && key->uids->next
&& key->uids->next->validity != GPGME_VALIDITY_UNKNOWN)
{
fprintf (stderr, "Second user ID has unexpectedly validity: %i\n",
key->uids->next->validity);
exit (1);
}
if (key->uids && key->uids->next && key->uids->next->signatures)
{
fprintf (stderr, "Second user ID unexpectedly signed\n");
exit (1);
}
if (keys[i].uid[1].name
&& strcmp (keys[i].uid[1].name, key->uids->next->name))
{
fprintf (stderr, "Unexpected name in second user ID: %s\n",
key->uids->next->name);
exit (1);
}
if (keys[i].uid[1].comment
&& strcmp (keys[i].uid[1].comment, key->uids->next->comment))
{
fprintf (stderr, "Unexpected comment in second user ID: %s\n",
key->uids->next->comment);
exit (1);
}
if (keys[i].uid[1].email
&& strcmp (keys[i].uid[1].email, key->uids->next->email))
{
fprintf (stderr, "Unexpected email in second user ID: %s\n",
key->uids->next->email);
exit (1);
}
if (key->uids && key->uids->next && key->uids->next->next
&& key->uids->next->next->revoked)
{
fprintf (stderr, "Third user ID unexpectedly revoked\n");
exit (1);
}
if (key->uids && key->uids->next && key->uids->next->next
&& key->uids->next->next->invalid)
{
fprintf (stderr, "Third user ID unexpectedly invalid\n");
exit (1);
}
if (key->uids && key->uids->next && key->uids->next->next
&& key->uids->next->next->validity != GPGME_VALIDITY_UNKNOWN)
{
fprintf (stderr, "Third user ID has unexpectedly validity: %i\n",
key->uids->next->next->validity);
exit (1);
}
if (key->uids && key->uids->next && key->uids->next->next
&& key->uids->next->next->signatures)
{
fprintf (stderr, "Third user ID unexpectedly signed\n");
exit (1);
}
if (keys[i].uid[2].name
&& strcmp (keys[i].uid[2].name, key->uids->next->next->name))
{
fprintf (stderr, "Unexpected name in third user ID: %s\n",
key->uids->next->next->name);
exit (1);
}
if (keys[i].uid[2].comment
&& strcmp (keys[i].uid[2].comment, key->uids->next->next->comment))
{
fprintf (stderr, "Unexpected comment in third user ID: %s\n",
key->uids->next->next->comment);
exit (1);
}
if (keys[i].uid[2].email
&& strcmp (keys[i].uid[2].email, key->uids->next->next->email))
{
fprintf (stderr, "Unexpected email in third user ID: %s\n",
key->uids->next->next->email);
exit (1);
}
gpgme_key_unref (key);
i++;
}
while (loop);
if (err != GPGME_EOF)
fail_if_err (err);
err = gpgme_op_keylist_end (ctx);
fail_if_err (err);
result = gpgme_op_keylist_result (ctx);
if (result->truncated)
{
fprintf (stderr, "Key listing unexpectedly truncated\n");
exit (1);
}
if (keys[i].fpr)
{
fprintf (stderr, "Less keys returned than expected\n");
exit (1);
}
gpgme_release (ctx);
check_two_contexts ();
return 0;
}

View File

@ -197,7 +197,7 @@ main (int argc, char *argv[])
gpgme_data_release (in);
gpgme_release (ctx);
gpgme_key_release (key[0]);
gpgme_key_release (key[1]);
gpgme_key_unref (key[0]);
gpgme_key_unref (key[1]);
return 0;
}

View File

@ -1,184 +1,351 @@
/* t-keylist.c - regression test
* Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001 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 General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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
*/
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2003 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 General Public License as published by
the Free Software Foundation; either version 2 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GPGME; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <gpgme.h>
#define fail_if_err(a) do { if(a) { \
fprintf (stderr, "%s:%d: GpgmeError %s\n", \
__FILE__, __LINE__, gpgme_strerror(a)); \
exit (1); } \
} while(0)
#define fail_if_err(err) \
do \
{ \
if (err) \
{ \
fprintf (stderr, "%s:%d: GpgmeError %s\n", \
__FILE__, __LINE__, gpgme_strerror (err)); \
exit (1); \
} \
} \
while (0)
static void
doit ( GpgmeCtx ctx, const char *pattern, int secret )
struct
{
GpgmeError err;
GpgmeKey key;
err = gpgme_op_keylist_start (ctx, pattern, secret );
fail_if_err (err);
while ( !(err = gpgme_op_keylist_next ( ctx, &key )) ) {
char *p;
const char *s;
int i;
printf ("<!-- Begin key object (%p) -->\n", key );
p = gpgme_key_get_as_xml ( key );
if ( p ) {
fputs ( p, stdout );
free (p);
}
else
fputs("<!-- Ooops: gpgme_key_get_as_xml failed -->\n", stdout );
for (i=0; ; i++ ) {
s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID, NULL, i );
if (!s)
break;
printf ("<!-- keyid.%d=%s -->\n", i, s );
s = gpgme_key_get_string_attr (key, GPGME_ATTR_ALGO, NULL, i );
printf ("<!-- algo.%d=%s -->\n", i, s );
s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEY_CAPS, NULL, i );
printf ("<!-- caps.%d=%s -->\n", i, s );
}
for (i=0; ; i++ ) {
s = gpgme_key_get_string_attr (key, GPGME_ATTR_NAME, NULL, i );
if (!s)
break;
printf ("<!-- name.%d=%s -->\n", i, s );
s = gpgme_key_get_string_attr (key, GPGME_ATTR_EMAIL, NULL, i );
printf ("<!-- email.%d=%s -->\n", i, s );
s = gpgme_key_get_string_attr (key, GPGME_ATTR_COMMENT, NULL, i );
printf ("<!-- comment.%d=%s -->\n", i, s );
}
fputs ("<!-- usable for:", stdout );
if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_ENCRYPT, NULL, 0 ))
fputs (" encryption", stdout);
if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_SIGN, NULL, 0 ))
fputs (" signing", stdout);
if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_CERTIFY, NULL, 0 ))
fputs (" certification", stdout);
fputs (" -->\n", stdout );
printf ("<!-- End key object (%p) -->\n", key );
gpgme_key_release (key);
}
if ( err != GPGME_EOF )
fail_if_err (err);
{
char *p;
p = gpgme_get_op_info (ctx, 0);
if (p)
{
fputs ("<!-- begin operation info -->\n", stdout);
fputs (p, stdout);
fputs ("<!-- end operation info -->\n", stdout);
free (p);
}
}
}
/*
* Check that there are no problems when we are using two context for
* listing keys.
*/
static void
check_two_contexts (void)
{
GpgmeError err;
GpgmeCtx ctx1, ctx2;
GpgmeKey key;
err = gpgme_new(&ctx1);
fail_if_err (err);
gpgme_set_protocol (ctx1, GPGME_PROTOCOL_CMS);
err = gpgme_op_keylist_start(ctx1, "", 1);
fail_if_err (err);
err = gpgme_new(&ctx2); fail_if_err (err);
gpgme_set_protocol (ctx2, GPGME_PROTOCOL_CMS);
err = gpgme_op_keylist_start(ctx2, "", 1);
fail_if_err (err);
while ( (err=gpgme_op_keylist_next(ctx2, &key)) != GPGME_EOF) {
gpgme_key_release (key);
}
if (err != GPGME_EOF)
fail_if_err (err);
while ( (err=gpgme_op_keylist_next(ctx1, &key)) != GPGME_EOF) {
gpgme_key_release (key);
}
if (err != GPGME_EOF)
fail_if_err (err);
char *fpr;
int secret;
unsigned long expires;
char *issuer_serial;
char *issuer_name;
char *chain_id;
char *uid;
}
keys[] =
{
{ "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E", 1, 1038908198, "00",
"CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=D\xc3\xbcsseldorf,C=DE",
NULL,
"CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=D\xc3\xbcsseldorf,C=DE" },
{ "DFA56FB5FC41E3A8921F77AD1622EEFD9152A5AD", 0, 1009821790, "01",
"1.2.840.113549.1.9.1=#63657274696679407063612E64666E2E6465,"
"CN=DFN Top Level Certification Authority,OU=DFN-PCA,"
"O=Deutsches Forschungsnetz,C=DE", NULL,
"1.2.840.113549.1.9.1=#63657274696679407063612E64666E2E6465,"
"CN=DFN Top Level Certification Authority,OU=DFN-PCA,"
"O=Deutsches Forschungsnetz,C=DE" },
{ "2C8F3C356AB761CB3674835B792CDA52937F9285", 0, 1009735200, "15",
"1.2.840.113549.1.9.1=#63657274696679407063612E64666E2E6465,"
"CN=DFN Top Level Certification Authority,OU=DFN-PCA,"
"O=Deutsches Forschungsnetz,C=DE",
"DFA56FB5FC41E3A8921F77AD1622EEFD9152A5AD",
"1.2.840.113549.1.9.1=#63657274696679407063612E64666E2E6465,"
"CN=DFN Server Certification Authority,OU=DFN-PCA,"
"O=Deutsches Forschungsnetz,C=DE" },
{ NULL }
};
int
main (int argc, char **argv )
main (int argc, char **argv)
{
GpgmeCtx ctx;
GpgmeError err;
int loop = 0;
int secret = 0;
const char *pattern;
GpgmeError err;
GpgmeCtx ctx;
GpgmeKey key;
GpgmeKeyListResult result;
int i = 0;
if( argc ) {
argc--; argv++;
}
err = gpgme_engine_check_version (GPGME_PROTOCOL_CMS);
fail_if_err (err);
err = gpgme_new (&ctx);
fail_if_err (err);
gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
err = gpgme_op_keylist_start (ctx, NULL, 0);
fail_if_err (err);
if (argc && !strcmp( *argv, "--loop" ) ) {
loop = 1;
argc--; argv++;
while (!(err = gpgme_op_keylist_next (ctx, &key)))
{
if (!keys[i].fpr)
{
fprintf (stderr, "More keys returned than expected\n");
exit (1);
}
/* Global key flags. */
if (key->revoked)
{
fprintf (stderr, "Key unexpectedly revoked\n");
exit (1);
}
if (key->expired)
{
fprintf (stderr, "Key unexpectedly expired\n");
exit (1);
}
if (key->disabled)
{
fprintf (stderr, "Key unexpectedly disabled\n");
exit (1);
}
if (key->invalid)
{
fprintf (stderr, "Key unexpectedly invalid\n");
exit (1);
}
if (key->can_encrypt != keys[i].secret)
{
fprintf (stderr, "Key unexpectedly%s usable for encryption\n",
key->can_encrypt ? "" : " not");
exit (1);
}
if (key->can_sign != keys[i].secret)
{
fprintf (stderr, "Key unexpectedly%s usable for signing\n",
key->can_sign ? "" : " not");
exit (1);
}
if (!key->can_certify)
{
fprintf (stderr, "Key unexpectedly unusable for certifications\n");
exit (1);
}
if (key->secret != keys[i].secret)
{
fprintf (stderr, "Key unexpectedly%s secret\n",
key->secret ? "" : " not");
exit (1);
}
if (key->protocol != GPGME_PROTOCOL_CMS)
{
fprintf (stderr, "Key has unexpected protocol: %s\n",
gpgme_get_protocol_name (key->protocol));
exit (1);
}
if (!key->issuer_serial)
{
fprintf (stderr, "Key unexpectedly misses issuer serial\n");
exit (1);
}
if (strcmp (key->issuer_serial, keys[i].issuer_serial))
{
fprintf (stderr, "Key has unexpected issuer serial: %s\n",
key->issuer_serial);
exit (1);
}
if (!key->issuer_name)
{
fprintf (stderr, "Key unexpectedly misses issuer name\n");
exit (1);
}
if (strcmp (key->issuer_name, keys[i].issuer_name))
{
fprintf (stderr, "Key has unexpected issuer name: %s\n",
key->issuer_name);
exit (1);
}
if (key->chain_id && !keys[i].chain_id)
{
fprintf (stderr, "Key unexpectedly carries chain ID: %s\n",
key->chain_id);
exit (1);
}
if (!key->chain_id && keys[i].chain_id)
{
fprintf (stderr, "Key unexpectedly carries no chain ID\n");
exit (1);
}
if (key->chain_id && strcmp (key->chain_id, keys[i].chain_id))
{
fprintf (stderr, "Key carries unexpected chain ID: %s\n",
key->chain_id);
exit (1);
}
if (key->owner_trust != GPGME_VALIDITY_UNKNOWN)
{
fprintf (stderr, "Key has unexpected owner trust: %i\n",
key->owner_trust);
exit (1);
}
if (!key->subkeys || key->subkeys->next)
{
fprintf (stderr, "Key has unexpected number of subkeys\n");
exit (1);
}
/* Primary key. */
if (key->subkeys->revoked)
{
fprintf (stderr, "Primary key unexpectedly revoked\n");
exit (1);
}
if (key->subkeys->expired)
{
fprintf (stderr, "Primary key unexpectedly expired\n");
exit (1);
}
if (key->subkeys->disabled)
{
fprintf (stderr, "Primary key unexpectedly disabled\n");
exit (1);
}
if (key->subkeys->invalid)
{
fprintf (stderr, "Primary key unexpectedly invalid\n");
exit (1);
}
if (key->subkeys->can_encrypt != keys[i].secret)
{
fprintf (stderr, "Key unexpectedly%s usable for encryption\n",
key->subkeys->can_encrypt ? "" : " not");
exit (1);
}
if (key->subkeys->can_sign != keys[i].secret)
{
fprintf (stderr, "Key unexpectedly%s usable for signing\n",
key->subkeys->can_sign ? "" : " not");
exit (1);
}
if (!key->subkeys->can_certify)
{
fprintf (stderr, "Primary key unexpectedly unusable for certifications\n");
exit (1);
}
if (key->subkeys->secret)
{
fprintf (stderr, "Primary key unexpectedly secret\n");
exit (1);
}
if (key->subkeys->pubkey_algo != GPGME_PK_RSA)
{
fprintf (stderr, "Primary key has unexpected public key algo: %s\n",
gpgme_pubkey_algo_name (key->subkeys->pubkey_algo));
exit (1);
}
if (key->subkeys->length != 1024)
{
fprintf (stderr, "Primary key has unexpected length: %i\n",
key->subkeys->length);
exit (1);
}
if (strcmp (key->subkeys->keyid, &keys[i].fpr[40 - 16]))
{
fprintf (stderr, "Primary key has unexpected key ID: %s\n",
key->subkeys->keyid);
exit (1);
}
if (strcmp (key->subkeys->fpr, keys[i].fpr))
{
fprintf (stderr, "Primary key has unexpected fingerprint: %s\n",
key->subkeys->fpr);
exit (1);
}
if (key->subkeys->expires != keys[i].expires)
{
fprintf (stderr, "Primary key unexpectedly expires: %lu\n",
key->subkeys->expires);
exit (1);
}
if (!key->uids || key->uids->next)
{
fprintf (stderr, "Key has unexpected number of user IDs\n");
exit (1);
}
if (key->uids->revoked)
{
fprintf (stderr, "User ID unexpectedly revoked\n");
exit (1);
}
if (key->uids->invalid)
{
fprintf (stderr, "User ID unexpectedly invalid\n");
exit (1);
}
if (key->uids->validity != GPGME_VALIDITY_UNKNOWN)
{
fprintf (stderr, "User ID unexpectedly validity: %i\n",
key->uids->validity);
exit (1);
}
if (key->uids->signatures)
{
fprintf (stderr, "User ID unexpectedly signed\n");
exit (1);
}
if (!key->uids->name || key->uids->name[0])
{
fprintf (stderr, "Unexpected name in user ID: %s\n",
key->uids->name);
exit (1);
}
if (!key->uids->comment || key->uids->comment[0])
{
fprintf (stderr, "Unexpected comment in user ID: %s\n",
key->uids->comment);
exit (1);
}
if (!key->uids->email || key->uids->email[0])
{
fprintf (stderr, "Unexpected email in user ID: %s\n",
key->uids->email);
exit (1);
}
if (!key->uids->uid || strcmp (key->uids->uid, keys[i].uid))
{
fprintf (stderr, "Unexpected uid in user ID: %s\n",
key->uids->uid);
exit (1);
}
gpgme_key_unref (key);
i++;
}
if (argc && !strcmp( *argv, "--secret" ) ) {
secret = 1;
argc--; argv++;
if (err != GPGME_EOF)
fail_if_err (err);
err = gpgme_op_keylist_end (ctx);
fail_if_err (err);
result = gpgme_op_keylist_result (ctx);
if (result->truncated)
{
fprintf (stderr, "Key listing unexpectedly truncated\n");
exit (1);
}
pattern = argc? *argv : NULL;
err = gpgme_engine_check_version (GPGME_PROTOCOL_CMS);
fail_if_err (err);
if (keys[i].fpr)
{
fprintf (stderr, "Less keys returned than expected\n");
exit (1);
}
err = gpgme_new (&ctx);
fail_if_err (err);
gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
gpgme_set_keylist_mode (ctx, 1); /* no validity calculation */
do {
fprintf (stderr, "** pattern=`%s'\n", pattern );
doit ( ctx, pattern, secret );
} while ( loop );
gpgme_release (ctx);
check_two_contexts ();
return 0;
gpgme_release (ctx);
return 0;
}