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)
|
||||
------------------------------------------------
|
||||
|
||||
* 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.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -23,6 +29,11 @@ gpgme_op_verify CHANGED: Take different data objects for
|
||||
gpgme_op_verify_start CHANGED: See gpgme_op_verify.
|
||||
gpgme_check_engine REMOVED: Deprecated since 0.3.0.
|
||||
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)
|
||||
|
@ -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>
|
||||
|
||||
* rungpg.c (_gpgme_gpg_spawn): Do not set parent fds to -1.
|
||||
|
@ -1,23 +1,22 @@
|
||||
/* context.h
|
||||
* Copyright (C) 2000 Werner Koch (dd9jn)
|
||||
* 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
|
||||
*/
|
||||
Copyright (C) 2000 Werner Koch (dd9jn)
|
||||
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 GPGME; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef CONTEXT_H
|
||||
#define CONTEXT_H
|
||||
@ -93,6 +92,7 @@ struct gpgme_context_s
|
||||
|
||||
/* 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;
|
||||
@ -124,6 +124,7 @@ struct user_id_s
|
||||
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;
|
||||
|
@ -57,18 +57,29 @@ _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
|
||||
_gpgme_decode_c_string (const char *src, char **destp)
|
||||
_gpgme_decode_c_string (const char *src, char **destp, int len)
|
||||
{
|
||||
char *dest;
|
||||
|
||||
/* We can malloc a buffer of the same length, because the converted
|
||||
string will never be larger. */
|
||||
dest = malloc (strlen (src) + 1);
|
||||
if (!dest)
|
||||
return mk_error (Out_Of_Core);
|
||||
if (len)
|
||||
dest = *destp;
|
||||
else
|
||||
{
|
||||
/* We can malloc a buffer of the same length, because the converted
|
||||
string will never be larger. */
|
||||
dest = malloc (strlen (src) + 1);
|
||||
if (!dest)
|
||||
return mk_error (Out_Of_Core);
|
||||
|
||||
*destp = dest;
|
||||
*destp = dest;
|
||||
}
|
||||
|
||||
while (*src)
|
||||
{
|
||||
|
@ -1,25 +1,26 @@
|
||||
/* gpgme.c - GnuPG Made Easy
|
||||
* Copyright (C) 2000 Werner Koch (dd9jn)
|
||||
* 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
|
||||
*/
|
||||
Copyright (C) 2000 Werner Koch (dd9jn)
|
||||
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 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>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -348,8 +349,9 @@ gpgme_set_keylist_mode (GpgmeCtx ctx, int mode)
|
||||
return mk_error (Invalid_Value);
|
||||
|
||||
if (!((mode & GPGME_KEYLIST_MODE_LOCAL)
|
||||
|| (mode & GPGME_KEYLIST_MODE_EXTERN)))
|
||||
return mk_error (Invalid_Value);
|
||||
|| (mode & GPGME_KEYLIST_MODE_EXTERN)
|
||||
|| (mode & GPGME_KEYLIST_MODE_SIGS)))
|
||||
return mk_error (Invalid_Value);
|
||||
|
||||
ctx->keylist_mode = mode;
|
||||
return 0;
|
||||
|
@ -196,7 +196,8 @@ typedef enum
|
||||
GPGME_ATTR_CHAINID = 28,
|
||||
GPGME_ATTR_SIG_STATUS = 29,
|
||||
GPGME_ATTR_ERRTOK = 30,
|
||||
GPGME_ATTR_SIG_SUMMARY = 31
|
||||
GPGME_ATTR_SIG_SUMMARY = 31,
|
||||
GPGME_ATTR_SIG_CLASS = 32
|
||||
}
|
||||
GpgmeAttr;
|
||||
|
||||
@ -611,6 +612,13 @@ GpgmeError gpgme_data_rewind (GpgmeData dh);
|
||||
|
||||
/* 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. */
|
||||
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,
|
||||
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. */
|
||||
void gpgme_trust_item_release (GpgmeTrustItem item);
|
||||
|
||||
|
676
gpgme/key.c
676
gpgme/key.c
@ -1,25 +1,26 @@
|
||||
/* key.c - Key and keyList objects
|
||||
* Copyright (C) 2000 Werner Koch (dd9jn)
|
||||
* 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
|
||||
*/
|
||||
/* key.c - Key objects.
|
||||
Copyright (C) 2000 Werner Koch (dd9jn)
|
||||
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 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>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -31,13 +32,11 @@
|
||||
#include "key.h"
|
||||
#include "sema.h"
|
||||
|
||||
#define ALLOC_CHUNK 1024
|
||||
#define my_isdigit(a) ((a) >='0' && (a) <= '9')
|
||||
|
||||
#if SIZEOF_UNSIGNED_INT < 4
|
||||
#error unsigned int too short to be used as a hash value
|
||||
#endif
|
||||
|
||||
|
||||
struct key_cache_item_s
|
||||
{
|
||||
struct key_cache_item_s *next;
|
||||
@ -82,6 +81,7 @@ hash_key (const char *fpr, unsigned int *rhash)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_gpgme_key_cache_init (void)
|
||||
{
|
||||
@ -251,7 +251,7 @@ _gpgme_key_cache_get (const char *fpr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char *
|
||||
pkalgo_to_string (int algo)
|
||||
{
|
||||
@ -288,12 +288,14 @@ key_new (GpgmeKey *r_key, int secret)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
GpgmeError
|
||||
_gpgme_key_new (GpgmeKey *r_key)
|
||||
{
|
||||
return key_new (r_key, 0);
|
||||
}
|
||||
|
||||
|
||||
GpgmeError
|
||||
_gpgme_key_new_secret (GpgmeKey *r_key)
|
||||
{
|
||||
@ -317,7 +319,7 @@ gpgme_key_ref (GpgmeKey key)
|
||||
UNLOCK (key_ref_lock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static struct subkey_s *
|
||||
add_subkey (GpgmeKey key, int secret)
|
||||
{
|
||||
@ -327,7 +329,7 @@ add_subkey (GpgmeKey key, int secret)
|
||||
if (!k)
|
||||
return NULL;
|
||||
|
||||
if(!(kk = key->keys.next))
|
||||
if (!(kk = key->keys.next))
|
||||
key->keys.next = k;
|
||||
else
|
||||
{
|
||||
@ -354,7 +356,173 @@ _gpgme_key_add_secret_subkey (GpgmeKey key)
|
||||
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:
|
||||
* @key: Key Object or NULL
|
||||
@ -406,6 +574,7 @@ gpgme_key_release (GpgmeKey key)
|
||||
free (key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gpgme_key_unref:
|
||||
* @key: Key Object
|
||||
@ -418,237 +587,41 @@ gpgme_key_unref (GpgmeKey key)
|
||||
gpgme_key_release (key);
|
||||
}
|
||||
|
||||
|
||||
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 (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
|
||||
*/
|
||||
|
||||
/* Take a name from the --with-colon listing, remove certain escape
|
||||
sequences sequences and put it into the list of UIDs. */
|
||||
GpgmeError
|
||||
_gpgme_key_append_name (GpgmeKey key, const char *s)
|
||||
_gpgme_key_append_name (GpgmeKey key, const char *src)
|
||||
{
|
||||
struct user_id_s *uid;
|
||||
char *d;
|
||||
char *dst;
|
||||
int src_len = strlen (src);
|
||||
|
||||
assert (key);
|
||||
/* 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. */
|
||||
uid = malloc (sizeof *uid + 2*strlen (s)+3);
|
||||
uid = malloc (sizeof (*uid) + 2 * src_len + 3);
|
||||
if (!uid)
|
||||
return mk_error (Out_Of_Core);
|
||||
memset (uid, 0, sizeof *uid);
|
||||
d = uid->name;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
if (*s != '\\')
|
||||
*d++ = *s++;
|
||||
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;
|
||||
dst = uid->name;
|
||||
_gpgme_decode_c_string (src, &dst, src_len + 1);
|
||||
|
||||
dst += src_len + 1;
|
||||
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
|
||||
parse_user_id (uid, d);
|
||||
parse_user_id (src, &uid->name_part, &uid->email_part,
|
||||
&uid->comment_part, dst);
|
||||
|
||||
if (key->uids)
|
||||
{
|
||||
struct user_id_s *u = key->uids;
|
||||
while (u->next)
|
||||
u = u->next;
|
||||
u->next = uid;
|
||||
}
|
||||
else
|
||||
if (!key->uids)
|
||||
key->uids = uid;
|
||||
if (key->last_uid)
|
||||
key->last_uid->next = uid;
|
||||
key->last_uid = uid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -662,6 +635,7 @@ add_otag (GpgmeData d, const char *tag)
|
||||
_gpgme_data_append_string (d, ">");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
add_ctag (GpgmeData d, const char *tag)
|
||||
{
|
||||
@ -670,6 +644,7 @@ add_ctag (GpgmeData d, const char *tag)
|
||||
_gpgme_data_append_string (d, ">\n");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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");
|
||||
if (u->invalid)
|
||||
_gpgme_data_append_string (d, " <invalid/>\n");
|
||||
if (u->revoked)
|
||||
_gpgme_data_append_string (d, " <revoked/>\n");
|
||||
add_tag_and_string (d, "raw", u->name);
|
||||
if (*u->name_part)
|
||||
add_tag_and_string (d, "name", u->name_part);
|
||||
if (*u->email_part)
|
||||
add_tag_and_string (d, "email", u->email_part);
|
||||
if (*u->comment_part)
|
||||
add_tag_and_string (d, "comment", u->comment_part);
|
||||
_gpgme_data_append_string (d, " </userid>\n");
|
||||
_gpgme_data_append_string (data, " <signature>\n");
|
||||
if (certsig->flags.invalid)
|
||||
_gpgme_data_append_string (data, " <invalid/>\n");
|
||||
if (certsig->flags.revoked)
|
||||
_gpgme_data_append_string (data, " <revoked/>\n");
|
||||
if (certsig->flags.expired)
|
||||
_gpgme_data_append_string (data, " <expired/>\n");
|
||||
add_tag_and_string (data, "keyid", certsig->keyid);
|
||||
add_tag_and_uint (data, "algo", certsig->algo);
|
||||
add_tag_and_time (data, "created", certsig->timestamp);
|
||||
add_tag_and_time (data, "expire", certsig->expires_at);
|
||||
if (*certsig->name)
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@ -817,8 +827,8 @@ capabilities_to_string (struct subkey_s *k)
|
||||
"esc"
|
||||
};
|
||||
return strings[(!!k->flags.can_encrypt << 2)
|
||||
| (!!k->flags.can_sign << 1)
|
||||
| (!!k->flags.can_certify )];
|
||||
| (!!k->flags.can_sign << 1)
|
||||
| (!!k->flags.can_certify)];
|
||||
}
|
||||
|
||||
|
||||
@ -972,6 +982,7 @@ gpgme_key_get_string_attr (GpgmeKey key, GpgmeAttr what,
|
||||
case GPGME_ATTR_SIG_STATUS:
|
||||
case GPGME_ATTR_SIG_SUMMARY:
|
||||
case GPGME_ATTR_ERRTOK:
|
||||
case GPGME_ATTR_SIG_CLASS:
|
||||
/* Not of any use here. */
|
||||
break;
|
||||
}
|
||||
@ -1102,3 +1113,154 @@ gpgme_key_get_ulong_attr (GpgmeKey key, GpgmeAttr what,
|
||||
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;
|
||||
}
|
||||
|
139
gpgme/key.h
139
gpgme/key.h
@ -1,23 +1,22 @@
|
||||
/* key.h
|
||||
* 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
|
||||
*/
|
||||
/* key.h - Key handling interface.
|
||||
Copyright (C) 2000 Werner Koch (dd9jn)
|
||||
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 GPGME; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef KEY_H
|
||||
#define KEY_H
|
||||
@ -26,68 +25,86 @@
|
||||
#include "types.h"
|
||||
#include "context.h"
|
||||
|
||||
struct certsig_s {
|
||||
|
||||
struct certsig_s
|
||||
{
|
||||
struct certsig_s *next;
|
||||
struct {
|
||||
unsigned int revoked:1 ;
|
||||
unsigned int expired:1 ;
|
||||
unsigned int invalid:1 ;
|
||||
struct
|
||||
{
|
||||
unsigned int revoked : 1;
|
||||
unsigned int expired : 1;
|
||||
unsigned int invalid : 1;
|
||||
unsigned int exportable : 1;
|
||||
} flags;
|
||||
char keyid[16+1];
|
||||
time_t timestamp; /* -1 for invalid, 0 for not available */
|
||||
time_t expires_at; /* 0 for does not expires */
|
||||
unsigned int algo;
|
||||
char keyid[16 + 1];
|
||||
time_t timestamp; /* -1 for invalid, 0 for not available. */
|
||||
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;
|
||||
unsigned int secret:1;
|
||||
struct {
|
||||
unsigned int revoked:1 ;
|
||||
unsigned int expired:1 ;
|
||||
unsigned int disabled:1 ;
|
||||
unsigned int invalid:1 ;
|
||||
unsigned int can_encrypt:1;
|
||||
unsigned int can_sign:1;
|
||||
unsigned int can_certify:1;
|
||||
struct
|
||||
{
|
||||
unsigned int revoked : 1;
|
||||
unsigned int expired : 1;
|
||||
unsigned int disabled : 1;
|
||||
unsigned int invalid : 1;
|
||||
unsigned int can_encrypt : 1;
|
||||
unsigned int can_sign : 1;
|
||||
unsigned int can_certify : 1;
|
||||
} flags;
|
||||
unsigned int key_algo;
|
||||
unsigned int key_len;
|
||||
char keyid[16+1];
|
||||
char *fingerprint; /* malloced hex digits */
|
||||
time_t timestamp; /* -1 for invalid, 0 for not available */
|
||||
time_t expires_at; /* 0 for does not expires */
|
||||
char keyid[16 + 1];
|
||||
char *fingerprint; /* Malloced hex digits. */
|
||||
time_t timestamp; /* -1 for invalid, 0 for not available. */
|
||||
time_t expires_at; /* 0 for does not expires. */
|
||||
};
|
||||
|
||||
struct gpgme_key_s {
|
||||
struct {
|
||||
unsigned int revoked:1 ;
|
||||
unsigned int expired:1 ;
|
||||
unsigned int disabled:1 ;
|
||||
unsigned int invalid:1 ;
|
||||
unsigned int can_encrypt:1;
|
||||
unsigned int can_sign:1;
|
||||
unsigned int can_certify:1;
|
||||
|
||||
struct gpgme_key_s
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned int revoked : 1;
|
||||
unsigned int expired : 1;
|
||||
unsigned int disabled : 1;
|
||||
unsigned int invalid : 1;
|
||||
unsigned int can_encrypt : 1;
|
||||
unsigned int can_sign : 1;
|
||||
unsigned int can_certify : 1;
|
||||
} gloflags;
|
||||
unsigned int ref_count;
|
||||
unsigned int secret:1;
|
||||
unsigned int x509:1;
|
||||
char *issuer_serial; /* malloced string used only with X.509 */
|
||||
char *issuer_name; /* ditto */
|
||||
char *chain_id; /* ditto */
|
||||
GpgmeValidity otrust; /* only used with OpenPGP */
|
||||
struct subkey_s keys;
|
||||
unsigned int secret : 1;
|
||||
unsigned int x509 : 1;
|
||||
char *issuer_serial; /* Malloced string used only with X.509. */
|
||||
char *issuer_name; /* Ditto. */
|
||||
char *chain_id; /* Ditto. */
|
||||
GpgmeValidity otrust; /* Only used with OpenPGP. */
|
||||
struct subkey_s keys;
|
||||
struct user_id_s *uids;
|
||||
struct user_id_s *last_uid;
|
||||
};
|
||||
|
||||
|
||||
void _gpgme_key_cache_init (void);
|
||||
void _gpgme_key_cache_add (GpgmeKey key);
|
||||
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_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 */
|
||||
|
898
gpgme/keylist.c
898
gpgme/keylist.c
File diff suppressed because it is too large
Load Diff
@ -1486,10 +1486,9 @@ gpg_keylist (void *engine, const char *pattern, int secret_only,
|
||||
if (!err)
|
||||
err = add_arg (gpg, "--with-fingerprint");
|
||||
if (!err)
|
||||
err = add_arg (gpg, (keylist_mode & GPGME_KEYLIST_MODE_SIGS) ?
|
||||
"--check-sigs" :
|
||||
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. */
|
||||
if (!err)
|
||||
@ -1519,7 +1518,9 @@ gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
|
||||
if (!err)
|
||||
err = add_arg (gpg, "--with-fingerprint");
|
||||
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. */
|
||||
if (!err)
|
||||
|
@ -85,7 +85,13 @@ FILE *fopencookie (void *cookie, const char *opentype,
|
||||
|
||||
|
||||
/*-- 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);
|
||||
|
||||
#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.
|
||||
**/
|
||||
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;
|
||||
GpgmeError err = 0;
|
||||
|
||||
if (!c || !r_key)
|
||||
if (!ctx || !r_key)
|
||||
return mk_error (Invalid_Value);
|
||||
if (c->pending || !c->result.verify)
|
||||
if (ctx->pending || !ctx->result.verify)
|
||||
return mk_error (Busy);
|
||||
|
||||
for (result = c->result.verify;
|
||||
for (result = ctx->result.verify;
|
||||
result && idx > 0; result = result->next, idx--)
|
||||
;
|
||||
if (!result)
|
||||
return mk_error (EOF);
|
||||
|
||||
if (strlen(result->fpr) < 16) /* We have at least a key ID. */
|
||||
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;
|
||||
return gpgme_get_key (ctx, result->fpr, r_key, 0, 0);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user