2002-12-04 Marcus Brinkmann <marcus@g10code.de>
* gpgme.h: Add prototype for gpgme_get_key. * key.c (gpgme_get_key): New function. * verify.c (gpgme_get_sig_key): Rewrite using gpgme_get_key. * gpgme.h: Add prototypes for new interfaces gpgme_key_sig_get_string_attr and gpgme_key_get_ulong_attr. (enum GpgmeAttr): New attribute GPGME_ATTR_SIG_CLASS. * gpgme.c (gpgme_set_keylist_mode): Allow GPGME_KEYLIST_MODE_SIGS. * key.h (struct certsig_s): New members ALGO, NAME_PART, EMAIL_PART, COMMENT_PART, NAME, SIG_STAT and SIG_CLASS. * conversion.c (_gpgme_decode_c_string): Add new parameter LEN. Use that to determine if allocation is desired or not. * util.h: Adjust prototype of _gpgme_decode_c_string. * keylist.c (keylist_colon_handler): Adjust caller of _gpgme_decode_c_string. * key.h (struct gpgme_key_s): New member last_uid. * key.c (_gpgme_key_append_name): Rewritten using _gpgme_decode_c_string and the last_uid pointer. (my_isdigit): Macro removed. (ALLOC_CHUNK): Likewise. * keylist.c (set_userid_flags): Use last_uid member of KEY. * context.h (struct user_id_s): New member last_certsig. * key.h: Add prototype for _gpgme_key_add_certsig. * key.c (_gpgme_key_add_certsig): New function. (set_user_id_part): Move function before _gpgme_key_add_certsig. (parse_user_id): Change first argument to SRC, add new arguments NAME, EMAIL and COMMENT. Change code to use these arguments instead going through UID. Move function before _gpgme_add_certsig. (parse_x509_user_id): Likewise. (_gpgme_key_append_name): Adjust arguments to parse_x509_user_id and parse_user_id invocation. (one_certsig_as_xml): New function. (one_uid_as_xml): Print signatures. * context.h (struct gpgme_context_s): New member TMP_UID. * keylist.c (keylist_colon_handler): Rewritten, implement "sig" record entries. * key.c (get_certsig): New function. (gpgme_key_sig_get_string_attr): Likewise. (gpgme_key_sig_get_ulong_attr): Likewise. * keylist.c: Include <ctype.h>. (my_isdigit): Macro removed. (set_mainkey_trust_info): Use isdigit, not my_isdigit. (set_userid_flags): Likewise. (set_subkey_trust_info): Likewise. (set_ownertrust): Likewise. (finish_key): Move function up a bit and remove prototype. * rungpg.c (gpg_keylist_ext): Correct precedence of signature listing mode. (gpg_keylist_ext): Implement signature listing mode.
This commit is contained in:
parent
7394638cdb
commit
1b495c5140
11
NEWS
11
NEWS
@ -1,6 +1,12 @@
|
|||||||
Noteworthy changes in version 0.4.0 (unreleased)
|
Noteworthy changes in version 0.4.0 (unreleased)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
|
* Supports signatures of user IDs in keys via the new
|
||||||
|
GPGME_KEYLIST_MODE_SIGS keylist mode and the
|
||||||
|
gpgme_key_sig_get_string_attr and gpgme_key_sig_get_ulong_attr
|
||||||
|
interfaces. The XML info about a key also includes the signatures
|
||||||
|
if available.
|
||||||
|
|
||||||
* New data object interface, which is more flexible and transparent.
|
* New data object interface, which is more flexible and transparent.
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -23,6 +29,11 @@ gpgme_op_verify CHANGED: Take different data objects for
|
|||||||
gpgme_op_verify_start CHANGED: See gpgme_op_verify.
|
gpgme_op_verify_start CHANGED: See gpgme_op_verify.
|
||||||
gpgme_check_engine REMOVED: Deprecated since 0.3.0.
|
gpgme_check_engine REMOVED: Deprecated since 0.3.0.
|
||||||
gpgme_op_genkey CHANGED: New parameter FPR.
|
gpgme_op_genkey CHANGED: New parameter FPR.
|
||||||
|
GPGME_KEYLIST_MODE_SIGS NEW
|
||||||
|
gpgme_key_sig_get_string_attr NEW
|
||||||
|
gpgme_key_sig_get_ulong_attr NEW
|
||||||
|
gpgme_get_key NEW
|
||||||
|
GPGME_ATTR_SIG_CLASS NEW
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Noteworthy changes in version 0.3.13 (2002-11-20)
|
Noteworthy changes in version 0.3.13 (2002-11-20)
|
||||||
|
@ -1,3 +1,62 @@
|
|||||||
|
2002-12-04 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* gpgme.h: Add prototype for gpgme_get_key.
|
||||||
|
* key.c (gpgme_get_key): New function.
|
||||||
|
* verify.c (gpgme_get_sig_key): Rewrite using gpgme_get_key.
|
||||||
|
|
||||||
|
* gpgme.h: Add prototypes for new interfaces
|
||||||
|
gpgme_key_sig_get_string_attr and gpgme_key_get_ulong_attr.
|
||||||
|
(enum GpgmeAttr): New attribute GPGME_ATTR_SIG_CLASS.
|
||||||
|
* gpgme.c (gpgme_set_keylist_mode): Allow GPGME_KEYLIST_MODE_SIGS.
|
||||||
|
* key.h (struct certsig_s): New members ALGO, NAME_PART,
|
||||||
|
EMAIL_PART, COMMENT_PART, NAME, SIG_STAT and SIG_CLASS.
|
||||||
|
|
||||||
|
* conversion.c (_gpgme_decode_c_string): Add new parameter LEN.
|
||||||
|
Use that to determine if allocation is desired or not.
|
||||||
|
* util.h: Adjust prototype of _gpgme_decode_c_string.
|
||||||
|
* keylist.c (keylist_colon_handler): Adjust caller of
|
||||||
|
_gpgme_decode_c_string.
|
||||||
|
|
||||||
|
* key.h (struct gpgme_key_s): New member last_uid.
|
||||||
|
* key.c (_gpgme_key_append_name): Rewritten using
|
||||||
|
_gpgme_decode_c_string and the last_uid pointer.
|
||||||
|
(my_isdigit): Macro removed.
|
||||||
|
(ALLOC_CHUNK): Likewise.
|
||||||
|
* keylist.c (set_userid_flags): Use last_uid member of KEY.
|
||||||
|
|
||||||
|
* context.h (struct user_id_s): New member last_certsig.
|
||||||
|
* key.h: Add prototype for _gpgme_key_add_certsig.
|
||||||
|
* key.c (_gpgme_key_add_certsig): New function.
|
||||||
|
(set_user_id_part): Move function before _gpgme_key_add_certsig.
|
||||||
|
(parse_user_id): Change first argument to SRC, add new arguments
|
||||||
|
NAME, EMAIL and COMMENT. Change code to use these arguments
|
||||||
|
instead going through UID. Move function before
|
||||||
|
_gpgme_add_certsig.
|
||||||
|
(parse_x509_user_id): Likewise.
|
||||||
|
(_gpgme_key_append_name): Adjust arguments to parse_x509_user_id
|
||||||
|
and parse_user_id invocation.
|
||||||
|
(one_certsig_as_xml): New function.
|
||||||
|
(one_uid_as_xml): Print signatures.
|
||||||
|
* context.h (struct gpgme_context_s): New member TMP_UID.
|
||||||
|
* keylist.c (keylist_colon_handler): Rewritten, implement "sig"
|
||||||
|
record entries.
|
||||||
|
|
||||||
|
* key.c (get_certsig): New function.
|
||||||
|
(gpgme_key_sig_get_string_attr): Likewise.
|
||||||
|
(gpgme_key_sig_get_ulong_attr): Likewise.
|
||||||
|
|
||||||
|
* keylist.c: Include <ctype.h>.
|
||||||
|
(my_isdigit): Macro removed.
|
||||||
|
(set_mainkey_trust_info): Use isdigit, not my_isdigit.
|
||||||
|
(set_userid_flags): Likewise.
|
||||||
|
(set_subkey_trust_info): Likewise.
|
||||||
|
(set_ownertrust): Likewise.
|
||||||
|
(finish_key): Move function up a bit and remove prototype.
|
||||||
|
|
||||||
|
* rungpg.c (gpg_keylist_ext): Correct precedence of signature
|
||||||
|
listing mode.
|
||||||
|
(gpg_keylist_ext): Implement signature listing mode.
|
||||||
|
|
||||||
2002-11-25 Marcus Brinkmann <marcus@g10code.de>
|
2002-11-25 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* rungpg.c (_gpgme_gpg_spawn): Do not set parent fds to -1.
|
* rungpg.c (_gpgme_gpg_spawn): Do not set parent fds to -1.
|
||||||
|
@ -1,23 +1,22 @@
|
|||||||
/* context.h
|
/* context.h
|
||||||
* Copyright (C) 2000 Werner Koch (dd9jn)
|
Copyright (C) 2000 Werner Koch (dd9jn)
|
||||||
* Copyright (C) 2001, 2002 g10 Code GmbH
|
Copyright (C) 2001, 2002 g10 Code GmbH
|
||||||
*
|
|
||||||
* This file is part of GPGME.
|
This file is part of GPGME.
|
||||||
*
|
|
||||||
* GPGME is free software; you can redistribute it and/or modify
|
GPGME is free software; you can redistribute it and/or modify it
|
||||||
* it under the terms of the GNU General Public License as published by
|
under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
(at your option) any later version.
|
||||||
*
|
|
||||||
* GPGME is distributed in the hope that it will be useful,
|
GPGME is distributed in the hope that it will be useful, but
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* GNU General Public License for more details.
|
General Public License for more details.
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
along with GPGME; if not, write to the Free Software Foundation,
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CONTEXT_H
|
#ifndef CONTEXT_H
|
||||||
#define CONTEXT_H
|
#define CONTEXT_H
|
||||||
@ -93,6 +92,7 @@ struct gpgme_context_s
|
|||||||
|
|
||||||
/* Used by keylist.c. */
|
/* Used by keylist.c. */
|
||||||
GpgmeKey tmp_key;
|
GpgmeKey tmp_key;
|
||||||
|
struct user_id_s *tmp_uid;
|
||||||
/* Something new is available. */
|
/* Something new is available. */
|
||||||
volatile int key_cond;
|
volatile int key_cond;
|
||||||
struct key_queue_item_s *key_queue;
|
struct key_queue_item_s *key_queue;
|
||||||
@ -124,6 +124,7 @@ struct user_id_s
|
|||||||
unsigned int invalid : 1;
|
unsigned int invalid : 1;
|
||||||
GpgmeValidity validity;
|
GpgmeValidity validity;
|
||||||
struct certsig_s *certsigs;
|
struct certsig_s *certsigs;
|
||||||
|
struct certsig_s *last_certsig;
|
||||||
const char *name_part; /* All 3 point into strings behind name */
|
const char *name_part; /* All 3 point into strings behind name */
|
||||||
const char *email_part; /* or to read-only strings. */
|
const char *email_part; /* or to read-only strings. */
|
||||||
const char *comment_part;
|
const char *comment_part;
|
||||||
|
@ -57,11 +57,21 @@ _gpgme_hextobyte (const byte *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Decode the C formatted string SRC and store the result in the
|
||||||
|
buffer *DESTP which is LEN bytes long. If LEN is zero, then a
|
||||||
|
large enough buffer is allocated with malloc and *DESTP is set to
|
||||||
|
the result. Currently, LEN is only used to specify if allocation
|
||||||
|
is desired or not, the caller is expected to make sure that *DESTP
|
||||||
|
is large enough if LEN is not zero. */
|
||||||
GpgmeError
|
GpgmeError
|
||||||
_gpgme_decode_c_string (const char *src, char **destp)
|
_gpgme_decode_c_string (const char *src, char **destp, int len)
|
||||||
{
|
{
|
||||||
char *dest;
|
char *dest;
|
||||||
|
|
||||||
|
if (len)
|
||||||
|
dest = *destp;
|
||||||
|
else
|
||||||
|
{
|
||||||
/* We can malloc a buffer of the same length, because the converted
|
/* We can malloc a buffer of the same length, because the converted
|
||||||
string will never be larger. */
|
string will never be larger. */
|
||||||
dest = malloc (strlen (src) + 1);
|
dest = malloc (strlen (src) + 1);
|
||||||
@ -69,6 +79,7 @@ _gpgme_decode_c_string (const char *src, char **destp)
|
|||||||
return mk_error (Out_Of_Core);
|
return mk_error (Out_Of_Core);
|
||||||
|
|
||||||
*destp = dest;
|
*destp = dest;
|
||||||
|
}
|
||||||
|
|
||||||
while (*src)
|
while (*src)
|
||||||
{
|
{
|
||||||
|
@ -1,25 +1,26 @@
|
|||||||
/* gpgme.c - GnuPG Made Easy
|
/* gpgme.c - GnuPG Made Easy
|
||||||
* Copyright (C) 2000 Werner Koch (dd9jn)
|
Copyright (C) 2000 Werner Koch (dd9jn)
|
||||||
* Copyright (C) 2001, 2002 g10 Code GmbH
|
Copyright (C) 2001, 2002 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
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. */
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -348,7 +349,8 @@ gpgme_set_keylist_mode (GpgmeCtx ctx, int mode)
|
|||||||
return mk_error (Invalid_Value);
|
return mk_error (Invalid_Value);
|
||||||
|
|
||||||
if (!((mode & GPGME_KEYLIST_MODE_LOCAL)
|
if (!((mode & GPGME_KEYLIST_MODE_LOCAL)
|
||||||
|| (mode & GPGME_KEYLIST_MODE_EXTERN)))
|
|| (mode & GPGME_KEYLIST_MODE_EXTERN)
|
||||||
|
|| (mode & GPGME_KEYLIST_MODE_SIGS)))
|
||||||
return mk_error (Invalid_Value);
|
return mk_error (Invalid_Value);
|
||||||
|
|
||||||
ctx->keylist_mode = mode;
|
ctx->keylist_mode = mode;
|
||||||
|
@ -196,7 +196,8 @@ typedef enum
|
|||||||
GPGME_ATTR_CHAINID = 28,
|
GPGME_ATTR_CHAINID = 28,
|
||||||
GPGME_ATTR_SIG_STATUS = 29,
|
GPGME_ATTR_SIG_STATUS = 29,
|
||||||
GPGME_ATTR_ERRTOK = 30,
|
GPGME_ATTR_ERRTOK = 30,
|
||||||
GPGME_ATTR_SIG_SUMMARY = 31
|
GPGME_ATTR_SIG_SUMMARY = 31,
|
||||||
|
GPGME_ATTR_SIG_CLASS = 32
|
||||||
}
|
}
|
||||||
GpgmeAttr;
|
GpgmeAttr;
|
||||||
|
|
||||||
@ -611,6 +612,13 @@ GpgmeError gpgme_data_rewind (GpgmeData dh);
|
|||||||
|
|
||||||
/* Key and trust functions. */
|
/* Key and trust functions. */
|
||||||
|
|
||||||
|
/* Get the key with the fingerprint FPR from the key cache or from the
|
||||||
|
crypto backend. If FORCE_UPDATE is true, force a refresh of the
|
||||||
|
key from the crypto backend and replace the key in the cache, if
|
||||||
|
any. If SECRET is true, get the secret key. */
|
||||||
|
GpgmeError gpgme_get_key (GpgmeCtx ctx, const char *fpr, GpgmeKey *r_key,
|
||||||
|
int secret, int force_update);
|
||||||
|
|
||||||
/* Acquire a reference to KEY. */
|
/* Acquire a reference to KEY. */
|
||||||
void gpgme_key_ref (GpgmeKey key);
|
void gpgme_key_ref (GpgmeKey key);
|
||||||
|
|
||||||
@ -635,6 +643,21 @@ const char *gpgme_key_get_string_attr (GpgmeKey key, GpgmeAttr what,
|
|||||||
unsigned long gpgme_key_get_ulong_attr (GpgmeKey key, GpgmeAttr what,
|
unsigned long gpgme_key_get_ulong_attr (GpgmeKey key, GpgmeAttr what,
|
||||||
const void *reserved, int idx);
|
const void *reserved, int idx);
|
||||||
|
|
||||||
|
/* Return the value of the attribute WHAT of a signature on user ID
|
||||||
|
UID_IDX in KEY, which has to be representable by a string. IDX
|
||||||
|
specifies the signature. */
|
||||||
|
const char *gpgme_key_sig_get_string_attr (GpgmeKey key, int uid_idx,
|
||||||
|
GpgmeAttr what,
|
||||||
|
const void *reserved, int idx);
|
||||||
|
|
||||||
|
/* Return the value of the attribute WHAT of a signature on user ID
|
||||||
|
UID_IDX in KEY, which has to be representable by an unsigned
|
||||||
|
integer string. IDX specifies the signature. */
|
||||||
|
unsigned long gpgme_key_sig_get_ulong_attr (GpgmeKey key, int uid_idx,
|
||||||
|
GpgmeAttr what,
|
||||||
|
const void *reserved, int idx);
|
||||||
|
|
||||||
|
|
||||||
/* Release the trust item ITEM. */
|
/* Release the trust item ITEM. */
|
||||||
void gpgme_trust_item_release (GpgmeTrustItem item);
|
void gpgme_trust_item_release (GpgmeTrustItem item);
|
||||||
|
|
||||||
|
670
gpgme/key.c
670
gpgme/key.c
@ -1,25 +1,26 @@
|
|||||||
/* key.c - Key and keyList objects
|
/* key.c - Key objects.
|
||||||
* Copyright (C) 2000 Werner Koch (dd9jn)
|
Copyright (C) 2000 Werner Koch (dd9jn)
|
||||||
* Copyright (C) 2001, 2002 g10 Code GmbH
|
Copyright (C) 2001, 2002 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
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. */
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -31,13 +32,11 @@
|
|||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "sema.h"
|
#include "sema.h"
|
||||||
|
|
||||||
#define ALLOC_CHUNK 1024
|
|
||||||
#define my_isdigit(a) ((a) >='0' && (a) <= '9')
|
|
||||||
|
|
||||||
#if SIZEOF_UNSIGNED_INT < 4
|
#if SIZEOF_UNSIGNED_INT < 4
|
||||||
#error unsigned int too short to be used as a hash value
|
#error unsigned int too short to be used as a hash value
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct key_cache_item_s
|
struct key_cache_item_s
|
||||||
{
|
{
|
||||||
struct key_cache_item_s *next;
|
struct key_cache_item_s *next;
|
||||||
@ -82,6 +81,7 @@ hash_key (const char *fpr, unsigned int *rhash)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_gpgme_key_cache_init (void)
|
_gpgme_key_cache_init (void)
|
||||||
{
|
{
|
||||||
@ -251,7 +251,7 @@ _gpgme_key_cache_get (const char *fpr)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
pkalgo_to_string (int algo)
|
pkalgo_to_string (int algo)
|
||||||
{
|
{
|
||||||
@ -288,12 +288,14 @@ key_new (GpgmeKey *r_key, int secret)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GpgmeError
|
GpgmeError
|
||||||
_gpgme_key_new (GpgmeKey *r_key)
|
_gpgme_key_new (GpgmeKey *r_key)
|
||||||
{
|
{
|
||||||
return key_new (r_key, 0);
|
return key_new (r_key, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GpgmeError
|
GpgmeError
|
||||||
_gpgme_key_new_secret (GpgmeKey *r_key)
|
_gpgme_key_new_secret (GpgmeKey *r_key)
|
||||||
{
|
{
|
||||||
@ -317,7 +319,7 @@ gpgme_key_ref (GpgmeKey key)
|
|||||||
UNLOCK (key_ref_lock);
|
UNLOCK (key_ref_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct subkey_s *
|
static struct subkey_s *
|
||||||
add_subkey (GpgmeKey key, int secret)
|
add_subkey (GpgmeKey key, int secret)
|
||||||
{
|
{
|
||||||
@ -354,7 +356,173 @@ _gpgme_key_add_secret_subkey (GpgmeKey key)
|
|||||||
return add_subkey (key, 1);
|
return add_subkey (key, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
set_user_id_part (char *tail, const char *buf, size_t len)
|
||||||
|
{
|
||||||
|
while (len && (buf[len - 1] == ' ' || buf[len - 1] == '\t'))
|
||||||
|
len--;
|
||||||
|
for (; len; len--)
|
||||||
|
*tail++ = *buf++;
|
||||||
|
*tail++ = 0;
|
||||||
|
return tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_user_id (const char *src, const char **name, const char **email,
|
||||||
|
const char **comment, char *tail)
|
||||||
|
{
|
||||||
|
const char *start = NULL;
|
||||||
|
int in_name = 0;
|
||||||
|
int in_email = 0;
|
||||||
|
int in_comment = 0;
|
||||||
|
|
||||||
|
while (*src)
|
||||||
|
{
|
||||||
|
if (in_email)
|
||||||
|
{
|
||||||
|
if (*src == '<')
|
||||||
|
/* Not legal but anyway. */
|
||||||
|
in_email++;
|
||||||
|
else if (*src == '>')
|
||||||
|
{
|
||||||
|
if (!--in_email && !*email)
|
||||||
|
{
|
||||||
|
*email = tail;
|
||||||
|
tail = set_user_id_part (tail, start, src - start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (in_comment)
|
||||||
|
{
|
||||||
|
if (*src == '(')
|
||||||
|
in_comment++;
|
||||||
|
else if (*src == ')')
|
||||||
|
{
|
||||||
|
if (!--in_comment && !*comment)
|
||||||
|
{
|
||||||
|
*comment = tail;
|
||||||
|
tail = set_user_id_part (tail, start, src - start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*src == '<')
|
||||||
|
{
|
||||||
|
if (in_name)
|
||||||
|
{
|
||||||
|
if (!*name)
|
||||||
|
{
|
||||||
|
*name = tail;
|
||||||
|
tail = set_user_id_part (tail, start, src - start);
|
||||||
|
}
|
||||||
|
in_name = 0;
|
||||||
|
}
|
||||||
|
in_email = 1;
|
||||||
|
start = src + 1;
|
||||||
|
}
|
||||||
|
else if (*src == '(')
|
||||||
|
{
|
||||||
|
if (in_name)
|
||||||
|
{
|
||||||
|
if (!*name)
|
||||||
|
{
|
||||||
|
*name = tail;
|
||||||
|
tail = set_user_id_part (tail, start, src - start);
|
||||||
|
}
|
||||||
|
in_name = 0;
|
||||||
|
}
|
||||||
|
in_comment = 1;
|
||||||
|
start = src + 1;
|
||||||
|
}
|
||||||
|
else if (!in_name && *src != ' ' && *src != '\t')
|
||||||
|
{
|
||||||
|
in_name = 1;
|
||||||
|
start = src;
|
||||||
|
}
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_name)
|
||||||
|
{
|
||||||
|
if (!*name)
|
||||||
|
{
|
||||||
|
*name = tail;
|
||||||
|
tail = set_user_id_part (tail, start, src - start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let unused parts point to an EOS. */
|
||||||
|
tail--;
|
||||||
|
if (!*name)
|
||||||
|
*name = tail;
|
||||||
|
if (!*email)
|
||||||
|
*email = tail;
|
||||||
|
if (!*comment)
|
||||||
|
*comment = tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_x509_user_id (const char *src, const char **name, const char **email,
|
||||||
|
const char **comment, char *tail)
|
||||||
|
{
|
||||||
|
if (*src == '<' && src[strlen (src) - 1] == '>')
|
||||||
|
*email = src;
|
||||||
|
|
||||||
|
/* Let unused parts point to an EOS. */
|
||||||
|
tail--;
|
||||||
|
if (!*name)
|
||||||
|
*name = tail;
|
||||||
|
if (!*email)
|
||||||
|
*email = tail;
|
||||||
|
if (!*comment)
|
||||||
|
*comment = tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct certsig_s *
|
||||||
|
_gpgme_key_add_certsig (GpgmeKey key, char *src)
|
||||||
|
{
|
||||||
|
int src_len = src ? strlen (src) : 0;
|
||||||
|
struct user_id_s *uid;
|
||||||
|
struct certsig_s *certsig;
|
||||||
|
|
||||||
|
assert (key); /* XXX */
|
||||||
|
|
||||||
|
uid = key->last_uid;
|
||||||
|
assert (uid); /* XXX */
|
||||||
|
|
||||||
|
/* We can malloc a buffer of the same length, because the converted
|
||||||
|
string will never be larger. Actually we allocate it twice the
|
||||||
|
size, so that we are able to store the parsed stuff there too. */
|
||||||
|
certsig = calloc (1, sizeof (*certsig) + 2 * src_len + 3);
|
||||||
|
if (!certsig)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (src)
|
||||||
|
{
|
||||||
|
char *dst = certsig->name;
|
||||||
|
_gpgme_decode_c_string (src, &dst, src_len + 1);
|
||||||
|
dst += src_len + 1;
|
||||||
|
if (key->x509)
|
||||||
|
parse_x509_user_id (src, &certsig->name_part, &certsig->email_part,
|
||||||
|
&certsig->comment_part, dst);
|
||||||
|
else
|
||||||
|
parse_user_id (src, &certsig->name_part, &certsig->email_part,
|
||||||
|
&certsig->comment_part, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!uid->certsigs)
|
||||||
|
uid->certsigs = certsig;
|
||||||
|
if (uid->last_certsig)
|
||||||
|
uid->last_certsig->next = certsig;
|
||||||
|
uid->last_certsig = certsig;
|
||||||
|
|
||||||
|
return certsig;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gpgme_key_release:
|
* gpgme_key_release:
|
||||||
* @key: Key Object or NULL
|
* @key: Key Object or NULL
|
||||||
@ -406,6 +574,7 @@ gpgme_key_release (GpgmeKey key)
|
|||||||
free (key);
|
free (key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gpgme_key_unref:
|
* gpgme_key_unref:
|
||||||
* @key: Key Object
|
* @key: Key Object
|
||||||
@ -418,237 +587,41 @@ gpgme_key_unref (GpgmeKey key)
|
|||||||
gpgme_key_release (key);
|
gpgme_key_release (key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *
|
/* Take a name from the --with-colon listing, remove certain escape
|
||||||
set_user_id_part (char *tail, const char *buf, size_t len)
|
sequences sequences and put it into the list of UIDs. */
|
||||||
{
|
|
||||||
while (len && (buf[len-1] == ' ' || buf[len-1] == '\t'))
|
|
||||||
len--;
|
|
||||||
for (; len; len--)
|
|
||||||
*tail++ = *buf++;
|
|
||||||
*tail++ = 0;
|
|
||||||
return tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
parse_user_id (struct user_id_s *uid, char *tail)
|
|
||||||
{
|
|
||||||
const char *s, *start=NULL;
|
|
||||||
int in_name = 0;
|
|
||||||
int in_email = 0;
|
|
||||||
int in_comment = 0;
|
|
||||||
|
|
||||||
for (s = uid->name; *s; s++)
|
|
||||||
{
|
|
||||||
if (in_email)
|
|
||||||
{
|
|
||||||
if (*s == '<')
|
|
||||||
/* Not legal but anyway. */
|
|
||||||
in_email++;
|
|
||||||
else if (*s == '>')
|
|
||||||
{
|
|
||||||
if (!--in_email)
|
|
||||||
{
|
|
||||||
if (!uid->email_part)
|
|
||||||
{
|
|
||||||
uid->email_part = tail;
|
|
||||||
tail = set_user_id_part ( tail, start, s-start );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (in_comment)
|
|
||||||
{
|
|
||||||
if (*s == '(')
|
|
||||||
in_comment++;
|
|
||||||
else if (*s== ')')
|
|
||||||
{
|
|
||||||
if (!--in_comment)
|
|
||||||
{
|
|
||||||
if (!uid->comment_part)
|
|
||||||
{
|
|
||||||
uid->comment_part = tail;
|
|
||||||
tail = set_user_id_part ( tail, start, s-start );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (*s == '<')
|
|
||||||
{
|
|
||||||
if (in_name)
|
|
||||||
{
|
|
||||||
if (!uid->name_part)
|
|
||||||
{
|
|
||||||
uid->name_part = tail;
|
|
||||||
tail = set_user_id_part (tail, start, s-start);
|
|
||||||
}
|
|
||||||
in_name = 0;
|
|
||||||
}
|
|
||||||
in_email = 1;
|
|
||||||
start = s+1;
|
|
||||||
}
|
|
||||||
else if (*s == '(')
|
|
||||||
{
|
|
||||||
if (in_name)
|
|
||||||
{
|
|
||||||
if (!uid->name_part)
|
|
||||||
{
|
|
||||||
uid->name_part = tail;
|
|
||||||
tail = set_user_id_part (tail, start, s-start );
|
|
||||||
}
|
|
||||||
in_name = 0;
|
|
||||||
}
|
|
||||||
in_comment = 1;
|
|
||||||
start = s+1;
|
|
||||||
}
|
|
||||||
else if (!in_name && *s != ' ' && *s != '\t')
|
|
||||||
{
|
|
||||||
in_name = 1;
|
|
||||||
start = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_name)
|
|
||||||
{
|
|
||||||
if (!uid->name_part)
|
|
||||||
{
|
|
||||||
uid->name_part = tail;
|
|
||||||
tail = set_user_id_part (tail, start, s-start);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Let unused parts point to an EOS. */
|
|
||||||
tail--;
|
|
||||||
if (!uid->name_part)
|
|
||||||
uid->name_part = tail;
|
|
||||||
if (!uid->email_part)
|
|
||||||
uid->email_part = tail;
|
|
||||||
if (!uid->comment_part)
|
|
||||||
uid->comment_part = tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
parse_x509_user_id (struct user_id_s *uid, char *tail)
|
|
||||||
{
|
|
||||||
const char *s;
|
|
||||||
|
|
||||||
s=uid->name;
|
|
||||||
if (*s == '<' && s[strlen (s) - 1] == '>')
|
|
||||||
uid->email_part = s;
|
|
||||||
|
|
||||||
/* Let unused parts point to an EOS. */
|
|
||||||
tail--;
|
|
||||||
if (!uid->name_part)
|
|
||||||
uid->name_part = tail;
|
|
||||||
if (!uid->email_part)
|
|
||||||
uid->email_part = tail;
|
|
||||||
if (!uid->comment_part)
|
|
||||||
uid->comment_part = tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Take a name from the --with-colon listing, remove certain escape sequences
|
|
||||||
* sequences and put it into the list of UIDs
|
|
||||||
*/
|
|
||||||
GpgmeError
|
GpgmeError
|
||||||
_gpgme_key_append_name (GpgmeKey key, const char *s)
|
_gpgme_key_append_name (GpgmeKey key, const char *src)
|
||||||
{
|
{
|
||||||
struct user_id_s *uid;
|
struct user_id_s *uid;
|
||||||
char *d;
|
char *dst;
|
||||||
|
int src_len = strlen (src);
|
||||||
|
|
||||||
assert (key);
|
assert (key);
|
||||||
/* We can malloc a buffer of the same length, because the converted
|
/* We can malloc a buffer of the same length, because the converted
|
||||||
string will never be larger. Actually we allocate it twice the
|
string will never be larger. Actually we allocate it twice the
|
||||||
size, so that we are able to store the parsed stuff there too. */
|
size, so that we are able to store the parsed stuff there too. */
|
||||||
uid = malloc (sizeof *uid + 2*strlen (s)+3);
|
uid = malloc (sizeof (*uid) + 2 * src_len + 3);
|
||||||
if (!uid)
|
if (!uid)
|
||||||
return mk_error (Out_Of_Core);
|
return mk_error (Out_Of_Core);
|
||||||
memset (uid, 0, sizeof *uid);
|
memset (uid, 0, sizeof *uid);
|
||||||
d = uid->name;
|
|
||||||
|
|
||||||
while (*s)
|
dst = uid->name;
|
||||||
{
|
_gpgme_decode_c_string (src, &dst, src_len + 1);
|
||||||
if (*s != '\\')
|
|
||||||
*d++ = *s++;
|
dst += src_len + 1;
|
||||||
else if (s[1] == '\\')
|
|
||||||
{
|
|
||||||
s++;
|
|
||||||
*d++ = *s++;
|
|
||||||
}
|
|
||||||
else if (s[1] == 'n')
|
|
||||||
{
|
|
||||||
s += 2;
|
|
||||||
*d++ = '\n';
|
|
||||||
}
|
|
||||||
else if (s[1] == 'r')
|
|
||||||
{
|
|
||||||
s += 2;
|
|
||||||
*d++ = '\r';
|
|
||||||
}
|
|
||||||
else if (s[1] == 'v')
|
|
||||||
{
|
|
||||||
s += 2;
|
|
||||||
*d++ = '\v';
|
|
||||||
}
|
|
||||||
else if (s[1] == 'b')
|
|
||||||
{
|
|
||||||
s += 2;
|
|
||||||
*d++ = '\b';
|
|
||||||
}
|
|
||||||
else if (s[1] == '0')
|
|
||||||
{
|
|
||||||
/* Hmmm: no way to express this */
|
|
||||||
s += 2;
|
|
||||||
*d++ = '\\';
|
|
||||||
*d++ = '\0';
|
|
||||||
}
|
|
||||||
else if (s[1] == 'x' && isxdigit (s[2]) && isxdigit (s[3]))
|
|
||||||
{
|
|
||||||
int val = _gpgme_hextobyte (&s[2]);
|
|
||||||
if (val == -1)
|
|
||||||
{
|
|
||||||
/* Should not happen. */
|
|
||||||
*d++ = *s++;
|
|
||||||
*d++ = *s++;
|
|
||||||
*d++ = *s++;
|
|
||||||
*d++ = *s++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!val)
|
|
||||||
{
|
|
||||||
*d++ = '\\';
|
|
||||||
*d++ = '\0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*(byte*)d++ = val;
|
|
||||||
s += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* should not happen */
|
|
||||||
s++;
|
|
||||||
*d++ = '\\';
|
|
||||||
*d++ = *s++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*d++ = 0;
|
|
||||||
if (key->x509)
|
if (key->x509)
|
||||||
parse_x509_user_id (uid, d);
|
parse_x509_user_id (src, &uid->name_part, &uid->email_part,
|
||||||
|
&uid->comment_part, dst);
|
||||||
else
|
else
|
||||||
parse_user_id (uid, d);
|
parse_user_id (src, &uid->name_part, &uid->email_part,
|
||||||
|
&uid->comment_part, dst);
|
||||||
|
|
||||||
if (key->uids)
|
if (!key->uids)
|
||||||
{
|
|
||||||
struct user_id_s *u = key->uids;
|
|
||||||
while (u->next)
|
|
||||||
u = u->next;
|
|
||||||
u->next = uid;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
key->uids = uid;
|
key->uids = uid;
|
||||||
|
if (key->last_uid)
|
||||||
|
key->last_uid->next = uid;
|
||||||
|
key->last_uid = uid;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -662,6 +635,7 @@ add_otag (GpgmeData d, const char *tag)
|
|||||||
_gpgme_data_append_string (d, ">");
|
_gpgme_data_append_string (d, ">");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_ctag (GpgmeData d, const char *tag)
|
add_ctag (GpgmeData d, const char *tag)
|
||||||
{
|
{
|
||||||
@ -670,6 +644,7 @@ add_ctag (GpgmeData d, const char *tag)
|
|||||||
_gpgme_data_append_string (d, ">\n");
|
_gpgme_data_append_string (d, ">\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_tag_and_string (GpgmeData d, const char *tag, const char *string)
|
add_tag_and_string (GpgmeData d, const char *tag, const char *string)
|
||||||
{
|
{
|
||||||
@ -678,6 +653,7 @@ add_tag_and_string (GpgmeData d, const char *tag, const char *string)
|
|||||||
add_ctag (d, tag);
|
add_ctag (d, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_tag_and_uint (GpgmeData d, const char *tag, unsigned int val)
|
add_tag_and_uint (GpgmeData d, const char *tag, unsigned int val)
|
||||||
{
|
{
|
||||||
@ -686,6 +662,7 @@ add_tag_and_uint (GpgmeData d, const char *tag, unsigned int val)
|
|||||||
add_tag_and_string (d, tag, buf);
|
add_tag_and_string (d, tag, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_tag_and_time (GpgmeData d, const char *tag, time_t val)
|
add_tag_and_time (GpgmeData d, const char *tag, time_t val)
|
||||||
{
|
{
|
||||||
@ -697,22 +674,55 @@ add_tag_and_time (GpgmeData d, const char *tag, time_t val)
|
|||||||
add_tag_and_string (d, tag, buf);
|
add_tag_and_string (d, tag, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
one_uid_as_xml (GpgmeData d, struct user_id_s *u)
|
one_certsig_as_xml (GpgmeData data, struct certsig_s *certsig)
|
||||||
{
|
{
|
||||||
_gpgme_data_append_string (d, " <userid>\n");
|
_gpgme_data_append_string (data, " <signature>\n");
|
||||||
if (u->invalid)
|
if (certsig->flags.invalid)
|
||||||
_gpgme_data_append_string (d, " <invalid/>\n");
|
_gpgme_data_append_string (data, " <invalid/>\n");
|
||||||
if (u->revoked)
|
if (certsig->flags.revoked)
|
||||||
_gpgme_data_append_string (d, " <revoked/>\n");
|
_gpgme_data_append_string (data, " <revoked/>\n");
|
||||||
add_tag_and_string (d, "raw", u->name);
|
if (certsig->flags.expired)
|
||||||
if (*u->name_part)
|
_gpgme_data_append_string (data, " <expired/>\n");
|
||||||
add_tag_and_string (d, "name", u->name_part);
|
add_tag_and_string (data, "keyid", certsig->keyid);
|
||||||
if (*u->email_part)
|
add_tag_and_uint (data, "algo", certsig->algo);
|
||||||
add_tag_and_string (d, "email", u->email_part);
|
add_tag_and_time (data, "created", certsig->timestamp);
|
||||||
if (*u->comment_part)
|
add_tag_and_time (data, "expire", certsig->expires_at);
|
||||||
add_tag_and_string (d, "comment", u->comment_part);
|
if (*certsig->name)
|
||||||
_gpgme_data_append_string (d, " </userid>\n");
|
add_tag_and_string (data, "raw", certsig->name);
|
||||||
|
if (*certsig->name_part)
|
||||||
|
add_tag_and_string (data, "name", certsig->name_part);
|
||||||
|
if (*certsig->email_part)
|
||||||
|
add_tag_and_string (data, "email", certsig->email_part);
|
||||||
|
if (*certsig->comment_part)
|
||||||
|
add_tag_and_string (data, "comment", certsig->comment_part);
|
||||||
|
_gpgme_data_append_string (data, " </signature>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
one_uid_as_xml (GpgmeData data, struct user_id_s *uid)
|
||||||
|
{
|
||||||
|
struct certsig_s *certsig;
|
||||||
|
|
||||||
|
_gpgme_data_append_string (data, " <userid>\n");
|
||||||
|
if (uid->invalid)
|
||||||
|
_gpgme_data_append_string (data, " <invalid/>\n");
|
||||||
|
if (uid->revoked)
|
||||||
|
_gpgme_data_append_string (data, " <revoked/>\n");
|
||||||
|
add_tag_and_string (data, "raw", uid->name);
|
||||||
|
if (*uid->name_part)
|
||||||
|
add_tag_and_string (data, "name", uid->name_part);
|
||||||
|
if (*uid->email_part)
|
||||||
|
add_tag_and_string (data, "email", uid->email_part);
|
||||||
|
if (*uid->comment_part)
|
||||||
|
add_tag_and_string (data, "comment", uid->comment_part);
|
||||||
|
|
||||||
|
/* Now the signatures. */
|
||||||
|
for (certsig = uid->certsigs; certsig; certsig = certsig->next)
|
||||||
|
one_certsig_as_xml (data, certsig);
|
||||||
|
_gpgme_data_append_string (data, " </userid>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -972,6 +982,7 @@ gpgme_key_get_string_attr (GpgmeKey key, GpgmeAttr what,
|
|||||||
case GPGME_ATTR_SIG_STATUS:
|
case GPGME_ATTR_SIG_STATUS:
|
||||||
case GPGME_ATTR_SIG_SUMMARY:
|
case GPGME_ATTR_SIG_SUMMARY:
|
||||||
case GPGME_ATTR_ERRTOK:
|
case GPGME_ATTR_ERRTOK:
|
||||||
|
case GPGME_ATTR_SIG_CLASS:
|
||||||
/* Not of any use here. */
|
/* Not of any use here. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1102,3 +1113,154 @@ gpgme_key_get_ulong_attr (GpgmeKey key, GpgmeAttr what,
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct certsig_s *
|
||||||
|
get_certsig (GpgmeKey key, int uid_idx, int idx)
|
||||||
|
{
|
||||||
|
struct user_id_s *uid;
|
||||||
|
struct certsig_s *certsig;
|
||||||
|
|
||||||
|
if (!key || uid_idx < 0 || idx < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
uid = key->uids;
|
||||||
|
while (uid && uid_idx > 0)
|
||||||
|
{
|
||||||
|
uid = uid->next;
|
||||||
|
uid_idx--;
|
||||||
|
}
|
||||||
|
if (!uid)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
certsig = uid->certsigs;
|
||||||
|
while (certsig && idx > 0)
|
||||||
|
{
|
||||||
|
certsig = certsig->next;
|
||||||
|
idx--;
|
||||||
|
}
|
||||||
|
return certsig;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gpgme_key_sig_get_string_attr (GpgmeKey key, int uid_idx, GpgmeAttr what,
|
||||||
|
const void *reserved, int idx)
|
||||||
|
{
|
||||||
|
struct certsig_s *certsig = get_certsig (key, uid_idx, idx);
|
||||||
|
|
||||||
|
if (!certsig || reserved)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
switch (what)
|
||||||
|
{
|
||||||
|
case GPGME_ATTR_KEYID:
|
||||||
|
return certsig->keyid;
|
||||||
|
|
||||||
|
case GPGME_ATTR_ALGO:
|
||||||
|
return pkalgo_to_string (certsig->algo);
|
||||||
|
|
||||||
|
case GPGME_ATTR_USERID:
|
||||||
|
return certsig->name;
|
||||||
|
|
||||||
|
case GPGME_ATTR_NAME:
|
||||||
|
return certsig->name_part;
|
||||||
|
|
||||||
|
case GPGME_ATTR_EMAIL:
|
||||||
|
return certsig->email_part;
|
||||||
|
|
||||||
|
case GPGME_ATTR_COMMENT:
|
||||||
|
return certsig->comment_part;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long
|
||||||
|
gpgme_key_sig_get_ulong_attr (GpgmeKey key, int uid_idx, GpgmeAttr what,
|
||||||
|
const void *reserved, int idx)
|
||||||
|
{
|
||||||
|
struct certsig_s *certsig = get_certsig (key, uid_idx, idx);
|
||||||
|
|
||||||
|
if (!certsig || reserved)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (what)
|
||||||
|
{
|
||||||
|
case GPGME_ATTR_ALGO:
|
||||||
|
return (unsigned long) certsig->algo;
|
||||||
|
|
||||||
|
case GPGME_ATTR_CREATED:
|
||||||
|
return certsig->timestamp < 0 ? 0L : (unsigned long) certsig->timestamp;
|
||||||
|
|
||||||
|
case GPGME_ATTR_EXPIRE:
|
||||||
|
return certsig->expires_at < 0 ? 0L : (unsigned long) certsig->expires_at;
|
||||||
|
|
||||||
|
case GPGME_ATTR_KEY_REVOKED:
|
||||||
|
return certsig->flags.revoked;
|
||||||
|
|
||||||
|
case GPGME_ATTR_KEY_INVALID:
|
||||||
|
return certsig->flags.invalid;
|
||||||
|
|
||||||
|
case GPGME_ATTR_KEY_EXPIRED:
|
||||||
|
return certsig->flags.expired;
|
||||||
|
|
||||||
|
case GPGME_ATTR_SIG_CLASS:
|
||||||
|
return certsig->sig_class;
|
||||||
|
|
||||||
|
case GPGME_ATTR_SIG_STATUS:
|
||||||
|
return certsig->sig_stat;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get the key with the fingerprint FPR from the key cache or from the
|
||||||
|
crypto backend. If FORCE_UPDATE is true, force a refresh of the
|
||||||
|
key from the crypto backend and replace the key in the cache, if
|
||||||
|
any. If SECRET is true, get the secret key. */
|
||||||
|
GpgmeError
|
||||||
|
gpgme_get_key (GpgmeCtx ctx, const char *fpr, GpgmeKey *r_key,
|
||||||
|
int secret, int force_update)
|
||||||
|
{
|
||||||
|
GpgmeCtx listctx;
|
||||||
|
GpgmeError err;
|
||||||
|
|
||||||
|
if (!ctx || !r_key)
|
||||||
|
return mk_error (Invalid_Value);
|
||||||
|
if (ctx->pending)
|
||||||
|
return mk_error (Busy);
|
||||||
|
|
||||||
|
if (strlen (fpr) < 16) /* We have at least a key ID. */
|
||||||
|
return mk_error (Invalid_Key);
|
||||||
|
|
||||||
|
if (!force_update)
|
||||||
|
{
|
||||||
|
*r_key = _gpgme_key_cache_get (fpr);
|
||||||
|
if (*r_key)
|
||||||
|
{
|
||||||
|
/* If the primary UID (if available) has no signatures, and
|
||||||
|
we are in the signature listing keylist mode, then try to
|
||||||
|
update the key below before returning. */
|
||||||
|
if (!((ctx->keylist_mode & GPGME_KEYLIST_MODE_SIGS)
|
||||||
|
&& (*r_key)->uids && !(*r_key)->uids->certsigs))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fixme: This can be optimized by keeping an internal context
|
||||||
|
used for such key listings. */
|
||||||
|
err = gpgme_new (&listctx);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
gpgme_set_protocol (listctx, gpgme_get_protocol (ctx));
|
||||||
|
gpgme_set_keylist_mode (listctx, ctx->keylist_mode);
|
||||||
|
err = gpgme_op_keylist_start (listctx, fpr, secret);
|
||||||
|
if (!err)
|
||||||
|
err = gpgme_op_keylist_next (listctx, r_key);
|
||||||
|
gpgme_release (listctx);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
93
gpgme/key.h
93
gpgme/key.h
@ -1,23 +1,22 @@
|
|||||||
/* key.h
|
/* key.h - Key handling interface.
|
||||||
* Copyright (C) 2000 Werner Koch (dd9jn)
|
Copyright (C) 2000 Werner Koch (dd9jn)
|
||||||
* Copyright (C) 2001 g10 Code GmbH
|
Copyright (C) 2001, 2002 g10 Code GmbH
|
||||||
*
|
|
||||||
* This file is part of GPGME.
|
This file is part of GPGME.
|
||||||
*
|
|
||||||
* GPGME is free software; you can redistribute it and/or modify
|
GPGME is free software; you can redistribute it and/or modify it
|
||||||
* it under the terms of the GNU General Public License as published by
|
under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
(at your option) any later version.
|
||||||
*
|
|
||||||
* GPGME is distributed in the hope that it will be useful,
|
GPGME is distributed in the hope that it will be useful, but
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* GNU General Public License for more details.
|
General Public License for more details.
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
along with GPGME; if not, write to the Free Software Foundation,
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef KEY_H
|
#ifndef KEY_H
|
||||||
#define KEY_H
|
#define KEY_H
|
||||||
@ -26,22 +25,36 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
|
||||||
struct certsig_s {
|
|
||||||
|
struct certsig_s
|
||||||
|
{
|
||||||
struct certsig_s *next;
|
struct certsig_s *next;
|
||||||
struct {
|
struct
|
||||||
|
{
|
||||||
unsigned int revoked : 1;
|
unsigned int revoked : 1;
|
||||||
unsigned int expired : 1;
|
unsigned int expired : 1;
|
||||||
unsigned int invalid : 1;
|
unsigned int invalid : 1;
|
||||||
|
unsigned int exportable : 1;
|
||||||
} flags;
|
} flags;
|
||||||
|
unsigned int algo;
|
||||||
char keyid[16 + 1];
|
char keyid[16 + 1];
|
||||||
time_t timestamp; /* -1 for invalid, 0 for not available */
|
time_t timestamp; /* -1 for invalid, 0 for not available. */
|
||||||
time_t expires_at; /* 0 for does not expires */
|
time_t expires_at; /* 0 for no expiration. */
|
||||||
|
GpgmeSigStat sig_stat;
|
||||||
|
unsigned int sig_class;
|
||||||
|
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];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct subkey_s {
|
|
||||||
|
struct subkey_s
|
||||||
|
{
|
||||||
struct subkey_s *next;
|
struct subkey_s *next;
|
||||||
unsigned int secret:1;
|
unsigned int secret:1;
|
||||||
struct {
|
struct
|
||||||
|
{
|
||||||
unsigned int revoked : 1;
|
unsigned int revoked : 1;
|
||||||
unsigned int expired : 1;
|
unsigned int expired : 1;
|
||||||
unsigned int disabled : 1;
|
unsigned int disabled : 1;
|
||||||
@ -53,13 +66,16 @@ struct subkey_s {
|
|||||||
unsigned int key_algo;
|
unsigned int key_algo;
|
||||||
unsigned int key_len;
|
unsigned int key_len;
|
||||||
char keyid[16 + 1];
|
char keyid[16 + 1];
|
||||||
char *fingerprint; /* malloced hex digits */
|
char *fingerprint; /* Malloced hex digits. */
|
||||||
time_t timestamp; /* -1 for invalid, 0 for not available */
|
time_t timestamp; /* -1 for invalid, 0 for not available. */
|
||||||
time_t expires_at; /* 0 for does not expires */
|
time_t expires_at; /* 0 for does not expires. */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gpgme_key_s {
|
|
||||||
struct {
|
struct gpgme_key_s
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
unsigned int revoked : 1;
|
unsigned int revoked : 1;
|
||||||
unsigned int expired : 1;
|
unsigned int expired : 1;
|
||||||
unsigned int disabled : 1;
|
unsigned int disabled : 1;
|
||||||
@ -71,23 +87,24 @@ struct gpgme_key_s {
|
|||||||
unsigned int ref_count;
|
unsigned int ref_count;
|
||||||
unsigned int secret : 1;
|
unsigned int secret : 1;
|
||||||
unsigned int x509 : 1;
|
unsigned int x509 : 1;
|
||||||
char *issuer_serial; /* malloced string used only with X.509 */
|
char *issuer_serial; /* Malloced string used only with X.509. */
|
||||||
char *issuer_name; /* ditto */
|
char *issuer_name; /* Ditto. */
|
||||||
char *chain_id; /* ditto */
|
char *chain_id; /* Ditto. */
|
||||||
GpgmeValidity otrust; /* only used with OpenPGP */
|
GpgmeValidity otrust; /* Only used with OpenPGP. */
|
||||||
struct subkey_s keys;
|
struct subkey_s keys;
|
||||||
struct user_id_s *uids;
|
struct user_id_s *uids;
|
||||||
|
struct user_id_s *last_uid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void _gpgme_key_cache_init (void);
|
void _gpgme_key_cache_init (void);
|
||||||
void _gpgme_key_cache_add (GpgmeKey key);
|
void _gpgme_key_cache_add (GpgmeKey key);
|
||||||
GpgmeKey _gpgme_key_cache_get (const char *fpr);
|
GpgmeKey _gpgme_key_cache_get (const char *fpr);
|
||||||
|
|
||||||
|
|
||||||
|
struct certsig_s *_gpgme_key_add_certsig (GpgmeKey key, char *src);
|
||||||
struct subkey_s *_gpgme_key_add_subkey (GpgmeKey key);
|
struct subkey_s *_gpgme_key_add_subkey (GpgmeKey key);
|
||||||
struct subkey_s *_gpgme_key_add_secret_subkey (GpgmeKey key);
|
struct subkey_s *_gpgme_key_add_secret_subkey (GpgmeKey key);
|
||||||
GpgmeError _gpgme_key_append_name ( GpgmeKey key, const char *s );
|
GpgmeError _gpgme_key_append_name (GpgmeKey key, const char *str);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* KEY_H */
|
#endif /* KEY_H */
|
||||||
|
668
gpgme/keylist.c
668
gpgme/keylist.c
@ -1,46 +1,45 @@
|
|||||||
/* keylist.c - key listing
|
/* keylist.c - Listing keys.
|
||||||
* Copyright (C) 2000 Werner Koch (dd9jn)
|
Copyright (C) 2000 Werner Koch (dd9jn)
|
||||||
* Copyright (C) 2001, 2002 g10 Code GmbH
|
Copyright (C) 2001, 2002 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
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. */
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "ops.h"
|
#include "ops.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
|
||||||
#define my_isdigit(a) ( (a) >='0' && (a) <= '9' )
|
|
||||||
|
|
||||||
struct keylist_result_s
|
struct keylist_result_s
|
||||||
{
|
{
|
||||||
int truncated;
|
int truncated;
|
||||||
GpgmeData xmlinfo;
|
GpgmeData xmlinfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void finish_key ( GpgmeCtx ctx );
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_gpgme_release_keylist_result (KeylistResult result)
|
_gpgme_release_keylist_result (KeylistResult result)
|
||||||
@ -50,6 +49,7 @@ _gpgme_release_keylist_result (KeylistResult result)
|
|||||||
free (result);
|
free (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Append some XML info. args is currently ignore but we might want
|
/* Append some XML info. args is currently ignore but we might want
|
||||||
to add more information in the future (like source of the
|
to add more information in the future (like source of the
|
||||||
keylisting. With args of NULL the XML structure is closed. */
|
keylisting. With args of NULL the XML structure is closed. */
|
||||||
@ -78,15 +78,11 @@ append_xml_keylistinfo (GpgmeData *rdh, char *args)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_gpgme_data_append_string (dh,
|
_gpgme_data_append_string (dh, " <keylisting>\n <truncated/>\n");
|
||||||
" <keylisting>\n"
|
|
||||||
" <truncated/>\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
keylist_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
|
keylist_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
|
||||||
{
|
{
|
||||||
@ -117,124 +113,218 @@ keylist_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static time_t
|
static time_t
|
||||||
parse_timestamp (char *p)
|
parse_timestamp (char *timestamp)
|
||||||
{
|
{
|
||||||
if (!*p)
|
if (!*timestamp)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return (time_t)strtoul (p, NULL, 10);
|
return (time_t) strtoul (timestamp, NULL, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_mainkey_trust_info (GpgmeKey key, const char *s)
|
set_mainkey_trust_info (GpgmeKey key, const char *src)
|
||||||
{
|
{
|
||||||
/* Look at letters and stop at the first digit. */
|
/* Look at letters and stop at the first digit. */
|
||||||
for (; *s && !my_isdigit (*s); s++)
|
while (*src && !isdigit (*src))
|
||||||
{
|
{
|
||||||
switch (*s)
|
switch (*src)
|
||||||
{
|
{
|
||||||
case 'e': key->keys.flags.expired = 1; break;
|
case 'e':
|
||||||
case 'r': key->keys.flags.revoked = 1; break;
|
key->keys.flags.expired = 1;
|
||||||
case 'd': key->keys.flags.disabled = 1; break;
|
break;
|
||||||
case 'i': key->keys.flags.invalid = 1; break;
|
|
||||||
|
case 'r':
|
||||||
|
key->keys.flags.revoked = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
key->keys.flags.disabled = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
key->keys.flags.invalid = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
src++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_userid_flags (GpgmeKey key, const char *s)
|
set_userid_flags (GpgmeKey key, const char *src)
|
||||||
{
|
{
|
||||||
struct user_id_s *u = key->uids;
|
struct user_id_s *uid = key->last_uid;
|
||||||
|
|
||||||
assert (u);
|
|
||||||
while (u->next)
|
|
||||||
u = u->next;
|
|
||||||
|
|
||||||
|
assert (uid);
|
||||||
/* Look at letters and stop at the first digit. */
|
/* Look at letters and stop at the first digit. */
|
||||||
for (; *s && !my_isdigit (*s); s++)
|
while (*src && !isdigit (*src))
|
||||||
{
|
{
|
||||||
switch (*s)
|
switch (*src)
|
||||||
{
|
{
|
||||||
case 'r': u->revoked = 1; break;
|
case 'r':
|
||||||
case 'i': u->invalid = 1; break;
|
uid->revoked = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'n': u->validity = GPGME_VALIDITY_NEVER; break;
|
case 'i':
|
||||||
case 'm': u->validity = GPGME_VALIDITY_MARGINAL; break;
|
uid->invalid = 1;
|
||||||
case 'f': u->validity = GPGME_VALIDITY_FULL; break;
|
break;
|
||||||
case 'u': u->validity = GPGME_VALIDITY_ULTIMATE; break;
|
|
||||||
|
case 'n':
|
||||||
|
uid->validity = GPGME_VALIDITY_NEVER;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
uid->validity = GPGME_VALIDITY_MARGINAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
uid->validity = GPGME_VALIDITY_FULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
uid->validity = GPGME_VALIDITY_ULTIMATE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
src++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_subkey_trust_info (struct subkey_s *k, const char *s)
|
set_subkey_trust_info (struct subkey_s *subkey, const char *src)
|
||||||
{
|
{
|
||||||
/* Look at letters and stop at the first digit. */
|
/* Look at letters and stop at the first digit. */
|
||||||
for (; *s && !my_isdigit (*s); s++)
|
while (*src && !isdigit (*src))
|
||||||
{
|
{
|
||||||
switch (*s)
|
switch (*src)
|
||||||
{
|
{
|
||||||
case 'e': k->flags.expired = 1; break;
|
case 'e':
|
||||||
case 'r': k->flags.revoked = 1; break;
|
subkey->flags.expired = 1;
|
||||||
case 'd': k->flags.disabled = 1; break;
|
break;
|
||||||
case 'i': k->flags.invalid = 1; break;
|
|
||||||
|
case 'r':
|
||||||
|
subkey->flags.revoked = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
subkey->flags.disabled = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
subkey->flags.invalid = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
src++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_mainkey_capability (GpgmeKey key, const char *s)
|
set_mainkey_capability (GpgmeKey key, const char *src)
|
||||||
{
|
{
|
||||||
for (; *s ; s++)
|
while (*src)
|
||||||
{
|
{
|
||||||
switch (*s)
|
switch (*src)
|
||||||
{
|
{
|
||||||
case 'e': key->keys.flags.can_encrypt = 1; break;
|
case 'e':
|
||||||
case 's': key->keys.flags.can_sign = 1; break;
|
key->keys.flags.can_encrypt = 1;
|
||||||
case 'c': key->keys.flags.can_certify = 1; break;
|
break;
|
||||||
case 'E': key->gloflags.can_encrypt = 1; break;
|
|
||||||
case 'S': key->gloflags.can_sign = 1; break;
|
case 's':
|
||||||
case 'C': key->gloflags.can_certify = 1; break;
|
key->keys.flags.can_sign = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
key->keys.flags.can_certify = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'E':
|
||||||
|
key->gloflags.can_encrypt = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
key->gloflags.can_sign = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
key->gloflags.can_certify = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
src++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_subkey_capability ( struct subkey_s *k, const char *s)
|
set_subkey_capability (struct subkey_s *subkey, const char *src)
|
||||||
{
|
{
|
||||||
for (; *s; s++)
|
while (*src)
|
||||||
{
|
{
|
||||||
switch (*s)
|
switch (*src)
|
||||||
{
|
{
|
||||||
case 'e': k->flags.can_encrypt = 1; break;
|
case 'e':
|
||||||
case 's': k->flags.can_sign = 1; break;
|
subkey->flags.can_encrypt = 1;
|
||||||
case 'c': k->flags.can_certify = 1; break;
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
subkey->flags.can_sign = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
subkey->flags.can_certify = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
src++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_ownertrust (GpgmeKey key, const char *s)
|
set_ownertrust (GpgmeKey key, const char *src)
|
||||||
{
|
{
|
||||||
/* Look at letters and stop at the first digit. */
|
/* Look at letters and stop at the first digit. */
|
||||||
for (; *s && !my_isdigit (*s); s++)
|
while (*src && !isdigit (*src))
|
||||||
{
|
{
|
||||||
switch (*s)
|
switch (*src)
|
||||||
{
|
{
|
||||||
case 'n': key->otrust = GPGME_VALIDITY_NEVER; break;
|
case 'n':
|
||||||
case 'm': key->otrust = GPGME_VALIDITY_MARGINAL; break;
|
key->otrust = GPGME_VALIDITY_NEVER;
|
||||||
case 'f': key->otrust = GPGME_VALIDITY_FULL; break;
|
break;
|
||||||
case 'u': key->otrust = GPGME_VALIDITY_ULTIMATE; break;
|
|
||||||
default : key->otrust = GPGME_VALIDITY_UNKNOWN; break;
|
case 'm':
|
||||||
|
key->otrust = GPGME_VALIDITY_MARGINAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
key->otrust = GPGME_VALIDITY_FULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
key->otrust = GPGME_VALIDITY_ULTIMATE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
key->otrust = GPGME_VALIDITY_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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. */
|
||||||
|
static void
|
||||||
|
finish_key (GpgmeCtx ctx)
|
||||||
|
{
|
||||||
|
GpgmeKey key = ctx->tmp_key;
|
||||||
|
|
||||||
|
ctx->tmp_key = NULL;
|
||||||
|
|
||||||
|
if (key)
|
||||||
|
_gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -242,67 +332,67 @@ set_ownertrust (GpgmeKey key, const char *s)
|
|||||||
static void
|
static void
|
||||||
keylist_colon_handler (GpgmeCtx ctx, char *line)
|
keylist_colon_handler (GpgmeCtx ctx, char *line)
|
||||||
{
|
{
|
||||||
char *p, *pend;
|
|
||||||
int field = 0;
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR, RT_SSB, RT_SEC,
|
RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR, RT_SSB, RT_SEC,
|
||||||
RT_CRT, RT_CRS
|
RT_CRT, RT_CRS, RT_REV
|
||||||
}
|
}
|
||||||
rectype = RT_NONE;
|
rectype = RT_NONE;
|
||||||
|
#define NR_FIELDS 13
|
||||||
|
char *field[NR_FIELDS];
|
||||||
|
int fields = 0;
|
||||||
GpgmeKey key = ctx->tmp_key;
|
GpgmeKey key = ctx->tmp_key;
|
||||||
int i;
|
struct subkey_s *subkey = NULL;
|
||||||
const char *trust_info = NULL;
|
struct certsig_s *certsig = NULL;
|
||||||
struct subkey_s *sk = NULL;
|
|
||||||
|
DEBUG3 ("keylist_colon_handler ctx = %p, key = %p, line = %s\n",
|
||||||
|
ctx, key, line ? line : "(null)");
|
||||||
|
|
||||||
DEBUG3 ("keylist_colon_handler ctx=%p, key=%p, line=%s\n", ctx, key,
|
|
||||||
line? line: "(null)");
|
|
||||||
if (ctx->error)
|
if (ctx->error)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!line)
|
if (!line)
|
||||||
{
|
{
|
||||||
/* EOF */
|
/* End Of File. */
|
||||||
finish_key (ctx);
|
finish_key (ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (p = line; p; p = pend)
|
while (line && fields < NR_FIELDS)
|
||||||
{
|
{
|
||||||
field++;
|
field[fields++] = line;
|
||||||
pend = strchr (p, ':');
|
line = strchr (line, ':');
|
||||||
if (pend)
|
if (line)
|
||||||
*pend++ = 0;
|
*(line++) = '\0';
|
||||||
|
|
||||||
if (field == 1)
|
|
||||||
{
|
|
||||||
if (!strcmp (p, "sig"))
|
|
||||||
rectype = RT_SIG;
|
|
||||||
else if (!strcmp (p, "uid") && key)
|
|
||||||
{
|
|
||||||
rectype = RT_UID;
|
|
||||||
key = ctx->tmp_key;
|
|
||||||
}
|
}
|
||||||
else if (!strcmp (p, "sub") && key)
|
|
||||||
|
if (!strcmp (field[0], "sig"))
|
||||||
|
rectype = RT_SIG;
|
||||||
|
else if (!strcmp (field[0], "rev"))
|
||||||
|
rectype = RT_REV;
|
||||||
|
else if (!strcmp (field[0], "uid") && key)
|
||||||
|
rectype = RT_UID;
|
||||||
|
else if (!strcmp (field[0], "sub") && key)
|
||||||
{
|
{
|
||||||
/* Start a new subkey. */
|
/* Start a new subkey. */
|
||||||
rectype = RT_SUB;
|
rectype = RT_SUB;
|
||||||
if (!(sk = _gpgme_key_add_subkey (key)))
|
if (!(subkey = _gpgme_key_add_subkey (key)))
|
||||||
{
|
{
|
||||||
ctx->error = mk_error (Out_Of_Core);
|
ctx->error = mk_error (Out_Of_Core);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strcmp (p, "ssb") && key)
|
else if (!strcmp (field[0], "ssb") && key)
|
||||||
{
|
{
|
||||||
/* Start a new secret subkey. */
|
/* Start a new secret subkey. */
|
||||||
rectype = RT_SSB;
|
rectype = RT_SSB;
|
||||||
if (!(sk = _gpgme_key_add_secret_subkey (key)))
|
if (!(subkey = _gpgme_key_add_secret_subkey (key)))
|
||||||
{
|
{
|
||||||
ctx->error = mk_error (Out_Of_Core);
|
ctx->error = mk_error (Out_Of_Core);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strcmp (p, "pub"))
|
else if (!strcmp (field[0], "pub"))
|
||||||
{
|
{
|
||||||
/* Start a new keyblock. */
|
/* Start a new keyblock. */
|
||||||
if (_gpgme_key_new (&key))
|
if (_gpgme_key_new (&key))
|
||||||
@ -316,7 +406,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
|
|||||||
assert (!ctx->tmp_key);
|
assert (!ctx->tmp_key);
|
||||||
ctx->tmp_key = key;
|
ctx->tmp_key = key;
|
||||||
}
|
}
|
||||||
else if (!strcmp (p, "sec"))
|
else if (!strcmp (field[0], "sec"))
|
||||||
{
|
{
|
||||||
/* Start a new keyblock, */
|
/* Start a new keyblock, */
|
||||||
if (_gpgme_key_new_secret (&key))
|
if (_gpgme_key_new_secret (&key))
|
||||||
@ -330,7 +420,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
|
|||||||
assert (!ctx->tmp_key);
|
assert (!ctx->tmp_key);
|
||||||
ctx->tmp_key = key;
|
ctx->tmp_key = key;
|
||||||
}
|
}
|
||||||
else if (!strcmp (p, "crt"))
|
else if (!strcmp (field[0], "crt"))
|
||||||
{
|
{
|
||||||
/* Start a new certificate. */
|
/* Start a new certificate. */
|
||||||
if (_gpgme_key_new (&key))
|
if (_gpgme_key_new (&key))
|
||||||
@ -345,7 +435,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
|
|||||||
assert (!ctx->tmp_key);
|
assert (!ctx->tmp_key);
|
||||||
ctx->tmp_key = key;
|
ctx->tmp_key = key;
|
||||||
}
|
}
|
||||||
else if (!strcmp (p, "crs"))
|
else if (!strcmp (field[0], "crs"))
|
||||||
{
|
{
|
||||||
/* Start a new certificate. */
|
/* Start a new certificate. */
|
||||||
if (_gpgme_key_new_secret (&key))
|
if (_gpgme_key_new_secret (&key))
|
||||||
@ -360,171 +450,240 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
|
|||||||
assert (!ctx->tmp_key);
|
assert (!ctx->tmp_key);
|
||||||
ctx->tmp_key = key;
|
ctx->tmp_key = key;
|
||||||
}
|
}
|
||||||
else if (!strcmp (p, "fpr") && key)
|
else if (!strcmp (field[0], "fpr") && key)
|
||||||
rectype = RT_FPR;
|
rectype = RT_FPR;
|
||||||
else
|
else
|
||||||
rectype = RT_NONE;
|
rectype = RT_NONE;
|
||||||
}
|
|
||||||
else if (rectype == RT_PUB || rectype == RT_SEC
|
/* Only look at signatures immediately following a user ID. For
|
||||||
|| rectype == RT_CRT || rectype == RT_CRS)
|
this, clear the user ID pointer when encountering anything but a
|
||||||
|
signature. */
|
||||||
|
if (rectype != RT_SIG && rectype != RT_REV)
|
||||||
|
ctx->tmp_uid = NULL;
|
||||||
|
|
||||||
|
switch (rectype)
|
||||||
{
|
{
|
||||||
switch (field)
|
case RT_CRT:
|
||||||
|
case RT_CRS:
|
||||||
|
/* Field 8 has the X.509 serial number. */
|
||||||
|
if (fields >= 8)
|
||||||
{
|
{
|
||||||
case 2: /* trust info */
|
key->issuer_serial = strdup (field[7]);
|
||||||
trust_info = p;
|
|
||||||
set_mainkey_trust_info (key, trust_info);
|
|
||||||
break;
|
|
||||||
case 3: /* key length */
|
|
||||||
i = atoi (p);
|
|
||||||
if (i > 1) /* ignore invalid values */
|
|
||||||
key->keys.key_len = i;
|
|
||||||
break;
|
|
||||||
case 4: /* pubkey algo */
|
|
||||||
i = atoi (p);
|
|
||||||
if (i >= 1 && i < 128)
|
|
||||||
key->keys.key_algo = i;
|
|
||||||
break;
|
|
||||||
case 5: /* long keyid */
|
|
||||||
if (strlen (p) == DIM(key->keys.keyid) - 1)
|
|
||||||
strcpy (key->keys.keyid, p);
|
|
||||||
break;
|
|
||||||
case 6: /* timestamp (seconds) */
|
|
||||||
key->keys.timestamp = parse_timestamp (p);
|
|
||||||
break;
|
|
||||||
case 7: /* expiration time (seconds) */
|
|
||||||
key->keys.expires_at = parse_timestamp (p);
|
|
||||||
break;
|
|
||||||
case 8: /* X.509 serial number */
|
|
||||||
if (rectype == RT_CRT || rectype == RT_CRS)
|
|
||||||
{
|
|
||||||
key->issuer_serial = strdup (p);
|
|
||||||
if (!key->issuer_serial)
|
if (!key->issuer_serial)
|
||||||
ctx->error = mk_error (Out_Of_Core);
|
ctx->error = mk_error (Out_Of_Core);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case 9: /* ownertrust */
|
/* Field 10 is not used for gpg due to --fixed-list-mode option
|
||||||
set_ownertrust (key, p);
|
but GPGSM stores the issuer name. */
|
||||||
break;
|
if (fields >= 10 && _gpgme_decode_c_string (field[9],
|
||||||
case 10:
|
&key->issuer_name, 0))
|
||||||
/* Not used for gpg due to --fixed-list-mode option but
|
|
||||||
GPGSM stores the issuer name. */
|
|
||||||
if (rectype == RT_CRT || rectype == RT_CRS)
|
|
||||||
if (_gpgme_decode_c_string (p, &key->issuer_name))
|
|
||||||
ctx->error = mk_error (Out_Of_Core);
|
ctx->error = mk_error (Out_Of_Core);
|
||||||
break;
|
/* Fall through! */
|
||||||
case 11: /* signature class */
|
|
||||||
break;
|
case RT_PUB:
|
||||||
case 12: /* capabilities */
|
case RT_SEC:
|
||||||
set_mainkey_capability (key, p);
|
/* Field 2 has the trust info. */
|
||||||
break;
|
if (fields >= 2)
|
||||||
case 13:
|
set_mainkey_trust_info (key, field[1]);
|
||||||
pend = NULL; /* we can stop here */
|
|
||||||
break;
|
/* Field 3 has the key length. */
|
||||||
}
|
if (fields >= 3)
|
||||||
}
|
|
||||||
else if ((rectype == RT_SUB || rectype== RT_SSB) && sk)
|
|
||||||
{
|
{
|
||||||
switch (field)
|
int i = atoi (field[2]);
|
||||||
|
/* Ignore invalid values. */
|
||||||
|
if (i > 1)
|
||||||
|
key->keys.key_len = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Field 4 has the public key algorithm. */
|
||||||
|
if (fields >= 4)
|
||||||
{
|
{
|
||||||
case 2: /* trust info */
|
int i = atoi (field[3]);
|
||||||
set_subkey_trust_info (sk, p);
|
|
||||||
break;
|
|
||||||
case 3: /* key length */
|
|
||||||
i = atoi (p);
|
|
||||||
if (i > 1) /* ignore invalid values */
|
|
||||||
sk->key_len = i;
|
|
||||||
break;
|
|
||||||
case 4: /* pubkey algo */
|
|
||||||
i = atoi (p);
|
|
||||||
if (i >= 1 && i < 128)
|
if (i >= 1 && i < 128)
|
||||||
sk->key_algo = i;
|
key->keys.key_algo = i;
|
||||||
break;
|
|
||||||
case 5: /* long keyid */
|
|
||||||
if (strlen (p) == DIM(sk->keyid) - 1)
|
|
||||||
strcpy (sk->keyid, p);
|
|
||||||
break;
|
|
||||||
case 6: /* timestamp (seconds) */
|
|
||||||
sk->timestamp = parse_timestamp (p);
|
|
||||||
break;
|
|
||||||
case 7: /* expiration time (seconds) */
|
|
||||||
sk->expires_at = parse_timestamp (p);
|
|
||||||
break;
|
|
||||||
case 8: /* reserved (LID) */
|
|
||||||
break;
|
|
||||||
case 9: /* ownertrust */
|
|
||||||
break;
|
|
||||||
case 10:/* user ID n/a for a subkey */
|
|
||||||
break;
|
|
||||||
case 11: /* signature class */
|
|
||||||
break;
|
|
||||||
case 12: /* capability */
|
|
||||||
set_subkey_capability (sk, p);
|
|
||||||
break;
|
|
||||||
case 13:
|
|
||||||
pend = NULL; /* we can stop here */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (rectype == RT_UID)
|
/* Field 5 has the long keyid. */
|
||||||
{
|
if (fields >= 5 && strlen (field[4]) == DIM(key->keys.keyid) - 1)
|
||||||
switch (field)
|
strcpy (key->keys.keyid, field[4]);
|
||||||
{
|
|
||||||
case 2: /* trust info */
|
/* Field 6 has the timestamp (seconds). */
|
||||||
trust_info = p; /*save for later */
|
if (fields >= 6)
|
||||||
|
key->keys.timestamp = parse_timestamp (field[5]);
|
||||||
|
|
||||||
|
/* Field 7 has the expiration time (seconds). */
|
||||||
|
if (fields >= 7)
|
||||||
|
key->keys.expires_at = parse_timestamp (field[6]);
|
||||||
|
|
||||||
|
/* Field 9 has the ownertrust. */
|
||||||
|
if (fields >= 9)
|
||||||
|
set_ownertrust (key, field[8]);
|
||||||
|
|
||||||
|
/* Field 11 has the signature class. */
|
||||||
|
|
||||||
|
/* Field 12 has the capabilities. */
|
||||||
|
if (fields >= 12)
|
||||||
|
set_mainkey_capability (key, field[11]);
|
||||||
break;
|
break;
|
||||||
case 10: /* user ID */
|
|
||||||
if (_gpgme_key_append_name (key, p))
|
case RT_SUB:
|
||||||
/* The only kind of error we can get*/
|
case RT_SSB:
|
||||||
|
/* Field 2 has the trust info. */
|
||||||
|
if (fields >= 2)
|
||||||
|
set_subkey_trust_info (subkey, field[1]);
|
||||||
|
|
||||||
|
/* Field 3 has the key length. */
|
||||||
|
if (fields >= 3)
|
||||||
|
{
|
||||||
|
int i = atoi (field[2]);
|
||||||
|
/* Ignore invalid values. */
|
||||||
|
if (i > 1)
|
||||||
|
subkey->key_len = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Field 4 has the public key algorithm. */
|
||||||
|
if (fields >= 4)
|
||||||
|
{
|
||||||
|
int i = atoi (field[3]);
|
||||||
|
if (i >= 1 && i < 128)
|
||||||
|
subkey->key_algo = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Field 5 has the long keyid. */
|
||||||
|
if (fields >= 5 && strlen (field[4]) == DIM(subkey->keyid) - 1)
|
||||||
|
strcpy (subkey->keyid, field[4]);
|
||||||
|
|
||||||
|
/* Field 6 has the timestamp (seconds). */
|
||||||
|
if (fields >= 6)
|
||||||
|
subkey->timestamp = parse_timestamp (field[5]);
|
||||||
|
|
||||||
|
/* Field 7 has the expiration time (seconds). */
|
||||||
|
if (fields >= 7)
|
||||||
|
subkey->expires_at = parse_timestamp (field[6]);
|
||||||
|
|
||||||
|
/* Field 8 is reserved (LID). */
|
||||||
|
/* Field 9 has the ownertrust. */
|
||||||
|
/* Field 10, the user ID, is n/a for a subkey. */
|
||||||
|
|
||||||
|
/* Field 11 has the signature class. */
|
||||||
|
|
||||||
|
/* Field 12 has the capabilities. */
|
||||||
|
if (fields >= 12)
|
||||||
|
set_subkey_capability (subkey, field[11]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RT_UID:
|
||||||
|
/* Field 2 has the trust info, and field 10 has the user ID. */
|
||||||
|
if (fields >= 10)
|
||||||
|
{
|
||||||
|
if (_gpgme_key_append_name (key, field[9]))
|
||||||
ctx->error = mk_error (Out_Of_Core);
|
ctx->error = mk_error (Out_Of_Core);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (trust_info)
|
if (field[1])
|
||||||
set_userid_flags (key, trust_info);
|
set_userid_flags (key, field[1]);
|
||||||
|
ctx->tmp_uid = key->last_uid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pend = NULL; /* we can stop here */
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
case RT_FPR:
|
||||||
else if (rectype == RT_FPR)
|
/* Field 10 has the fingerprint (take only the first one). */
|
||||||
|
if (fields >= 10 && !key->keys.fingerprint && field[9] && *field[9])
|
||||||
{
|
{
|
||||||
switch (field)
|
key->keys.fingerprint = strdup (field[9]);
|
||||||
{
|
|
||||||
case 10: /* fingerprint (take only the first one)*/
|
|
||||||
if (!key->keys.fingerprint && *p)
|
|
||||||
{
|
|
||||||
key->keys.fingerprint = strdup (p);
|
|
||||||
if (!key->keys.fingerprint)
|
if (!key->keys.fingerprint)
|
||||||
ctx->error = mk_error (Out_Of_Core);
|
ctx->error = mk_error (Out_Of_Core);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case 13: /* gpgsm chain ID (take only the first one)*/
|
/* Field 13 has the gpgsm chain ID (take only the first one). */
|
||||||
if (!key->chain_id && *p)
|
if (fields >= 13 && !key->chain_id && *field[12])
|
||||||
{
|
{
|
||||||
key->chain_id = strdup (p);
|
key->chain_id = strdup (field[12]);
|
||||||
if (!key->chain_id)
|
if (!key->chain_id)
|
||||||
ctx->error = mk_error (Out_Of_Core);
|
ctx->error = mk_error (Out_Of_Core);
|
||||||
}
|
}
|
||||||
pend = NULL; /* that is all we want */
|
break;
|
||||||
|
|
||||||
|
case RT_SIG:
|
||||||
|
case RT_REV:
|
||||||
|
if (!ctx->tmp_uid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
ctx->error = mk_error (Out_Of_Core);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Field 2 has the calculated trust ('!', '-', '?', '%'). */
|
||||||
|
if (fields >= 2)
|
||||||
|
switch (field[1][0])
|
||||||
|
{
|
||||||
|
case '!':
|
||||||
|
certsig->sig_stat = GPGME_SIG_STAT_GOOD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '-':
|
||||||
|
certsig->sig_stat = GPGME_SIG_STAT_BAD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
certsig->sig_stat = GPGME_SIG_STAT_NOKEY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '%':
|
||||||
|
certsig->sig_stat = GPGME_SIG_STAT_ERROR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
certsig->sig_stat = GPGME_SIG_STAT_NONE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Field 4 has the public key algorithm. */
|
||||||
/*
|
if (fields >= 4)
|
||||||
* We have read an entire key into ctx->tmp_key and should now finish
|
|
||||||
* it. It is assumed that this releases ctx->tmp_key.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
finish_key (GpgmeCtx ctx)
|
|
||||||
{
|
{
|
||||||
GpgmeKey key = ctx->tmp_key;
|
int i = atoi (field[3]);
|
||||||
|
if (i >= 1 && i < 128)
|
||||||
|
certsig->algo = i;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->tmp_key = NULL;
|
/* Field 5 has the long keyid. */
|
||||||
|
if (fields >= 5 && strlen (field[4]) == DIM(certsig->keyid) - 1)
|
||||||
|
strcpy (certsig->keyid, field[4]);
|
||||||
|
|
||||||
if (key)
|
/* Field 6 has the timestamp (seconds). */
|
||||||
_gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
|
if (fields >= 6)
|
||||||
|
certsig->timestamp = parse_timestamp (field[5]);
|
||||||
|
|
||||||
|
/* Field 7 has the expiration time (seconds). */
|
||||||
|
if (fields >= 7)
|
||||||
|
certsig->expires_at = parse_timestamp (field[6]);
|
||||||
|
|
||||||
|
/* Field 11 has the signature class (eg, 0x30 means revoked). */
|
||||||
|
if (fields >= 11)
|
||||||
|
if (field[10][0] && field[10][1])
|
||||||
|
{
|
||||||
|
int class = _gpgme_hextobyte (field[10]);
|
||||||
|
if (class >= 0)
|
||||||
|
{
|
||||||
|
certsig->sig_class = class;
|
||||||
|
if (class == 0x30)
|
||||||
|
certsig->flags.revoked = 1;
|
||||||
|
}
|
||||||
|
if (field[10][2] == 'x')
|
||||||
|
certsig->flags.exportable = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RT_NONE:
|
||||||
|
/* Unknown record. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -593,9 +752,9 @@ gpgme_op_keylist_start (GpgmeCtx ctx, const char *pattern, int secret_only)
|
|||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
/* We don't want to use the verbose mode as this will also print
|
/* We don't want to use the verbose mode as this will also print the
|
||||||
the key signatures which is in most cases not needed and furthermore we
|
key signatures which is in most cases not needed and furthermore
|
||||||
just ignore those lines - This should speed up things */
|
we just ignore those lines - This should speed up things. */
|
||||||
_gpgme_engine_set_verbosity (ctx->engine, 0);
|
_gpgme_engine_set_verbosity (ctx->engine, 0);
|
||||||
|
|
||||||
err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
|
err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
|
||||||
@ -647,15 +806,16 @@ gpgme_op_keylist_ext_start (GpgmeCtx ctx, const char *pattern[],
|
|||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
/* We don't want to use the verbose mode as this will also print
|
/* We don't want to use the verbose mode as this will also print the
|
||||||
the key signatures which is in most cases not needed and furthermore we
|
key signatures which is in most cases not needed and furthermore
|
||||||
just ignore those lines - This should speed up things */
|
we just ignore those lines - This should speed up things. */
|
||||||
_gpgme_engine_set_verbosity (ctx->engine, 0);
|
_gpgme_engine_set_verbosity (ctx->engine, 0);
|
||||||
|
|
||||||
err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
|
err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
|
||||||
reserved, ctx->keylist_mode);
|
reserved, ctx->keylist_mode);
|
||||||
|
|
||||||
if (!err) /* And kick off the process. */
|
/* And kick off the process. */
|
||||||
|
if (!err)
|
||||||
err = _gpgme_engine_start (ctx->engine, ctx);
|
err = _gpgme_engine_start (ctx->engine, ctx);
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
@ -1486,10 +1486,9 @@ gpg_keylist (void *engine, const char *pattern, int secret_only,
|
|||||||
if (!err)
|
if (!err)
|
||||||
err = add_arg (gpg, "--with-fingerprint");
|
err = add_arg (gpg, "--with-fingerprint");
|
||||||
if (!err)
|
if (!err)
|
||||||
err = add_arg (gpg, (keylist_mode & GPGME_KEYLIST_MODE_SIGS) ?
|
err = add_arg (gpg, secret_only ? "--list-secret-keys"
|
||||||
"--check-sigs" :
|
: ((keylist_mode & GPGME_KEYLIST_MODE_SIGS)
|
||||||
secret_only ? "--list-secret-keys"
|
? "--check-sigs" : "--list-keys"));
|
||||||
: "--list-keys");
|
|
||||||
|
|
||||||
/* Tell the gpg object about the data. */
|
/* Tell the gpg object about the data. */
|
||||||
if (!err)
|
if (!err)
|
||||||
@ -1519,7 +1518,9 @@ gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
|
|||||||
if (!err)
|
if (!err)
|
||||||
err = add_arg (gpg, "--with-fingerprint");
|
err = add_arg (gpg, "--with-fingerprint");
|
||||||
if (!err)
|
if (!err)
|
||||||
err = add_arg (gpg, secret_only ? "--list-secret-keys" : "--list-keys");
|
err = add_arg (gpg, secret_only ? "--list-secret-keys"
|
||||||
|
: ((keylist_mode & GPGME_KEYLIST_MODE_SIGS)
|
||||||
|
? "--check-sigs" : "--list-keys"));
|
||||||
|
|
||||||
/* Tell the gpg object about the data. */
|
/* Tell the gpg object about the data. */
|
||||||
if (!err)
|
if (!err)
|
||||||
|
@ -85,7 +85,13 @@ FILE *fopencookie (void *cookie, const char *opentype,
|
|||||||
|
|
||||||
|
|
||||||
/*-- conversion.c --*/
|
/*-- conversion.c --*/
|
||||||
GpgmeError _gpgme_decode_c_string (const char *src, char **destp);
|
/* Decode the C formatted string SRC and store the result in the
|
||||||
|
buffer *DESTP which is LEN bytes long. If LEN is zero, then a
|
||||||
|
large enough buffer is allocated with malloc and *DESTP is set to
|
||||||
|
the result. Currently, LEN is only used to specify if allocation
|
||||||
|
is desired or not, the caller is expected to make sure that *DESTP
|
||||||
|
is large enough if LEN is not zero. */
|
||||||
|
GpgmeError _gpgme_decode_c_string (const char *src, char **destp, int len);
|
||||||
int _gpgme_hextobyte (const byte *str);
|
int _gpgme_hextobyte (const byte *str);
|
||||||
|
|
||||||
#endif /* UTIL_H */
|
#endif /* UTIL_H */
|
||||||
|
@ -643,42 +643,20 @@ gpgme_get_sig_ulong_attr (GpgmeCtx c, int idx, GpgmeAttr what, int reserved)
|
|||||||
* indicate that there are no more signatures.
|
* indicate that there are no more signatures.
|
||||||
**/
|
**/
|
||||||
GpgmeError
|
GpgmeError
|
||||||
gpgme_get_sig_key (GpgmeCtx c, int idx, GpgmeKey *r_key)
|
gpgme_get_sig_key (GpgmeCtx ctx, int idx, GpgmeKey *r_key)
|
||||||
{
|
{
|
||||||
VerifyResult result;
|
VerifyResult result;
|
||||||
GpgmeError err = 0;
|
|
||||||
|
|
||||||
if (!c || !r_key)
|
if (!ctx || !r_key)
|
||||||
return mk_error (Invalid_Value);
|
return mk_error (Invalid_Value);
|
||||||
if (c->pending || !c->result.verify)
|
if (ctx->pending || !ctx->result.verify)
|
||||||
return mk_error (Busy);
|
return mk_error (Busy);
|
||||||
|
|
||||||
for (result = c->result.verify;
|
for (result = ctx->result.verify;
|
||||||
result && idx > 0; result = result->next, idx--)
|
result && idx > 0; result = result->next, idx--)
|
||||||
;
|
;
|
||||||
if (!result)
|
if (!result)
|
||||||
return mk_error (EOF);
|
return mk_error (EOF);
|
||||||
|
|
||||||
if (strlen(result->fpr) < 16) /* We have at least a key ID. */
|
return gpgme_get_key (ctx, result->fpr, r_key, 0, 0);
|
||||||
return mk_error (Invalid_Key);
|
|
||||||
|
|
||||||
*r_key = _gpgme_key_cache_get (result->fpr);
|
|
||||||
if (!*r_key)
|
|
||||||
{
|
|
||||||
GpgmeCtx listctx;
|
|
||||||
|
|
||||||
/* Fixme: This can be optimized by keeping an internal context
|
|
||||||
used for such key listings. */
|
|
||||||
err = gpgme_new (&listctx);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
gpgme_set_protocol (listctx, gpgme_get_protocol (c));
|
|
||||||
gpgme_set_keylist_mode (listctx, c->keylist_mode);
|
|
||||||
err = gpgme_op_keylist_start (listctx, result->fpr, 0);
|
|
||||||
if (!err)
|
|
||||||
err = gpgme_op_keylist_next (listctx, r_key);
|
|
||||||
gpgme_release (listctx);
|
|
||||||
}
|
}
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user