mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-21 10:09:57 +01:00
gpg: Lookup a missing public key of the current card via LDAP.
* g10/getkey.c (get_seckey_default_or_card): Lookup a missing public key from the current card via LDAP. * g10/call-dirmngr.c: Include keyserver-intetnal.h. (gpg_dirmngr_ks_get): Rename arg quick into flags. Take care of the new LDAP flag. * g10/keyserver-internal.h (KEYSERVER_IMPORT_FLAG_QUICK): New. Replace the use of the value 1 for the former quick arg. (KEYSERVER_IMPORT_FLAG_LDAP): New. * g10/keyserver.c (keyserver_get_chunk): Increase the reserved line length. * dirmngr/ks-action.c (ks_action_get): Add arg ldap_only. * dirmngr/server.c (cmd_ks_get): Add option --ldap. -- This change makes it easy to start working with gnupg: Just insert the smartcard or token provided to you and the first time you sign a message the public key associated with the current card will be imported and everything is set without any configuration. This works only with an LDAP directory because it can be expected that the public key has been put into the LDAP during card personalization. Of course an LDAP server needs to be configured; in a Windows AD domain this can be a mere "keyserver ldap:///" in dirmngr.conf. Other configured keyservers are ignored. Requirements for the card driver: The $SIGNKEYID attribute must exists and a query for the KEY-FPR attribute needs to return the OpenPGP fingerprint for that key. This is currently supported for OpenPGP cards and certain PKCS#15 cards. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
30f90fc857
commit
d7e707170f
@ -211,7 +211,7 @@ ks_action_search (ctrl_t ctrl, uri_item_t keyservers,
|
||||
keyservers and write the result to the provided output stream. */
|
||||
gpg_error_t
|
||||
ks_action_get (ctrl_t ctrl, uri_item_t keyservers,
|
||||
strlist_t patterns, estream_t outfp)
|
||||
strlist_t patterns, int ldap_only, estream_t outfp)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
gpg_error_t first_err = 0;
|
||||
@ -238,6 +238,9 @@ ks_action_get (ctrl_t ctrl, uri_item_t keyservers,
|
||||
|| strcmp (uri->parsed_uri->scheme, "https") == 0);
|
||||
int is_ldap = 0;
|
||||
|
||||
if (ldap_only)
|
||||
is_hkp_s = is_http_s = 0;
|
||||
|
||||
#if USE_LDAP
|
||||
is_ldap = (strcmp (uri->parsed_uri->scheme, "ldap") == 0
|
||||
|| strcmp (uri->parsed_uri->scheme, "ldaps") == 0
|
||||
|
@ -26,7 +26,7 @@ gpg_error_t ks_action_resolve (ctrl_t ctrl, uri_item_t keyservers);
|
||||
gpg_error_t ks_action_search (ctrl_t ctrl, uri_item_t keyservers,
|
||||
strlist_t patterns, estream_t outfp);
|
||||
gpg_error_t ks_action_get (ctrl_t ctrl, uri_item_t keyservers,
|
||||
strlist_t patterns, estream_t outfp);
|
||||
strlist_t patterns, int ldap_only, estream_t outfp);
|
||||
gpg_error_t ks_action_fetch (ctrl_t ctrl, const char *url, estream_t outfp);
|
||||
gpg_error_t ks_action_put (ctrl_t ctrl, uri_item_t keyservers,
|
||||
void *data, size_t datalen,
|
||||
|
@ -2403,11 +2403,12 @@ cmd_ks_search (assuan_context_t ctx, char *line)
|
||||
|
||||
|
||||
static const char hlp_ks_get[] =
|
||||
"KS_GET {<pattern>}\n"
|
||||
"KS_GET [--quick] [--ldap] {<pattern>}\n"
|
||||
"\n"
|
||||
"Get the keys matching PATTERN from the configured OpenPGP keyservers\n"
|
||||
"(see command KEYSERVER). Each pattern should be a keyid, a fingerprint,\n"
|
||||
"or an exact name indicated by the '=' prefix.";
|
||||
"or an exact name indicated by the '=' prefix. Option --quick uses a\n"
|
||||
"shorter timeout; --ldap will use only ldap servers";
|
||||
static gpg_error_t
|
||||
cmd_ks_get (assuan_context_t ctx, char *line)
|
||||
{
|
||||
@ -2416,9 +2417,11 @@ cmd_ks_get (assuan_context_t ctx, char *line)
|
||||
strlist_t list, sl;
|
||||
char *p;
|
||||
estream_t outfp;
|
||||
int ldap_only;
|
||||
|
||||
if (has_option (line, "--quick"))
|
||||
ctrl->timeout = opt.connect_quick_timeout;
|
||||
ldap_only = has_option (line, "--ldap");
|
||||
line = skip_options (line);
|
||||
|
||||
/* Break the line into a strlist. Each pattern is by
|
||||
@ -2460,7 +2463,8 @@ cmd_ks_get (assuan_context_t ctx, char *line)
|
||||
ctrl->server_local->inhibit_data_logging = 1;
|
||||
ctrl->server_local->inhibit_data_logging_now = 0;
|
||||
ctrl->server_local->inhibit_data_logging_count = 0;
|
||||
err = ks_action_get (ctrl, ctrl->server_local->keyservers, list, outfp);
|
||||
err = ks_action_get (ctrl, ctrl->server_local->keyservers,
|
||||
list, ldap_only, outfp);
|
||||
es_fclose (outfp);
|
||||
ctrl->server_local->inhibit_data_logging = 0;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "../common/asshelp.h"
|
||||
#include "../common/keyserver.h"
|
||||
#include "../common/status.h"
|
||||
#include "keyserver-internal.h"
|
||||
#include "call-dirmngr.h"
|
||||
|
||||
|
||||
@ -637,7 +638,9 @@ ks_get_data_cb (void *opaque, const void *data, size_t datalen)
|
||||
don't need to escape the patterns before sending them to the
|
||||
server.
|
||||
|
||||
If QUICK is set the dirmngr is advised to use a shorter timeout.
|
||||
Bit values for FLAGS are:
|
||||
- KEYSERVER_IMPORT_FLAG_QUICK :: dirmngr shall use a shorter timeout.
|
||||
- KEYSERVER_IMPORT_FLAG_LDAP :: dirmngr shall only use LDAP or NTDS.
|
||||
|
||||
If R_SOURCE is not NULL the source of the data is stored as a
|
||||
malloced string there. If a source is not known NULL is stored.
|
||||
@ -649,7 +652,8 @@ ks_get_data_cb (void *opaque, const void *data, size_t datalen)
|
||||
are able to ask for (1000-10-1)/(2+8+1) = 90 keys at once. */
|
||||
gpg_error_t
|
||||
gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern,
|
||||
keyserver_spec_t override_keyserver, int quick,
|
||||
keyserver_spec_t override_keyserver,
|
||||
unsigned int flags,
|
||||
estream_t *r_fp, char **r_source)
|
||||
{
|
||||
gpg_error_t err;
|
||||
@ -695,7 +699,12 @@ gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern,
|
||||
|
||||
/* Lump all patterns into one string. */
|
||||
init_membuf (&mb, 1024);
|
||||
put_membuf_str (&mb, quick? "KS_GET --quick --" : "KS_GET --");
|
||||
put_membuf_str (&mb, "KS_GET");
|
||||
if ((flags & KEYSERVER_IMPORT_FLAG_QUICK))
|
||||
put_membuf_str (&mb, " --quick");
|
||||
if ((flags & KEYSERVER_IMPORT_FLAG_LDAP))
|
||||
put_membuf_str (&mb, " --ldap");
|
||||
put_membuf_str (&mb, " --");
|
||||
for (idx=0; pattern[idx]; idx++)
|
||||
{
|
||||
put_membuf (&mb, " ", 1); /* Append Delimiter. */
|
||||
|
@ -26,7 +26,8 @@ gpg_error_t gpg_dirmngr_ks_search (ctrl_t ctrl, const char *searchstr,
|
||||
gpg_error_t (*cb)(void*, int, char *),
|
||||
void *cb_value);
|
||||
gpg_error_t gpg_dirmngr_ks_get (ctrl_t ctrl, char *pattern[],
|
||||
keyserver_spec_t override_keyserver, int quick,
|
||||
keyserver_spec_t override_keyserver,
|
||||
unsigned int flags,
|
||||
estream_t *r_fp, char **r_source);
|
||||
gpg_error_t gpg_dirmngr_ks_fetch (ctrl_t ctrl,
|
||||
const char *url, estream_t *r_fp);
|
||||
|
18
g10/getkey.c
18
g10/getkey.c
@ -3875,6 +3875,24 @@ get_seckey_default_or_card (ctrl_t ctrl, PKT_public_key *pk,
|
||||
else if (fpr_card)
|
||||
{
|
||||
err = get_pubkey_byfprint (ctrl, pk, NULL, fpr_card, fpr_len);
|
||||
if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
|
||||
{
|
||||
if (opt.debug)
|
||||
log_debug ("using LDAP to find public key for current card\n");
|
||||
err = keyserver_import_fprint (ctrl, fpr_card, fpr_len,
|
||||
opt.keyserver,
|
||||
KEYSERVER_IMPORT_FLAG_LDAP);
|
||||
if (!err)
|
||||
err = get_pubkey_byfprint (ctrl, pk, NULL, fpr_card, fpr_len);
|
||||
else if (gpg_err_code (err) == GPG_ERR_NO_DATA
|
||||
|| gpg_err_code (err) == GPG_ERR_NO_KEYSERVER)
|
||||
{
|
||||
/* Dirmngr returns NO DATA is the selected keyserver
|
||||
* does not have the requested key. It returns NO
|
||||
* KEYSERVER if no LDAP keyservers are configured. */
|
||||
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||
}
|
||||
}
|
||||
|
||||
/* The key on card can be not suitable for requested usage. */
|
||||
if (gpg_err_code (err) == GPG_ERR_UNUSABLE_PUBKEY)
|
||||
|
12
g10/gpgv.c
12
g10/gpgv.c
@ -423,23 +423,23 @@ keyserver_any_configured (ctrl_t ctrl)
|
||||
}
|
||||
|
||||
int
|
||||
keyserver_import_keyid (u32 *keyid, void *dummy, int quick)
|
||||
keyserver_import_keyid (u32 *keyid, void *dummy, unsigned int flags)
|
||||
{
|
||||
(void)keyid;
|
||||
(void)dummy;
|
||||
(void)quick;
|
||||
(void)flags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
|
||||
struct keyserver_spec *keyserver, int quick)
|
||||
struct keyserver_spec *keyserver, unsigned int flags)
|
||||
{
|
||||
(void)ctrl;
|
||||
(void)fprint;
|
||||
(void)fprint_len;
|
||||
(void)keyserver;
|
||||
(void)quick;
|
||||
(void)flags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -451,12 +451,12 @@ keyserver_import_cert (const char *name)
|
||||
}
|
||||
|
||||
gpg_error_t
|
||||
keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick,
|
||||
keyserver_import_wkd (ctrl_t ctrl, const char *name, unsigned int flags,
|
||||
unsigned char **fpr, size_t *fpr_len)
|
||||
{
|
||||
(void)ctrl;
|
||||
(void)name;
|
||||
(void)quick;
|
||||
(void)flags;
|
||||
(void)fpr;
|
||||
(void)fpr_len;
|
||||
return GPG_ERR_BUG;
|
||||
|
@ -25,6 +25,10 @@
|
||||
#include "../common/iobuf.h"
|
||||
#include "../common/types.h"
|
||||
|
||||
/* Flags for the keyserver import functions. */
|
||||
#define KEYSERVER_IMPORT_FLAG_QUICK 1
|
||||
#define KEYSERVER_IMPORT_FLAG_LDAP 2
|
||||
|
||||
int parse_keyserver_options(char *options);
|
||||
void free_keyserver_spec(struct keyserver_spec *keyserver);
|
||||
struct keyserver_spec *keyserver_match(struct keyserver_spec *spec);
|
||||
@ -35,15 +39,18 @@ int keyserver_any_configured (ctrl_t ctrl);
|
||||
int keyserver_export (ctrl_t ctrl, strlist_t users);
|
||||
int keyserver_import (ctrl_t ctrl, strlist_t users);
|
||||
int keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
|
||||
struct keyserver_spec *keyserver, int quick);
|
||||
struct keyserver_spec *keyserver,
|
||||
unsigned int flags);
|
||||
int keyserver_import_keyid (ctrl_t ctrl, u32 *keyid,
|
||||
struct keyserver_spec *keyserver, int quick);
|
||||
struct keyserver_spec *keyserver,
|
||||
unsigned int flags);
|
||||
gpg_error_t keyserver_refresh (ctrl_t ctrl, strlist_t users);
|
||||
gpg_error_t keyserver_search (ctrl_t ctrl, strlist_t tokens);
|
||||
int keyserver_fetch (ctrl_t ctrl, strlist_t urilist, int origin);
|
||||
int keyserver_import_cert (ctrl_t ctrl, const char *name, int dane_mode,
|
||||
unsigned char **fpr,size_t *fpr_len);
|
||||
gpg_error_t keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick,
|
||||
gpg_error_t keyserver_import_wkd (ctrl_t ctrl, const char *name,
|
||||
unsigned int flags,
|
||||
unsigned char **fpr, size_t *fpr_len);
|
||||
int keyserver_import_ntds (ctrl_t ctrl, const char *name,
|
||||
unsigned char **fpr,size_t *fpr_len);
|
||||
|
@ -105,7 +105,7 @@ static struct parse_options keyserver_opts[]=
|
||||
static gpg_error_t keyserver_get (ctrl_t ctrl,
|
||||
KEYDB_SEARCH_DESC *desc, int ndesc,
|
||||
struct keyserver_spec *override_keyserver,
|
||||
int quick,
|
||||
unsigned int flags,
|
||||
unsigned char **r_fpr, size_t *r_fprlen);
|
||||
static gpg_error_t keyserver_put (ctrl_t ctrl, strlist_t keyspecs);
|
||||
|
||||
@ -1156,7 +1156,8 @@ keyserver_import_ntds (ctrl_t ctrl, const char *mbox,
|
||||
|
||||
int
|
||||
keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
|
||||
struct keyserver_spec *keyserver, int quick)
|
||||
struct keyserver_spec *keyserver,
|
||||
unsigned int flags)
|
||||
{
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
|
||||
@ -1172,12 +1173,13 @@ keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
|
||||
|
||||
/* TODO: Warn here if the fingerprint we got doesn't match the one
|
||||
we asked for? */
|
||||
return keyserver_get (ctrl, &desc, 1, keyserver, quick, NULL, NULL);
|
||||
return keyserver_get (ctrl, &desc, 1, keyserver, flags, NULL, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
keyserver_import_keyid (ctrl_t ctrl,
|
||||
u32 *keyid,struct keyserver_spec *keyserver, int quick)
|
||||
u32 *keyid,struct keyserver_spec *keyserver,
|
||||
unsigned int flags)
|
||||
{
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
|
||||
@ -1187,7 +1189,7 @@ keyserver_import_keyid (ctrl_t ctrl,
|
||||
desc.u.kid[0]=keyid[0];
|
||||
desc.u.kid[1]=keyid[1];
|
||||
|
||||
return keyserver_get (ctrl, &desc, 1, keyserver, quick, NULL, NULL);
|
||||
return keyserver_get (ctrl, &desc, 1, keyserver, flags, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -1579,7 +1581,7 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
|
||||
int *r_ndesc_used,
|
||||
import_stats_t stats_handle,
|
||||
struct keyserver_spec *override_keyserver,
|
||||
int quick,
|
||||
unsigned int flags,
|
||||
unsigned char **r_fpr, size_t *r_fprlen)
|
||||
|
||||
{
|
||||
@ -1608,7 +1610,7 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
|
||||
single request will be rejected only later by gpg_dirmngr_ks_get
|
||||
but we are sure that R_NDESC_USED has been updated. This avoids
|
||||
a possible indefinite loop. */
|
||||
linelen = 17; /* "KS_GET --quick --" */
|
||||
linelen = 24; /* "KS_GET --quick --ldap --" */
|
||||
for (npat=npat_fpr=0, idx=0; idx < ndesc; idx++)
|
||||
{
|
||||
int quiet = 0;
|
||||
@ -1732,7 +1734,7 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
|
||||
|
||||
only_fprs = (npat && npat == npat_fpr);
|
||||
|
||||
err = gpg_dirmngr_ks_get (ctrl, pattern, override_keyserver, quick,
|
||||
err = gpg_dirmngr_ks_get (ctrl, pattern, override_keyserver, flags,
|
||||
&datastream, &source);
|
||||
for (idx=0; idx < npat; idx++)
|
||||
xfree (pattern[idx]);
|
||||
@ -1786,11 +1788,12 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
|
||||
(DESC,NDESC). Allowed search modes are keyid, fingerprint, and
|
||||
exact searches. OVERRIDE_KEYSERVER gives an optional override
|
||||
keyserver. If (R_FPR,R_FPRLEN) are not NULL, they may return the
|
||||
fingerprint of a single imported key. If QUICK is set, dirmngr is
|
||||
advised to use a shorter timeout. */
|
||||
fingerprint of a single imported key. If the FLAG bit
|
||||
KEYSERVER_IMPORT_FLAG_QUICK is set, dirmngr is advised to use a
|
||||
shorter timeout. */
|
||||
static gpg_error_t
|
||||
keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
|
||||
struct keyserver_spec *override_keyserver, int quick,
|
||||
struct keyserver_spec *override_keyserver, unsigned int flags,
|
||||
unsigned char **r_fpr, size_t *r_fprlen)
|
||||
{
|
||||
gpg_error_t err;
|
||||
@ -1803,7 +1806,7 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
|
||||
for (;;)
|
||||
{
|
||||
err = keyserver_get_chunk (ctrl, desc, ndesc, &ndesc_used, stats_handle,
|
||||
override_keyserver, quick, r_fpr, r_fprlen);
|
||||
override_keyserver, flags, r_fpr, r_fprlen);
|
||||
if (!err)
|
||||
any_good = 1;
|
||||
if (err || ndesc_used >= ndesc)
|
||||
@ -2031,7 +2034,7 @@ keyserver_import_cert (ctrl_t ctrl, const char *name, int dane_mode,
|
||||
|
||||
/* Import a key using the Web Key Directory protocol. */
|
||||
gpg_error_t
|
||||
keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick,
|
||||
keyserver_import_wkd (ctrl_t ctrl, const char *name, unsigned int flags,
|
||||
unsigned char **fpr, size_t *fpr_len)
|
||||
{
|
||||
gpg_error_t err;
|
||||
@ -2050,7 +2053,7 @@ keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick,
|
||||
return err;
|
||||
}
|
||||
|
||||
err = gpg_dirmngr_wkd_get (ctrl, mbox, quick, &key, &url);
|
||||
err = gpg_dirmngr_wkd_get (ctrl, mbox, flags, &key, &url);
|
||||
if (err)
|
||||
;
|
||||
else if (key)
|
||||
|
@ -2011,7 +2011,8 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
free_public_key (pk);
|
||||
pk = NULL;
|
||||
glo_ctrl.in_auto_key_retrieve++;
|
||||
res = keyserver_import_keyid (c->ctrl, sig->keyid,spec, 1);
|
||||
res = keyserver_import_keyid (c->ctrl, sig->keyid,spec,
|
||||
KEYSERVER_IMPORT_FLAG_QUICK);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
if (!res)
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, NULL,
|
||||
@ -2050,7 +2051,8 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
free_public_key (pk);
|
||||
pk = NULL;
|
||||
glo_ctrl.in_auto_key_retrieve++;
|
||||
res = keyserver_import_wkd (c->ctrl, sig->signers_uid, 1, NULL, NULL);
|
||||
res = keyserver_import_wkd (c->ctrl, sig->signers_uid,
|
||||
KEYSERVER_IMPORT_FLAG_QUICK, NULL, NULL);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
/* Fixme: If the fingerprint is embedded in the signature,
|
||||
* compare it to the fingerprint of the returned key. */
|
||||
@ -2082,7 +2084,8 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
free_public_key (pk);
|
||||
pk = NULL;
|
||||
glo_ctrl.in_auto_key_retrieve++;
|
||||
res = keyserver_import_fprint (c->ctrl, p, n, opt.keyserver, 1);
|
||||
res = keyserver_import_fprint (c->ctrl, p, n, opt.keyserver,
|
||||
KEYSERVER_IMPORT_FLAG_QUICK);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
if (!res)
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, NULL,
|
||||
|
@ -181,23 +181,23 @@ keyserver_any_configured (ctrl_t ctrl)
|
||||
}
|
||||
|
||||
int
|
||||
keyserver_import_keyid (u32 *keyid, void *dummy, int quick)
|
||||
keyserver_import_keyid (u32 *keyid, void *dummy, unsigned int flags)
|
||||
{
|
||||
(void)keyid;
|
||||
(void)dummy;
|
||||
(void)quick;
|
||||
(void)flags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
|
||||
struct keyserver_spec *keyserver, int quick)
|
||||
struct keyserver_spec *keyserver, unsigned int flags)
|
||||
{
|
||||
(void)ctrl;
|
||||
(void)fprint;
|
||||
(void)fprint_len;
|
||||
(void)keyserver;
|
||||
(void)quick;
|
||||
(void)flags;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -209,12 +209,12 @@ keyserver_import_cert (const char *name)
|
||||
}
|
||||
|
||||
gpg_error_t
|
||||
keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick,
|
||||
keyserver_import_wkd (ctrl_t ctrl, const char *name, unsigned int flags,
|
||||
unsigned char **fpr, size_t *fpr_len)
|
||||
{
|
||||
(void)ctrl;
|
||||
(void)name;
|
||||
(void)quick;
|
||||
(void)flags;
|
||||
(void)fpr;
|
||||
(void)fpr_len;
|
||||
return GPG_ERR_BUG;
|
||||
|
Loading…
x
Reference in New Issue
Block a user