mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
Merge branch 'master' into switch-to-gpgk
This commit is contained in:
commit
a5118b19c1
183
NEWS
183
NEWS
@ -1,6 +1,184 @@
|
|||||||
Noteworthy changes in version 2.3.0 (unreleased)
|
Noteworthy changes in version 2.3.0 (unreleased)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
|
Changes also found in 2.2.16:
|
||||||
|
|
||||||
|
* gpg,gpgsm: Fix deadlock on Windows due to a keybox sharing
|
||||||
|
violation. [#4505]
|
||||||
|
|
||||||
|
* gpg: Allow deletion of subkeys with --delete-key. This finally
|
||||||
|
makes the bang-suffix work as expected for that command. [#4457]
|
||||||
|
|
||||||
|
* gpg: Replace SHA-1 by SHA-256 in self-signatures when updating
|
||||||
|
them with --quick-set-expire or --quick-set-primary-uid. [#4508]
|
||||||
|
|
||||||
|
* gpg: Improve the photo image viewer selection. [#4334]
|
||||||
|
|
||||||
|
* gpg: Fix decryption with --use-embedded-filename. [#4500]
|
||||||
|
|
||||||
|
* gpg: Remove hints on using the --keyserver option. [#4512]
|
||||||
|
|
||||||
|
* gpg: Fix export of certain secret keys with comments. [#4490]
|
||||||
|
|
||||||
|
* gpg: Reject too long user-ids in --quick-gen-key. [#4532]
|
||||||
|
|
||||||
|
* gpg: Fix a double free in the best key selection code. [#4462]
|
||||||
|
|
||||||
|
* gpg: Fix the key generation dialog for switching back from EdDSA
|
||||||
|
to ECDSA.
|
||||||
|
|
||||||
|
* gpg: Use AES-192 with SHA-384 to comply with RFC-6637.
|
||||||
|
|
||||||
|
* gpg: Use only the addrspec from the Signer's UID subpacket to
|
||||||
|
mitigate a problem with another implementation.
|
||||||
|
|
||||||
|
* gpg: Skip invalid packets during a keyring listing and sync
|
||||||
|
diagnostics with the output.
|
||||||
|
|
||||||
|
* gpgsm: Avoid confusing diagnostic when signing with the default
|
||||||
|
key. [#4535]
|
||||||
|
|
||||||
|
* agent: Do not delete any secret key in --dry-run mode.
|
||||||
|
|
||||||
|
* agent: Fix failures on 64 bit big-endian boxes related to URIs in
|
||||||
|
a keyfile. [#4501]
|
||||||
|
|
||||||
|
* agent: Stop scdaemon after a reload with disable-scdaemon newly
|
||||||
|
configured. [#4326]
|
||||||
|
|
||||||
|
* dirmngr: Improve caching algorithm for WKD domains.
|
||||||
|
|
||||||
|
* dirmngr: Support other hash algorithms than SHA-1 for OCSP. [#3966]
|
||||||
|
|
||||||
|
* gpgconf: Make --homedir work for --launch. [#4496]
|
||||||
|
|
||||||
|
* gpgconf: Before --launch check for a valid config file. [#4497]
|
||||||
|
|
||||||
|
* wkd: Do not import more than 5 keys from one WKD address.
|
||||||
|
|
||||||
|
* wkd: Accept keys which are stored in armored format in the
|
||||||
|
directory.
|
||||||
|
|
||||||
|
* The installer for Windows now comes with signed binaries.
|
||||||
|
|
||||||
|
Release-info: https://dev.gnupg.org/T4509
|
||||||
|
See-also: gnupg-announce/2019q2/000438.html
|
||||||
|
|
||||||
|
Changes also found in 2.2.15:
|
||||||
|
|
||||||
|
* sm: Fix --logger-fd and --status-fd on Windows for non-standard
|
||||||
|
file descriptors.
|
||||||
|
|
||||||
|
* sm: Allow decryption even if expired keys are configured. [#4431]
|
||||||
|
|
||||||
|
* agent: Change command KEYINFO to print ssh fingerprints with other
|
||||||
|
hash algos.
|
||||||
|
|
||||||
|
* dirmngr: Fix build problems on Solaris due to the use of reserved
|
||||||
|
symbol names. [#4420]
|
||||||
|
|
||||||
|
* wkd: New commands --print-wkd-hash and --print-wkd-url for
|
||||||
|
gpg-wks-client.
|
||||||
|
|
||||||
|
Release-info: https://dev.gnupg.org/T4434
|
||||||
|
See-also: gnupg-announce/2019q1/000436.html
|
||||||
|
|
||||||
|
Changes also found in 2.2.14:
|
||||||
|
|
||||||
|
* gpg: Allow import of PGP desktop exported secret keys. Also avoid
|
||||||
|
importing secret keys if the secret keyblock is not valid. [#4392]
|
||||||
|
|
||||||
|
* gpg: Make invalid primary key algo obvious in key listings.
|
||||||
|
|
||||||
|
* sm: Do not mark a certificate in a key listing as de-vs compliant
|
||||||
|
if its use for a signature will not be possible.
|
||||||
|
|
||||||
|
* sm: Fix certificate creation with key on card.
|
||||||
|
|
||||||
|
* sm: Create rsa3072 bit certificates by default.
|
||||||
|
|
||||||
|
* sm: Print Yubikey attestation extensions with --dump-cert.
|
||||||
|
|
||||||
|
* agent: Fix cancellation handling for scdaemon.
|
||||||
|
|
||||||
|
* agent: Support --mode=ssh option for CLEAR_PASSPHRASE. [#4340]
|
||||||
|
|
||||||
|
* scd: Fix flushing of the CA-FPR DOs in app-openpgp.
|
||||||
|
|
||||||
|
* scd: Avoid a conflict error with the "undefined" app.
|
||||||
|
|
||||||
|
* dirmngr: Add CSRF protection exception for protonmail.
|
||||||
|
|
||||||
|
* dirmngr: Fix build problems with gcc 9 in libdns.
|
||||||
|
|
||||||
|
* gpgconf: New option --show-socket for use with --launch.
|
||||||
|
|
||||||
|
* gpgtar: Make option -C work for archive creation.
|
||||||
|
|
||||||
|
Release-info: https://dev.gnupg.org/T4412
|
||||||
|
See-also: gnupg-announce/2019q1/000435.html
|
||||||
|
|
||||||
|
Changes also found in 2.2.13:
|
||||||
|
|
||||||
|
* gpg: Implement key lookup via keygrip (using the & prefix).
|
||||||
|
|
||||||
|
* gpg: Allow generating Ed25519 key from existing key.
|
||||||
|
|
||||||
|
* gpg: Emit an ERROR status line if no key was found with -k.
|
||||||
|
|
||||||
|
* gpg: Stop early when trying to create a primary Elgamal key. [#4329]
|
||||||
|
|
||||||
|
* gpgsm: Print the card's key algorithms along with their keygrips
|
||||||
|
in interactive key generation.
|
||||||
|
|
||||||
|
* agent: Clear bogus pinentry cache in the error case. [#4348]
|
||||||
|
|
||||||
|
* scd: Support "acknowledge button" feature.
|
||||||
|
|
||||||
|
* scd: Fix for USB INTERRUPT transfer. [#4308]
|
||||||
|
|
||||||
|
* wks: Do no use compression for the the encrypted challenge and
|
||||||
|
response.
|
||||||
|
|
||||||
|
Release-info: https://dev.gnupg.org/T4290
|
||||||
|
See-also: gnupg-announce/2019q1/000434.html
|
||||||
|
|
||||||
|
Changes also found in 2.2.12:
|
||||||
|
|
||||||
|
* tools: New commands --install-key and --remove-key for
|
||||||
|
gpg-wks-client. This allows to prepare a Web Key Directory on a
|
||||||
|
local file system for later upload to a web server.
|
||||||
|
|
||||||
|
* gpg: New --list-option "show-only-fpr-mbox". This makes the use
|
||||||
|
of the new gpg-wks-client --install-key command easier on Windows.
|
||||||
|
|
||||||
|
* gpg: Improve processing speed when --skip-verify is used.
|
||||||
|
|
||||||
|
* gpg: Fix a bug where a LF was accidentally written to the console.
|
||||||
|
|
||||||
|
* gpg: --card-status now shows whether a card has the new KDF
|
||||||
|
feature enabled.
|
||||||
|
|
||||||
|
* agent: New runtime option --s2k-calibration=MSEC. New configure
|
||||||
|
option --with-agent-s2k-calibration=MSEC. [#3399]
|
||||||
|
|
||||||
|
* dirmngr: Try another keyserver from the pool on receiving a 502,
|
||||||
|
503, or 504 error. [#4175]
|
||||||
|
|
||||||
|
* dirmngr: Avoid possible CSRF attacks via http redirects. A HTTP
|
||||||
|
query will not anymore follow a 3xx redirect unless the Location
|
||||||
|
header gives the same host. If the host is different only the
|
||||||
|
host and port is taken from the Location header and the original
|
||||||
|
path and query parts are kept.
|
||||||
|
|
||||||
|
* dirmngr: New command FLUSHCRL to flush all CRLS from disk and
|
||||||
|
memory. [#3967]
|
||||||
|
|
||||||
|
* New simplified Chinese translation (zh_CN).
|
||||||
|
|
||||||
|
Release-info: https://dev.gnupg.org/T4289
|
||||||
|
See-also: gnupg-announce/2018q4/000433.html
|
||||||
|
|
||||||
Changes also found in 2.2.11:
|
Changes also found in 2.2.11:
|
||||||
|
|
||||||
* gpgsm: Fix CRL loading when intermediate certicates are not yet
|
* gpgsm: Fix CRL loading when intermediate certicates are not yet
|
||||||
@ -388,6 +566,11 @@ Noteworthy changes in version 2.3.0 (unreleased)
|
|||||||
Version 2.2.9 (2018-07-12)
|
Version 2.2.9 (2018-07-12)
|
||||||
Version 2.2.10 (2018-08-30)
|
Version 2.2.10 (2018-08-30)
|
||||||
Version 2.2.11 (2018-11-06)
|
Version 2.2.11 (2018-11-06)
|
||||||
|
Version 2.2.12 (2018-12-14)
|
||||||
|
Version 2.2.13 (2019-02-12)
|
||||||
|
Version 2.2.14 (2019-03-19)
|
||||||
|
Version 2.2.15 (2019-03-26)
|
||||||
|
Version 2.2.16 (2019-05-28)
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 2.2.0 (2017-08-28)
|
Noteworthy changes in version 2.2.0 (2017-08-28)
|
||||||
|
@ -361,6 +361,15 @@ typedef int (*lookup_ttl_t)(const char *hexgrip);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Information from scdaemon for card keys. */
|
||||||
|
struct card_key_info_s
|
||||||
|
{
|
||||||
|
struct card_key_info_s *next;
|
||||||
|
char keygrip[40];
|
||||||
|
char *serialno;
|
||||||
|
char *idstr;
|
||||||
|
};
|
||||||
|
|
||||||
/*-- gpg-agent.c --*/
|
/*-- gpg-agent.c --*/
|
||||||
void agent_exit (int rc)
|
void agent_exit (int rc)
|
||||||
GPGRT_ATTR_NORETURN; /* Also implemented in other tools */
|
GPGRT_ATTR_NORETURN; /* Also implemented in other tools */
|
||||||
@ -389,8 +398,11 @@ void bump_key_eventcounter (void);
|
|||||||
void bump_card_eventcounter (void);
|
void bump_card_eventcounter (void);
|
||||||
void start_command_handler (ctrl_t, gnupg_fd_t, gnupg_fd_t);
|
void start_command_handler (ctrl_t, gnupg_fd_t, gnupg_fd_t);
|
||||||
gpg_error_t pinentry_loopback (ctrl_t, const char *keyword,
|
gpg_error_t pinentry_loopback (ctrl_t, const char *keyword,
|
||||||
unsigned char **buffer, size_t *size,
|
unsigned char **buffer, size_t *size,
|
||||||
size_t max_length);
|
size_t max_length);
|
||||||
|
gpg_error_t pinentry_loopback_confirm (ctrl_t ctrl, const char *desc,
|
||||||
|
int ask_confirmation,
|
||||||
|
const char *ok, const char *notok);
|
||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
int serve_mmapped_ssh_request (ctrl_t ctrl,
|
int serve_mmapped_ssh_request (ctrl_t ctrl,
|
||||||
@ -414,7 +426,8 @@ void start_command_handler_ssh (ctrl_t, gnupg_fd_t);
|
|||||||
gpg_error_t agent_modify_description (const char *in, const char *comment,
|
gpg_error_t agent_modify_description (const char *in, const char *comment,
|
||||||
const gcry_sexp_t key, char **result);
|
const gcry_sexp_t key, char **result);
|
||||||
int agent_write_private_key (const unsigned char *grip,
|
int agent_write_private_key (const unsigned char *grip,
|
||||||
const void *buffer, size_t length, int force);
|
const void *buffer, size_t length, int force,
|
||||||
|
const char *serialno, const char *keyref);
|
||||||
gpg_error_t agent_key_from_file (ctrl_t ctrl,
|
gpg_error_t agent_key_from_file (ctrl_t ctrl,
|
||||||
const char *cache_nonce,
|
const char *cache_nonce,
|
||||||
const char *desc_text,
|
const char *desc_text,
|
||||||
@ -543,10 +556,12 @@ void agent_reload_trustlist (void);
|
|||||||
|
|
||||||
/*-- divert-scd.c --*/
|
/*-- divert-scd.c --*/
|
||||||
int divert_pksign (ctrl_t ctrl, const char *desc_text,
|
int divert_pksign (ctrl_t ctrl, const char *desc_text,
|
||||||
|
const unsigned char *grip,
|
||||||
const unsigned char *digest, size_t digestlen, int algo,
|
const unsigned char *digest, size_t digestlen, int algo,
|
||||||
const unsigned char *shadow_info, unsigned char **r_sig,
|
const unsigned char *shadow_info, unsigned char **r_sig,
|
||||||
size_t *r_siglen);
|
size_t *r_siglen);
|
||||||
int divert_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
int divert_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||||
|
const unsigned char *grip,
|
||||||
const unsigned char *cipher,
|
const unsigned char *cipher,
|
||||||
const unsigned char *shadow_info,
|
const unsigned char *shadow_info,
|
||||||
char **r_buf, size_t *r_len, int *r_padding);
|
char **r_buf, size_t *r_len, int *r_padding);
|
||||||
@ -603,6 +618,10 @@ int agent_card_scd (ctrl_t ctrl, const char *cmdline,
|
|||||||
int (*getpin_cb)(void *, const char *,
|
int (*getpin_cb)(void *, const char *,
|
||||||
const char *, char*, size_t),
|
const char *, char*, size_t),
|
||||||
void *getpin_cb_arg, void *assuan_context);
|
void *getpin_cb_arg, void *assuan_context);
|
||||||
|
void agent_card_free_keyinfo (struct card_key_info_s *l);
|
||||||
|
gpg_error_t agent_card_keyinfo (ctrl_t ctrl, const char *keygrip,
|
||||||
|
struct card_key_info_s **result);
|
||||||
|
void agent_card_killscd (void);
|
||||||
|
|
||||||
|
|
||||||
/*-- learncard.c --*/
|
/*-- learncard.c --*/
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <npth.h>
|
#include <npth.h>
|
||||||
|
|
||||||
#include "agent.h"
|
#include "agent.h"
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#ifndef HAVE_W32_SYSTEM
|
#ifndef HAVE_W32_SYSTEM
|
||||||
@ -424,7 +423,17 @@ start_pinentry (ctrl_t ctrl)
|
|||||||
opt.no_grab? "OPTION no-grab":"OPTION grab",
|
opt.no_grab? "OPTION no-grab":"OPTION grab",
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return unlock_pinentry (ctrl, rc);
|
{
|
||||||
|
if (gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED
|
||||||
|
|| gpg_err_code (rc) == GPG_ERR_UNKNOWN_OPTION)
|
||||||
|
{
|
||||||
|
if (opt.verbose)
|
||||||
|
log_info ("Option no-grab/grab is ignored by pinentry.\n");
|
||||||
|
/* Keep going even if the feature is not supported. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return unlock_pinentry (ctrl, rc);
|
||||||
|
}
|
||||||
|
|
||||||
value = session_env_getenv (ctrl->session_env, "GPG_TTY");
|
value = session_env_getenv (ctrl->session_env, "GPG_TTY");
|
||||||
if (value)
|
if (value)
|
||||||
@ -439,7 +448,7 @@ start_pinentry (ctrl_t ctrl)
|
|||||||
return unlock_pinentry (ctrl, rc);
|
return unlock_pinentry (ctrl, rc);
|
||||||
}
|
}
|
||||||
value = session_env_getenv (ctrl->session_env, "TERM");
|
value = session_env_getenv (ctrl->session_env, "TERM");
|
||||||
if (value)
|
if (value && *value)
|
||||||
{
|
{
|
||||||
char *optstr;
|
char *optstr;
|
||||||
if (asprintf (&optstr, "OPTION ttytype=%s", value) < 0 )
|
if (asprintf (&optstr, "OPTION ttytype=%s", value) < 0 )
|
||||||
@ -949,15 +958,14 @@ build_cmd_setdesc (char *line, size_t linelen, const char *desc)
|
|||||||
static void *
|
static void *
|
||||||
watch_sock (void *arg)
|
watch_sock (void *arg)
|
||||||
{
|
{
|
||||||
gnupg_fd_t *p = (gnupg_fd_t *)arg;
|
|
||||||
pid_t pid = assuan_get_pid (entry_ctx);
|
pid_t pid = assuan_get_pid (entry_ctx);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
gnupg_fd_t sock = *p;
|
|
||||||
fd_set fdset;
|
fd_set fdset;
|
||||||
struct timeval timeout = { 0, 500000 };
|
struct timeval timeout = { 0, 500000 };
|
||||||
|
gnupg_fd_t sock = *(gnupg_fd_t *)arg;
|
||||||
|
|
||||||
if (sock == GNUPG_INVALID_FD)
|
if (sock == GNUPG_INVALID_FD)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -995,18 +1003,11 @@ watch_sock (void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Ask pinentry to get a pin by "GETPIN" command, spawning a thread
|
|
||||||
detecting the socket's EOF.
|
|
||||||
*/
|
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
do_getpin (ctrl_t ctrl, struct entry_parm_s *parm)
|
watch_sock_start (gnupg_fd_t *sock_p, npth_t *thread_p)
|
||||||
{
|
{
|
||||||
npth_attr_t tattr;
|
npth_attr_t tattr;
|
||||||
gpg_error_t rc;
|
|
||||||
int err;
|
int err;
|
||||||
npth_t thread;
|
|
||||||
int saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
|
|
||||||
gnupg_fd_t sock_watched = ctrl->thread_startup.fd;
|
|
||||||
|
|
||||||
err = npth_attr_init (&tattr);
|
err = npth_attr_init (&tattr);
|
||||||
if (err)
|
if (err)
|
||||||
@ -1016,7 +1017,7 @@ do_getpin (ctrl_t ctrl, struct entry_parm_s *parm)
|
|||||||
}
|
}
|
||||||
npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
|
npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
|
||||||
|
|
||||||
err = npth_create (&thread, &tattr, watch_sock, (void *)&sock_watched);
|
err = npth_create (thread_p, &tattr, watch_sock, sock_p);
|
||||||
npth_attr_destroy (&tattr);
|
npth_attr_destroy (&tattr);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@ -1024,6 +1025,36 @@ do_getpin (ctrl_t ctrl, struct entry_parm_s *parm)
|
|||||||
return gpg_error_from_errno (err);
|
return gpg_error_from_errno (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
watch_sock_end (gnupg_fd_t *sock_p, npth_t *thread_p)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
*sock_p = GNUPG_INVALID_FD;
|
||||||
|
err = npth_join (*thread_p, NULL);
|
||||||
|
if (err)
|
||||||
|
log_error ("watch_sock_end: error joining thread: %s\n", strerror (err));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Ask pinentry to get a pin by "GETPIN" command, spawning a thread
|
||||||
|
detecting the socket's EOF.
|
||||||
|
*/
|
||||||
|
static gpg_error_t
|
||||||
|
do_getpin (ctrl_t ctrl, struct entry_parm_s *parm)
|
||||||
|
{
|
||||||
|
gpg_error_t rc;
|
||||||
|
int saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
|
||||||
|
gnupg_fd_t sock_watched = ctrl->thread_startup.fd;
|
||||||
|
npth_t thread;
|
||||||
|
|
||||||
|
rc = watch_sock_start (&sock_watched, &thread);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
assuan_begin_confidential (entry_ctx);
|
assuan_begin_confidential (entry_ctx);
|
||||||
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, parm,
|
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, parm,
|
||||||
inq_quality, entry_ctx,
|
inq_quality, entry_ctx,
|
||||||
@ -1040,10 +1071,7 @@ do_getpin (ctrl_t ctrl, struct entry_parm_s *parm)
|
|||||||
&& gpg_err_code (rc) == GPG_ERR_CANCELED)
|
&& gpg_err_code (rc) == GPG_ERR_CANCELED)
|
||||||
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
|
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
|
||||||
|
|
||||||
sock_watched = GNUPG_INVALID_FD;
|
watch_sock_end (&sock_watched, &thread);
|
||||||
err = npth_join (thread, NULL);
|
|
||||||
if (err)
|
|
||||||
log_error ("do_getpin: error joining thread: %s\n", strerror (err));
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -1392,6 +1420,9 @@ agent_get_confirmation (ctrl_t ctrl,
|
|||||||
if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
|
if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
|
||||||
return gpg_error (GPG_ERR_CANCELED);
|
return gpg_error (GPG_ERR_CANCELED);
|
||||||
|
|
||||||
|
if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
|
||||||
|
return pinentry_loopback_confirm (ctrl, desc, 1, ok, notok);
|
||||||
|
|
||||||
return gpg_error (GPG_ERR_NO_PIN_ENTRY);
|
return gpg_error (GPG_ERR_NO_PIN_ENTRY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1445,70 +1476,38 @@ agent_get_confirmation (ctrl_t ctrl,
|
|||||||
return unlock_pinentry (ctrl, rc);
|
return unlock_pinentry (ctrl, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = assuan_transact (entry_ctx, "CONFIRM",
|
{
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
gnupg_fd_t sock_watched = ctrl->thread_startup.fd;
|
||||||
if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
|
npth_t thread;
|
||||||
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
|
|
||||||
|
|
||||||
return unlock_pinentry (ctrl, rc);
|
rc = watch_sock_start (&sock_watched, &thread);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = assuan_transact (entry_ctx, "CONFIRM",
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
|
||||||
|
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
|
||||||
|
|
||||||
|
watch_sock_end (&sock_watched, &thread);
|
||||||
|
|
||||||
|
return unlock_pinentry (ctrl, rc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Pop up the PINentry, display the text DESC and a button with the
|
|
||||||
text OK_BTN (which may be NULL to use the default of "OK") and wait
|
|
||||||
for the user to hit this button. The return value is not
|
|
||||||
relevant. */
|
|
||||||
int
|
|
||||||
agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
char line[ASSUAN_LINELENGTH];
|
|
||||||
|
|
||||||
if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
|
|
||||||
return gpg_error (GPG_ERR_CANCELED);
|
|
||||||
|
|
||||||
rc = start_pinentry (ctrl);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
if (desc)
|
|
||||||
build_cmd_setdesc (line, DIM(line), desc);
|
|
||||||
else
|
|
||||||
snprintf (line, DIM(line), "RESET");
|
|
||||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
/* Most pinentries out in the wild return the old Assuan error code
|
|
||||||
for canceled which gets translated to an assuan Cancel error and
|
|
||||||
not to the code for a user cancel. Fix this here. */
|
|
||||||
if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
|
|
||||||
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
|
|
||||||
|
|
||||||
if (rc)
|
|
||||||
return unlock_pinentry (ctrl, rc);
|
|
||||||
|
|
||||||
if (ok_btn)
|
|
||||||
{
|
|
||||||
snprintf (line, DIM(line), "SETOK %s", ok_btn);
|
|
||||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL,
|
|
||||||
NULL, NULL, NULL);
|
|
||||||
if (rc)
|
|
||||||
return unlock_pinentry (ctrl, rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
|
|
||||||
NULL, NULL, NULL);
|
|
||||||
if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
|
|
||||||
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
|
|
||||||
|
|
||||||
return unlock_pinentry (ctrl, rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The thread running the popup message. */
|
/* The thread running the popup message. */
|
||||||
static void *
|
static void *
|
||||||
popup_message_thread (void *arg)
|
popup_message_thread (void *arg)
|
||||||
{
|
{
|
||||||
(void)arg;
|
gpg_error_t rc;
|
||||||
|
gnupg_fd_t sock_watched = *(gnupg_fd_t *)arg;
|
||||||
|
npth_t thread;
|
||||||
|
|
||||||
|
rc = watch_sock_start (&sock_watched, &thread);
|
||||||
|
if (rc)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/* We use the --one-button hack instead of the MESSAGE command to
|
/* We use the --one-button hack instead of the MESSAGE command to
|
||||||
allow the use of old Pinentries. Those old Pinentries will then
|
allow the use of old Pinentries. Those old Pinentries will then
|
||||||
@ -1516,6 +1515,7 @@ popup_message_thread (void *arg)
|
|||||||
annoyance. */
|
annoyance. */
|
||||||
assuan_transact (entry_ctx, "CONFIRM --one-button",
|
assuan_transact (entry_ctx, "CONFIRM --one-button",
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
watch_sock_end (&sock_watched, &thread);
|
||||||
popup_finished = 1;
|
popup_finished = 1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1536,7 +1536,15 @@ agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
|
if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
|
||||||
return gpg_error (GPG_ERR_CANCELED);
|
{
|
||||||
|
if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
|
||||||
|
return gpg_error (GPG_ERR_CANCELED);
|
||||||
|
|
||||||
|
if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
|
||||||
|
return pinentry_loopback_confirm (ctrl, desc, 0, ok_btn, NULL);
|
||||||
|
|
||||||
|
return gpg_error (GPG_ERR_NO_PIN_ENTRY);
|
||||||
|
}
|
||||||
|
|
||||||
rc = start_pinentry (ctrl);
|
rc = start_pinentry (ctrl);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -1564,7 +1572,8 @@ agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
|
|||||||
npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
|
npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
|
||||||
|
|
||||||
popup_finished = 0;
|
popup_finished = 0;
|
||||||
err = npth_create (&popup_tid, &tattr, popup_message_thread, NULL);
|
err = npth_create (&popup_tid, &tattr, popup_message_thread,
|
||||||
|
&ctrl->thread_startup.fd);
|
||||||
npth_attr_destroy (&tattr);
|
npth_attr_destroy (&tattr);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@ -1587,6 +1596,9 @@ agent_popup_message_stop (ctrl_t ctrl)
|
|||||||
|
|
||||||
(void)ctrl;
|
(void)ctrl;
|
||||||
|
|
||||||
|
if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!popup_tid || !entry_ctx)
|
if (!popup_tid || !entry_ctx)
|
||||||
{
|
{
|
||||||
log_debug ("agent_popup_message_stop called with no active popup\n");
|
log_debug ("agent_popup_message_stop called with no active popup\n");
|
||||||
|
174
agent/call-scd.c
174
agent/call-scd.c
@ -25,7 +25,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#ifdef HAVE_SIGNAL_H
|
#ifdef HAVE_SIGNAL_H
|
||||||
# include <signal.h>
|
# include <signal.h>
|
||||||
@ -330,13 +329,13 @@ start_scd (ctrl_t ctrl)
|
|||||||
{
|
{
|
||||||
ctrl->scd_local = xtrycalloc (1, sizeof *ctrl->scd_local);
|
ctrl->scd_local = xtrycalloc (1, sizeof *ctrl->scd_local);
|
||||||
if (!ctrl->scd_local)
|
if (!ctrl->scd_local)
|
||||||
{
|
{
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
rc = npth_mutex_unlock (&start_scd_lock);
|
rc = npth_mutex_unlock (&start_scd_lock);
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error ("failed to release the start_scd lock: %s\n", strerror (rc));
|
log_error ("failed to release the start_scd lock: %s\n", strerror (rc));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
ctrl->scd_local->next_local = scd_local_list;
|
ctrl->scd_local->next_local = scd_local_list;
|
||||||
scd_local_list = ctrl->scd_local;
|
scd_local_list = ctrl->scd_local;
|
||||||
}
|
}
|
||||||
@ -1282,6 +1281,156 @@ agent_card_cardlist (ctrl_t ctrl, strlist_t *result)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct card_keyinfo_parm_s {
|
||||||
|
int error;
|
||||||
|
struct card_key_info_s *list;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Callback function for agent_card_keylist. */
|
||||||
|
static gpg_error_t
|
||||||
|
card_keyinfo_cb (void *opaque, const char *line)
|
||||||
|
{
|
||||||
|
struct card_keyinfo_parm_s *parm = opaque;
|
||||||
|
const char *keyword = line;
|
||||||
|
int keywordlen;
|
||||||
|
|
||||||
|
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
|
||||||
|
;
|
||||||
|
while (spacep (line))
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if (keywordlen == 7 && !memcmp (keyword, "KEYINFO", keywordlen))
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
int n;
|
||||||
|
struct card_key_info_s *keyinfo;
|
||||||
|
struct card_key_info_s **l_p = &parm->list;
|
||||||
|
|
||||||
|
while ((*l_p))
|
||||||
|
l_p = &(*l_p)->next;
|
||||||
|
|
||||||
|
keyinfo = xtrycalloc (1, sizeof *keyinfo);
|
||||||
|
if (!keyinfo)
|
||||||
|
{
|
||||||
|
alloc_error:
|
||||||
|
if (!parm->error)
|
||||||
|
parm->error = gpg_error_from_syserror ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n=0,s=line; hexdigitp (s); s++, n++)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (n != 40)
|
||||||
|
{
|
||||||
|
parm_error:
|
||||||
|
if (!parm->error)
|
||||||
|
parm->error = gpg_error (GPG_ERR_ASS_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (keyinfo->keygrip, line, 40);
|
||||||
|
|
||||||
|
line = s;
|
||||||
|
|
||||||
|
if (!*line)
|
||||||
|
goto parm_error;
|
||||||
|
|
||||||
|
while (spacep (line))
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if (*line++ != 'T')
|
||||||
|
goto parm_error;
|
||||||
|
|
||||||
|
if (!*line)
|
||||||
|
goto parm_error;
|
||||||
|
|
||||||
|
while (spacep (line))
|
||||||
|
line++;
|
||||||
|
|
||||||
|
for (n=0,s=line; hexdigitp (s); s++, n++)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (!n)
|
||||||
|
goto parm_error;
|
||||||
|
|
||||||
|
keyinfo->serialno = xtrymalloc (n+1);
|
||||||
|
if (!keyinfo->serialno)
|
||||||
|
goto alloc_error;
|
||||||
|
|
||||||
|
memcpy (keyinfo->serialno, line, n);
|
||||||
|
keyinfo->serialno[n] = 0;
|
||||||
|
|
||||||
|
line = s;
|
||||||
|
|
||||||
|
if (!*line)
|
||||||
|
goto parm_error;
|
||||||
|
|
||||||
|
while (spacep (line))
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if (!*line)
|
||||||
|
goto parm_error;
|
||||||
|
|
||||||
|
keyinfo->idstr = xtrystrdup (line);
|
||||||
|
if (!keyinfo->idstr)
|
||||||
|
goto alloc_error;
|
||||||
|
|
||||||
|
*l_p = keyinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
agent_card_free_keyinfo (struct card_key_info_s *l)
|
||||||
|
{
|
||||||
|
struct card_key_info_s *l_next;
|
||||||
|
|
||||||
|
for (; l; l = l_next)
|
||||||
|
{
|
||||||
|
l_next = l->next;
|
||||||
|
free (l->serialno);
|
||||||
|
free (l->idstr);
|
||||||
|
free (l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call the scdaemon to check if a key of KEYGRIP is available, or
|
||||||
|
retrieve list of available keys on cards. On success the allocated
|
||||||
|
structure is stored at RESULT. On error an error code is returned
|
||||||
|
and NULL is stored at RESULT. */
|
||||||
|
gpg_error_t
|
||||||
|
agent_card_keyinfo (ctrl_t ctrl, const char *keygrip,
|
||||||
|
struct card_key_info_s **result)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct card_keyinfo_parm_s parm;
|
||||||
|
char line[ASSUAN_LINELENGTH];
|
||||||
|
|
||||||
|
*result = NULL;
|
||||||
|
|
||||||
|
memset (&parm, 0, sizeof parm);
|
||||||
|
snprintf (line, sizeof line, "KEYINFO %s", keygrip ? keygrip : "--list");
|
||||||
|
|
||||||
|
err = start_scd (ctrl);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = assuan_transact (ctrl->scd_local->ctx, line,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
card_keyinfo_cb, &parm);
|
||||||
|
if (!err && parm.error)
|
||||||
|
err = parm.error;
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
*result = parm.list;
|
||||||
|
else
|
||||||
|
agent_card_free_keyinfo (parm.list);
|
||||||
|
|
||||||
|
return unlock_scd (ctrl, err);
|
||||||
|
}
|
||||||
|
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
pass_status_thru (void *opaque, const char *line)
|
pass_status_thru (void *opaque, const char *line)
|
||||||
@ -1366,3 +1515,12 @@ agent_card_scd (ctrl_t ctrl, const char *cmdline,
|
|||||||
|
|
||||||
return unlock_scd (ctrl, 0);
|
return unlock_scd (ctrl, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
agent_card_killscd (void)
|
||||||
|
{
|
||||||
|
if (primary_scd_ctx == NULL)
|
||||||
|
return;
|
||||||
|
assuan_transact (primary_scd_ctx, "KILLSCD",
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
@ -41,7 +41,6 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <assert.h>
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
#ifndef HAVE_W32_SYSTEM
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
@ -1030,7 +1029,7 @@ search_control_file (ssh_control_file_t cf, const char *hexgrip,
|
|||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
|
|
||||||
assert (strlen (hexgrip) == 40 );
|
log_assert (strlen (hexgrip) == 40 );
|
||||||
|
|
||||||
if (r_disabled)
|
if (r_disabled)
|
||||||
*r_disabled = 0;
|
*r_disabled = 0;
|
||||||
@ -2646,7 +2645,7 @@ ssh_handler_request_identities (ctrl_t ctrl,
|
|||||||
continue; /* Should not happen. */
|
continue; /* Should not happen. */
|
||||||
if (cf->item.disabled)
|
if (cf->item.disabled)
|
||||||
continue;
|
continue;
|
||||||
assert (strlen (cf->item.hexgrip) == 40);
|
log_assert (strlen (cf->item.hexgrip) == 40);
|
||||||
hex2bin (cf->item.hexgrip, grip, sizeof (grip));
|
hex2bin (cf->item.hexgrip, grip, sizeof (grip));
|
||||||
|
|
||||||
err = agent_public_key_from_file (ctrl, grip, &key_public);
|
err = agent_public_key_from_file (ctrl, grip, &key_public);
|
||||||
@ -3008,8 +3007,8 @@ ssh_key_to_protected_buffer (gcry_sexp_t key, const char *passphrase,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, buffer_new, buffer_new_n);
|
buffer_new_n = gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON,
|
||||||
/* FIXME: guarantee? */
|
buffer_new, buffer_new_n);
|
||||||
|
|
||||||
if (*passphrase)
|
if (*passphrase)
|
||||||
err = agent_protect (buffer_new, passphrase, buffer, buffer_n, 0, -1);
|
err = agent_protect (buffer_new, passphrase, buffer, buffer_n, 0, -1);
|
||||||
@ -3142,7 +3141,7 @@ ssh_identity_register (ctrl_t ctrl, ssh_key_type_spec_t *spec,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Store this key to our key storage. */
|
/* Store this key to our key storage. */
|
||||||
err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0);
|
err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0, NULL, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
@ -1075,7 +1074,7 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
|||||||
|
|
||||||
|
|
||||||
static const char hlp_keyinfo[] =
|
static const char hlp_keyinfo[] =
|
||||||
"KEYINFO [--[ssh-]list] [--data] [--ssh-fpr] [--with-ssh] <keygrip>\n"
|
"KEYINFO [--[ssh-]list] [--data] [--ssh-fpr[=algo]] [--with-ssh] <keygrip>\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Return information about the key specified by the KEYGRIP. If the\n"
|
"Return information about the key specified by the KEYGRIP. If the\n"
|
||||||
"key is not available GPG_ERR_NOT_FOUND is returned. If the option\n"
|
"key is not available GPG_ERR_NOT_FOUND is returned. If the option\n"
|
||||||
@ -1111,7 +1110,9 @@ static const char hlp_keyinfo[] =
|
|||||||
" '-' - Unknown protection.\n"
|
" '-' - Unknown protection.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"FPR returns the formatted ssh-style fingerprint of the key. It is only\n"
|
"FPR returns the formatted ssh-style fingerprint of the key. It is only\n"
|
||||||
" printed if the option --ssh-fpr has been used. It defaults to '-'.\n"
|
" printed if the option --ssh-fpr has been used. If ALGO is not given\n"
|
||||||
|
" to that option the default ssh fingerprint algo is used. Without the\n"
|
||||||
|
" option a '-' is printed.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"TTL is the TTL in seconds for that key or '-' if n/a.\n"
|
"TTL is the TTL in seconds for that key or '-' if n/a.\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -1119,13 +1120,14 @@ static const char hlp_keyinfo[] =
|
|||||||
" 'D' - The key has been disabled,\n"
|
" 'D' - The key has been disabled,\n"
|
||||||
" 'S' - The key is listed in sshcontrol (requires --with-ssh),\n"
|
" 'S' - The key is listed in sshcontrol (requires --with-ssh),\n"
|
||||||
" 'c' - Use of the key needs to be confirmed,\n"
|
" 'c' - Use of the key needs to be confirmed,\n"
|
||||||
|
" 'A' - The key is available on card,\n"
|
||||||
" '-' - No flags given.\n"
|
" '-' - No flags given.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"More information may be added in the future.";
|
"More information may be added in the future.";
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx,
|
do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx,
|
||||||
int data, int with_ssh_fpr, int in_ssh,
|
int data, int with_ssh_fpr, int in_ssh,
|
||||||
int ttl, int disabled, int confirm)
|
int ttl, int disabled, int confirm, int on_card)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
char hexgrip[40+1];
|
char hexgrip[40+1];
|
||||||
@ -1166,6 +1168,8 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx,
|
|||||||
strcat (flagsbuf, "S");
|
strcat (flagsbuf, "S");
|
||||||
if (confirm)
|
if (confirm)
|
||||||
strcat (flagsbuf, "c");
|
strcat (flagsbuf, "c");
|
||||||
|
if (on_card)
|
||||||
|
strcat (flagsbuf, "A");
|
||||||
if (!*flagsbuf)
|
if (!*flagsbuf)
|
||||||
strcpy (flagsbuf, "-");
|
strcpy (flagsbuf, "-");
|
||||||
|
|
||||||
@ -1198,7 +1202,7 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx,
|
|||||||
|
|
||||||
if (!agent_raw_key_from_file (ctrl, grip, &key))
|
if (!agent_raw_key_from_file (ctrl, grip, &key))
|
||||||
{
|
{
|
||||||
ssh_get_fingerprint_string (key, GCRY_MD_MD5, &fpr);
|
ssh_get_fingerprint_string (key, with_ssh_fpr, &fpr);
|
||||||
gcry_sexp_release (key);
|
gcry_sexp_release (key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1256,8 +1260,8 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Entry int for the command KEYINFO. This function handles the
|
/* Entry into the command KEYINFO. This function handles the
|
||||||
command option processing. For details see hlp_keyinfo above. */
|
* command option processing. For details see hlp_keyinfo above. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
cmd_keyinfo (assuan_context_t ctx, char *line)
|
cmd_keyinfo (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
@ -1270,6 +1274,9 @@ cmd_keyinfo (assuan_context_t ctx, char *line)
|
|||||||
ssh_control_file_t cf = NULL;
|
ssh_control_file_t cf = NULL;
|
||||||
char hexgrip[41];
|
char hexgrip[41];
|
||||||
int disabled, ttl, confirm, is_ssh;
|
int disabled, ttl, confirm, is_ssh;
|
||||||
|
struct card_key_info_s *keyinfo_on_cards;
|
||||||
|
struct card_key_info_s *l;
|
||||||
|
int on_card;
|
||||||
|
|
||||||
if (ctrl->restricted)
|
if (ctrl->restricted)
|
||||||
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
|
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
|
||||||
@ -1279,13 +1286,29 @@ cmd_keyinfo (assuan_context_t ctx, char *line)
|
|||||||
else
|
else
|
||||||
list_mode = has_option (line, "--list");
|
list_mode = has_option (line, "--list");
|
||||||
opt_data = has_option (line, "--data");
|
opt_data = has_option (line, "--data");
|
||||||
opt_ssh_fpr = has_option (line, "--ssh-fpr");
|
|
||||||
|
if (has_option_name (line, "--ssh-fpr"))
|
||||||
|
{
|
||||||
|
if (has_option (line, "--ssh-fpr=md5"))
|
||||||
|
opt_ssh_fpr = GCRY_MD_MD5;
|
||||||
|
else if (has_option (line, "--ssh-fpr=sha1"))
|
||||||
|
opt_ssh_fpr = GCRY_MD_SHA1;
|
||||||
|
else if (has_option (line, "--ssh-fpr=sha256"))
|
||||||
|
opt_ssh_fpr = GCRY_MD_SHA256;
|
||||||
|
else
|
||||||
|
opt_ssh_fpr = opt.ssh_fingerprint_digest;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
opt_ssh_fpr = 0;
|
||||||
|
|
||||||
opt_with_ssh = has_option (line, "--with-ssh");
|
opt_with_ssh = has_option (line, "--with-ssh");
|
||||||
line = skip_options (line);
|
line = skip_options (line);
|
||||||
|
|
||||||
if (opt_with_ssh || list_mode == 2)
|
if (opt_with_ssh || list_mode == 2)
|
||||||
cf = ssh_open_control_file ();
|
cf = ssh_open_control_file ();
|
||||||
|
|
||||||
|
agent_card_keyinfo (ctrl, NULL, &keyinfo_on_cards);
|
||||||
|
|
||||||
if (list_mode == 2)
|
if (list_mode == 2)
|
||||||
{
|
{
|
||||||
if (cf)
|
if (cf)
|
||||||
@ -1295,8 +1318,14 @@ cmd_keyinfo (assuan_context_t ctx, char *line)
|
|||||||
{
|
{
|
||||||
if (hex2bin (hexgrip, grip, 20) < 0 )
|
if (hex2bin (hexgrip, grip, 20) < 0 )
|
||||||
continue; /* Bad hex string. */
|
continue; /* Bad hex string. */
|
||||||
|
|
||||||
|
on_card = 0;
|
||||||
|
for (l = keyinfo_on_cards; l; l = l->next)
|
||||||
|
if (!memcmp (l->keygrip, hexgrip, 40))
|
||||||
|
on_card = 1;
|
||||||
|
|
||||||
err = do_one_keyinfo (ctrl, grip, ctx, opt_data, opt_ssh_fpr, 1,
|
err = do_one_keyinfo (ctrl, grip, ctx, opt_data, opt_ssh_fpr, 1,
|
||||||
ttl, disabled, confirm);
|
ttl, disabled, confirm, on_card);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -1346,8 +1375,13 @@ cmd_keyinfo (assuan_context_t ctx, char *line)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
on_card = 0;
|
||||||
|
for (l = keyinfo_on_cards; l; l = l->next)
|
||||||
|
if (!memcmp (l->keygrip, hexgrip, 40))
|
||||||
|
on_card = 1;
|
||||||
|
|
||||||
err = do_one_keyinfo (ctrl, grip, ctx, opt_data, opt_ssh_fpr, is_ssh,
|
err = do_one_keyinfo (ctrl, grip, ctx, opt_data, opt_ssh_fpr, is_ssh,
|
||||||
ttl, disabled, confirm);
|
ttl, disabled, confirm, on_card);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -1369,11 +1403,17 @@ cmd_keyinfo (assuan_context_t ctx, char *line)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
on_card = 0;
|
||||||
|
for (l = keyinfo_on_cards; l; l = l->next)
|
||||||
|
if (!memcmp (l->keygrip, line, 40))
|
||||||
|
on_card = 1;
|
||||||
|
|
||||||
err = do_one_keyinfo (ctrl, grip, ctx, opt_data, opt_ssh_fpr, is_ssh,
|
err = do_one_keyinfo (ctrl, grip, ctx, opt_data, opt_ssh_fpr, is_ssh,
|
||||||
ttl, disabled, confirm);
|
ttl, disabled, confirm, on_card);
|
||||||
}
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
agent_card_free_keyinfo (keyinfo_on_cards);
|
||||||
ssh_close_control_file (cf);
|
ssh_close_control_file (cf);
|
||||||
if (dir)
|
if (dir)
|
||||||
closedir (dir);
|
closedir (dir);
|
||||||
@ -2196,7 +2236,7 @@ cmd_import_key (assuan_context_t ctx, char *line)
|
|||||||
goto leave; /* Invalid canonical encoded S-expression. */
|
goto leave; /* Invalid canonical encoded S-expression. */
|
||||||
if (passphrase)
|
if (passphrase)
|
||||||
{
|
{
|
||||||
assert (!opt_unattended);
|
log_assert (!opt_unattended);
|
||||||
if (!cache_nonce)
|
if (!cache_nonce)
|
||||||
{
|
{
|
||||||
char buf[12];
|
char buf[12];
|
||||||
@ -2239,10 +2279,11 @@ cmd_import_key (assuan_context_t ctx, char *line)
|
|||||||
err = agent_protect (key, passphrase, &finalkey, &finalkeylen,
|
err = agent_protect (key, passphrase, &finalkey, &finalkeylen,
|
||||||
ctrl->s2k_count, -1);
|
ctrl->s2k_count, -1);
|
||||||
if (!err)
|
if (!err)
|
||||||
err = agent_write_private_key (grip, finalkey, finalkeylen, force);
|
err = agent_write_private_key (grip, finalkey, finalkeylen, force,
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
err = agent_write_private_key (grip, key, realkeylen, force);
|
err = agent_write_private_key (grip, key, realkeylen, force, NULL, NULL);
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
gcry_sexp_release (openpgp_sexp);
|
gcry_sexp_release (openpgp_sexp);
|
||||||
@ -3069,7 +3110,7 @@ cmd_getinfo (assuan_context_t ctx, char *line)
|
|||||||
{
|
{
|
||||||
cmdopt = line;
|
cmdopt = line;
|
||||||
if (!command_has_option (cmd, cmdopt))
|
if (!command_has_option (cmd, cmdopt))
|
||||||
rc = gpg_error (GPG_ERR_GENERAL);
|
rc = gpg_error (GPG_ERR_FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3083,7 +3124,7 @@ cmd_getinfo (assuan_context_t ctx, char *line)
|
|||||||
}
|
}
|
||||||
else if (!strcmp (line, "restricted"))
|
else if (!strcmp (line, "restricted"))
|
||||||
{
|
{
|
||||||
rc = ctrl->restricted? 0 : gpg_error (GPG_ERR_GENERAL);
|
rc = ctrl->restricted? 0 : gpg_error (GPG_ERR_FALSE);
|
||||||
}
|
}
|
||||||
else if (ctrl->restricted)
|
else if (ctrl->restricted)
|
||||||
{
|
{
|
||||||
@ -3117,7 +3158,7 @@ cmd_getinfo (assuan_context_t ctx, char *line)
|
|||||||
}
|
}
|
||||||
else if (!strcmp (line, "scd_running"))
|
else if (!strcmp (line, "scd_running"))
|
||||||
{
|
{
|
||||||
rc = agent_scd_check_running ()? 0 : gpg_error (GPG_ERR_GENERAL);
|
rc = agent_scd_check_running ()? 0 : gpg_error (GPG_ERR_FALSE);
|
||||||
}
|
}
|
||||||
else if (!strcmp (line, "std_env_names"))
|
else if (!strcmp (line, "std_env_names"))
|
||||||
{
|
{
|
||||||
@ -3639,3 +3680,26 @@ pinentry_loopback(ctrl_t ctrl, const char *keyword,
|
|||||||
assuan_end_confidential (ctx);
|
assuan_end_confidential (ctx);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper for the pinentry loopback mode to ask confirmation
|
||||||
|
or just to show message. */
|
||||||
|
gpg_error_t
|
||||||
|
pinentry_loopback_confirm (ctrl_t ctrl, const char *desc,
|
||||||
|
int ask_confirmation,
|
||||||
|
const char *ok, const char *notok)
|
||||||
|
{
|
||||||
|
gpg_error_t err = 0;
|
||||||
|
assuan_context_t ctx = ctrl->server_local->assuan_ctx;
|
||||||
|
|
||||||
|
if (desc)
|
||||||
|
err = print_assuan_status (ctx, "SETDESC", "%s", desc);
|
||||||
|
if (!err && ok)
|
||||||
|
err = print_assuan_status (ctx, "SETOK", "%s", ok);
|
||||||
|
if (!err && notok)
|
||||||
|
err = print_assuan_status (ctx, "SETNOTOK", "%s", notok);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
err = assuan_inquire (ctx, ask_confirmation ? "CONFIRM 1" : "CONFIRM 0",
|
||||||
|
NULL, NULL, 0);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "agent.h"
|
#include "agent.h"
|
||||||
#include "../common/i18n.h"
|
#include "../common/i18n.h"
|
||||||
@ -571,7 +570,7 @@ do_unprotect (const char *passphrase,
|
|||||||
}
|
}
|
||||||
skey[i] = NULL;
|
skey[i] = NULL;
|
||||||
skeylen = i;
|
skeylen = i;
|
||||||
assert (skeylen <= skeysize);
|
log_assert (skeylen <= skeysize);
|
||||||
|
|
||||||
/* Note: at this point NDATA should be 2 for a simple
|
/* Note: at this point NDATA should be 2 for a simple
|
||||||
checksum or 20 for the sha1 digest. */
|
checksum or 20 for the sha1 digest. */
|
||||||
@ -1067,7 +1066,8 @@ convert_from_openpgp_native (ctrl_t ctrl,
|
|||||||
if (!agent_protect (*r_key, passphrase,
|
if (!agent_protect (*r_key, passphrase,
|
||||||
&protectedkey, &protectedkeylen,
|
&protectedkey, &protectedkeylen,
|
||||||
ctrl->s2k_count, -1))
|
ctrl->s2k_count, -1))
|
||||||
agent_write_private_key (grip, protectedkey, protectedkeylen, 1);
|
agent_write_private_key (grip, protectedkey, protectedkeylen, 1,
|
||||||
|
NULL, NULL);
|
||||||
xfree (protectedkey);
|
xfree (protectedkey);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1076,7 +1076,7 @@ convert_from_openpgp_native (ctrl_t ctrl,
|
|||||||
agent_write_private_key (grip,
|
agent_write_private_key (grip,
|
||||||
*r_key,
|
*r_key,
|
||||||
gcry_sexp_canon_len (*r_key, 0, NULL,NULL),
|
gcry_sexp_canon_len (*r_key, 0, NULL,NULL),
|
||||||
1);
|
1, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1104,8 +1104,8 @@ apply_protection (gcry_mpi_t *array, int npkey, int nskey,
|
|||||||
int ndata;
|
int ndata;
|
||||||
unsigned char *p, *data;
|
unsigned char *p, *data;
|
||||||
|
|
||||||
assert (npkey < nskey);
|
log_assert (npkey < nskey);
|
||||||
assert (nskey < DIM (bufarr));
|
log_assert (nskey < DIM (bufarr));
|
||||||
|
|
||||||
/* Collect only the secret key parameters into BUFARR et al and
|
/* Collect only the secret key parameters into BUFARR et al and
|
||||||
compute the required size of the data buffer. */
|
compute the required size of the data buffer. */
|
||||||
@ -1142,7 +1142,7 @@ apply_protection (gcry_mpi_t *array, int npkey, int nskey,
|
|||||||
xfree (bufarr[i]);
|
xfree (bufarr[i]);
|
||||||
bufarr[i] = NULL;
|
bufarr[i] = NULL;
|
||||||
}
|
}
|
||||||
assert (p == data + ndata - 20);
|
log_assert (p == data + ndata - 20);
|
||||||
|
|
||||||
/* Append a hash of the secret key parameters. */
|
/* Append a hash of the secret key parameters. */
|
||||||
gcry_md_hash_buffer (GCRY_MD_SHA1, p, data, ndata - 20);
|
gcry_md_hash_buffer (GCRY_MD_SHA1, p, data, ndata - 20);
|
||||||
|
@ -32,28 +32,50 @@
|
|||||||
#include "../common/sexp-parse.h"
|
#include "../common/sexp-parse.h"
|
||||||
|
|
||||||
|
|
||||||
static int
|
static gpg_error_t
|
||||||
ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
|
ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info,
|
||||||
|
const unsigned char *grip, char **r_kid)
|
||||||
{
|
{
|
||||||
int rc, i;
|
int i;
|
||||||
char *serialno;
|
char *serialno;
|
||||||
int no_card = 0;
|
int no_card = 0;
|
||||||
char *desc;
|
char *desc;
|
||||||
char *want_sn, *want_kid, *want_sn_disp;
|
char *want_sn, *want_kid, *want_sn_disp;
|
||||||
int len;
|
int len;
|
||||||
|
struct card_key_info_s *keyinfo;
|
||||||
|
gpg_error_t err;
|
||||||
|
char hexgrip[41];
|
||||||
|
|
||||||
*r_kid = NULL;
|
*r_kid = NULL;
|
||||||
|
|
||||||
rc = parse_shadow_info (shadow_info, &want_sn, &want_kid, NULL);
|
/* Scan device(s), and check if key for GRIP is available. */
|
||||||
if (rc)
|
err = agent_card_serialno (ctrl, &serialno, NULL);
|
||||||
return rc;
|
if (!err)
|
||||||
|
{
|
||||||
|
xfree (serialno);
|
||||||
|
bin2hex (grip, 20, hexgrip);
|
||||||
|
err = agent_card_keyinfo (ctrl, hexgrip, &keyinfo);
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
/* Key for GRIP found, use it directly. */
|
||||||
|
agent_card_free_keyinfo (keyinfo);
|
||||||
|
if ((*r_kid = xtrystrdup (hexgrip)))
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = parse_shadow_info (shadow_info, &want_sn, &want_kid, NULL);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
want_sn_disp = xtrystrdup (want_sn);
|
want_sn_disp = xtrystrdup (want_sn);
|
||||||
if (!want_sn_disp)
|
if (!want_sn_disp)
|
||||||
{
|
{
|
||||||
rc = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
xfree (want_sn);
|
xfree (want_sn);
|
||||||
xfree (want_kid);
|
xfree (want_kid);
|
||||||
return rc;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen (want_sn_disp);
|
len = strlen (want_sn_disp);
|
||||||
@ -76,8 +98,8 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
rc = agent_card_serialno (ctrl, &serialno, want_sn);
|
err = agent_card_serialno (ctrl, &serialno, want_sn);
|
||||||
if (!rc)
|
if (!err)
|
||||||
{
|
{
|
||||||
log_debug ("detected card with S/N %s\n", serialno);
|
log_debug ("detected card with S/N %s\n", serialno);
|
||||||
i = strcmp (serialno, want_sn);
|
i = strcmp (serialno, want_sn);
|
||||||
@ -91,24 +113,24 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
|
|||||||
return 0; /* yes, we have the correct card */
|
return 0; /* yes, we have the correct card */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (gpg_err_code (rc) == GPG_ERR_ENODEV)
|
else if (gpg_err_code (err) == GPG_ERR_ENODEV)
|
||||||
{
|
{
|
||||||
log_debug ("no device present\n");
|
log_debug ("no device present\n");
|
||||||
rc = 0;
|
err = 0;
|
||||||
no_card = 1;
|
no_card = 1;
|
||||||
}
|
}
|
||||||
else if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT)
|
else if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
|
||||||
{
|
{
|
||||||
log_debug ("no card present\n");
|
log_debug ("no card present\n");
|
||||||
rc = 0;
|
err = 0;
|
||||||
no_card = 2;
|
no_card = 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_error ("error accessing card: %s\n", gpg_strerror (rc));
|
log_error ("error accessing card: %s\n", gpg_strerror (err));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rc)
|
if (!err)
|
||||||
{
|
{
|
||||||
if (asprintf (&desc,
|
if (asprintf (&desc,
|
||||||
"%s:%%0A%%0A"
|
"%s:%%0A%%0A"
|
||||||
@ -119,24 +141,24 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
|
|||||||
"insert the one with serial number"),
|
"insert the one with serial number"),
|
||||||
want_sn_disp) < 0)
|
want_sn_disp) < 0)
|
||||||
{
|
{
|
||||||
rc = out_of_core ();
|
err = out_of_core ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rc = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
|
err = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
|
||||||
if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK &&
|
if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK &&
|
||||||
gpg_err_code (rc) == GPG_ERR_NO_PIN_ENTRY)
|
gpg_err_code (err) == GPG_ERR_NO_PIN_ENTRY)
|
||||||
rc = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
|
err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
|
||||||
|
|
||||||
xfree (desc);
|
xfree (desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rc)
|
if (err)
|
||||||
{
|
{
|
||||||
xfree (want_sn_disp);
|
xfree (want_sn_disp);
|
||||||
xfree (want_sn);
|
xfree (want_sn);
|
||||||
xfree (want_kid);
|
xfree (want_kid);
|
||||||
return rc;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -434,7 +456,7 @@ getpin_cb (void *opaque, const char *desc_text, const char *info,
|
|||||||
*
|
*
|
||||||
* FIXME: Explain the other args. */
|
* FIXME: Explain the other args. */
|
||||||
int
|
int
|
||||||
divert_pksign (ctrl_t ctrl, const char *desc_text,
|
divert_pksign (ctrl_t ctrl, const char *desc_text, const unsigned char *grip,
|
||||||
const unsigned char *digest, size_t digestlen, int algo,
|
const unsigned char *digest, size_t digestlen, int algo,
|
||||||
const unsigned char *shadow_info, unsigned char **r_sig,
|
const unsigned char *shadow_info, unsigned char **r_sig,
|
||||||
size_t *r_siglen)
|
size_t *r_siglen)
|
||||||
@ -446,7 +468,7 @@ divert_pksign (ctrl_t ctrl, const char *desc_text,
|
|||||||
|
|
||||||
(void)desc_text;
|
(void)desc_text;
|
||||||
|
|
||||||
rc = ask_for_card (ctrl, shadow_info, &kid);
|
rc = ask_for_card (ctrl, shadow_info, grip, &kid);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -490,6 +512,7 @@ divert_pksign (ctrl_t ctrl, const char *desc_text,
|
|||||||
R_PADDING with -1 for not known. */
|
R_PADDING with -1 for not known. */
|
||||||
int
|
int
|
||||||
divert_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
divert_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||||
|
const unsigned char *grip,
|
||||||
const unsigned char *cipher,
|
const unsigned char *cipher,
|
||||||
const unsigned char *shadow_info,
|
const unsigned char *shadow_info,
|
||||||
char **r_buf, size_t *r_len, int *r_padding)
|
char **r_buf, size_t *r_len, int *r_padding)
|
||||||
@ -581,7 +604,7 @@ divert_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
ciphertext = s;
|
ciphertext = s;
|
||||||
ciphertextlen = n;
|
ciphertextlen = n;
|
||||||
|
|
||||||
rc = ask_for_card (ctrl, shadow_info, &kid);
|
rc = ask_for_card (ctrl, shadow_info, grip, &kid);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
232
agent/findkey.c
232
agent/findkey.c
@ -1,7 +1,7 @@
|
|||||||
/* findkey.c - Locate the secret key
|
/* findkey.c - Locate the secret key
|
||||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
|
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
|
||||||
* 2010, 2011 Free Software Foundation, Inc.
|
* 2010, 2011 Free Software Foundation, Inc.
|
||||||
* Copyright (C) 2014 Werner Koch
|
* Copyright (C) 2014, 2019 Werner Koch
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -26,10 +26,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <npth.h> /* (we use pth_sleep) */
|
#include <npth.h> /* (we use pth_sleep) */
|
||||||
|
|
||||||
#include "agent.h"
|
#include "agent.h"
|
||||||
@ -52,15 +50,47 @@ struct try_unprotect_arg_s
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Repalce all linefeeds in STRING by "%0A" and return a new malloced
|
||||||
|
* string. May return NULL on memory error. */
|
||||||
|
static char *
|
||||||
|
linefeed_to_percent0A (const char *string)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
size_t n;
|
||||||
|
char *buf, *p;
|
||||||
|
|
||||||
|
for (n=0, s=string; *s; s++)
|
||||||
|
if (*s == '\n')
|
||||||
|
n += 3;
|
||||||
|
else
|
||||||
|
n++;
|
||||||
|
p = buf = xtrymalloc (n+1);
|
||||||
|
if (!buf)
|
||||||
|
return NULL;
|
||||||
|
for (s=string; *s; s++)
|
||||||
|
if (*s == '\n')
|
||||||
|
{
|
||||||
|
memcpy (p, "%0A", 3);
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*p++ = *s;
|
||||||
|
*p = 0;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Note: Ownership of FNAME and FP are moved to this function. */
|
/* Note: Ownership of FNAME and FP are moved to this function. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
write_extended_private_key (char *fname, estream_t fp, int update,
|
write_extended_private_key (char *fname, estream_t fp, int update,
|
||||||
const void *buf, size_t len)
|
const void *buf, size_t len,
|
||||||
|
const char *serialno, const char *keyref)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
nvc_t pk = NULL;
|
nvc_t pk = NULL;
|
||||||
gcry_sexp_t key = NULL;
|
gcry_sexp_t key = NULL;
|
||||||
int remove = 0;
|
int remove = 0;
|
||||||
|
char *token = NULL;
|
||||||
|
|
||||||
if (update)
|
if (update)
|
||||||
{
|
{
|
||||||
@ -93,6 +123,37 @@ write_extended_private_key (char *fname, estream_t fp, int update,
|
|||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
/* If requested write a Token line. */
|
||||||
|
if (serialno && keyref)
|
||||||
|
{
|
||||||
|
nve_t item;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
token = strconcat (serialno, " ", keyref, NULL);
|
||||||
|
if (!token)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fixme: the strcmp should compare only the first two strings. */
|
||||||
|
for (item = nvc_lookup (pk, "Token:");
|
||||||
|
item;
|
||||||
|
item = nve_next_value (item, "Token:"))
|
||||||
|
if ((s = nve_value (item)) && !strcmp (s, token))
|
||||||
|
break;
|
||||||
|
if (!item)
|
||||||
|
{
|
||||||
|
/* No token or no token with that value exists. Add a new
|
||||||
|
* one so that keys which have been stored on several cards
|
||||||
|
* are well supported. */
|
||||||
|
err = nvc_add (pk, "Token:", token);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
err = es_fseek (fp, 0, SEEK_SET);
|
err = es_fseek (fp, 0, SEEK_SET);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -132,15 +193,18 @@ write_extended_private_key (char *fname, estream_t fp, int update,
|
|||||||
xfree (fname);
|
xfree (fname);
|
||||||
gcry_sexp_release (key);
|
gcry_sexp_release (key);
|
||||||
nvc_release (pk);
|
nvc_release (pk);
|
||||||
|
xfree (token);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write an S-expression formatted key to our key storage. With FORCE
|
/* Write an S-expression formatted key to our key storage. With FORCE
|
||||||
passed as true an existing key with the given GRIP will get
|
* passed as true an existing key with the given GRIP will get
|
||||||
overwritten. */
|
* overwritten. If SERIALNO and KEYREF are give an a Token line is added to
|
||||||
|
* th key if the extended format ist used. */
|
||||||
int
|
int
|
||||||
agent_write_private_key (const unsigned char *grip,
|
agent_write_private_key (const unsigned char *grip,
|
||||||
const void *buffer, size_t length, int force)
|
const void *buffer, size_t length, int force,
|
||||||
|
const char *serialno, const char *keyref)
|
||||||
{
|
{
|
||||||
char *fname;
|
char *fname;
|
||||||
estream_t fp;
|
estream_t fp;
|
||||||
@ -208,17 +272,20 @@ agent_write_private_key (const unsigned char *grip,
|
|||||||
if (first != '(')
|
if (first != '(')
|
||||||
{
|
{
|
||||||
/* Key is already in the extended format. */
|
/* Key is already in the extended format. */
|
||||||
return write_extended_private_key (fname, fp, 1, buffer, length);
|
return write_extended_private_key (fname, fp, 1, buffer, length,
|
||||||
|
serialno, keyref);
|
||||||
}
|
}
|
||||||
if (first == '(' && opt.enable_extended_key_format)
|
if (first == '(' && opt.enable_extended_key_format)
|
||||||
{
|
{
|
||||||
/* Key is in the old format - but we want the extended format. */
|
/* Key is in the old format - but we want the extended format. */
|
||||||
return write_extended_private_key (fname, fp, 0, buffer, length);
|
return write_extended_private_key (fname, fp, 0, buffer, length,
|
||||||
|
serialno, keyref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt.enable_extended_key_format)
|
if (opt.enable_extended_key_format)
|
||||||
return write_extended_private_key (fname, fp, 0, buffer, length);
|
return write_extended_private_key (fname, fp, 0, buffer, length,
|
||||||
|
serialno, keyref);
|
||||||
|
|
||||||
if (es_fwrite (buffer, length, 1, fp) != 1)
|
if (es_fwrite (buffer, length, 1, fp) != 1)
|
||||||
{
|
{
|
||||||
@ -267,7 +334,7 @@ try_unprotect_cb (struct pin_entry_info_s *pi)
|
|||||||
gnupg_isotime_t now, protected_at, tmptime;
|
gnupg_isotime_t now, protected_at, tmptime;
|
||||||
char *desc = NULL;
|
char *desc = NULL;
|
||||||
|
|
||||||
assert (!arg->unprotected_key);
|
log_assert (!arg->unprotected_key);
|
||||||
|
|
||||||
arg->change_required = 0;
|
arg->change_required = 0;
|
||||||
err = agent_unprotect (ctrl, arg->protected_key, pi->pin, protected_at,
|
err = agent_unprotect (ctrl, arg->protected_key, pi->pin, protected_at,
|
||||||
@ -332,6 +399,33 @@ try_unprotect_cb (struct pin_entry_info_s *pi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return true if the STRING has an %C or %c expando. */
|
||||||
|
static int
|
||||||
|
has_comment_expando (const char *string)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
int percent = 0;
|
||||||
|
|
||||||
|
if (!string)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (s = string; *s; s++)
|
||||||
|
{
|
||||||
|
if (percent)
|
||||||
|
{
|
||||||
|
if (*s == 'c' || *s == 'C')
|
||||||
|
return 1;
|
||||||
|
percent = 0;
|
||||||
|
}
|
||||||
|
else if (*s == '%')
|
||||||
|
percent = 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Modify a Key description, replacing certain special format
|
/* Modify a Key description, replacing certain special format
|
||||||
characters. List of currently supported replacements:
|
characters. List of currently supported replacements:
|
||||||
|
|
||||||
@ -644,7 +738,7 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert (arg.unprotected_key);
|
log_assert (arg.unprotected_key);
|
||||||
if (arg.change_required)
|
if (arg.change_required)
|
||||||
{
|
{
|
||||||
/* The callback told as that the user should change their
|
/* The callback told as that the user should change their
|
||||||
@ -652,7 +746,7 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
|
|||||||
size_t canlen, erroff;
|
size_t canlen, erroff;
|
||||||
gcry_sexp_t s_skey;
|
gcry_sexp_t s_skey;
|
||||||
|
|
||||||
assert (arg.unprotected_key);
|
log_assert (arg.unprotected_key);
|
||||||
canlen = gcry_sexp_canon_len (arg.unprotected_key, 0, NULL, NULL);
|
canlen = gcry_sexp_canon_len (arg.unprotected_key, 0, NULL, NULL);
|
||||||
rc = gcry_sexp_sscan (&s_skey, &erroff,
|
rc = gcry_sexp_sscan (&s_skey, &erroff,
|
||||||
(char*)arg.unprotected_key, canlen);
|
(char*)arg.unprotected_key, canlen);
|
||||||
@ -695,10 +789,13 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
|
|||||||
|
|
||||||
|
|
||||||
/* Read the key identified by GRIP from the private key directory and
|
/* Read the key identified by GRIP from the private key directory and
|
||||||
return it as an gcrypt S-expression object in RESULT. On failure
|
* return it as an gcrypt S-expression object in RESULT. If R_KEYMETA
|
||||||
returns an error code and stores NULL at RESULT. */
|
* is not NULl and the extended key format is used, the meta data
|
||||||
|
* items are stored there. However the "Key:" item is removed from
|
||||||
|
* it. On failure returns an error code and stores NULL at RESULT and
|
||||||
|
* R_KEYMETA. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
read_key_file (const unsigned char *grip, gcry_sexp_t *result)
|
read_key_file (const unsigned char *grip, gcry_sexp_t *result, nvc_t *r_keymeta)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
char *fname;
|
char *fname;
|
||||||
@ -711,6 +808,8 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
|
|||||||
char first;
|
char first;
|
||||||
|
|
||||||
*result = NULL;
|
*result = NULL;
|
||||||
|
if (r_keymeta)
|
||||||
|
*r_keymeta = NULL;
|
||||||
|
|
||||||
bin2hex (grip, 20, hexgrip);
|
bin2hex (grip, 20, hexgrip);
|
||||||
strcpy (hexgrip+40, ".key");
|
strcpy (hexgrip+40, ".key");
|
||||||
@ -749,7 +848,7 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
|
|||||||
if (first != '(')
|
if (first != '(')
|
||||||
{
|
{
|
||||||
/* Key is in extended format. */
|
/* Key is in extended format. */
|
||||||
nvc_t pk;
|
nvc_t pk = NULL;
|
||||||
int line;
|
int line;
|
||||||
|
|
||||||
err = nvc_parse_private_key (&pk, &line, fp);
|
err = nvc_parse_private_key (&pk, &line, fp);
|
||||||
@ -761,12 +860,17 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
err = nvc_get_private_key (pk, result);
|
err = nvc_get_private_key (pk, result);
|
||||||
nvc_release (pk);
|
|
||||||
if (err)
|
if (err)
|
||||||
log_error ("error getting private key from '%s': %s\n",
|
log_error ("error getting private key from '%s': %s\n",
|
||||||
fname, gpg_strerror (err));
|
fname, gpg_strerror (err));
|
||||||
|
else
|
||||||
|
nvc_delete_named (pk, "Key:");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!err && r_keymeta)
|
||||||
|
*r_keymeta = pk;
|
||||||
|
else
|
||||||
|
nvc_release (pk);
|
||||||
xfree (fname);
|
xfree (fname);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -866,6 +970,8 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
size_t len, buflen, erroff;
|
size_t len, buflen, erroff;
|
||||||
gcry_sexp_t s_skey;
|
gcry_sexp_t s_skey;
|
||||||
|
nvc_t keymeta = NULL;
|
||||||
|
char *desc_text_buffer = NULL; /* Used in case we extend DESC_TEXT. */
|
||||||
|
|
||||||
*result = NULL;
|
*result = NULL;
|
||||||
if (shadow_info)
|
if (shadow_info)
|
||||||
@ -873,7 +979,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
if (r_passphrase)
|
if (r_passphrase)
|
||||||
*r_passphrase = NULL;
|
*r_passphrase = NULL;
|
||||||
|
|
||||||
err = read_key_file (grip, &s_skey);
|
err = read_key_file (grip, &s_skey, &keymeta);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||||
@ -886,7 +992,11 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
now. */
|
now. */
|
||||||
err = make_canon_sexp (s_skey, &buf, &len);
|
err = make_canon_sexp (s_skey, &buf, &len);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
{
|
||||||
|
nvc_release (keymeta);
|
||||||
|
xfree (desc_text_buffer);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
switch (agent_private_key_type (buf))
|
switch (agent_private_key_type (buf))
|
||||||
{
|
{
|
||||||
@ -911,25 +1021,43 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
case PRIVATE_KEY_PROTECTED:
|
case PRIVATE_KEY_PROTECTED:
|
||||||
{
|
{
|
||||||
char *desc_text_final;
|
char *desc_text_final;
|
||||||
char *comment = NULL;
|
char *comment_buffer = NULL;
|
||||||
|
const char *comment = NULL;
|
||||||
|
|
||||||
/* Note, that we will take the comment as a C string for
|
/* Note, that we will take the comment as a C string for
|
||||||
display purposes; i.e. all stuff beyond a Nul character is
|
* display purposes; i.e. all stuff beyond a Nul character is
|
||||||
ignored. */
|
* ignored. If a "Label" entry is available in the meta data
|
||||||
{
|
* this is used instead of the s-ecpression comment. */
|
||||||
gcry_sexp_t comment_sexp;
|
if (keymeta && (comment = nvc_get_string (keymeta, "Label:")))
|
||||||
|
{
|
||||||
|
if (strchr (comment, '\n')
|
||||||
|
&& (comment_buffer = linefeed_to_percent0A (comment)))
|
||||||
|
comment = comment_buffer;
|
||||||
|
/* In case DESC_TEXT has no escape pattern for a comment
|
||||||
|
* we append one. */
|
||||||
|
if (desc_text && !has_comment_expando (desc_text))
|
||||||
|
{
|
||||||
|
desc_text_buffer = strconcat (desc_text, "%0A%C", NULL);
|
||||||
|
if (desc_text_buffer)
|
||||||
|
desc_text = desc_text_buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gcry_sexp_t comment_sexp;
|
||||||
|
|
||||||
comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
|
comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
|
||||||
if (comment_sexp)
|
if (comment_sexp)
|
||||||
comment = gcry_sexp_nth_string (comment_sexp, 1);
|
comment_buffer = gcry_sexp_nth_string (comment_sexp, 1);
|
||||||
gcry_sexp_release (comment_sexp);
|
gcry_sexp_release (comment_sexp);
|
||||||
}
|
comment = comment_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
desc_text_final = NULL;
|
desc_text_final = NULL;
|
||||||
if (desc_text)
|
if (desc_text)
|
||||||
err = agent_modify_description (desc_text, comment, s_skey,
|
err = agent_modify_description (desc_text, comment, s_skey,
|
||||||
&desc_text_final);
|
&desc_text_final);
|
||||||
gcry_free (comment);
|
gcry_free (comment_buffer);
|
||||||
|
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
@ -984,6 +1112,8 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
xfree (*r_passphrase);
|
xfree (*r_passphrase);
|
||||||
*r_passphrase = NULL;
|
*r_passphrase = NULL;
|
||||||
}
|
}
|
||||||
|
nvc_release (keymeta);
|
||||||
|
xfree (desc_text_buffer);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1000,10 +1130,14 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
xfree (*r_passphrase);
|
xfree (*r_passphrase);
|
||||||
*r_passphrase = NULL;
|
*r_passphrase = NULL;
|
||||||
}
|
}
|
||||||
|
nvc_release (keymeta);
|
||||||
|
xfree (desc_text_buffer);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
*result = s_skey;
|
*result = s_skey;
|
||||||
|
nvc_release (keymeta);
|
||||||
|
xfree (desc_text_buffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1203,7 +1337,7 @@ agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
|
|||||||
|
|
||||||
*result = NULL;
|
*result = NULL;
|
||||||
|
|
||||||
err = read_key_file (grip, &s_skey);
|
err = read_key_file (grip, &s_skey, NULL);
|
||||||
if (!err)
|
if (!err)
|
||||||
*result = s_skey;
|
*result = s_skey;
|
||||||
return err;
|
return err;
|
||||||
@ -1230,6 +1364,7 @@ agent_public_key_from_file (ctrl_t ctrl,
|
|||||||
gcry_sexp_t uri_sexp, comment_sexp;
|
gcry_sexp_t uri_sexp, comment_sexp;
|
||||||
const char *uri, *comment;
|
const char *uri, *comment;
|
||||||
size_t uri_length, comment_length;
|
size_t uri_length, comment_length;
|
||||||
|
int uri_intlen, comment_intlen;
|
||||||
char *format, *p;
|
char *format, *p;
|
||||||
void *args[2+7+2+2+1]; /* Size is 2 + max. # of elements + 2 for uri + 2
|
void *args[2+7+2+2+1]; /* Size is 2 + max. # of elements + 2 for uri + 2
|
||||||
for comment + end-of-list. */
|
for comment + end-of-list. */
|
||||||
@ -1241,7 +1376,7 @@ agent_public_key_from_file (ctrl_t ctrl,
|
|||||||
|
|
||||||
*result = NULL;
|
*result = NULL;
|
||||||
|
|
||||||
err = read_key_file (grip, &s_skey);
|
err = read_key_file (grip, &s_skey, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -1278,7 +1413,7 @@ agent_public_key_from_file (ctrl_t ctrl,
|
|||||||
such a task. After all that is what we do in protect.c. Need
|
such a task. After all that is what we do in protect.c. Need
|
||||||
to find common patterns and write a straightformward API to use
|
to find common patterns and write a straightformward API to use
|
||||||
them. */
|
them. */
|
||||||
assert (sizeof (size_t) <= sizeof (void*));
|
log_assert (sizeof (size_t) <= sizeof (void*));
|
||||||
|
|
||||||
format = xtrymalloc (15+4+7*npkey+10+15+1+1);
|
format = xtrymalloc (15+4+7*npkey+10+15+1+1);
|
||||||
if (!format)
|
if (!format)
|
||||||
@ -1303,27 +1438,29 @@ agent_public_key_from_file (ctrl_t ctrl,
|
|||||||
*p++ = '(';
|
*p++ = '(';
|
||||||
*p++ = *s++;
|
*p++ = *s++;
|
||||||
p = stpcpy (p, " %m)");
|
p = stpcpy (p, " %m)");
|
||||||
assert (argidx < DIM (args));
|
log_assert (argidx < DIM (args));
|
||||||
args[argidx++] = &array[idx];
|
args[argidx++] = &array[idx];
|
||||||
}
|
}
|
||||||
*p++ = ')';
|
*p++ = ')';
|
||||||
if (uri)
|
if (uri)
|
||||||
{
|
{
|
||||||
p = stpcpy (p, "(uri %b)");
|
p = stpcpy (p, "(uri %b)");
|
||||||
assert (argidx+1 < DIM (args));
|
log_assert (argidx+1 < DIM (args));
|
||||||
args[argidx++] = (void *)&uri_length;
|
uri_intlen = (int)uri_length;
|
||||||
|
args[argidx++] = (void *)&uri_intlen;
|
||||||
args[argidx++] = (void *)&uri;
|
args[argidx++] = (void *)&uri;
|
||||||
}
|
}
|
||||||
if (comment)
|
if (comment)
|
||||||
{
|
{
|
||||||
p = stpcpy (p, "(comment %b)");
|
p = stpcpy (p, "(comment %b)");
|
||||||
assert (argidx+1 < DIM (args));
|
log_assert (argidx+1 < DIM (args));
|
||||||
args[argidx++] = (void *)&comment_length;
|
comment_intlen = (int)comment_length;
|
||||||
|
args[argidx++] = (void *)&comment_intlen;
|
||||||
args[argidx++] = (void*)&comment;
|
args[argidx++] = (void*)&comment;
|
||||||
}
|
}
|
||||||
*p++ = ')';
|
*p++ = ')';
|
||||||
*p = 0;
|
*p = 0;
|
||||||
assert (argidx < DIM (args));
|
log_assert (argidx < DIM (args));
|
||||||
args[argidx] = NULL;
|
args[argidx] = NULL;
|
||||||
|
|
||||||
err = gcry_sexp_build_array (&list, NULL, format, args);
|
err = gcry_sexp_build_array (&list, NULL, format, args);
|
||||||
@ -1386,7 +1523,7 @@ agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
|
|||||||
{
|
{
|
||||||
gcry_sexp_t sexp;
|
gcry_sexp_t sexp;
|
||||||
|
|
||||||
err = read_key_file (grip, &sexp);
|
err = read_key_file (grip, &sexp, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||||
@ -1420,7 +1557,7 @@ agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
|
|||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
n = gcry_sexp_canon_len (s, 0, NULL, NULL);
|
n = gcry_sexp_canon_len (s, 0, NULL, NULL);
|
||||||
assert (n);
|
log_assert (n);
|
||||||
*r_shadow_info = xtrymalloc (n);
|
*r_shadow_info = xtrymalloc (n);
|
||||||
if (!*r_shadow_info)
|
if (!*r_shadow_info)
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
@ -1470,7 +1607,7 @@ agent_delete_key (ctrl_t ctrl, const char *desc_text,
|
|||||||
char *default_desc = NULL;
|
char *default_desc = NULL;
|
||||||
int key_type;
|
int key_type;
|
||||||
|
|
||||||
err = read_key_file (grip, &s_skey);
|
err = read_key_file (grip, &s_skey, NULL);
|
||||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||||
err = gpg_error (GPG_ERR_NO_SECKEY);
|
err = gpg_error (GPG_ERR_NO_SECKEY);
|
||||||
if (err)
|
if (err)
|
||||||
@ -1580,6 +1717,13 @@ agent_write_shadow_key (const unsigned char *grip,
|
|||||||
unsigned char *shdkey;
|
unsigned char *shdkey;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
|
/* Just in case some caller did not parse the stuff correctly, skip
|
||||||
|
* leading spaces. */
|
||||||
|
while (spacep (serialno))
|
||||||
|
serialno++;
|
||||||
|
while (spacep (keyid))
|
||||||
|
keyid++;
|
||||||
|
|
||||||
shadow_info = make_shadow_info (serialno, keyid);
|
shadow_info = make_shadow_info (serialno, keyid);
|
||||||
if (!shadow_info)
|
if (!shadow_info)
|
||||||
return gpg_error_from_syserror ();
|
return gpg_error_from_syserror ();
|
||||||
@ -1593,7 +1737,7 @@ agent_write_shadow_key (const unsigned char *grip,
|
|||||||
}
|
}
|
||||||
|
|
||||||
len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
|
len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
|
||||||
err = agent_write_private_key (grip, shdkey, len, force);
|
err = agent_write_private_key (grip, shdkey, len, force, serialno, keyid);
|
||||||
xfree (shdkey);
|
xfree (shdkey);
|
||||||
if (err)
|
if (err)
|
||||||
log_error ("error writing key: %s\n", gpg_strerror (err));
|
log_error ("error writing key: %s\n", gpg_strerror (err));
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "agent.h"
|
#include "agent.h"
|
||||||
#include "../common/i18n.h"
|
#include "../common/i18n.h"
|
||||||
@ -47,12 +46,12 @@ store_key (gcry_sexp_t private, const char *passphrase, int force,
|
|||||||
}
|
}
|
||||||
|
|
||||||
len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, NULL, 0);
|
len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||||
assert (len);
|
log_assert (len);
|
||||||
buf = gcry_malloc_secure (len);
|
buf = gcry_malloc_secure (len);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return out_of_core ();
|
return out_of_core ();
|
||||||
len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, buf, len);
|
len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, buf, len);
|
||||||
assert (len);
|
log_assert (len);
|
||||||
|
|
||||||
if (passphrase)
|
if (passphrase)
|
||||||
{
|
{
|
||||||
@ -68,7 +67,7 @@ store_key (gcry_sexp_t private, const char *passphrase, int force,
|
|||||||
buf = p;
|
buf = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = agent_write_private_key (grip, buf, len, force);
|
rc = agent_write_private_key (grip, buf, len, force, NULL, NULL);
|
||||||
xfree (buf);
|
xfree (buf);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -127,7 +126,7 @@ check_passphrase_pattern (ctrl_t ctrl, const char *pw)
|
|||||||
argv[i++] = "--",
|
argv[i++] = "--",
|
||||||
argv[i++] = opt.check_passphrase_pattern,
|
argv[i++] = opt.check_passphrase_pattern,
|
||||||
argv[i] = NULL;
|
argv[i] = NULL;
|
||||||
assert (i < sizeof argv);
|
log_assert (i < sizeof argv);
|
||||||
|
|
||||||
if (gnupg_spawn_process_fd (pgmname, argv, fileno (infp), -1, -1, &pid))
|
if (gnupg_spawn_process_fd (pgmname, argv, fileno (infp), -1, -1, &pid))
|
||||||
result = 1; /* Execute error - assume password should no be used. */
|
result = 1; /* Execute error - assume password should no be used. */
|
||||||
@ -149,27 +148,10 @@ check_passphrase_pattern (ctrl_t ctrl, const char *pw)
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
take_this_one_anyway2 (ctrl_t ctrl, const char *desc, const char *anyway_btn)
|
take_this_one_anyway (ctrl_t ctrl, const char *desc, const char *anyway_btn)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
return agent_get_confirmation (ctrl, desc,
|
||||||
|
anyway_btn, L_("Enter new passphrase"), 0);
|
||||||
if (opt.enforce_passphrase_constraints)
|
|
||||||
{
|
|
||||||
err = agent_show_message (ctrl, desc, L_("Enter new passphrase"));
|
|
||||||
if (!err)
|
|
||||||
err = gpg_error (GPG_ERR_CANCELED);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
err = agent_get_confirmation (ctrl, desc,
|
|
||||||
anyway_btn, L_("Enter new passphrase"), 0);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
take_this_one_anyway (ctrl_t ctrl, const char *desc)
|
|
||||||
{
|
|
||||||
return take_this_one_anyway2 (ctrl, desc, L_("Take this one anyway"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -212,8 +194,8 @@ check_passphrase_constraints (ctrl_t ctrl, const char *pw,
|
|||||||
if (opt.enforce_passphrase_constraints)
|
if (opt.enforce_passphrase_constraints)
|
||||||
*failed_constraint = xstrdup (desc);
|
*failed_constraint = xstrdup (desc);
|
||||||
else
|
else
|
||||||
err = take_this_one_anyway2 (ctrl, desc,
|
err = take_this_one_anyway (ctrl, desc,
|
||||||
L_("Yes, protection is not needed"));
|
L_("Yes, protection is not needed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -311,7 +293,7 @@ check_passphrase_constraints (ctrl_t ctrl, const char *pw,
|
|||||||
*failed_constraint = msg;
|
*failed_constraint = msg;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
err = take_this_one_anyway (ctrl, msg);
|
err = take_this_one_anyway (ctrl, msg, L_("Take this one anyway"));
|
||||||
xfree (msg);
|
xfree (msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -557,7 +539,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
if (DBG_CRYPTO)
|
if (DBG_CRYPTO)
|
||||||
log_debug ("returning public key\n");
|
log_debug ("returning public key\n");
|
||||||
len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, NULL, 0);
|
len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||||
assert (len);
|
log_assert (len);
|
||||||
buf = xtrymalloc (len);
|
buf = xtrymalloc (len);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
{
|
{
|
||||||
@ -567,7 +549,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
return tmperr;
|
return tmperr;
|
||||||
}
|
}
|
||||||
len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, buf, len);
|
len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, buf, len);
|
||||||
assert (len);
|
log_assert (len);
|
||||||
put_membuf (outbuf, buf, len);
|
put_membuf (outbuf, buf, len);
|
||||||
gcry_sexp_release (s_public);
|
gcry_sexp_release (s_public);
|
||||||
xfree (buf);
|
xfree (buf);
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -1952,7 +1951,7 @@ agent_set_progress_cb (void (*cb)(ctrl_t ctrl, const char *what,
|
|||||||
static void
|
static void
|
||||||
agent_init_default_ctrl (ctrl_t ctrl)
|
agent_init_default_ctrl (ctrl_t ctrl)
|
||||||
{
|
{
|
||||||
assert (ctrl->session_env);
|
log_assert (ctrl->session_env);
|
||||||
|
|
||||||
/* Note we ignore malloc errors because we can't do much about it
|
/* Note we ignore malloc errors because we can't do much about it
|
||||||
and the request will fail anyway shortly after this
|
and the request will fail anyway shortly after this
|
||||||
@ -2442,6 +2441,9 @@ agent_sighup_action (void)
|
|||||||
"pinentry" binary that one can be used in case the
|
"pinentry" binary that one can be used in case the
|
||||||
"pinentry-basic" fallback was in use. */
|
"pinentry-basic" fallback was in use. */
|
||||||
gnupg_module_name_flush_some ();
|
gnupg_module_name_flush_some ();
|
||||||
|
|
||||||
|
if (opt.disable_scdaemon)
|
||||||
|
agent_card_killscd ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,8 @@ hexadecimal representation of the keygrip[2] and suffixed with ".key".
|
|||||||
|
|
||||||
* Extended Private Key Format
|
* Extended Private Key Format
|
||||||
|
|
||||||
GnuPG 2.3+ will use a new format to store private keys that is both
|
** Overview
|
||||||
|
GnuPG 2.3+ uses a new format to store private keys that is both
|
||||||
more flexible and easier to read and edit by human beings. The new
|
more flexible and easier to read and edit by human beings. The new
|
||||||
format stores name,value-pairs using the common mail and http header
|
format stores name,value-pairs using the common mail and http header
|
||||||
convention. Example (here indented with two spaces):
|
convention. Example (here indented with two spaces):
|
||||||
@ -28,6 +29,8 @@ convention. Example (here indented with two spaces):
|
|||||||
Use-for-ssh: yes
|
Use-for-ssh: yes
|
||||||
OpenSSH-cert: long base64 encoded string wrapped so that this
|
OpenSSH-cert: long base64 encoded string wrapped so that this
|
||||||
key file can be easily edited with a standard editor.
|
key file can be easily edited with a standard editor.
|
||||||
|
Token: D2760001240102000005000011730000 OPENPGP.1
|
||||||
|
Token: FF020001008A77C1 PIV.9C
|
||||||
Key: (shadowed-private-key
|
Key: (shadowed-private-key
|
||||||
(rsa
|
(rsa
|
||||||
(n #00AA1AD2A55FD8C8FDE9E1941772D9CC903FA43B268CB1B5A1BAFDC900
|
(n #00AA1AD2A55FD8C8FDE9E1941772D9CC903FA43B268CB1B5A1BAFDC900
|
||||||
@ -52,33 +55,66 @@ Keys in the extended format can be recognized by looking at the first
|
|||||||
byte of the file. If it starts with a '(' it is a naked S-expression,
|
byte of the file. If it starts with a '(' it is a naked S-expression,
|
||||||
otherwise it is a key in extended format.
|
otherwise it is a key in extended format.
|
||||||
|
|
||||||
** Names
|
*** Names
|
||||||
|
|
||||||
A name must start with a letter and end with a colon. Valid
|
A name must start with a letter and end with a colon. Valid
|
||||||
characters are all ASCII letters, numbers and the hyphen. Comparison
|
characters are all ASCII letters, numbers and the hyphen. Comparison
|
||||||
of names is done case insensitively. Names may be used several times
|
of names is done case insensitively. Names may be used several times
|
||||||
to represent an array of values.
|
to represent an array of values. Note that the name "Key" is special
|
||||||
|
in that it is madandory must occur only once.
|
||||||
The name "Key:" is special in that it may occur only once and the
|
|
||||||
associated value holds the actual S-expression with the cryptographic
|
|
||||||
key. The S-expression is formatted using the 'Advanced Format'
|
|
||||||
(GCRYSEXP_FMT_ADVANCED) that avoids non-printable characters so that
|
|
||||||
the file can be easily inspected and edited. See section 'Private Key
|
|
||||||
Format' below for details.
|
|
||||||
|
|
||||||
** Values
|
|
||||||
|
|
||||||
|
*** Values
|
||||||
Values are UTF-8 encoded strings. Values can be wrapped at any point,
|
Values are UTF-8 encoded strings. Values can be wrapped at any point,
|
||||||
and continued in the next line indicated by leading whitespace. A
|
and continued in the next line indicated by leading whitespace. A
|
||||||
continuation line with one leading space does not introduce a blank so
|
continuation line with one leading space does not introduce a blank so
|
||||||
that the lines can be effectively concatenated. A blank line as part
|
that the lines can be effectively concatenated. A blank line as part
|
||||||
of a continuation line encodes a newline.
|
of a continuation line encodes a newline.
|
||||||
|
|
||||||
** Comments
|
*** Comments
|
||||||
|
|
||||||
Lines containing only whitespace, and lines starting with whitespace
|
Lines containing only whitespace, and lines starting with whitespace
|
||||||
followed by '#' are considered to be comments and are ignored.
|
followed by '#' are considered to be comments and are ignored.
|
||||||
|
|
||||||
|
** Well defined names
|
||||||
|
|
||||||
|
*** Description
|
||||||
|
This is a human readable string describing the key.
|
||||||
|
|
||||||
|
*** Key
|
||||||
|
The name "Key" is special in that it is mandatory and must occur only
|
||||||
|
once. The associated value holds the actual S-expression with the
|
||||||
|
cryptographic key. The S-expression is formatted using the 'Advanced
|
||||||
|
Format' (GCRYSEXP_FMT_ADVANCED) that avoids non-printable characters
|
||||||
|
so that the file can be easily inspected and edited. See section
|
||||||
|
'Private Key Format' below for details.
|
||||||
|
|
||||||
|
*** Label
|
||||||
|
This is a short human readable description for the key which can be
|
||||||
|
used by the software to describe the key in a user interface. For
|
||||||
|
example as part of the description in a prompt for a PIN or
|
||||||
|
passphrase. It is often used instead of a comment element as present
|
||||||
|
in the S-expression of the "Key" item.
|
||||||
|
|
||||||
|
*** OpenSSH-cert
|
||||||
|
This takes a base64 encoded string wrapped so that this
|
||||||
|
key file can be easily edited with a standard editor. Several of such
|
||||||
|
items can be used.
|
||||||
|
|
||||||
|
*** Token
|
||||||
|
If such an item exists it overrides the info given by the "shadow"
|
||||||
|
parameter in the S-expression. Using this item makes it possible to
|
||||||
|
describe a key which is stored on several tokens and also makes it
|
||||||
|
easy to update this info using a standard editor. The syntax is the
|
||||||
|
same as with the "shadow" parameter:
|
||||||
|
|
||||||
|
- Serialnumber of the token
|
||||||
|
- Key reference from the token in full format (e.g. "OpenPGP.2")
|
||||||
|
- An optional fixed length of the PIN.
|
||||||
|
|
||||||
|
*** Use-for-ssh
|
||||||
|
If given and the value is "yes" or "1" the key is allowed for use by
|
||||||
|
gpg-agent's ssh-agent implementation. This is thus the same as
|
||||||
|
putting the keygrip into the 'sshcontrol' file. Only one such item
|
||||||
|
should exist.
|
||||||
|
|
||||||
* Private Key Format
|
* Private Key Format
|
||||||
** Unprotected Private Key Format
|
** Unprotected Private Key Format
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
@ -86,8 +85,8 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = divert_pkdecrypt (ctrl, desc_text, ciphertext, shadow_info,
|
rc = divert_pkdecrypt (ctrl, desc_text, ctrl->keygrip, ciphertext,
|
||||||
&buf, &len, r_padding);
|
shadow_info, &buf, &len, r_padding);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_error ("smartcard decryption failed: %s\n", gpg_strerror (rc));
|
log_error ("smartcard decryption failed: %s\n", gpg_strerror (rc));
|
||||||
@ -119,10 +118,10 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
gcry_sexp_dump (s_plain);
|
gcry_sexp_dump (s_plain);
|
||||||
}
|
}
|
||||||
len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, NULL, 0);
|
len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||||
assert (len);
|
log_assert (len);
|
||||||
buf = xmalloc (len);
|
buf = xmalloc (len);
|
||||||
len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, buf, len);
|
len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, buf, len);
|
||||||
assert (len);
|
log_assert (len);
|
||||||
if (*buf == '(')
|
if (*buf == '(')
|
||||||
put_membuf (outbuf, buf, len);
|
put_membuf (outbuf, buf, len);
|
||||||
else
|
else
|
||||||
|
@ -24,8 +24,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "agent.h"
|
#include "agent.h"
|
||||||
@ -46,16 +44,21 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
s = gcry_md_algo_name (algo);
|
s = gcry_md_algo_name (algo);
|
||||||
if (s && strlen (s) < 16)
|
if (!s || strlen (s) >= 16)
|
||||||
|
{
|
||||||
|
hash = NULL;
|
||||||
|
rc = gpg_error (GPG_ERR_DIGEST_ALGO);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
for (i=0; i < strlen (s); i++)
|
for (i=0; s[i]; i++)
|
||||||
tmp[i] = tolower (s[i]);
|
tmp[i] = ascii_tolower (s[i]);
|
||||||
tmp[i] = '\0';
|
tmp[i] = '\0';
|
||||||
}
|
|
||||||
|
|
||||||
rc = gcry_sexp_build (&hash, NULL,
|
rc = gcry_sexp_build (&hash, NULL,
|
||||||
"(data (flags pkcs1) (hash %s %b))",
|
"(data (flags pkcs1) (hash %s %b))",
|
||||||
tmp, (int)mdlen, md);
|
tmp, (int)mdlen, md);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -250,13 +253,13 @@ do_encode_raw_pkcs1 (const byte *md, size_t mdlen, unsigned int nbits,
|
|||||||
frame[n++] = 0;
|
frame[n++] = 0;
|
||||||
frame[n++] = 1; /* Block type. */
|
frame[n++] = 1; /* Block type. */
|
||||||
i = nframe - mdlen - 3 ;
|
i = nframe - mdlen - 3 ;
|
||||||
assert (i >= 8); /* At least 8 bytes of padding. */
|
log_assert (i >= 8); /* At least 8 bytes of padding. */
|
||||||
memset (frame+n, 0xff, i );
|
memset (frame+n, 0xff, i );
|
||||||
n += i;
|
n += i;
|
||||||
frame[n++] = 0;
|
frame[n++] = 0;
|
||||||
memcpy (frame+n, md, mdlen );
|
memcpy (frame+n, md, mdlen );
|
||||||
n += mdlen;
|
n += mdlen;
|
||||||
assert (n == nframe);
|
log_assert (n == nframe);
|
||||||
|
|
||||||
/* Create the S-expression. */
|
/* Create the S-expression. */
|
||||||
rc = gcry_sexp_build (&hash, NULL,
|
rc = gcry_sexp_build (&hash, NULL,
|
||||||
@ -354,6 +357,7 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
agent_modify_description (desc_text, NULL, s_skey, &desc2);
|
agent_modify_description (desc_text, NULL, s_skey, &desc2);
|
||||||
|
|
||||||
err = divert_pksign (ctrl, desc2? desc2 : desc_text,
|
err = divert_pksign (ctrl, desc2? desc2 : desc_text,
|
||||||
|
ctrl->keygrip,
|
||||||
data, datalen,
|
data, datalen,
|
||||||
ctrl->digest.algo,
|
ctrl->digest.algo,
|
||||||
shadow_info, &buf, &len);
|
shadow_info, &buf, &len);
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#ifdef HAVE_LOCALE_H
|
#ifdef HAVE_LOCALE_H
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#ifdef HAVE_LOCALE_H
|
#ifdef HAVE_LOCALE_H
|
||||||
@ -198,10 +197,10 @@ make_canonical (const char *fname, const char *buf, size_t buflen)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
|
len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||||
assert (len);
|
log_assert (len);
|
||||||
result = xmalloc (len);
|
result = xmalloc (len);
|
||||||
len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, result, len);
|
len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, result, len);
|
||||||
assert (len);
|
log_assert (len);
|
||||||
gcry_sexp_release (sexp);
|
gcry_sexp_release (sexp);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -222,10 +221,10 @@ make_advanced (const unsigned char *buf, size_t buflen)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
|
len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
|
||||||
assert (len);
|
log_assert (len);
|
||||||
result = xmalloc (len);
|
result = xmalloc (len);
|
||||||
len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len);
|
len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len);
|
||||||
assert (len);
|
log_assert (len);
|
||||||
gcry_sexp_release (sexp);
|
gcry_sexp_release (sexp);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -433,7 +432,7 @@ read_and_shadow (const char *fname)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resultlen = gcry_sexp_canon_len (result, 0, NULL,NULL);
|
resultlen = gcry_sexp_canon_len (result, 0, NULL,NULL);
|
||||||
assert (resultlen);
|
log_assert (resultlen);
|
||||||
|
|
||||||
if (opt_armor)
|
if (opt_armor)
|
||||||
{
|
{
|
||||||
@ -469,7 +468,7 @@ show_shadow_info (const char *fname)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
infolen = gcry_sexp_canon_len (info, 0, NULL,NULL);
|
infolen = gcry_sexp_canon_len (info, 0, NULL,NULL);
|
||||||
assert (infolen);
|
log_assert (infolen);
|
||||||
|
|
||||||
if (opt_armor)
|
if (opt_armor)
|
||||||
{
|
{
|
||||||
@ -496,7 +495,7 @@ show_file (const char *fname)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
keylen = gcry_sexp_canon_len (key, 0, NULL,NULL);
|
keylen = gcry_sexp_canon_len (key, 0, NULL,NULL);
|
||||||
assert (keylen);
|
log_assert (keylen);
|
||||||
|
|
||||||
if (opt_canonical)
|
if (opt_canonical)
|
||||||
{
|
{
|
||||||
@ -723,7 +722,7 @@ get_passphrase (int promptno)
|
|||||||
gpg_strerror (err));
|
gpg_strerror (err));
|
||||||
agent_exit (0);
|
agent_exit (0);
|
||||||
}
|
}
|
||||||
assert (pw);
|
log_assert (pw);
|
||||||
|
|
||||||
return pw;
|
return pw;
|
||||||
}
|
}
|
||||||
@ -799,12 +798,15 @@ agent_askpin (ctrl_t ctrl,
|
|||||||
* to stdout. */
|
* to stdout. */
|
||||||
int
|
int
|
||||||
agent_write_private_key (const unsigned char *grip,
|
agent_write_private_key (const unsigned char *grip,
|
||||||
const void *buffer, size_t length, int force)
|
const void *buffer, size_t length, int force,
|
||||||
|
const char *serialno, const char *keyref)
|
||||||
{
|
{
|
||||||
char hexgrip[40+4+1];
|
char hexgrip[40+4+1];
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
(void)force;
|
(void)force;
|
||||||
|
(void)serialno;
|
||||||
|
(void)keyref;
|
||||||
|
|
||||||
bin2hex (grip, 20, hexgrip);
|
bin2hex (grip, 20, hexgrip);
|
||||||
strcpy (hexgrip+40, ".key");
|
strcpy (hexgrip+40, ".key");
|
||||||
|
@ -528,7 +528,7 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
|
|||||||
memcpy (p, iv+blklen, blklen); /* Add padding. */
|
memcpy (p, iv+blklen, blklen); /* Add padding. */
|
||||||
p += blklen;
|
p += blklen;
|
||||||
}
|
}
|
||||||
assert ( p - outbuf == outlen);
|
log_assert ( p - outbuf == outlen);
|
||||||
if (use_ocb)
|
if (use_ocb)
|
||||||
{
|
{
|
||||||
gcry_cipher_final (hd);
|
gcry_cipher_final (hd);
|
||||||
@ -718,11 +718,11 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
|
|||||||
hash_end = s;
|
hash_end = s;
|
||||||
s++;
|
s++;
|
||||||
/* Skip to the end of the S-expression. */
|
/* Skip to the end of the S-expression. */
|
||||||
assert (depth == 1);
|
log_assert (depth == 1);
|
||||||
rc = sskip (&s, &depth);
|
rc = sskip (&s, &depth);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
assert (!depth);
|
log_assert (!depth);
|
||||||
real_end = s-1;
|
real_end = s-1;
|
||||||
|
|
||||||
rc = do_encryption (hash_begin, hash_end - hash_begin + 1,
|
rc = do_encryption (hash_begin, hash_end - hash_begin + 1,
|
||||||
@ -760,7 +760,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
|
|||||||
|
|
||||||
memcpy (p, prot_end+1, real_end - prot_end);
|
memcpy (p, prot_end+1, real_end - prot_end);
|
||||||
p += real_end - prot_end;
|
p += real_end - prot_end;
|
||||||
assert ( p - *result == *resultlen);
|
log_assert ( p - *result == *resultlen);
|
||||||
xfree (protected);
|
xfree (protected);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -999,7 +999,7 @@ merge_lists (const unsigned char *protectedkey,
|
|||||||
|
|
||||||
/* Skip over the protected list element in the original list. */
|
/* Skip over the protected list element in the original list. */
|
||||||
s = protectedkey + replacepos;
|
s = protectedkey + replacepos;
|
||||||
assert (*s == '(');
|
log_assert (*s == '(');
|
||||||
s++;
|
s++;
|
||||||
i = 1;
|
i = 1;
|
||||||
rc = sskip (&s, &i);
|
rc = sskip (&s, &i);
|
||||||
@ -1026,7 +1026,7 @@ merge_lists (const unsigned char *protectedkey,
|
|||||||
rc = sskip (&s, &i);
|
rc = sskip (&s, &i);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto failure;
|
goto failure;
|
||||||
assert (s[-1] == ')');
|
log_assert (s[-1] == ')');
|
||||||
endpos = s; /* one behind the end of the list */
|
endpos = s; /* one behind the end of the list */
|
||||||
|
|
||||||
/* Append the rest. */
|
/* Append the rest. */
|
||||||
@ -1571,7 +1571,7 @@ agent_shadow_key (const unsigned char *pubkey,
|
|||||||
point = s; /* insert right before the point */
|
point = s; /* insert right before the point */
|
||||||
depth--;
|
depth--;
|
||||||
s++;
|
s++;
|
||||||
assert (depth == 1);
|
log_assert (depth == 1);
|
||||||
|
|
||||||
/* Calculate required length by taking in account: the "shadowed-"
|
/* Calculate required length by taking in account: the "shadowed-"
|
||||||
prefix, the "shadowed", "t1-v1" as well as some parenthesis */
|
prefix, the "shadowed", "t1-v1" as well as some parenthesis */
|
||||||
@ -1667,7 +1667,8 @@ agent_get_shadow_info (const unsigned char *shadowkey,
|
|||||||
R_HEXSN and the Id string as a malloced string at R_IDSTR. On
|
R_HEXSN and the Id string as a malloced string at R_IDSTR. On
|
||||||
error an error code is returned and NULL is stored at the result
|
error an error code is returned and NULL is stored at the result
|
||||||
parameters addresses. If the serial number or the ID string is not
|
parameters addresses. If the serial number or the ID string is not
|
||||||
required, NULL may be passed for them. */
|
required, NULL may be passed for them. Note that R_PINLEN is
|
||||||
|
currently not used by any caller. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
parse_shadow_info (const unsigned char *shadow_info,
|
parse_shadow_info (const unsigned char *shadow_info,
|
||||||
char **r_hexsn, char **r_idstr, int *r_pinlen)
|
char **r_hexsn, char **r_idstr, int *r_pinlen)
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <npth.h>
|
#include <npth.h>
|
||||||
@ -550,7 +549,7 @@ insert_colons (const char *string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
assert (strlen (buffer) <= nnew);
|
log_assert (strlen (buffer) <= nnew);
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
@ -624,6 +624,7 @@ Section "GnuPG" SEC_gnupg
|
|||||||
File "bin/gpgsm.exe"
|
File "bin/gpgsm.exe"
|
||||||
File "bin/gpgconf.exe"
|
File "bin/gpgconf.exe"
|
||||||
File "bin/gpg-connect-agent.exe"
|
File "bin/gpg-connect-agent.exe"
|
||||||
|
File "bin/gpg-card.exe"
|
||||||
File "bin/gpgtar.exe"
|
File "bin/gpgtar.exe"
|
||||||
File "libexec/dirmngr_ldap.exe"
|
File "libexec/dirmngr_ldap.exe"
|
||||||
File "libexec/gpg-preset-passphrase.exe"
|
File "libexec/gpg-preset-passphrase.exe"
|
||||||
@ -1313,6 +1314,7 @@ Section "-un.gnupg"
|
|||||||
Delete "$INSTDIR\bin\gpgconf.exe"
|
Delete "$INSTDIR\bin\gpgconf.exe"
|
||||||
Delete "$INSTDIR\bin\gpg-connect-agent.exe"
|
Delete "$INSTDIR\bin\gpg-connect-agent.exe"
|
||||||
Delete "$INSTDIR\bin\gpgtar.exe"
|
Delete "$INSTDIR\bin\gpgtar.exe"
|
||||||
|
Delete "$INSTDIR\bin\gpg-card.exe"
|
||||||
Delete "$INSTDIR\bin\dirmngr_ldap.exe"
|
Delete "$INSTDIR\bin\dirmngr_ldap.exe"
|
||||||
Delete "$INSTDIR\bin\gpg-preset-passphrase.exe"
|
Delete "$INSTDIR\bin\gpg-preset-passphrase.exe"
|
||||||
Delete "$INSTDIR\bin\gpg-wks-client.exe"
|
Delete "$INSTDIR\bin\gpg-wks-client.exe"
|
||||||
|
@ -149,13 +149,13 @@ if MAINTAINER_MODE
|
|||||||
audit-events.h: Makefile.am mkstrtable.awk exaudit.awk audit.h
|
audit-events.h: Makefile.am mkstrtable.awk exaudit.awk audit.h
|
||||||
$(AWK) -f $(srcdir)/exaudit.awk $(srcdir)/audit.h \
|
$(AWK) -f $(srcdir)/exaudit.awk $(srcdir)/audit.h \
|
||||||
| $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=3 -v nogettext=1 \
|
| $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=3 -v nogettext=1 \
|
||||||
-v namespace=eventstr_ > $(srcdir)/audit-events.h
|
-v pkg_namespace=eventstr_ > $(srcdir)/audit-events.h
|
||||||
|
|
||||||
# Create the status-codes.h include file from status.h
|
# Create the status-codes.h include file from status.h
|
||||||
status-codes.h: Makefile.am mkstrtable.awk exstatus.awk status.h
|
status-codes.h: Makefile.am mkstrtable.awk exstatus.awk status.h
|
||||||
$(AWK) -f $(srcdir)/exstatus.awk $(srcdir)/status.h \
|
$(AWK) -f $(srcdir)/exstatus.awk $(srcdir)/status.h \
|
||||||
| $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=3 -v nogettext=1 \
|
| $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=3 -v nogettext=1 \
|
||||||
-v namespace=statusstr_ > $(srcdir)/status-codes.h
|
-v pkg_namespace=statusstr_ > $(srcdir)/status-codes.h
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -856,6 +856,7 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
|
|||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
int cr_flags;
|
int cr_flags;
|
||||||
char *cmdline;
|
char *cmdline;
|
||||||
|
BOOL in_job = FALSE;
|
||||||
|
|
||||||
|
|
||||||
/* We don't use ENVP. */
|
/* We don't use ENVP. */
|
||||||
@ -884,6 +885,50 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
|
|||||||
| GetPriorityClass (GetCurrentProcess ())
|
| GetPriorityClass (GetCurrentProcess ())
|
||||||
| CREATE_NEW_PROCESS_GROUP
|
| CREATE_NEW_PROCESS_GROUP
|
||||||
| DETACHED_PROCESS);
|
| DETACHED_PROCESS);
|
||||||
|
|
||||||
|
/* Check if we were spawned as part of a Job.
|
||||||
|
* In a job we need to add CREATE_BREAKAWAY_FROM_JOB
|
||||||
|
* to the cr_flags, otherwise our child processes
|
||||||
|
* are killed when we terminate. */
|
||||||
|
if (!IsProcessInJob (GetCurrentProcess(), NULL, &in_job))
|
||||||
|
{
|
||||||
|
log_error ("IsProcessInJob() failed: %s\n", w32_strerror (-1));
|
||||||
|
in_job = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_job)
|
||||||
|
{
|
||||||
|
/* Only try to break away from job if it is allowed, otherwise
|
||||||
|
* CreateProcess() would fail with an "Access is denied" error. */
|
||||||
|
JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
|
||||||
|
if (!QueryInformationJobObject (NULL, JobObjectExtendedLimitInformation,
|
||||||
|
&info, sizeof info, NULL))
|
||||||
|
{
|
||||||
|
log_error ("QueryInformationJobObject() failed: %s\n",
|
||||||
|
w32_strerror (-1));
|
||||||
|
}
|
||||||
|
else if ((info.BasicLimitInformation.LimitFlags &
|
||||||
|
JOB_OBJECT_LIMIT_BREAKAWAY_OK))
|
||||||
|
{
|
||||||
|
log_debug ("Using CREATE_BREAKAWAY_FROM_JOB flag\n");
|
||||||
|
cr_flags |= CREATE_BREAKAWAY_FROM_JOB;
|
||||||
|
}
|
||||||
|
else if ((info.BasicLimitInformation.LimitFlags &
|
||||||
|
JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK))
|
||||||
|
{
|
||||||
|
/* The child process should automatically detach from the job. */
|
||||||
|
log_debug ("Not using CREATE_BREAKAWAY_FROM_JOB flag; "
|
||||||
|
"JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK is set\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* It seems that the child process must remain in the job.
|
||||||
|
* This is not necessarily an error, although it can cause premature
|
||||||
|
* termination of the child process when the job is closed. */
|
||||||
|
log_debug ("Not using CREATE_BREAKAWAY_FROM_JOB flag\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", */
|
/* log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", */
|
||||||
/* pgmname, cmdline); */
|
/* pgmname, cmdline); */
|
||||||
if (!CreateProcess (pgmname, /* Program to start. */
|
if (!CreateProcess (pgmname, /* Program to start. */
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
#
|
#
|
||||||
# The variable prefix can be used to prepend a string to each message.
|
# The variable prefix can be used to prepend a string to each message.
|
||||||
#
|
#
|
||||||
# The variable namespace can be used to prepend a string to each
|
# The variable pkg_namespace can be used to prepend a string to each
|
||||||
# variable and macro name.
|
# variable and macro name.
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
@ -101,7 +101,7 @@ header {
|
|||||||
print "/* The purpose of this complex string table is to produce";
|
print "/* The purpose of this complex string table is to produce";
|
||||||
print " optimal code with a minimum of relocations. */";
|
print " optimal code with a minimum of relocations. */";
|
||||||
print "";
|
print "";
|
||||||
print "static const char " namespace "msgstr[] = ";
|
print "static const char " pkg_namespace "msgstr[] = ";
|
||||||
header = 0;
|
header = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -109,7 +109,7 @@ header {
|
|||||||
}
|
}
|
||||||
|
|
||||||
!header {
|
!header {
|
||||||
sub (/\#.+/, "");
|
sub (/#.+/, "");
|
||||||
sub (/[ ]+$/, ""); # Strip trailing space and tab characters.
|
sub (/[ ]+$/, ""); # Strip trailing space and tab characters.
|
||||||
|
|
||||||
if (/^$/)
|
if (/^$/)
|
||||||
@ -149,14 +149,14 @@ END {
|
|||||||
else
|
else
|
||||||
print " gettext_noop (\"" prefix last_msgstr "\");";
|
print " gettext_noop (\"" prefix last_msgstr "\");";
|
||||||
print "";
|
print "";
|
||||||
print "static const int " namespace "msgidx[] =";
|
print "static const int " pkg_namespace "msgidx[] =";
|
||||||
print " {";
|
print " {";
|
||||||
for (i = 0; i < coded_msgs; i++)
|
for (i = 0; i < coded_msgs; i++)
|
||||||
print " " pos[i] ",";
|
print " " pos[i] ",";
|
||||||
print " " pos[coded_msgs];
|
print " " pos[coded_msgs];
|
||||||
print " };";
|
print " };";
|
||||||
print "";
|
print "";
|
||||||
print "#define " namespace "msgidxof(code) (0 ? -1 \\";
|
print "#define " pkg_namespace "msgidxof(code) (0 ? -1 \\";
|
||||||
|
|
||||||
# Gather the ranges.
|
# Gather the ranges.
|
||||||
skip = code[0];
|
skip = code[0];
|
||||||
|
@ -514,6 +514,21 @@ nvc_delete (nvc_t pk, nve_t entry)
|
|||||||
nve_release (entry, pk->private_key_mode);
|
nve_release (entry, pk->private_key_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Delete the entries with NAME from PK. */
|
||||||
|
void
|
||||||
|
nvc_delete_named (nvc_t pk, const char *name)
|
||||||
|
{
|
||||||
|
nve_t e;
|
||||||
|
|
||||||
|
if (!valid_name (name))
|
||||||
|
return;
|
||||||
|
|
||||||
|
while ((e = nvc_lookup (pk, name)))
|
||||||
|
nvc_delete (pk, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Lookup and iteration. */
|
/* Lookup and iteration. */
|
||||||
@ -563,6 +578,25 @@ nve_next_value (nve_t entry, const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the string for the first entry in NVC with NAME. If an
|
||||||
|
* entry with NAME is missing in NVC or its value is the empty string
|
||||||
|
* NULL is returned. Note that the The returned string is a pointer
|
||||||
|
* into NVC. */
|
||||||
|
const char *
|
||||||
|
nvc_get_string (nvc_t nvc, const char *name)
|
||||||
|
{
|
||||||
|
nve_t item;
|
||||||
|
|
||||||
|
if (!nvc)
|
||||||
|
return NULL;
|
||||||
|
item = nvc_lookup (nvc, name);
|
||||||
|
if (!item)
|
||||||
|
return NULL;
|
||||||
|
return nve_value (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Private key handling. */
|
/* Private key handling. */
|
||||||
@ -778,29 +812,56 @@ nvc_parse_private_key (nvc_t *result, int *errlinep, estream_t stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper fpr nvc_write. */
|
||||||
|
static gpg_error_t
|
||||||
|
write_one_entry (nve_t entry, estream_t stream)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
strlist_t sl;
|
||||||
|
|
||||||
|
if (entry->name)
|
||||||
|
es_fputs (entry->name, stream);
|
||||||
|
|
||||||
|
err = assert_raw_value (entry);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
for (sl = entry->raw_value; sl; sl = sl->next)
|
||||||
|
es_fputs (sl->d, stream);
|
||||||
|
|
||||||
|
if (es_ferror (stream))
|
||||||
|
return my_error_from_syserror ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Write a representation of PK to STREAM. */
|
/* Write a representation of PK to STREAM. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
nvc_write (nvc_t pk, estream_t stream)
|
nvc_write (nvc_t pk, estream_t stream)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err = 0;
|
||||||
nve_t entry;
|
nve_t entry;
|
||||||
strlist_t s;
|
nve_t keyentry = NULL;
|
||||||
|
|
||||||
for (entry = pk->first; entry; entry = entry->next)
|
for (entry = pk->first; entry; entry = entry->next)
|
||||||
{
|
{
|
||||||
if (entry->name)
|
if (pk->private_key_mode
|
||||||
es_fputs (entry->name, stream);
|
&& entry->name && !ascii_strcasecmp (entry->name, "Key:"))
|
||||||
|
{
|
||||||
|
if (!keyentry)
|
||||||
|
keyentry = entry;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
err = assert_raw_value (entry);
|
err = write_one_entry (entry, stream);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
for (s = entry->raw_value; s; s = s->next)
|
|
||||||
es_fputs (s->d, stream);
|
|
||||||
|
|
||||||
if (es_ferror (stream))
|
|
||||||
return my_error_from_syserror ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
/* In private key mode we write the Key always last. */
|
||||||
|
if (keyentry)
|
||||||
|
err = write_one_entry (keyentry, stream);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,9 @@ nve_t nve_next (nve_t entry);
|
|||||||
/* Get the next entry with the given name. */
|
/* Get the next entry with the given name. */
|
||||||
nve_t nve_next_value (nve_t entry, const char *name);
|
nve_t nve_next_value (nve_t entry, const char *name);
|
||||||
|
|
||||||
|
/* Return the string for the first entry in NVC with NAME or NULL. */
|
||||||
|
const char *nvc_get_string (nvc_t nvc, const char *name);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Adding and modifying values. */
|
/* Adding and modifying values. */
|
||||||
@ -88,6 +91,9 @@ gpg_error_t nvc_set (nvc_t pk, const char *name, const char *value);
|
|||||||
/* Delete the given entry from PK. */
|
/* Delete the given entry from PK. */
|
||||||
void nvc_delete (nvc_t pk, nve_t pke);
|
void nvc_delete (nvc_t pk, nve_t pke);
|
||||||
|
|
||||||
|
/* Delete the entries with NAME from PK. */
|
||||||
|
void nvc_delete_named (nvc_t pk, const char *name);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Private key handling. */
|
/* Private key handling. */
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
#include "openpgpdefs.h"
|
#include "openpgpdefs.h"
|
||||||
|
|
||||||
|
|
||||||
/* Pack an s2k iteration count into the form specified in RFC-48800.
|
/* Pack an s2k iteration count into the form specified in RFC-4880.
|
||||||
* If we're in between valid values, round up. */
|
* If we're in between valid values, round up. */
|
||||||
unsigned char
|
unsigned char
|
||||||
encode_s2k_iterations (int iterations)
|
encode_s2k_iterations (int iterations)
|
||||||
|
@ -581,9 +581,9 @@ get_pk_algo_from_canon_sexp (const unsigned char *keydata, size_t keydatalen)
|
|||||||
|
|
||||||
/* Given the public key S_PKEY, return a new buffer with a descriptive
|
/* Given the public key S_PKEY, return a new buffer with a descriptive
|
||||||
* string for its algorithm. This function may return NULL on memory
|
* string for its algorithm. This function may return NULL on memory
|
||||||
* error. */
|
* error. If R_ALGOID is not NULL the gcrypt algo id is stored there. */
|
||||||
char *
|
char *
|
||||||
pubkey_algo_string (gcry_sexp_t s_pkey)
|
pubkey_algo_string (gcry_sexp_t s_pkey, enum gcry_pk_algos *r_algoid)
|
||||||
{
|
{
|
||||||
const char *prefix;
|
const char *prefix;
|
||||||
gcry_sexp_t l1;
|
gcry_sexp_t l1;
|
||||||
@ -591,6 +591,9 @@ pubkey_algo_string (gcry_sexp_t s_pkey)
|
|||||||
int algo;
|
int algo;
|
||||||
char *result;
|
char *result;
|
||||||
|
|
||||||
|
if (r_algoid)
|
||||||
|
*r_algoid = 0;
|
||||||
|
|
||||||
l1 = gcry_sexp_find_token (s_pkey, "public-key", 0);
|
l1 = gcry_sexp_find_token (s_pkey, "public-key", 0);
|
||||||
if (!l1)
|
if (!l1)
|
||||||
return xtrystrdup ("E_no_key");
|
return xtrystrdup ("E_no_key");
|
||||||
@ -632,6 +635,8 @@ pubkey_algo_string (gcry_sexp_t s_pkey)
|
|||||||
else
|
else
|
||||||
result = xtryasprintf ("X_algo_%d", algo);
|
result = xtryasprintf ("X_algo_%d", algo);
|
||||||
|
|
||||||
|
if (r_algoid)
|
||||||
|
*r_algoid = algo;
|
||||||
xfree (algoname);
|
xfree (algoname);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -292,6 +292,7 @@ run_modification_tests (void)
|
|||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
nvc_t pk;
|
nvc_t pk;
|
||||||
|
nve_t e;
|
||||||
gcry_sexp_t key;
|
gcry_sexp_t key;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
@ -344,6 +345,30 @@ run_modification_tests (void)
|
|||||||
assert (strcmp (buf, "") == 0);
|
assert (strcmp (buf, "") == 0);
|
||||||
xfree (buf);
|
xfree (buf);
|
||||||
|
|
||||||
|
/* Test whether we can delete an entry by name. */
|
||||||
|
err = nvc_add (pk, "Key:", "(3:foo)");
|
||||||
|
assert (!err);
|
||||||
|
e = nvc_lookup (pk, "Key:");
|
||||||
|
assert (e);
|
||||||
|
nvc_delete_named (pk, "Kez:"); /* Delete an inexistant name. */
|
||||||
|
e = nvc_lookup (pk, "Key:");
|
||||||
|
assert (e);
|
||||||
|
nvc_delete_named (pk, "Key:");
|
||||||
|
e = nvc_lookup (pk, "Key:");
|
||||||
|
assert (!e);
|
||||||
|
|
||||||
|
/* Ditto but now whether it deletes all entries with that name. We
|
||||||
|
* don't use "Key" because that name is special in private key mode. */
|
||||||
|
err = nvc_add (pk, "AKey:", "A-value");
|
||||||
|
assert (!err);
|
||||||
|
err = nvc_add (pk, "AKey:", "B-value");
|
||||||
|
assert (!err);
|
||||||
|
e = nvc_lookup (pk, "AKey:");
|
||||||
|
assert (e);
|
||||||
|
nvc_delete_named (pk, "AKey:");
|
||||||
|
e = nvc_lookup (pk, "AKey:");
|
||||||
|
assert (!e);
|
||||||
|
|
||||||
nvc_set (pk, "Foo:", "A really long value spanning across multiple lines"
|
nvc_set (pk, "Foo:", "A really long value spanning across multiple lines"
|
||||||
" that has to be wrapped at a convenient space.");
|
" that has to be wrapped at a convenient space.");
|
||||||
buf = nvc_to_string (pk);
|
buf = nvc_to_string (pk);
|
||||||
|
@ -380,8 +380,10 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
|
|||||||
}
|
}
|
||||||
else if (!hexprefix)
|
else if (!hexprefix)
|
||||||
{
|
{
|
||||||
/* The fingerprint in an X.509 listing is often delimited by
|
/* The fingerprint of an X.509 listing is often delimited by
|
||||||
colons, so we try to single this case out. */
|
* colons, so we try to single this case out. Note that the
|
||||||
|
* OpenPGP bang suffix is not supported here. */
|
||||||
|
desc->exact = 0;
|
||||||
mode = 0;
|
mode = 0;
|
||||||
hexlength = strspn (s, ":0123456789abcdefABCDEF");
|
hexlength = strspn (s, ":0123456789abcdefABCDEF");
|
||||||
if (hexlength == 59 && (!s[hexlength] || spacep (s+hexlength)))
|
if (hexlength == 59 && (!s[hexlength] || spacep (s+hexlength)))
|
||||||
@ -454,7 +456,6 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
|
|||||||
}
|
}
|
||||||
if (!mode) /* Default to substring search. */
|
if (!mode) /* Default to substring search. */
|
||||||
{
|
{
|
||||||
desc->exact = 0;
|
|
||||||
desc->u.name = s;
|
desc->u.name = s;
|
||||||
mode = KEYDB_SEARCH_MODE_SUBSTR;
|
mode = KEYDB_SEARCH_MODE_SUBSTR;
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ gpg_error_t get_rsa_pk_from_canon_sexp (const unsigned char *keydata,
|
|||||||
int get_pk_algo_from_key (gcry_sexp_t key);
|
int get_pk_algo_from_key (gcry_sexp_t key);
|
||||||
int get_pk_algo_from_canon_sexp (const unsigned char *keydata,
|
int get_pk_algo_from_canon_sexp (const unsigned char *keydata,
|
||||||
size_t keydatalen);
|
size_t keydatalen);
|
||||||
char *pubkey_algo_string (gcry_sexp_t s_pkey);
|
char *pubkey_algo_string (gcry_sexp_t s_pkey, enum gcry_pk_algos *r_algoid);
|
||||||
|
|
||||||
/*-- convert.c --*/
|
/*-- convert.c --*/
|
||||||
int hex2bin (const char *string, void *buffer, size_t length);
|
int hex2bin (const char *string, void *buffer, size_t length);
|
||||||
|
@ -1471,6 +1471,9 @@ find_cert_bysubject (ctrl_t ctrl, const char *subject_dn, ksba_sexp_t keyid)
|
|||||||
{
|
{
|
||||||
ksba_cert_ref (ci->cert);
|
ksba_cert_ref (ci->cert);
|
||||||
release_cache_lock ();
|
release_cache_lock ();
|
||||||
|
if (DBG_LOOKUP)
|
||||||
|
log_debug ("%s: certificate found in the cache"
|
||||||
|
" via ocsp_certs\n", __func__);
|
||||||
return ci->cert; /* We use this certificate. */
|
return ci->cert; /* We use this certificate. */
|
||||||
}
|
}
|
||||||
release_cache_lock ();
|
release_cache_lock ();
|
||||||
@ -1478,7 +1481,7 @@ find_cert_bysubject (ctrl_t ctrl, const char *subject_dn, ksba_sexp_t keyid)
|
|||||||
log_debug ("find_cert_bysubject: certificate not in ocsp_certs\n");
|
log_debug ("find_cert_bysubject: certificate not in ocsp_certs\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No check whether the certificate is cached. */
|
/* Now check whether the certificate is cached. */
|
||||||
for (seq=0; (cert = get_cert_bysubject (subject_dn, seq)); seq++)
|
for (seq=0; (cert = get_cert_bysubject (subject_dn, seq)); seq++)
|
||||||
{
|
{
|
||||||
if (!keyid)
|
if (!keyid)
|
||||||
@ -1487,6 +1490,9 @@ find_cert_bysubject (ctrl_t ctrl, const char *subject_dn, ksba_sexp_t keyid)
|
|||||||
&& !cmp_simple_canon_sexp (keyid, subj))
|
&& !cmp_simple_canon_sexp (keyid, subj))
|
||||||
{
|
{
|
||||||
xfree (subj);
|
xfree (subj);
|
||||||
|
if (DBG_LOOKUP)
|
||||||
|
log_debug ("%s: certificate found in the cache"
|
||||||
|
" via subject DN\n", __func__);
|
||||||
break; /* Found matching cert. */
|
break; /* Found matching cert. */
|
||||||
}
|
}
|
||||||
xfree (subj);
|
xfree (subj);
|
||||||
@ -1495,6 +1501,34 @@ find_cert_bysubject (ctrl_t ctrl, const char *subject_dn, ksba_sexp_t keyid)
|
|||||||
if (cert)
|
if (cert)
|
||||||
return cert; /* Done. */
|
return cert; /* Done. */
|
||||||
|
|
||||||
|
/* If we do not have a subject DN but have a keyid, try to locate it
|
||||||
|
* by keyid. */
|
||||||
|
if (!subject_dn && keyid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
cert_item_t ci;
|
||||||
|
ksba_sexp_t ski;
|
||||||
|
|
||||||
|
acquire_cache_read_lock ();
|
||||||
|
for (i=0; i < 256; i++)
|
||||||
|
for (ci=cert_cache[i]; ci; ci = ci->next)
|
||||||
|
if (ci->cert && !ksba_cert_get_subj_key_id (ci->cert, NULL, &ski))
|
||||||
|
{
|
||||||
|
if (!cmp_simple_canon_sexp (keyid, ski))
|
||||||
|
{
|
||||||
|
ksba_free (ski);
|
||||||
|
ksba_cert_ref (ci->cert);
|
||||||
|
release_cache_lock ();
|
||||||
|
if (DBG_LOOKUP)
|
||||||
|
log_debug ("%s: certificate found in the cache"
|
||||||
|
" via ski\n", __func__);
|
||||||
|
return ci->cert;
|
||||||
|
}
|
||||||
|
ksba_free (ski);
|
||||||
|
}
|
||||||
|
release_cache_lock ();
|
||||||
|
}
|
||||||
|
|
||||||
if (DBG_LOOKUP)
|
if (DBG_LOOKUP)
|
||||||
log_debug ("find_cert_bysubject: certificate not in cache\n");
|
log_debug ("find_cert_bysubject: certificate not in cache\n");
|
||||||
|
|
||||||
|
@ -2217,8 +2217,8 @@ static void dns_p_dump3(struct dns_packet *P, struct dns_rr_i *I, FILE *fp) {
|
|||||||
|
|
||||||
|
|
||||||
void dns_p_dump(struct dns_packet *P, FILE *fp) {
|
void dns_p_dump(struct dns_packet *P, FILE *fp) {
|
||||||
struct dns_rr_i _I = { 0 };
|
struct dns_rr_i I_instance = { 0 };
|
||||||
dns_p_dump3(P, &_I, fp);
|
dns_p_dump3(P, &I_instance, fp);
|
||||||
} /* dns_p_dump() */
|
} /* dns_p_dump() */
|
||||||
|
|
||||||
|
|
||||||
@ -5275,8 +5275,8 @@ error:
|
|||||||
|
|
||||||
|
|
||||||
struct dns_packet *dns_hosts_query(struct dns_hosts *hosts, struct dns_packet *Q, int *error_) {
|
struct dns_packet *dns_hosts_query(struct dns_hosts *hosts, struct dns_packet *Q, int *error_) {
|
||||||
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _P = { 0 };
|
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } P_instance = { 0 };
|
||||||
struct dns_packet *P = dns_p_init(&_P.p, 512);
|
struct dns_packet *P = dns_p_init(&P_instance.p, 512);
|
||||||
struct dns_packet *A = 0;
|
struct dns_packet *A = 0;
|
||||||
struct dns_rr rr;
|
struct dns_rr rr;
|
||||||
struct dns_hosts_entry *ent;
|
struct dns_hosts_entry *ent;
|
||||||
@ -6837,7 +6837,7 @@ unsigned dns_hints_grep(struct sockaddr **sa, socklen_t *sa_len, unsigned lim, s
|
|||||||
|
|
||||||
|
|
||||||
struct dns_packet *dns_hints_query(struct dns_hints *hints, struct dns_packet *Q, int *error_) {
|
struct dns_packet *dns_hints_query(struct dns_hints *hints, struct dns_packet *Q, int *error_) {
|
||||||
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _P = { 0 };
|
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } P_instance = { 0 };
|
||||||
struct dns_packet *A, *P;
|
struct dns_packet *A, *P;
|
||||||
struct dns_rr rr;
|
struct dns_rr rr;
|
||||||
char zone[DNS_D_MAXNAME + 1];
|
char zone[DNS_D_MAXNAME + 1];
|
||||||
@ -6846,11 +6846,11 @@ struct dns_packet *dns_hints_query(struct dns_hints *hints, struct dns_packet *Q
|
|||||||
struct sockaddr *sa;
|
struct sockaddr *sa;
|
||||||
socklen_t slen;
|
socklen_t slen;
|
||||||
int error;
|
int error;
|
||||||
struct dns_rr_i _I = { 0 };
|
struct dns_rr_i I_instance = { 0 };
|
||||||
|
|
||||||
_I.section = DNS_S_QUESTION;
|
I_instance.section = DNS_S_QUESTION;
|
||||||
|
|
||||||
if (!dns_rr_grep(&rr, 1, &_I, Q, &error))
|
if (!dns_rr_grep(&rr, 1, &I_instance, Q, &error))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!(zlen = dns_d_expand(zone, sizeof zone, rr.dn.p, Q, &error)))
|
if (!(zlen = dns_d_expand(zone, sizeof zone, rr.dn.p, Q, &error)))
|
||||||
@ -6858,7 +6858,7 @@ struct dns_packet *dns_hints_query(struct dns_hints *hints, struct dns_packet *Q
|
|||||||
else if (zlen >= sizeof zone)
|
else if (zlen >= sizeof zone)
|
||||||
goto toolong;
|
goto toolong;
|
||||||
|
|
||||||
P = dns_p_init(&_P.p, 512);
|
P = dns_p_init(&P_instance.p, 512);
|
||||||
dns_header(P)->qr = 1;
|
dns_header(P)->qr = 1;
|
||||||
|
|
||||||
if ((error = dns_rr_copy(P, &rr, Q)))
|
if ((error = dns_rr_copy(P, &rr, Q)))
|
||||||
@ -8463,8 +8463,8 @@ error:
|
|||||||
|
|
||||||
|
|
||||||
static struct dns_packet *dns_res_glue(struct dns_resolver *R, struct dns_packet *Q) {
|
static struct dns_packet *dns_res_glue(struct dns_resolver *R, struct dns_packet *Q) {
|
||||||
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _P = { 0 };
|
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } P_instance = { 0 };
|
||||||
struct dns_packet *P = dns_p_init(&_P.p, 512);
|
struct dns_packet *P = dns_p_init(&P_instance.p, 512);
|
||||||
char qname[DNS_D_MAXNAME + 1];
|
char qname[DNS_D_MAXNAME + 1];
|
||||||
size_t qlen;
|
size_t qlen;
|
||||||
enum dns_type qtype;
|
enum dns_type qtype;
|
||||||
@ -8537,20 +8537,20 @@ static int dns_res_nameserv_cmp(struct dns_rr *a, struct dns_rr *b, struct dns_r
|
|||||||
int cmp, error;
|
int cmp, error;
|
||||||
|
|
||||||
if (!(error = dns_ns_parse(&ns, a, P))) {
|
if (!(error = dns_ns_parse(&ns, a, P))) {
|
||||||
struct dns_rr_i _I = { 0 };
|
struct dns_rr_i I_instance = { 0 };
|
||||||
|
|
||||||
_I.section = (DNS_S_ALL & ~DNS_S_QD);
|
I_instance.section = (DNS_S_ALL & ~DNS_S_QD);
|
||||||
_I.name = ns.host;
|
I_instance.name = ns.host;
|
||||||
_I.type = DNS_T_A;
|
I_instance.type = DNS_T_A;
|
||||||
glued[0] = !!dns_rr_grep(&x, 1, &_I, P, &error);
|
glued[0] = !!dns_rr_grep(&x, 1, &I_instance, P, &error);
|
||||||
}
|
}
|
||||||
if (!(error = dns_ns_parse(&ns, b, P))) {
|
if (!(error = dns_ns_parse(&ns, b, P))) {
|
||||||
struct dns_rr_i _I = { 0 };
|
struct dns_rr_i I_instance = { 0 };
|
||||||
|
|
||||||
_I.section = (DNS_S_ALL & ~DNS_S_QD);
|
I_instance.section = (DNS_S_ALL & ~DNS_S_QD);
|
||||||
_I.name = ns.host;
|
I_instance.name = ns.host;
|
||||||
_I.type = DNS_T_A;
|
I_instance.type = DNS_T_A;
|
||||||
glued[1] = !!dns_rr_grep(&y, 1, &_I, P, &error);
|
glued[1] = !!dns_rr_grep(&y, 1, &I_instance, P, &error);
|
||||||
}
|
}
|
||||||
if ((cmp = glued[1] - glued[0])) {
|
if ((cmp = glued[1] - glued[0])) {
|
||||||
return cmp;
|
return cmp;
|
||||||
@ -9916,13 +9916,13 @@ exec:
|
|||||||
return dns_ai_setent(ent, &any, rr.type, ai);
|
return dns_ai_setent(ent, &any, rr.type, ai);
|
||||||
case DNS_AI_S_SUBMIT_G:
|
case DNS_AI_S_SUBMIT_G:
|
||||||
{
|
{
|
||||||
struct dns_rr_i _I = { 0 };
|
struct dns_rr_i I_instance = { 0 };
|
||||||
|
|
||||||
_I.section = DNS_S_QD;
|
I_instance.section = DNS_S_QD;
|
||||||
_I.name = ai->g.name;
|
I_instance.name = ai->g.name;
|
||||||
_I.type = ai->g.type;
|
I_instance.type = ai->g.type;
|
||||||
/* skip if already queried */
|
/* skip if already queried */
|
||||||
if (dns_rr_grep(&rr, 1, &_I, ai->glue, &error))
|
if (dns_rr_grep(&rr, 1, &I_instance, ai->glue, &error))
|
||||||
dns_ai_goto(DNS_AI_S_FOREACH_I);
|
dns_ai_goto(DNS_AI_S_FOREACH_I);
|
||||||
/* skip if we recursed (CNAME chains should have been handled in the resolver) */
|
/* skip if we recursed (CNAME chains should have been handled in the resolver) */
|
||||||
if (++ai->g_depth > 1)
|
if (++ai->g_depth > 1)
|
||||||
@ -10598,7 +10598,7 @@ static struct dns_trace *trace(const char *mode) {
|
|||||||
|
|
||||||
|
|
||||||
static void print_packet(struct dns_packet *P, FILE *fp) {
|
static void print_packet(struct dns_packet *P, FILE *fp) {
|
||||||
struct dns_rr_i _I = { 0 };
|
struct dns_rr_i I_instance = { 0 };
|
||||||
I.sort = MAIN.sort;
|
I.sort = MAIN.sort;
|
||||||
dns_p_dump3(P, &I, fp);
|
dns_p_dump3(P, &I, fp);
|
||||||
|
|
||||||
@ -10608,10 +10608,10 @@ static void print_packet(struct dns_packet *P, FILE *fp) {
|
|||||||
|
|
||||||
|
|
||||||
static int parse_packet(int argc DNS_NOTUSED, char *argv[] DNS_NOTUSED) {
|
static int parse_packet(int argc DNS_NOTUSED, char *argv[] DNS_NOTUSED) {
|
||||||
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _P = { 0 };
|
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } P_instance = { 0 };
|
||||||
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _Q = { 0 };
|
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } Q_instance = { 0 };
|
||||||
struct dns_packet *P = dns_p_init(&_P.p, 512);
|
struct dns_packet *P = dns_p_init(&P_instance.p, 512);
|
||||||
struct dns_packet *Q = dns_p_init(&_Q.p, 512);
|
struct dns_packet *Q = dns_p_init(&Q_instance.p, 512);
|
||||||
enum dns_section section;
|
enum dns_section section;
|
||||||
struct dns_rr rr;
|
struct dns_rr rr;
|
||||||
int error;
|
int error;
|
||||||
@ -10655,7 +10655,7 @@ static int parse_packet(int argc DNS_NOTUSED, char *argv[] DNS_NOTUSED) {
|
|||||||
const char *dn = "ns8.yahoo.com";
|
const char *dn = "ns8.yahoo.com";
|
||||||
char *_name = dns_d_init(_p, sizeof _p, dn, strlen (dn), DNS_D_ANCHOR);
|
char *_name = dns_d_init(_p, sizeof _p, dn, strlen (dn), DNS_D_ANCHOR);
|
||||||
struct dns_rr rrset[32];
|
struct dns_rr rrset[32];
|
||||||
struct dns_rr_i _I = { 0 };
|
struct dns_rr_i I_instance = { 0 };
|
||||||
struct dns_rr_i *rri = &I;
|
struct dns_rr_i *rri = &I;
|
||||||
unsigned rrcount = dns_rr_grep(rrset, lengthof(rrset), rri, Q, &error);
|
unsigned rrcount = dns_rr_grep(rrset, lengthof(rrset), rri, Q, &error);
|
||||||
|
|
||||||
@ -10818,8 +10818,8 @@ static int show_hosts(int argc DNS_NOTUSED, char *argv[] DNS_NOTUSED) {
|
|||||||
|
|
||||||
|
|
||||||
static int query_hosts(int argc, char *argv[]) {
|
static int query_hosts(int argc, char *argv[]) {
|
||||||
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _Q = { 0 };
|
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } Q_instance = { 0 };
|
||||||
struct dns_packet *Q = dns_p_init(&_Q.p, 512);
|
struct dns_packet *Q = dns_p_init(&Q_instance.p, 512);
|
||||||
struct dns_packet *A;
|
struct dns_packet *A;
|
||||||
char qname[DNS_D_MAXNAME + 1];
|
char qname[DNS_D_MAXNAME + 1];
|
||||||
size_t qlen;
|
size_t qlen;
|
||||||
@ -10937,8 +10937,8 @@ static int dump_random(int argc, char *argv[]) {
|
|||||||
|
|
||||||
|
|
||||||
static int send_query(int argc, char *argv[]) {
|
static int send_query(int argc, char *argv[]) {
|
||||||
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _Q = { 0 };
|
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } Q_instance = { 0 };
|
||||||
struct dns_packet *A, *Q = dns_p_init(&_Q.p, 512);
|
struct dns_packet *A, *Q = dns_p_init(&Q_instance.p, 512);
|
||||||
char host[INET6_ADDRSTRLEN + 1];
|
char host[INET6_ADDRSTRLEN + 1];
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
struct dns_socket *so;
|
struct dns_socket *so;
|
||||||
@ -11033,10 +11033,10 @@ static int show_hints(int argc, char *argv[]) {
|
|||||||
if (0 == strcmp(how, "plain")) {
|
if (0 == strcmp(how, "plain")) {
|
||||||
dns_hints_dump(hints, stdout);
|
dns_hints_dump(hints, stdout);
|
||||||
} else {
|
} else {
|
||||||
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _P = { 0 };
|
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } P_instance = { 0 };
|
||||||
struct dns_packet *query, *answer;
|
struct dns_packet *query, *answer;
|
||||||
|
|
||||||
query = dns_p_init(&_P.p, 512);
|
query = dns_p_init(&P_instance.p, 512);
|
||||||
|
|
||||||
if ((error = dns_p_push(query, DNS_S_QUESTION, who, strlen(who), DNS_T_A, DNS_C_IN, 0, 0)))
|
if ((error = dns_p_push(query, DNS_S_QUESTION, who, strlen(who), DNS_T_A, DNS_C_IN, 0, 0)))
|
||||||
panic("%s: %s", who, dns_strerror(error));
|
panic("%s: %s", who, dns_strerror(error));
|
||||||
@ -11199,8 +11199,8 @@ static int echo_port(int argc DNS_NOTUSED, char *argv[] DNS_NOTUSED) {
|
|||||||
panic("127.0.0.1:5353: %s", dns_strerror(errno));
|
panic("127.0.0.1:5353: %s", dns_strerror(errno));
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } _P = { 0 };
|
union { unsigned char b[dns_p_calcsize((512))]; struct dns_packet p; } P_instance = { 0 };
|
||||||
struct dns_packet *pkt = dns_p_init(&_P.p, 512);
|
struct dns_packet *pkt = dns_p_init(&P_instance.p, 512);
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
socklen_t slen = sizeof ss;
|
socklen_t slen = sizeof ss;
|
||||||
ssize_t count;
|
ssize_t count;
|
||||||
|
@ -47,6 +47,7 @@ struct domaininfo_s
|
|||||||
unsigned int wkd_not_found:1; /* A WKD query failed. */
|
unsigned int wkd_not_found:1; /* A WKD query failed. */
|
||||||
unsigned int wkd_supported:1; /* One WKD entry was found. */
|
unsigned int wkd_supported:1; /* One WKD entry was found. */
|
||||||
unsigned int wkd_not_supported:1; /* Definitely does not support WKD. */
|
unsigned int wkd_not_supported:1; /* Definitely does not support WKD. */
|
||||||
|
unsigned int keepmark:1; /* Private to insert_or_update(). */
|
||||||
char name[1];
|
char name[1];
|
||||||
};
|
};
|
||||||
typedef struct domaininfo_s *domaininfo_t;
|
typedef struct domaininfo_s *domaininfo_t;
|
||||||
@ -143,7 +144,10 @@ insert_or_update (const char *domain,
|
|||||||
{
|
{
|
||||||
domaininfo_t di;
|
domaininfo_t di;
|
||||||
domaininfo_t di_new;
|
domaininfo_t di_new;
|
||||||
domaininfo_t di_cut;
|
domaininfo_t drop = NULL;
|
||||||
|
domaininfo_t drop_extra = NULL;
|
||||||
|
int nkept = 0;
|
||||||
|
int ndropped = 0;
|
||||||
u32 hash;
|
u32 hash;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
@ -162,7 +166,6 @@ insert_or_update (const char *domain,
|
|||||||
|
|
||||||
/* Need to do another lookup because the malloc is a system call and
|
/* Need to do another lookup because the malloc is a system call and
|
||||||
* thus the hash array may have been changed by another thread. */
|
* thus the hash array may have been changed by another thread. */
|
||||||
di_cut = NULL;
|
|
||||||
for (count=0, di = domainbuckets[hash]; di; di = di->next, count++)
|
for (count=0, di = domainbuckets[hash]; di; di = di->next, count++)
|
||||||
if (!strcmp (di->name, domain))
|
if (!strcmp (di->name, domain))
|
||||||
{
|
{
|
||||||
@ -172,16 +175,89 @@ insert_or_update (const char *domain,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Before we insert we need to check whether the chain gets too long. */
|
/* Before we insert we need to check whether the chain gets too long. */
|
||||||
di_cut = NULL;
|
|
||||||
if (count >= MAX_DOMAINBUCKET_LEN)
|
if (count >= MAX_DOMAINBUCKET_LEN)
|
||||||
{
|
{
|
||||||
for (count=0, di = domainbuckets[hash]; di; di = di->next, count++)
|
domaininfo_t bucket;
|
||||||
if (count >= MAX_DOMAINBUCKET_LEN/2)
|
domaininfo_t *array;
|
||||||
{
|
int narray, idx;
|
||||||
di_cut = di->next;
|
domaininfo_t keep = NULL;
|
||||||
di->next = NULL;
|
|
||||||
break;
|
/* Unlink from the global list before doing a syscall. */
|
||||||
}
|
bucket = domainbuckets[hash];
|
||||||
|
domainbuckets[hash] = NULL;
|
||||||
|
|
||||||
|
array = xtrycalloc (count, sizeof *array);
|
||||||
|
if (!array)
|
||||||
|
{
|
||||||
|
/* That's bad; give up the entire bucket. */
|
||||||
|
log_error ("domaininfo: error allocating helper array: %s\n",
|
||||||
|
gpg_strerror (gpg_err_code_from_syserror ()));
|
||||||
|
drop_extra = bucket;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
narray = 0;
|
||||||
|
|
||||||
|
/* Move all items into an array for easier processing. */
|
||||||
|
for (di = bucket; di; di = di->next)
|
||||||
|
array[narray++] = di;
|
||||||
|
log_assert (narray == count);
|
||||||
|
|
||||||
|
/* Mark all item in the array which are flagged to support wkd
|
||||||
|
* but not more than half of the maximum. This way we will at
|
||||||
|
* the end drop half of the items. */
|
||||||
|
count = 0;
|
||||||
|
for (idx=0; idx < narray; idx++)
|
||||||
|
{
|
||||||
|
di = array[idx];
|
||||||
|
di->keepmark = 0; /* Clear flag here on the first pass. */
|
||||||
|
if (di->wkd_supported && count < MAX_DOMAINBUCKET_LEN/2)
|
||||||
|
{
|
||||||
|
di->keepmark = 1;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Now mark those which are marked as not found. */
|
||||||
|
/* FIXME: we should use an LRU algorithm here. */
|
||||||
|
for (idx=0; idx < narray; idx++)
|
||||||
|
{
|
||||||
|
di = array[idx];
|
||||||
|
if (!di->keepmark
|
||||||
|
&& di->wkd_not_supported && count < MAX_DOMAINBUCKET_LEN/2)
|
||||||
|
{
|
||||||
|
di->keepmark = 1;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build a bucket list and a second list for later freeing the
|
||||||
|
* items (we can't do it directly because a free is a system
|
||||||
|
* call and we want to avoid locks in this module. Note that
|
||||||
|
* the kept items will be reversed order which does not matter. */
|
||||||
|
for (idx=0; idx < narray; idx++)
|
||||||
|
{
|
||||||
|
di = array[idx];
|
||||||
|
if (di->keepmark)
|
||||||
|
{
|
||||||
|
di->next = keep;
|
||||||
|
keep = di;
|
||||||
|
nkept++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
di->next = drop;
|
||||||
|
drop = di;
|
||||||
|
ndropped++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In case another thread added new stuff to the domain list we
|
||||||
|
* simply drop them instead all. It would also be possible to
|
||||||
|
* append them to our list but then we can't guarantee that a
|
||||||
|
* bucket list is almost all of the time limited to
|
||||||
|
* MAX_DOMAINBUCKET_LEN. Not sure whether this is really a
|
||||||
|
* sensible strategy. */
|
||||||
|
drop_extra = domainbuckets[hash];
|
||||||
|
domainbuckets[hash] = keep;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert */
|
/* Insert */
|
||||||
@ -190,17 +266,28 @@ insert_or_update (const char *domain,
|
|||||||
di->next = domainbuckets[hash];
|
di->next = domainbuckets[hash];
|
||||||
domainbuckets[hash] = di;
|
domainbuckets[hash] = di;
|
||||||
|
|
||||||
/* Remove the rest of the cutted chain. */
|
if (opt.verbose && (nkept || ndropped))
|
||||||
while (di_cut)
|
log_info ("domaininfo: bucket=%lu kept=%d purged=%d\n",
|
||||||
|
(unsigned long)hash, nkept, ndropped);
|
||||||
|
|
||||||
|
leave:
|
||||||
|
/* Remove the dropped items. */
|
||||||
|
while (drop)
|
||||||
{
|
{
|
||||||
di = di_cut->next;
|
di = drop->next;
|
||||||
xfree (di_cut);
|
xfree (drop);
|
||||||
di_cut = di;
|
drop = di;
|
||||||
|
}
|
||||||
|
while (drop_extra)
|
||||||
|
{
|
||||||
|
di = drop_extra->next;
|
||||||
|
xfree (drop_extra);
|
||||||
|
drop_extra = di;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Helper for domaininfo_set_no_name. */
|
/* Helper for domaininfo_set_no_name. May not do any syscalls. */
|
||||||
static void
|
static void
|
||||||
set_no_name_cb (domaininfo_t di, int insert_mode)
|
set_no_name_cb (domaininfo_t di, int insert_mode)
|
||||||
{
|
{
|
||||||
@ -224,7 +311,7 @@ domaininfo_set_no_name (const char *domain)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Helper for domaininfo_set_wkd_supported. */
|
/* Helper for domaininfo_set_wkd_supported. May not do any syscalls. */
|
||||||
static void
|
static void
|
||||||
set_wkd_supported_cb (domaininfo_t di, int insert_mode)
|
set_wkd_supported_cb (domaininfo_t di, int insert_mode)
|
||||||
{
|
{
|
||||||
@ -245,7 +332,7 @@ domaininfo_set_wkd_supported (const char *domain)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Helper for domaininfo_set_wkd_not_supported. */
|
/* Helper for domaininfo_set_wkd_not_supported. May not do any syscalls. */
|
||||||
static void
|
static void
|
||||||
set_wkd_not_supported_cb (domaininfo_t di, int insert_mode)
|
set_wkd_not_supported_cb (domaininfo_t di, int insert_mode)
|
||||||
{
|
{
|
||||||
@ -265,7 +352,7 @@ domaininfo_set_wkd_not_supported (const char *domain)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Helper for domaininfo_set_wkd_not_found. */
|
/* Helper for domaininfo_set_wkd_not_found. May not do any syscalls. */
|
||||||
static void
|
static void
|
||||||
set_wkd_not_found_cb (domaininfo_t di, int insert_mode)
|
set_wkd_not_found_cb (domaininfo_t di, int insert_mode)
|
||||||
{
|
{
|
||||||
|
@ -3536,8 +3536,13 @@ same_host_p (parsed_uri_t a, parsed_uri_t b)
|
|||||||
{ "protonmail.com", "api.protonmail.com" },
|
{ "protonmail.com", "api.protonmail.com" },
|
||||||
{ NULL, "api.protonmail.ch" },
|
{ NULL, "api.protonmail.ch" },
|
||||||
{ "protonmail.ch", "api.protonmail.com" },
|
{ "protonmail.ch", "api.protonmail.com" },
|
||||||
{ NULL, "api.protonmail.ch" }
|
{ NULL, "api.protonmail.ch" },
|
||||||
|
{ "pm.me", "api.protonmail.ch" }
|
||||||
};
|
};
|
||||||
|
static const char *subdomains[] =
|
||||||
|
{
|
||||||
|
"openpgpkey."
|
||||||
|
};
|
||||||
int i;
|
int i;
|
||||||
const char *from;
|
const char *from;
|
||||||
|
|
||||||
@ -3559,6 +3564,22 @@ same_host_p (parsed_uri_t a, parsed_uri_t b)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Also consider hosts the same if they differ only in a subdomain;
|
||||||
|
* in both direction. This allows to have redirection between the
|
||||||
|
* WKD advanced and direct lookup methods. */
|
||||||
|
for (i=0; i < DIM (subdomains); i++)
|
||||||
|
{
|
||||||
|
const char *subdom = subdomains[i];
|
||||||
|
size_t subdomlen = strlen (subdom);
|
||||||
|
|
||||||
|
if (!ascii_strncasecmp (a->host, subdom, subdomlen)
|
||||||
|
&& !ascii_strcasecmp (a->host + subdomlen, b->host))
|
||||||
|
return 1;
|
||||||
|
if (!ascii_strncasecmp (b->host, subdom, subdomlen)
|
||||||
|
&& !ascii_strcasecmp (b->host + subdomlen, a->host))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,10 @@
|
|||||||
/* Number of retries done for a dead host etc. */
|
/* Number of retries done for a dead host etc. */
|
||||||
#define SEND_REQUEST_RETRIES 3
|
#define SEND_REQUEST_RETRIES 3
|
||||||
|
|
||||||
|
/* Number of retries done in case of transient errors. */
|
||||||
|
#define SEND_REQUEST_EXTRA_RETRIES 5
|
||||||
|
|
||||||
|
|
||||||
enum ks_protocol { KS_PROTOCOL_HKP, KS_PROTOCOL_HKPS, KS_PROTOCOL_MAX };
|
enum ks_protocol { KS_PROTOCOL_HKP, KS_PROTOCOL_HKPS, KS_PROTOCOL_MAX };
|
||||||
|
|
||||||
/* Objects used to maintain information about hosts. */
|
/* Objects used to maintain information about hosts. */
|
||||||
@ -1217,6 +1221,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
|
|||||||
/* FIXME: I am not sure whey we allow a downgrade for hkp requests.
|
/* FIXME: I am not sure whey we allow a downgrade for hkp requests.
|
||||||
* Needs at least an explanation here.. */
|
* Needs at least an explanation here.. */
|
||||||
|
|
||||||
|
once_more:
|
||||||
err = http_session_new (&session, httphost,
|
err = http_session_new (&session, httphost,
|
||||||
((ctrl->http_no_crl? HTTP_FLAG_NO_CRL : 0)
|
((ctrl->http_no_crl? HTTP_FLAG_NO_CRL : 0)
|
||||||
| HTTP_FLAG_TRUST_DEF),
|
| HTTP_FLAG_TRUST_DEF),
|
||||||
@ -1226,7 +1231,6 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
|
|||||||
http_session_set_log_cb (session, cert_log_cb);
|
http_session_set_log_cb (session, cert_log_cb);
|
||||||
http_session_set_timeout (session, ctrl->timeout);
|
http_session_set_timeout (session, ctrl->timeout);
|
||||||
|
|
||||||
once_more:
|
|
||||||
err = http_open (ctrl, &http,
|
err = http_open (ctrl, &http,
|
||||||
post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
|
post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
|
||||||
request,
|
request,
|
||||||
@ -1306,6 +1310,8 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
|
|||||||
request = request_buffer;
|
request = request_buffer;
|
||||||
http_close (http, 0);
|
http_close (http, 0);
|
||||||
http = NULL;
|
http = NULL;
|
||||||
|
http_session_release (session);
|
||||||
|
session = NULL;
|
||||||
}
|
}
|
||||||
goto once_more;
|
goto once_more;
|
||||||
|
|
||||||
@ -1313,6 +1319,10 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
|
|||||||
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
case 413: /* Payload too large */
|
||||||
|
err = gpg_error (GPG_ERR_TOO_LARGE);
|
||||||
|
goto leave;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log_error (_("error accessing '%s': http status %u\n"),
|
log_error (_("error accessing '%s': http status %u\n"),
|
||||||
request, http_get_status_code (http));
|
request, http_get_status_code (http));
|
||||||
@ -1349,10 +1359,12 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
|
|||||||
with REQUEST. The function returns true if the caller shall try
|
with REQUEST. The function returns true if the caller shall try
|
||||||
again. TRIES_LEFT points to a variable to track the number of
|
again. TRIES_LEFT points to a variable to track the number of
|
||||||
retries; this function decrements it and won't return true if it is
|
retries; this function decrements it and won't return true if it is
|
||||||
down to zero. */
|
down to zero. EXTRA_TRIES_LEFT does the same but only for
|
||||||
|
transient http status codes. */
|
||||||
static int
|
static int
|
||||||
handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
|
handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
|
||||||
unsigned int http_status, unsigned int *tries_left)
|
unsigned int http_status, unsigned int *tries_left,
|
||||||
|
unsigned int *extra_tries_left)
|
||||||
{
|
{
|
||||||
int retry = 0;
|
int retry = 0;
|
||||||
|
|
||||||
@ -1408,9 +1420,12 @@ handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
|
|||||||
|
|
||||||
case 503: /* Service Unavailable */
|
case 503: /* Service Unavailable */
|
||||||
case 504: /* Gateway Timeout */
|
case 504: /* Gateway Timeout */
|
||||||
log_info ("selecting a different host due to a %u (%s)",
|
if (*extra_tries_left)
|
||||||
http_status, http_status2string (http_status));
|
{
|
||||||
retry = 1;
|
log_info ("selecting a different host due to a %u (%s)",
|
||||||
|
http_status, http_status2string (http_status));
|
||||||
|
retry = 2;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1420,8 +1435,16 @@ handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*tries_left)
|
if (retry == 2)
|
||||||
--*tries_left;
|
{
|
||||||
|
if (*extra_tries_left)
|
||||||
|
--*extra_tries_left;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*tries_left)
|
||||||
|
--*tries_left;
|
||||||
|
}
|
||||||
|
|
||||||
return retry;
|
return retry;
|
||||||
}
|
}
|
||||||
@ -1446,6 +1469,7 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
|
|||||||
char *httphost = NULL;
|
char *httphost = NULL;
|
||||||
unsigned int http_status;
|
unsigned int http_status;
|
||||||
unsigned int tries = SEND_REQUEST_RETRIES;
|
unsigned int tries = SEND_REQUEST_RETRIES;
|
||||||
|
unsigned int extra_tries = SEND_REQUEST_EXTRA_RETRIES;
|
||||||
|
|
||||||
*r_fp = NULL;
|
*r_fp = NULL;
|
||||||
|
|
||||||
@ -1521,7 +1545,8 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
|
|||||||
/* Send the request. */
|
/* Send the request. */
|
||||||
err = send_request (ctrl, request, hostport, httphost, httpflags,
|
err = send_request (ctrl, request, hostport, httphost, httpflags,
|
||||||
NULL, NULL, &fp, &http_status);
|
NULL, NULL, &fp, &http_status);
|
||||||
if (handle_send_request_error (ctrl, err, request, http_status, &tries))
|
if (handle_send_request_error (ctrl, err, request, http_status,
|
||||||
|
&tries, &extra_tries))
|
||||||
{
|
{
|
||||||
reselect = 1;
|
reselect = 1;
|
||||||
goto again;
|
goto again;
|
||||||
@ -1591,6 +1616,7 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
|
|||||||
unsigned int httpflags;
|
unsigned int httpflags;
|
||||||
unsigned int http_status;
|
unsigned int http_status;
|
||||||
unsigned int tries = SEND_REQUEST_RETRIES;
|
unsigned int tries = SEND_REQUEST_RETRIES;
|
||||||
|
unsigned int extra_tries = SEND_REQUEST_EXTRA_RETRIES;
|
||||||
|
|
||||||
*r_fp = NULL;
|
*r_fp = NULL;
|
||||||
|
|
||||||
@ -1664,7 +1690,8 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
|
|||||||
/* Send the request. */
|
/* Send the request. */
|
||||||
err = send_request (ctrl, request, hostport, httphost, httpflags,
|
err = send_request (ctrl, request, hostport, httphost, httpflags,
|
||||||
NULL, NULL, &fp, &http_status);
|
NULL, NULL, &fp, &http_status);
|
||||||
if (handle_send_request_error (ctrl, err, request, http_status, &tries))
|
if (handle_send_request_error (ctrl, err, request, http_status,
|
||||||
|
&tries, &extra_tries))
|
||||||
{
|
{
|
||||||
reselect = 1;
|
reselect = 1;
|
||||||
goto again;
|
goto again;
|
||||||
@ -1740,6 +1767,7 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
|
|||||||
unsigned int httpflags;
|
unsigned int httpflags;
|
||||||
unsigned int http_status;
|
unsigned int http_status;
|
||||||
unsigned int tries = SEND_REQUEST_RETRIES;
|
unsigned int tries = SEND_REQUEST_RETRIES;
|
||||||
|
unsigned int extra_tries = SEND_REQUEST_EXTRA_RETRIES;
|
||||||
|
|
||||||
parm.datastring = NULL;
|
parm.datastring = NULL;
|
||||||
|
|
||||||
@ -1778,7 +1806,8 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
|
|||||||
/* Send the request. */
|
/* Send the request. */
|
||||||
err = send_request (ctrl, request, hostport, httphost, 0,
|
err = send_request (ctrl, request, hostport, httphost, 0,
|
||||||
put_post_cb, &parm, &fp, &http_status);
|
put_post_cb, &parm, &fp, &http_status);
|
||||||
if (handle_send_request_error (ctrl, err, request, http_status, &tries))
|
if (handle_send_request_error (ctrl, err, request, http_status,
|
||||||
|
&tries, &extra_tries))
|
||||||
{
|
{
|
||||||
reselect = 1;
|
reselect = 1;
|
||||||
goto again;
|
goto again;
|
||||||
|
@ -174,6 +174,10 @@ ks_http_fetch (ctrl_t ctrl, const char *url, unsigned int flags,
|
|||||||
}
|
}
|
||||||
goto once_more;
|
goto once_more;
|
||||||
|
|
||||||
|
case 413: /* Payload too large */
|
||||||
|
err = gpg_error (GPG_ERR_TOO_LARGE);
|
||||||
|
goto leave;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log_error (_("error accessing '%s': http status %u\n"),
|
log_error (_("error accessing '%s': http status %u\n"),
|
||||||
url, http_get_status_code (http));
|
url, http_get_status_code (http));
|
||||||
|
109
dirmngr/ocsp.c
109
dirmngr/ocsp.c
@ -116,10 +116,15 @@ read_response (estream_t fp, unsigned char **r_buffer, size_t *r_buflen)
|
|||||||
|
|
||||||
/* Construct an OCSP request, send it to the configured OCSP responder
|
/* Construct an OCSP request, send it to the configured OCSP responder
|
||||||
and parse the response. On success the OCSP context may be used to
|
and parse the response. On success the OCSP context may be used to
|
||||||
further process the response. */
|
further process the response. The signature value and the
|
||||||
|
production date are returned at R_SIGVAL and R_PRODUCED_AT; they
|
||||||
|
may be NULL or an empty string if not available. A new hash
|
||||||
|
context is returned at R_MD. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md,
|
do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp,
|
||||||
const char *url, ksba_cert_t cert, ksba_cert_t issuer_cert)
|
const char *url, ksba_cert_t cert, ksba_cert_t issuer_cert,
|
||||||
|
ksba_sexp_t *r_sigval, ksba_isotime_t r_produced_at,
|
||||||
|
gcry_md_hd_t *r_md)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
unsigned char *request, *response;
|
unsigned char *request, *response;
|
||||||
@ -132,6 +137,10 @@ do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md,
|
|||||||
|
|
||||||
(void)ctrl;
|
(void)ctrl;
|
||||||
|
|
||||||
|
*r_sigval = NULL;
|
||||||
|
*r_produced_at = 0;
|
||||||
|
*r_md = NULL;
|
||||||
|
|
||||||
if (dirmngr_use_tor ())
|
if (dirmngr_use_tor ())
|
||||||
{
|
{
|
||||||
/* For now we do not allow OCSP via Tor due to possible privacy
|
/* For now we do not allow OCSP via Tor due to possible privacy
|
||||||
@ -238,6 +247,10 @@ do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 413: /* Payload too large */
|
||||||
|
err = gpg_error (GPG_ERR_TOO_LARGE);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log_error (_("error accessing '%s': http status %u\n"),
|
log_error (_("error accessing '%s': http status %u\n"),
|
||||||
url, http_get_status_code (http));
|
url, http_get_status_code (http));
|
||||||
@ -259,6 +272,7 @@ do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md,
|
|||||||
xfree (free_this);
|
xfree (free_this);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
/* log_printhex (response, responselen, "ocsp response"); */
|
||||||
|
|
||||||
err = ksba_ocsp_parse_response (ocsp, response, responselen,
|
err = ksba_ocsp_parse_response (ocsp, response, responselen,
|
||||||
&response_status);
|
&response_status);
|
||||||
@ -286,11 +300,34 @@ do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md,
|
|||||||
}
|
}
|
||||||
if (response_status == KSBA_OCSP_RSPSTATUS_SUCCESS)
|
if (response_status == KSBA_OCSP_RSPSTATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
|
int hash_algo;
|
||||||
|
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
log_info (_("OCSP responder at '%s' status: %s\n"), url, t);
|
log_info (_("OCSP responder at '%s' status: %s\n"), url, t);
|
||||||
|
|
||||||
|
/* Get the signature value now because we can all this fucntion
|
||||||
|
* only once. */
|
||||||
|
*r_sigval = ksba_ocsp_get_sig_val (ocsp, r_produced_at);
|
||||||
|
|
||||||
|
hash_algo = hash_algo_from_sigval (*r_sigval);
|
||||||
|
if (!hash_algo)
|
||||||
|
{
|
||||||
|
if (opt.verbose)
|
||||||
|
log_info ("ocsp: using SHA-256 as fallback hash algo.\n");
|
||||||
|
hash_algo = GCRY_MD_SHA256;
|
||||||
|
}
|
||||||
|
err = gcry_md_open (r_md, hash_algo, 0);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error (_("failed to establish a hashing context for OCSP: %s\n"),
|
||||||
|
gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
if (DBG_HASHING)
|
||||||
|
gcry_md_debug (*r_md, "ocsp");
|
||||||
|
|
||||||
err = ksba_ocsp_hash_response (ocsp, response, responselen,
|
err = ksba_ocsp_hash_response (ocsp, response, responselen,
|
||||||
HASH_FNC, md);
|
HASH_FNC, *r_md);
|
||||||
if (err)
|
if (err)
|
||||||
log_error (_("hashing the OCSP response for '%s' failed: %s\n"),
|
log_error (_("hashing the OCSP response for '%s' failed: %s\n"),
|
||||||
url, gpg_strerror (err));
|
url, gpg_strerror (err));
|
||||||
@ -301,8 +338,17 @@ do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md,
|
|||||||
err = gpg_error (GPG_ERR_GENERAL);
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
xfree (response);
|
xfree (response);
|
||||||
xfree (free_this);
|
xfree (free_this);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
xfree (*r_sigval);
|
||||||
|
*r_sigval = NULL;
|
||||||
|
*r_produced_at = 0;
|
||||||
|
gcry_md_close (*r_md);
|
||||||
|
*r_md = NULL;
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,7 +433,7 @@ check_signature_core (ctrl_t ctrl, ksba_cert_t cert, gcry_sexp_t s_sig,
|
|||||||
|
|
||||||
/* We simply ignore all errors. */
|
/* We simply ignore all errors. */
|
||||||
gcry_sexp_release (s_pkey);
|
gcry_sexp_release (s_pkey);
|
||||||
return -1;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -406,18 +452,27 @@ check_signature (ctrl_t ctrl,
|
|||||||
int algo, cert_idx;
|
int algo, cert_idx;
|
||||||
gcry_sexp_t s_hash;
|
gcry_sexp_t s_hash;
|
||||||
ksba_cert_t cert;
|
ksba_cert_t cert;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
/* Create a suitable S-expression with the hash value of our response. */
|
/* Create a suitable S-expression with the hash value of our response. */
|
||||||
gcry_md_final (md);
|
gcry_md_final (md);
|
||||||
algo = gcry_md_get_algo (md);
|
algo = gcry_md_get_algo (md);
|
||||||
if (algo != GCRY_MD_SHA1 )
|
s = gcry_md_algo_name (algo);
|
||||||
|
if (algo && s && strlen (s) < 16)
|
||||||
{
|
{
|
||||||
log_error (_("only SHA-1 is supported for OCSP responses\n"));
|
char hashalgostr[16+1];
|
||||||
return gpg_error (GPG_ERR_DIGEST_ALGO);
|
int i;
|
||||||
|
|
||||||
|
for (i=0; s[i]; i++)
|
||||||
|
hashalgostr[i] = ascii_tolower (s[i]);
|
||||||
|
hashalgostr[i] = 0;
|
||||||
|
err = gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash %s %b))",
|
||||||
|
hashalgostr,
|
||||||
|
(int)gcry_md_get_algo_dlen (algo),
|
||||||
|
gcry_md_read (md, algo));
|
||||||
}
|
}
|
||||||
err = gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash sha1 %b))",
|
else
|
||||||
gcry_md_get_algo_dlen (algo),
|
err = gpg_error (GPG_ERR_DIGEST_ALGO);
|
||||||
gcry_md_read (md, algo));
|
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
log_error (_("creating S-expression failed: %s\n"), gcry_strerror (err));
|
log_error (_("creating S-expression failed: %s\n"), gcry_strerror (err));
|
||||||
@ -461,6 +516,7 @@ check_signature (ctrl_t ctrl,
|
|||||||
{
|
{
|
||||||
cert_ref_t cref;
|
cert_ref_t cref;
|
||||||
|
|
||||||
|
/* dump_cert ("from ocsp response", cert); */
|
||||||
cref = xtrymalloc (sizeof *cref);
|
cref = xtrymalloc (sizeof *cref);
|
||||||
if (!cref)
|
if (!cref)
|
||||||
log_error (_("allocating list item failed: %s\n"),
|
log_error (_("allocating list item failed: %s\n"),
|
||||||
@ -496,8 +552,6 @@ check_signature (ctrl_t ctrl,
|
|||||||
}
|
}
|
||||||
log_printf ("not found\n");
|
log_printf ("not found\n");
|
||||||
}
|
}
|
||||||
ksba_free (name);
|
|
||||||
ksba_free (keyid);
|
|
||||||
|
|
||||||
if (cert)
|
if (cert)
|
||||||
{
|
{
|
||||||
@ -506,10 +560,24 @@ check_signature (ctrl_t ctrl,
|
|||||||
ksba_cert_release (cert);
|
ksba_cert_release (cert);
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
|
ksba_free (name);
|
||||||
|
ksba_free (keyid);
|
||||||
gcry_sexp_release (s_hash);
|
gcry_sexp_release (s_hash);
|
||||||
return 0; /* Successfully verified the signature. */
|
return 0; /* Successfully verified the signature. */
|
||||||
}
|
}
|
||||||
|
log_error ("responder certificate ");
|
||||||
|
if (name)
|
||||||
|
log_printf ("'/%s' ", name);
|
||||||
|
if (keyid)
|
||||||
|
{
|
||||||
|
log_printf ("{");
|
||||||
|
dump_serial (keyid);
|
||||||
|
log_printf ("} ");
|
||||||
|
}
|
||||||
|
log_printf ("did not verify: %s\n", gpg_strerror (err));
|
||||||
}
|
}
|
||||||
|
ksba_free (name);
|
||||||
|
ksba_free (keyid);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcry_sexp_release (s_hash);
|
gcry_sexp_release (s_hash);
|
||||||
@ -584,8 +652,6 @@ ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Figure out the OCSP responder to use.
|
/* Figure out the OCSP responder to use.
|
||||||
1. Try to get the reponder from the certificate.
|
1. Try to get the reponder from the certificate.
|
||||||
We do only take http and https style URIs into account.
|
We do only take http and https style URIs into account.
|
||||||
@ -642,14 +708,8 @@ ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Ask the OCSP responder. */
|
/* Ask the OCSP responder. */
|
||||||
err = gcry_md_open (&md, GCRY_MD_SHA1, 0);
|
err = do_ocsp_request (ctrl, ocsp, url, cert, issuer_cert,
|
||||||
if (err)
|
&sigval, produced_at, &md);
|
||||||
{
|
|
||||||
log_error (_("failed to establish a hashing context for OCSP: %s\n"),
|
|
||||||
gpg_strerror (err));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
err = do_ocsp_request (ctrl, ocsp, md, url, cert, issuer_cert);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
@ -681,8 +741,7 @@ ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We got a useful answer, check that the answer has a valid signature. */
|
/* We got a useful answer, check that the answer has a valid signature. */
|
||||||
sigval = ksba_ocsp_get_sig_val (ocsp, produced_at);
|
if (!sigval || !*produced_at || !md)
|
||||||
if (!sigval || !*produced_at)
|
|
||||||
{
|
{
|
||||||
err = gpg_error (GPG_ERR_INV_OBJ);
|
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||||
goto leave;
|
goto leave;
|
||||||
|
@ -1572,6 +1572,7 @@ Description of some debug flags:
|
|||||||
| ecc/* | 11 | ECC (set your own capabilities) |
|
| ecc/* | 11 | ECC (set your own capabilities) |
|
||||||
| ecc/e | 12 | ECC (encrypt only) |
|
| ecc/e | 12 | ECC (encrypt only) |
|
||||||
| keygrip | 13 | Existing key |
|
| keygrip | 13 | Existing key |
|
||||||
|
| cardkey | 14 | Existing key from card |
|
||||||
|
|
||||||
If one of the "foo/*" names are used a "keygen.flags" prompt needs
|
If one of the "foo/*" names are used a "keygen.flags" prompt needs
|
||||||
to be answered as well. Instead of toggling the predefined flags,
|
to be answered as well. Instead of toggling the predefined flags,
|
||||||
|
@ -95,7 +95,7 @@ myman_pages = gpgsm.1 gpg-agent.1 dirmngr.8 scdaemon.1 \
|
|||||||
watchgnupg.1 gpgconf.1 addgnupghome.8 gpg-preset-passphrase.1 \
|
watchgnupg.1 gpgconf.1 addgnupghome.8 gpg-preset-passphrase.1 \
|
||||||
gpg-connect-agent.1 gpgparsemail.1 symcryptrun.1 gpgtar.1 \
|
gpg-connect-agent.1 gpgparsemail.1 symcryptrun.1 gpgtar.1 \
|
||||||
applygnupgdefaults.8 gpg-wks-client.1 gpg-wks-server.1 \
|
applygnupgdefaults.8 gpg-wks-client.1 gpg-wks-server.1 \
|
||||||
dirmngr-client.1 gpg-card.1
|
dirmngr-client.1 gpg-card.1 gpg-check-pattern.1
|
||||||
if USE_GPG2_HACK
|
if USE_GPG2_HACK
|
||||||
myman_pages += gpg2.1 gpgv2.1
|
myman_pages += gpg2.1 gpgv2.1
|
||||||
else
|
else
|
||||||
@ -121,6 +121,7 @@ mkdefsinc: mkdefsinc.c Makefile ../config.h
|
|||||||
$(CC_FOR_BUILD) -I. -I.. -I$(srcdir) $(AM_CPPFLAGS) \
|
$(CC_FOR_BUILD) -I. -I.. -I$(srcdir) $(AM_CPPFLAGS) \
|
||||||
-o $@ $(srcdir)/mkdefsinc.c
|
-o $@ $(srcdir)/mkdefsinc.c
|
||||||
|
|
||||||
|
if MAINTAINER_MODE
|
||||||
.svg.eps:
|
.svg.eps:
|
||||||
convert `test -f '$<' || echo '$(srcdir)/'`$< $@
|
convert `test -f '$<' || echo '$(srcdir)/'`$< $@
|
||||||
|
|
||||||
@ -141,6 +142,7 @@ mkdefsinc: mkdefsinc.c Makefile ../config.h
|
|||||||
|
|
||||||
.fig.pdf:
|
.fig.pdf:
|
||||||
fig2dev -L pdf `test -f '$<' || echo '$(srcdir)/'`$< $@
|
fig2dev -L pdf `test -f '$<' || echo '$(srcdir)/'`$< $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
yat2m-stamp: $(myman_sources) defs.inc
|
yat2m-stamp: $(myman_sources) defs.inc
|
||||||
|
@ -251,7 +251,7 @@ The option @option{--use-tor} switches Dirmngr and thus GnuPG into
|
|||||||
``Tor mode'' to route all network access via Tor (an anonymity
|
``Tor mode'' to route all network access via Tor (an anonymity
|
||||||
network). Certain other features are disabled in this mode. The
|
network). Certain other features are disabled in this mode. The
|
||||||
effect of @option{--use-tor} cannot be overridden by any other command
|
effect of @option{--use-tor} cannot be overridden by any other command
|
||||||
or even be reloading gpg-agent. The use of @option{--no-use-tor}
|
or even by reloading dirmngr. The use of @option{--no-use-tor}
|
||||||
disables the use of Tor. The default is to use Tor if it is available
|
disables the use of Tor. The default is to use Tor if it is available
|
||||||
on startup or after reloading dirmngr.
|
on startup or after reloading dirmngr.
|
||||||
|
|
||||||
@ -1178,5 +1178,3 @@ as a binary blob.
|
|||||||
@c used for this. The first one starts a search and the second one is
|
@c used for this. The first one starts a search and the second one is
|
||||||
@c used to retrieve certificate after certificate.
|
@c used to retrieve certificate after certificate.
|
||||||
@c
|
@c
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,9 +8,9 @@
|
|||||||
@node Smart Card Tool
|
@node Smart Card Tool
|
||||||
@chapter Smart Card Tool
|
@chapter Smart Card Tool
|
||||||
|
|
||||||
GnuPG comes with tool to administrate smart cards and USB tokens. This
|
GnuPG comes with a tool to administrate smart cards and USB tokens.
|
||||||
tool is an extension of the @option{--edit-key} command available with
|
This tool is an enhanced version of the @option{--edit-key} command
|
||||||
@command{gpg}.
|
available with @command{gpg}.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* gpg-card:: Administrate smart cards.
|
* gpg-card:: Administrate smart cards.
|
||||||
@ -135,7 +135,7 @@ featuring the PIV application (requires Yubikey-5). We assume that
|
|||||||
the credentials have not yet been changed and thus are:
|
the credentials have not yet been changed and thus are:
|
||||||
@table @asis
|
@table @asis
|
||||||
@item Authentication key
|
@item Authentication key
|
||||||
This is a 24 byte key described by the hex string
|
This is a 24 byte key described by the hex string @*
|
||||||
@code{010203040506070801020304050607080102030405060708}.
|
@code{010203040506070801020304050607080102030405060708}.
|
||||||
@item PIV Application PIN
|
@item PIV Application PIN
|
||||||
This is the string @code{123456}.
|
This is the string @code{123456}.
|
||||||
@ -164,11 +164,13 @@ Version ..........: 2.1
|
|||||||
[...]
|
[...]
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
It can be seen by the ``Application type'' line that GnuPG selected the
|
It can be seen by the ``Application type'' line that GnuPG selected
|
||||||
OpenPGP application of the Yubikey. This is because GnuPG assigns the
|
the OpenPGP application of the Yubikey. This is because GnuPG assigns
|
||||||
highest priority to the OpenPGP application. To use the PIV
|
the highest priority to the OpenPGP application. To use the PIV
|
||||||
application of the Yubikey, the OpenPGP application needs to be
|
application of the Yubikey several methods can be used:
|
||||||
disabled:
|
|
||||||
|
With a Yubikey 5 or later the OpenPGP application on the Yubikey can
|
||||||
|
be disabled:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
gpg/card> yubikey disable all opgp
|
gpg/card> yubikey disable all opgp
|
||||||
@ -186,8 +188,32 @@ gpg/card> reset
|
|||||||
|
|
||||||
The @code{reset} is required so that the GnuPG system rereads the
|
The @code{reset} is required so that the GnuPG system rereads the
|
||||||
card. Note that disabled applications keep all their data and can at
|
card. Note that disabled applications keep all their data and can at
|
||||||
any time be re-enabled (see @emph{help yubikey}). Now a @emph{list}
|
any time be re-enabled (use @kbd{help yubikey}).
|
||||||
command shows this:
|
|
||||||
|
Another option, which works for all Yubikey versions, is to disable
|
||||||
|
the support for OpenPGP cards in scdaemon. This is done by adding the
|
||||||
|
line
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
disable-application openpgp
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
to @file{~/.gnupg/scdaemon.conf} and by restarting scdaemon, either by
|
||||||
|
killing the process or by using @kbd{gpgconf --kill scdaemon}. Finally
|
||||||
|
the default order in which card applications are tried by scdaemon can
|
||||||
|
be changed. For example to prefer PIV over OpenPGP it is sufficient
|
||||||
|
to add
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
application-priority piv
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
to @file{~/.gnupg/scdaemon.conf} and to restart @command{scdaemon}.
|
||||||
|
This has an effect only on tokens which support both, PIV and OpenPGP,
|
||||||
|
but does not hamper the use of OpenPGP only tokens.
|
||||||
|
|
||||||
|
With one of these methods employed the @code{list} command of
|
||||||
|
@command{gpg-card} shows this:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
gpg/card> list
|
gpg/card> list
|
||||||
@ -210,7 +236,12 @@ Key management ...: [none]
|
|||||||
keyref .....: PIV.9D
|
keyref .....: PIV.9D
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
Note that the ``Displayed s/sn'' is printed on the token and also
|
In case several tokens are plugged into the computer, gpg-card will
|
||||||
|
show only one. To show another token the number of the token (0, 1,
|
||||||
|
2, ...) can be given as an argument to the @code{list} command. The
|
||||||
|
command @kbd{list --cards} prints a list of all inserted tokens.
|
||||||
|
|
||||||
|
Note that the ``Displayed s/n'' is printed on the token and also
|
||||||
shown in Pinentry prompts asking for the PIN. The four standard key
|
shown in Pinentry prompts asking for the PIN. The four standard key
|
||||||
slots are always shown, if other key slots are initialized they are
|
slots are always shown, if other key slots are initialized they are
|
||||||
shown as well. The @emph{PIV authentication} key (internal reference
|
shown as well. The @emph{PIV authentication} key (internal reference
|
||||||
@ -231,11 +262,11 @@ which needs to be provided only once so that decryption operations can
|
|||||||
then be done until the card is reset or removed from the reader or USB
|
then be done until the card is reset or removed from the reader or USB
|
||||||
port.
|
port.
|
||||||
|
|
||||||
We now generate tree of the four keys. Note that GnuPG does currently
|
We now generate three of the four keys. Note that GnuPG does
|
||||||
not use the the @emph{Card authentication} key but because it is
|
currently not use the the @emph{Card authentication} key; however,
|
||||||
mandatory by the specs we create it anyway. Key generation requires
|
that key is mandatory by the PIV standard and thus we create it too.
|
||||||
that we authenticate to the card. This can be done either on the
|
Key generation requires that we authenticate to the card. This can be
|
||||||
command line (which would reveal the key):
|
done either on the command line (which would reveal the key):
|
||||||
|
|
||||||
@example
|
@example
|
||||||
gpg/card> auth 010203040506070801020304050607080102030405060708
|
gpg/card> auth 010203040506070801020304050607080102030405060708
|
||||||
@ -360,7 +391,7 @@ gpgsm: total number processed: 1
|
|||||||
gpgsm: imported: 1
|
gpgsm: imported: 1
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
Note the last steps which imported the created certificate. If you
|
Note the last step which imported the created certificate. If you
|
||||||
you instead created a certificate signing request (CSR) instead of a
|
you instead created a certificate signing request (CSR) instead of a
|
||||||
self-signed certificate and sent this off to a CA you would do the
|
self-signed certificate and sent this off to a CA you would do the
|
||||||
same import step with the certificate received from the CA. Take note
|
same import step with the certificate received from the CA. Take note
|
||||||
@ -507,7 +538,111 @@ As usual use ssh-add with the uppercase @samp{-L} to list the public
|
|||||||
ssh key. To use the certificates with Thunderbird or Mozilla, please
|
ssh key. To use the certificates with Thunderbird or Mozilla, please
|
||||||
consult the Scute manual for details.
|
consult the Scute manual for details.
|
||||||
|
|
||||||
|
If you want to use the same PIV keys also for OpenPGP (for example on
|
||||||
|
a Yubikey to avoid switching between OpenPGP and PIV), this is also
|
||||||
|
possible:
|
||||||
|
|
||||||
|
@example
|
||||||
|
$ gpgsm --learn
|
||||||
|
$ gpg --full-gen-key
|
||||||
|
Please select what kind of key you want:
|
||||||
|
(1) RSA and RSA (default)
|
||||||
|
(2) DSA and Elgamal
|
||||||
|
(3) DSA (sign only)
|
||||||
|
(4) RSA (sign only)
|
||||||
|
(14) Existing key from card
|
||||||
|
Your selection? 14
|
||||||
|
Serial number of the card: FF020001008A77C1
|
||||||
|
Available keys:
|
||||||
|
(1) 213D1825FDE0F8240CB4E4229F01AF90AC658C2E PIV.9A nistp384 (auth)
|
||||||
|
(2) 7A53E6CFFE7220A0E646B4632EE29E5A7104499C PIV.9E nistp256 (auth)
|
||||||
|
(3) 32A6C6FAFCB8421878608AAB452D5470DD3223ED PIV.9C rsa2048 (cert,sign)
|
||||||
|
(4) 34798AAFE0A7565088101CC4AE31C5C8C74461CB PIV.9D rsa2048 (encr)
|
||||||
|
Your selection? 3
|
||||||
|
Please specify how long the key should be valid.
|
||||||
|
0 = key does not expire
|
||||||
|
<n> = key expires in n days
|
||||||
|
<n>w = key expires in n weeks
|
||||||
|
<n>m = key expires in n months
|
||||||
|
<n>y = key expires in n years
|
||||||
|
Key is valid for? (0)
|
||||||
|
Key does not expire at all
|
||||||
|
Is this correct? (y/N) y
|
||||||
|
|
||||||
|
GnuPG needs to construct a user ID to identify your key.
|
||||||
|
|
||||||
|
Real name:
|
||||||
|
Email address: otto@@example.net
|
||||||
|
Comment:
|
||||||
|
You selected this USER-ID:
|
||||||
|
"otto@@example.net"
|
||||||
|
|
||||||
|
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
|
||||||
|
gpg: key C3AFA9ED971BB365 marked as ultimately trusted
|
||||||
|
gpg: revocation certificate stored as '[...]D971BB365.rev'
|
||||||
|
public and secret key created and signed.
|
||||||
|
|
||||||
|
Note that this key cannot be used for encryption. You may want to use
|
||||||
|
the command "--edit-key" to generate a subkey for this purpose.
|
||||||
|
pub rsa2048 2019-04-04 [SC]
|
||||||
|
7F899AE2FB73159DD68A1B20C3AFA9ED971BB365
|
||||||
|
uid otto@@example.net
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Note that you will be asked two times to enter the PIN of your PIV
|
||||||
|
card. If you run @command{gpg} in @option{--expert} mode you will
|
||||||
|
also ge given the option to change the usage flags of the key. The next
|
||||||
|
typescript shows how to add the encryption subkey:
|
||||||
|
|
||||||
|
@example
|
||||||
|
$ gpg --edit-key 7F899AE2FB73159DD68A1B20C3AFA9ED971BB365
|
||||||
|
Secret key is available.
|
||||||
|
|
||||||
|
sec rsa2048/C3AFA9ED971BB365
|
||||||
|
created: 2019-04-04 expires: never usage: SC
|
||||||
|
card-no: FF020001008A77C1
|
||||||
|
trust: ultimate validity: ultimate
|
||||||
|
[ultimate] (1). otto@@example.net
|
||||||
|
gpg> addkey
|
||||||
|
Secret parts of primary key are stored on-card.
|
||||||
|
Please select what kind of key you want:
|
||||||
|
(3) DSA (sign only)
|
||||||
|
(4) RSA (sign only)
|
||||||
|
(5) Elgamal (encrypt only)
|
||||||
|
(6) RSA (encrypt only)
|
||||||
|
(14) Existing key from card
|
||||||
|
Your selection? 14
|
||||||
|
Serial number of the card: FF020001008A77C1
|
||||||
|
Available keys:
|
||||||
|
(1) 213D1825FDE0F8240CB4E4229F01AF90AC658C2E PIV.9A nistp384 (auth)
|
||||||
|
(2) 7A53E6CFFE7220A0E646B4632EE29E5A7104499C PIV.9E nistp256 (auth)
|
||||||
|
(3) 32A6C6FAFCB8421878608AAB452D5470DD3223ED PIV.9C rsa2048 (cert,sign)
|
||||||
|
(4) 34798AAFE0A7565088101CC4AE31C5C8C74461CB PIV.9D rsa2048 (encr)
|
||||||
|
Your selection? 4
|
||||||
|
Please specify how long the key should be valid.
|
||||||
|
0 = key does not expire
|
||||||
|
<n> = key expires in n days
|
||||||
|
<n>w = key expires in n weeks
|
||||||
|
<n>m = key expires in n months
|
||||||
|
<n>y = key expires in n years
|
||||||
|
Key is valid for? (0)
|
||||||
|
Key does not expire at all
|
||||||
|
Is this correct? (y/N) y
|
||||||
|
Really create? (y/N) y
|
||||||
|
|
||||||
|
sec rsa2048/C3AFA9ED971BB365
|
||||||
|
created: 2019-04-04 expires: never usage: SC
|
||||||
|
card-no: FF020001008A77C1
|
||||||
|
trust: ultimate validity: ultimate
|
||||||
|
ssb rsa2048/7067860A98FCE6E1
|
||||||
|
created: 2019-04-04 expires: never usage: E
|
||||||
|
card-no: FF020001008A77C1
|
||||||
|
[ultimate] (1). otto@@example.net
|
||||||
|
|
||||||
|
gpg> save
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Now you can use your PIV card also with @command{gpg}.
|
||||||
|
|
||||||
@c @mansect examples
|
@c @mansect examples
|
||||||
|
|
||||||
|
152
doc/gpg.texi
152
doc/gpg.texi
@ -346,12 +346,17 @@ numbers 1-9 or "T" for 10 and above to indicate trust signature levels
|
|||||||
|
|
||||||
|
|
||||||
@item --locate-keys
|
@item --locate-keys
|
||||||
|
@itemx --locate-external-keys
|
||||||
@opindex locate-keys
|
@opindex locate-keys
|
||||||
|
@opindex locate-external-keys
|
||||||
Locate the keys given as arguments. This command basically uses the
|
Locate the keys given as arguments. This command basically uses the
|
||||||
same algorithm as used when locating keys for encryption or signing and
|
same algorithm as used when locating keys for encryption or signing
|
||||||
may thus be used to see what keys @command{@gpgname} might use. In
|
and may thus be used to see what keys @command{@gpgname} might use.
|
||||||
particular external methods as defined by @option{--auto-key-locate} may
|
In particular external methods as defined by
|
||||||
be used to locate a key. Only public keys are listed.
|
@option{--auto-key-locate} may be used to locate a key. Only public
|
||||||
|
keys are listed. The variant @option{--locate-external-keys} does not
|
||||||
|
consider a locally existing key and can thus be used to force the
|
||||||
|
refresh of a key via the defined external methods.
|
||||||
|
|
||||||
@item --show-keys
|
@item --show-keys
|
||||||
@opindex show-keys
|
@opindex show-keys
|
||||||
@ -404,7 +409,10 @@ functionality is also available as the subcommand "passwd" with the
|
|||||||
@opindex delete-keys
|
@opindex delete-keys
|
||||||
Remove key from the public keyring. In batch mode either @option{--yes} is
|
Remove key from the public keyring. In batch mode either @option{--yes} is
|
||||||
required or the key must be specified by fingerprint. This is a
|
required or the key must be specified by fingerprint. This is a
|
||||||
safeguard against accidental deletion of multiple keys.
|
safeguard against accidental deletion of multiple keys. If the
|
||||||
|
exclamation mark syntax is used with the fingerprint of a subkey only
|
||||||
|
that subkey is deleted; if the exclamation mark is used with the
|
||||||
|
fingerprint of the primary key the entire public key is deleted.
|
||||||
|
|
||||||
@item --delete-secret-keys @var{name}
|
@item --delete-secret-keys @var{name}
|
||||||
@opindex delete-secret-keys
|
@opindex delete-secret-keys
|
||||||
@ -413,7 +421,10 @@ specified by fingerprint. The option @option{--yes} can be used to
|
|||||||
advice gpg-agent not to request a confirmation. This extra
|
advice gpg-agent not to request a confirmation. This extra
|
||||||
pre-caution is done because @command{@gpgname} can't be sure that the
|
pre-caution is done because @command{@gpgname} can't be sure that the
|
||||||
secret key (as controlled by gpg-agent) is only used for the given
|
secret key (as controlled by gpg-agent) is only used for the given
|
||||||
OpenPGP public key.
|
OpenPGP public key. If the exclamation mark syntax is used with the
|
||||||
|
fingerprint of a subkey only the secret part of that subkey is
|
||||||
|
deleted; if the exclamation mark is used with the fingerprint of the
|
||||||
|
primary key only the secret part of the primary key is deleted.
|
||||||
|
|
||||||
|
|
||||||
@item --delete-secret-and-public-key @var{name}
|
@item --delete-secret-and-public-key @var{name}
|
||||||
@ -434,9 +445,8 @@ file given with option @option{--output}. Use together with
|
|||||||
@item --send-keys @var{keyIDs}
|
@item --send-keys @var{keyIDs}
|
||||||
@opindex send-keys
|
@opindex send-keys
|
||||||
Similar to @option{--export} but sends the keys to a keyserver.
|
Similar to @option{--export} but sends the keys to a keyserver.
|
||||||
Fingerprints may be used instead of key IDs. Option
|
Fingerprints may be used instead of key IDs.
|
||||||
@option{--keyserver} must be used to give the name of this
|
Don't send your complete keyring to a keyserver --- select
|
||||||
keyserver. Don't send your complete keyring to a keyserver --- select
|
|
||||||
only those keys which are new or changed by you. If no @var{keyIDs}
|
only those keys which are new or changed by you. If no @var{keyIDs}
|
||||||
are given, @command{@gpgname} does nothing.
|
are given, @command{@gpgname} does nothing.
|
||||||
|
|
||||||
@ -491,27 +501,25 @@ signatures, user-IDs and subkeys.
|
|||||||
@opindex receive-keys
|
@opindex receive-keys
|
||||||
@itemx --recv-keys @var{keyIDs}
|
@itemx --recv-keys @var{keyIDs}
|
||||||
@opindex recv-keys
|
@opindex recv-keys
|
||||||
Import the keys with the given @var{keyIDs} from a keyserver. Option
|
Import the keys with the given @var{keyIDs} from a keyserver.
|
||||||
@option{--keyserver} must be used to give the name of this keyserver.
|
|
||||||
|
|
||||||
@item --refresh-keys
|
@item --refresh-keys
|
||||||
@opindex refresh-keys
|
@opindex refresh-keys
|
||||||
Request updates from a keyserver for keys that already exist on the
|
Request updates from a keyserver for keys that already exist on the
|
||||||
local keyring. This is useful for updating a key with the latest
|
local keyring. This is useful for updating a key with the latest
|
||||||
signatures, user IDs, etc. Calling this with no arguments will refresh
|
signatures, user IDs, etc. Calling this with no arguments will refresh
|
||||||
the entire keyring. Option @option{--keyserver} must be used to give the
|
the entire keyring.
|
||||||
name of the keyserver for all keys that do not have preferred keyservers
|
|
||||||
set (see @option{--keyserver-options honor-keyserver-url}).
|
|
||||||
|
|
||||||
@item --search-keys @var{names}
|
@item --search-keys @var{names}
|
||||||
@opindex search-keys
|
@opindex search-keys
|
||||||
Search the keyserver for the given @var{names}. Multiple names given here will
|
Search the keyserver for the given @var{names}. Multiple names given
|
||||||
be joined together to create the search string for the keyserver.
|
here will be joined together to create the search string for the
|
||||||
Option @option{--keyserver} must be used to give the name of this
|
keyserver. Note that keyservers search for @var{names} in a different
|
||||||
keyserver. Keyservers that support different search methods allow using
|
and simpler way than gpg does. The best choice is to use a mail
|
||||||
the syntax specified in "How to specify a user ID" below. Note that
|
address. Due to data privacy reasons keyservers may even not even
|
||||||
different keyserver types support different search methods. Currently
|
allow searching by user id or mail address and thus may only return
|
||||||
only LDAP supports them all.
|
results when being used with the @option{--recv-key} command to
|
||||||
|
search by key fingerprint or keyid.
|
||||||
|
|
||||||
@item --fetch-keys @var{URIs}
|
@item --fetch-keys @var{URIs}
|
||||||
@opindex fetch-keys
|
@opindex fetch-keys
|
||||||
@ -1330,8 +1338,8 @@ give the opposite meaning. The options are:
|
|||||||
|
|
||||||
@item show-only-fpr-mbox
|
@item show-only-fpr-mbox
|
||||||
@opindex list-options:show-only-fpr-mbox
|
@opindex list-options:show-only-fpr-mbox
|
||||||
For each valid user-id which also has a valid mail address print
|
For each user-id which has a valid mail address print
|
||||||
only the fingerprint and the mail address.
|
only the fingerprint followed by the mail address.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@item --verify-options @var{parameters}
|
@item --verify-options @var{parameters}
|
||||||
@ -1429,19 +1437,24 @@ viewed (e.g. "f"), "%V" for the calculated validity as a string (e.g.
|
|||||||
and "%%" for an actual percent sign. If neither %i or %I are present,
|
and "%%" for an actual percent sign. If neither %i or %I are present,
|
||||||
then the photo will be supplied to the viewer on standard input.
|
then the photo will be supplied to the viewer on standard input.
|
||||||
|
|
||||||
The default viewer is "xloadimage -fork -quiet -title 'KeyID 0x%k'
|
On Unix the default viewer is
|
||||||
STDIN". Note that if your image viewer program is not secure, then
|
@code{xloadimage -fork -quiet -title 'KeyID 0x%k' STDIN}
|
||||||
executing it from GnuPG does not make it secure.
|
with a fallback to
|
||||||
|
@code{display -title 'KeyID 0x%k' %i}
|
||||||
|
and finally to
|
||||||
|
@code{xdg-open %i}.
|
||||||
|
On Windows
|
||||||
|
@code{!ShellExecute 400 %i} is used; here the command is a meta
|
||||||
|
command to use that API call followed by a wait time in milliseconds
|
||||||
|
which is used to give the viewer time to read the temporary image file
|
||||||
|
before gpg deletes it again. Note that if your image viewer program
|
||||||
|
is not secure, then executing it from gpg does not make it secure.
|
||||||
|
|
||||||
@item --exec-path @var{string}
|
@item --exec-path @var{string}
|
||||||
@opindex exec-path
|
@opindex exec-path
|
||||||
@efindex PATH
|
@efindex PATH
|
||||||
Sets a list of directories to search for photo viewers and keyserver
|
Sets a list of directories to search for photo viewers If not provided
|
||||||
helpers. If not provided, keyserver helpers use the compiled-in
|
photo viewers use the @code{PATH} environment variable.
|
||||||
default directory, and photo viewers use the @code{PATH} environment
|
|
||||||
variable.
|
|
||||||
Note, that on W32 system this value is ignored when searching for
|
|
||||||
keyserver helpers.
|
|
||||||
|
|
||||||
@item --keyring @var{file}
|
@item --keyring @var{file}
|
||||||
@opindex keyring
|
@opindex keyring
|
||||||
@ -1766,12 +1779,11 @@ list. The default is "local,wkd".
|
|||||||
PGP Universal method of checking @samp{ldap://keys.(thedomain)}.
|
PGP Universal method of checking @samp{ldap://keys.(thedomain)}.
|
||||||
|
|
||||||
@item keyserver
|
@item keyserver
|
||||||
Locate a key using whatever keyserver is defined using the
|
Locate a key using a keyserver.
|
||||||
@option{--keyserver} option.
|
|
||||||
|
|
||||||
@item keyserver-URL
|
@item keyserver-URL
|
||||||
In addition, a keyserver URL as used in the @option{--keyserver} option
|
In addition, a keyserver URL as used in the @command{dirmngr}
|
||||||
may be used here to query that particular keyserver.
|
configuration may be used here to query that particular keyserver.
|
||||||
|
|
||||||
@item local
|
@item local
|
||||||
Locate the key using the local keyrings. This mechanism allows the user to
|
Locate the key using the local keyrings. This mechanism allows the user to
|
||||||
@ -1802,10 +1814,26 @@ These options enable or disable the automatic retrieving of keys from
|
|||||||
a keyserver when verifying signatures made by keys that are not on the
|
a keyserver when verifying signatures made by keys that are not on the
|
||||||
local keyring. The default is @option{--no-auto-key-retrieve}.
|
local keyring. The default is @option{--no-auto-key-retrieve}.
|
||||||
|
|
||||||
If the method "wkd" is included in the list of methods given to
|
The order of methods tried to lookup the key is:
|
||||||
@option{auto-key-locate}, the signer's user ID is part of the
|
|
||||||
signature, and the option @option{--disable-signer-uid} is not used,
|
1. If a preferred keyserver is specified in the signature and the
|
||||||
the "wkd" method may also be used to retrieve a key.
|
option @option{honor-keyserver-url} is active (which is not the
|
||||||
|
default), that keyserver is tried. Note that the creator of the
|
||||||
|
signature uses the option @option{--sig-keyserver-url} to specify the
|
||||||
|
preferred keyserver for data signatures.
|
||||||
|
|
||||||
|
2. If the signature has the Signer's UID set (e.g. using
|
||||||
|
@option{--sender} while creating the signature) a Web Key Directory
|
||||||
|
(WKD) lookup is done. This is the default configuration but can be
|
||||||
|
disabled by removing WKD from the auto-key-locate list or by using the
|
||||||
|
option @option{--disable-signer-uid}.
|
||||||
|
|
||||||
|
3. If the option @option{honor-pka-record} is active, the legacy PKA
|
||||||
|
method is used.
|
||||||
|
|
||||||
|
4. If any keyserver is configured and the Issuer Fingerprint is part
|
||||||
|
of the signature (since GnuPG 2.1.16), the configured keyservers are
|
||||||
|
tried.
|
||||||
|
|
||||||
Note that this option makes a "web bug" like behavior possible.
|
Note that this option makes a "web bug" like behavior possible.
|
||||||
Keyserver or Web Key Directory operators can see which keys you
|
Keyserver or Web Key Directory operators can see which keys you
|
||||||
@ -1905,6 +1933,11 @@ are available for all keyserver types, some common options are:
|
|||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
The default list of options is: "self-sigs-only, import-clean,
|
||||||
|
repair-keys, repair-pks-subkey-bug, export-attributes,
|
||||||
|
honor-pka-record".
|
||||||
|
|
||||||
|
|
||||||
@item --completes-needed @var{n}
|
@item --completes-needed @var{n}
|
||||||
@opindex compliant-needed
|
@opindex compliant-needed
|
||||||
Number of completely trusted users to introduce a new
|
Number of completely trusted users to introduce a new
|
||||||
@ -2334,7 +2367,16 @@ opposite meaning. The options are:
|
|||||||
can be used to update only the subkeys or other non-user id related
|
can be used to update only the subkeys or other non-user id related
|
||||||
information.
|
information.
|
||||||
|
|
||||||
@item repair-keys. After import, fix various problems with the
|
@item self-sigs-only
|
||||||
|
Accept only self-signatures while importing a key. All other
|
||||||
|
key-signatures are skipped at an early import stage. This option
|
||||||
|
can be used with @code{keyserver-options} to mitigate attempts to
|
||||||
|
flood a key with bogus signatures from a keyserver. The drawback is
|
||||||
|
that all other valid key-signatures, as required by the Web of Trust
|
||||||
|
are also not imported.
|
||||||
|
|
||||||
|
@item repair-keys
|
||||||
|
After import, fix various problems with the
|
||||||
keys. For example, this reorders signatures, and strips duplicate
|
keys. For example, this reorders signatures, and strips duplicate
|
||||||
signatures. Defaults to yes.
|
signatures. Defaults to yes.
|
||||||
|
|
||||||
@ -2628,11 +2670,11 @@ legacy non-MDC message is exceptionally required, the option
|
|||||||
|
|
||||||
@item --disable-signer-uid
|
@item --disable-signer-uid
|
||||||
@opindex disable-signer-uid
|
@opindex disable-signer-uid
|
||||||
By default the user ID of the signing key is embedded in the data
|
By default the user ID of the signing key is embedded in the data signature.
|
||||||
signature. As of now this is only done if the signing key has been
|
As of now this is only done if the signing key has been specified with
|
||||||
specified with @option{local-user} using a mail address. This
|
@option{local-user} using a mail address, or with @option{sender}. This
|
||||||
information can be helpful for verifier to locate the key; see
|
information can be helpful for verifier to locate the key; see option
|
||||||
option @option{--auto-key-retrieve}.
|
@option{--auto-key-retrieve}.
|
||||||
|
|
||||||
@item --personal-cipher-preferences @var{string}
|
@item --personal-cipher-preferences @var{string}
|
||||||
@opindex personal-cipher-preferences
|
@opindex personal-cipher-preferences
|
||||||
@ -3021,7 +3063,8 @@ to display the message. This option overrides @option{--set-filename}.
|
|||||||
@itemx --no-use-embedded-filename
|
@itemx --no-use-embedded-filename
|
||||||
@opindex use-embedded-filename
|
@opindex use-embedded-filename
|
||||||
Try to create a file with a name as embedded in the data. This can be
|
Try to create a file with a name as embedded in the data. This can be
|
||||||
a dangerous option as it enables overwriting files. Defaults to no.
|
a dangerous option as it enables overwriting files. Defaults to no.
|
||||||
|
Note that the option @option{--output} overrides this option.
|
||||||
|
|
||||||
@item --cipher-algo @var{name}
|
@item --cipher-algo @var{name}
|
||||||
@opindex cipher-algo
|
@opindex cipher-algo
|
||||||
@ -3080,10 +3123,14 @@ the same thing.
|
|||||||
@opindex cert-digest-algo
|
@opindex cert-digest-algo
|
||||||
Use @var{name} as the message digest algorithm used when signing a
|
Use @var{name} as the message digest algorithm used when signing a
|
||||||
key. Running the program with the command @option{--version} yields a
|
key. Running the program with the command @option{--version} yields a
|
||||||
list of supported algorithms. Be aware that if you choose an algorithm
|
list of supported algorithms. Be aware that if you choose an
|
||||||
that GnuPG supports but other OpenPGP implementations do not, then some
|
algorithm that GnuPG supports but other OpenPGP implementations do
|
||||||
users will not be able to use the key signatures you make, or quite
|
not, then some users will not be able to use the key signatures you
|
||||||
possibly your entire key.
|
make, or quite possibly your entire key. Note also that a public key
|
||||||
|
algorithm must be compatible with the specified digest algorithm; thus
|
||||||
|
selecting an arbitrary digest algorithm may result in error messages
|
||||||
|
from lower crypto layers or lead to security flaws.
|
||||||
|
|
||||||
|
|
||||||
@item --disable-cipher-algo @var{name}
|
@item --disable-cipher-algo @var{name}
|
||||||
@opindex disable-cipher-algo
|
@opindex disable-cipher-algo
|
||||||
@ -3288,7 +3335,8 @@ secret keyrings.
|
|||||||
|
|
||||||
@item --no-keyring
|
@item --no-keyring
|
||||||
@opindex no-keyring
|
@opindex no-keyring
|
||||||
Do not add use any keyrings even if specified as options.
|
Do not use any keyring at all. This overrides the default and all
|
||||||
|
options which specify keyrings.
|
||||||
|
|
||||||
@item --skip-verify
|
@item --skip-verify
|
||||||
@opindex skip-verify
|
@opindex skip-verify
|
||||||
|
@ -349,7 +349,8 @@ verbose commands to @command{gpgsm}, such as @samp{-vv}.
|
|||||||
|
|
||||||
@item --policy-file @var{filename}
|
@item --policy-file @var{filename}
|
||||||
@opindex policy-file
|
@opindex policy-file
|
||||||
Change the default name of the policy file to @var{filename}.
|
Change the default name of the policy file to @var{filename}. The
|
||||||
|
default name is @file{policies.txt}.
|
||||||
|
|
||||||
@item --agent-program @var{file}
|
@item --agent-program @var{file}
|
||||||
@opindex agent-program
|
@opindex agent-program
|
||||||
|
@ -288,17 +288,9 @@ To get a list of available CCID readers you may use this command:
|
|||||||
|
|
||||||
@item --card-timeout @var{n}
|
@item --card-timeout @var{n}
|
||||||
@opindex card-timeout
|
@opindex card-timeout
|
||||||
If @var{n} is not 0 and no client is actively using the card, the card
|
This option is deprecated. In GnuPG 2.0, it used to be used for
|
||||||
will be powered down after @var{n} seconds. Powering down the card
|
DISCONNECT command to control timing issue. Since DISCONNECT command
|
||||||
avoids a potential risk of damaging a card when used with certain
|
works synchronously, it has no effect.
|
||||||
cheap readers. This also allows applications that are not aware of
|
|
||||||
Scdaemon to access the card. The disadvantage of using a card timeout
|
|
||||||
is that accessing the card takes longer and that the user needs to
|
|
||||||
enter the PIN again after the next power up.
|
|
||||||
|
|
||||||
Note that with the current version of Scdaemon the card is powered
|
|
||||||
down immediately at the next timer tick for any value of @var{n} other
|
|
||||||
than 0.
|
|
||||||
|
|
||||||
@item --enable-pinpad-varlen
|
@item --enable-pinpad-varlen
|
||||||
@opindex enable-pinpad-varlen
|
@opindex enable-pinpad-varlen
|
||||||
@ -332,6 +324,21 @@ This option disables the use of the card application named
|
|||||||
@var{name}. This is mainly useful for debugging or if a application
|
@var{name}. This is mainly useful for debugging or if a application
|
||||||
with lower priority should be used by default.
|
with lower priority should be used by default.
|
||||||
|
|
||||||
|
@item --application-priority @var{namelist}
|
||||||
|
@opindex application-priority
|
||||||
|
This option allows to change the order in which applications of a card
|
||||||
|
a tried if no specific application was requested. @var{namelist} is a
|
||||||
|
space or comma delimited list of application names. Unknown names are
|
||||||
|
simply skipped. Applications not mentioned in the list are put in the
|
||||||
|
former order at the end of the new priority list.
|
||||||
|
|
||||||
|
To get the list of current active applications, use
|
||||||
|
@cartouche
|
||||||
|
@smallexample
|
||||||
|
gpg-connect-agent 'scd getinfo app_list' /bye
|
||||||
|
@end smallexample
|
||||||
|
@end cartouche
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
All the long options may also be given in the configuration file after
|
All the long options may also be given in the configuration file after
|
||||||
@ -767,4 +774,3 @@ length up to N bytes. If N is not given a default value is used
|
|||||||
@command{gpg2}(1)
|
@command{gpg2}(1)
|
||||||
@end ifset
|
@end ifset
|
||||||
@include see-also-note.texi
|
@include see-also-note.texi
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ GnuPG comes with a couple of smaller tools:
|
|||||||
* gpgparsemail:: Parse a mail message into an annotated format
|
* gpgparsemail:: Parse a mail message into an annotated format
|
||||||
* symcryptrun:: Call a simple symmetric encryption tool.
|
* symcryptrun:: Call a simple symmetric encryption tool.
|
||||||
* gpgtar:: Encrypt or sign files into an archive.
|
* gpgtar:: Encrypt or sign files into an archive.
|
||||||
|
* gpg-check-pattern:: Check a passphrase on stdin against the patternfile.
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@c
|
@c
|
||||||
@ -352,11 +353,12 @@ may use this command to ensure that they are started. Using "all" for
|
|||||||
|
|
||||||
@item --kill [@var{component}]
|
@item --kill [@var{component}]
|
||||||
@opindex kill
|
@opindex kill
|
||||||
Kill the given component. Components which support killing are
|
Kill the given component that runs as a daemon, including
|
||||||
@command{gpg-agent} and @command{scdaemon}. Components which don't
|
@command{gpg-agent}, @command{dirmngr}, and @command{scdaemon}. A
|
||||||
support reloading are ignored. Using "all" for @var{component} kills
|
@command{component} which does not run as a daemon will be ignored.
|
||||||
all components running as daemons. Note that as of now reload and
|
Using "all" for @var{component} kills all components running as
|
||||||
kill have the same effect for @command{scdaemon}.
|
daemons. Note that as of now reload and kill have the same effect for
|
||||||
|
@command{scdaemon}.
|
||||||
|
|
||||||
@item --create-socketdir
|
@item --create-socketdir
|
||||||
@opindex create-socketdir
|
@opindex create-socketdir
|
||||||
@ -392,6 +394,8 @@ extends numerical field values by human-readable descriptions.
|
|||||||
@opindex quiet
|
@opindex quiet
|
||||||
Try to be as quiet as possible.
|
Try to be as quiet as possible.
|
||||||
|
|
||||||
|
@include opt-homedir.texi
|
||||||
|
|
||||||
@item -n
|
@item -n
|
||||||
@itemx --dry-run
|
@itemx --dry-run
|
||||||
Do not actually change anything. This is currently only implemented
|
Do not actually change anything. This is currently only implemented
|
||||||
@ -2107,3 +2111,50 @@ gpgtar --list-archive test1
|
|||||||
@command{tar}(1),
|
@command{tar}(1),
|
||||||
@end ifset
|
@end ifset
|
||||||
@include see-also-note.texi
|
@include see-also-note.texi
|
||||||
|
|
||||||
|
@c
|
||||||
|
@c GPG-CHECK-PATTERN
|
||||||
|
@c
|
||||||
|
@manpage gpg-check-pattern.1
|
||||||
|
@node gpg-check-pattern
|
||||||
|
@section Check a passphrase on stdin against the patternfile
|
||||||
|
@ifset manverb
|
||||||
|
.B gpg-check-pattern
|
||||||
|
\- Check a passphrase on stdin against the patternfile
|
||||||
|
@end ifset
|
||||||
|
|
||||||
|
@mansect synopsis
|
||||||
|
@ifset manverb
|
||||||
|
.B gpg\-check\-pattern
|
||||||
|
.RI [ options ]
|
||||||
|
.I patternfile
|
||||||
|
@end ifset
|
||||||
|
|
||||||
|
@mansect description
|
||||||
|
@command{gpg-check-pattern} checks a passphrase given on stdin against
|
||||||
|
a specified pattern file.
|
||||||
|
|
||||||
|
@mansect options
|
||||||
|
@noindent
|
||||||
|
|
||||||
|
@table @gnupgtabopt
|
||||||
|
|
||||||
|
@item --verbose
|
||||||
|
@opindex verbose
|
||||||
|
Enable extra informational output.
|
||||||
|
|
||||||
|
@item --check
|
||||||
|
@opindex check
|
||||||
|
Run only a syntax check on the patternfile.
|
||||||
|
|
||||||
|
@item --null
|
||||||
|
@opindex null
|
||||||
|
Input is expected to be null delimited.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@mansect see also
|
||||||
|
@ifset isman
|
||||||
|
@command{gpg}(1),
|
||||||
|
@end ifset
|
||||||
|
@include see-also-note.texi
|
||||||
|
@ -101,6 +101,14 @@ fingerprint and the mailbox separated by a space. The command
|
|||||||
@option{--remove-key} removes a key from that directory, its only
|
@option{--remove-key} removes a key from that directory, its only
|
||||||
argument is a user-id.
|
argument is a user-id.
|
||||||
|
|
||||||
|
The command @option{--print-wkd-hash} prints the WKD user-id identifiers
|
||||||
|
and the corresponding mailboxes from the user-ids given on the command
|
||||||
|
line or via stdin (one user-id per line).
|
||||||
|
|
||||||
|
The command @option{--print-wkd-url} prints the URLs used to fetch the
|
||||||
|
key for the given user-ids from WKD. The meanwhile preferred format
|
||||||
|
with sub-domains is used here.
|
||||||
|
|
||||||
@command{gpg-wks-client} is not commonly invoked directly and thus it
|
@command{gpg-wks-client} is not commonly invoked directly and thus it
|
||||||
is not installed in the bin directory. Here is an example how it can
|
is not installed in the bin directory. Here is an example how it can
|
||||||
be invoked manually to check for a Web Key Directory entry for
|
be invoked manually to check for a Web Key Directory entry for
|
||||||
|
@ -724,7 +724,8 @@ proc_texi_cmd (FILE *fp, const char *command, const char *rest, size_t len,
|
|||||||
{ "url", 0, "\\fB", "\\fR" },
|
{ "url", 0, "\\fB", "\\fR" },
|
||||||
{ "sc", 0, "\\fB", "\\fR" },
|
{ "sc", 0, "\\fB", "\\fR" },
|
||||||
{ "var", 0, "\\fI", "\\fR" },
|
{ "var", 0, "\\fI", "\\fR" },
|
||||||
{ "samp", 0, "\\(aq", "\\(aq" },
|
{ "samp", 0, "\\(oq", "\\(cq" },
|
||||||
|
{ "kbd", 0, "\\(oq", "\\(cq" },
|
||||||
{ "file", 0, "\\(oq\\fI","\\fR\\(cq" },
|
{ "file", 0, "\\(oq\\fI","\\fR\\(cq" },
|
||||||
{ "env", 0, "\\(oq\\fI","\\fR\\(cq" },
|
{ "env", 0, "\\(oq\\fI","\\fR\\(cq" },
|
||||||
{ "acronym", 0 },
|
{ "acronym", 0 },
|
||||||
|
@ -121,6 +121,7 @@ common_source = \
|
|||||||
sig-check.c \
|
sig-check.c \
|
||||||
keylist.c \
|
keylist.c \
|
||||||
pkglue.c pkglue.h \
|
pkglue.c pkglue.h \
|
||||||
|
objcache.c objcache.h \
|
||||||
ecdh.c
|
ecdh.c
|
||||||
|
|
||||||
gpg_sources = server.c \
|
gpg_sources = server.c \
|
||||||
|
@ -1394,10 +1394,10 @@ armor_filter( void *opaque, int control,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* write the comment strings */
|
/* write the comment strings */
|
||||||
for(s=comment->d;comment;comment=comment->next,s=comment->d)
|
for(;comment;comment=comment->next)
|
||||||
{
|
{
|
||||||
iobuf_writestr(a, "Comment: " );
|
iobuf_writestr(a, "Comment: " );
|
||||||
for( ; *s; s++ )
|
for( s=comment->d; *s; s++ )
|
||||||
{
|
{
|
||||||
if( *s == '\n' )
|
if( *s == '\n' )
|
||||||
iobuf_writestr(a, "\\n" );
|
iobuf_writestr(a, "\\n" );
|
||||||
|
@ -447,15 +447,21 @@ do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
|
|||||||
* Without forcing HDRLEN to 2 in this case an indeterminate length
|
* Without forcing HDRLEN to 2 in this case an indeterminate length
|
||||||
* packet would be written which is not allowed. Note that we are
|
* packet would be written which is not allowed. Note that we are
|
||||||
* always called with a CTB indicating an old packet header format,
|
* always called with a CTB indicating an old packet header format,
|
||||||
* so that forcing a 2 octet header works. */
|
* so that forcing a 2 octet header works. We also check for the
|
||||||
|
* maximum allowed packet size by the parser using an arbitrary
|
||||||
|
* extra 10 bytes for header data. */
|
||||||
if (uid->attrib_data)
|
if (uid->attrib_data)
|
||||||
{
|
{
|
||||||
|
if (uid->attrib_len > MAX_ATTR_PACKET_LENGTH - 10)
|
||||||
|
return gpg_error (GPG_ERR_TOO_LARGE);
|
||||||
hdrlen = uid->attrib_len? 0 : 2;
|
hdrlen = uid->attrib_len? 0 : 2;
|
||||||
write_header2 (out, ctb, uid->attrib_len, hdrlen);
|
write_header2 (out, ctb, uid->attrib_len, hdrlen);
|
||||||
rc = iobuf_write( out, uid->attrib_data, uid->attrib_len );
|
rc = iobuf_write( out, uid->attrib_data, uid->attrib_len );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (uid->len > MAX_UID_PACKET_LENGTH - 10)
|
||||||
|
return gpg_error (GPG_ERR_TOO_LARGE);
|
||||||
hdrlen = uid->len? 0 : 2;
|
hdrlen = uid->len? 0 : 2;
|
||||||
write_header2 (out, ctb, uid->len, hdrlen);
|
write_header2 (out, ctb, uid->len, hdrlen);
|
||||||
rc = iobuf_write( out, uid->name, uid->len );
|
rc = iobuf_write( out, uid->name, uid->len );
|
||||||
|
489
g10/call-agent.c
489
g10/call-agent.c
@ -41,6 +41,7 @@
|
|||||||
#include "../common/status.h"
|
#include "../common/status.h"
|
||||||
#include "../common/shareddefs.h"
|
#include "../common/shareddefs.h"
|
||||||
#include "../common/host2net.h"
|
#include "../common/host2net.h"
|
||||||
|
#include "../common/ttyio.h"
|
||||||
|
|
||||||
#define CONTROL_D ('D' - 'A' + 1)
|
#define CONTROL_D ('D' - 'A' + 1)
|
||||||
|
|
||||||
@ -48,6 +49,13 @@
|
|||||||
static assuan_context_t agent_ctx = NULL;
|
static assuan_context_t agent_ctx = NULL;
|
||||||
static int did_early_card_test;
|
static int did_early_card_test;
|
||||||
|
|
||||||
|
struct confirm_parm_s
|
||||||
|
{
|
||||||
|
char *desc;
|
||||||
|
char *ok;
|
||||||
|
char *notok;
|
||||||
|
};
|
||||||
|
|
||||||
struct default_inq_parm_s
|
struct default_inq_parm_s
|
||||||
{
|
{
|
||||||
ctrl_t ctrl;
|
ctrl_t ctrl;
|
||||||
@ -57,6 +65,7 @@ struct default_inq_parm_s
|
|||||||
u32 *mainkeyid;
|
u32 *mainkeyid;
|
||||||
int pubkey_algo;
|
int pubkey_algo;
|
||||||
} keyinfo;
|
} keyinfo;
|
||||||
|
struct confirm_parm_s *confirm;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cipher_parm_s
|
struct cipher_parm_s
|
||||||
@ -136,6 +145,7 @@ default_inq_cb (void *opaque, const char *line)
|
|||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
struct default_inq_parm_s *parm = opaque;
|
struct default_inq_parm_s *parm = opaque;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
if (has_leading_keyword (line, "PINENTRY_LAUNCHED"))
|
if (has_leading_keyword (line, "PINENTRY_LAUNCHED"))
|
||||||
{
|
{
|
||||||
@ -151,7 +161,7 @@ default_inq_cb (void *opaque, const char *line)
|
|||||||
{
|
{
|
||||||
if (have_static_passphrase ())
|
if (have_static_passphrase ())
|
||||||
{
|
{
|
||||||
const char *s = get_static_passphrase ();
|
s = get_static_passphrase ();
|
||||||
err = assuan_send_data (parm->ctx, s, strlen (s));
|
err = assuan_send_data (parm->ctx, s, strlen (s));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -176,6 +186,27 @@ default_inq_cb (void *opaque, const char *line)
|
|||||||
xfree (pw);
|
xfree (pw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ((s = has_leading_keyword (line, "CONFIRM"))
|
||||||
|
&& opt.pinentry_mode == PINENTRY_MODE_LOOPBACK
|
||||||
|
&& parm->confirm)
|
||||||
|
{
|
||||||
|
int ask = atoi (s);
|
||||||
|
int yes;
|
||||||
|
|
||||||
|
if (ask)
|
||||||
|
{
|
||||||
|
yes = cpr_get_answer_is_yes (NULL, parm->confirm->desc);
|
||||||
|
if (yes)
|
||||||
|
err = assuan_send_data (parm->ctx, NULL, 0);
|
||||||
|
else
|
||||||
|
err = gpg_error (GPG_ERR_NOT_CONFIRMED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tty_printf ("%s", parm->confirm->desc);
|
||||||
|
err = assuan_send_data (parm->ctx, NULL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
log_debug ("ignoring gpg-agent inquiry '%s'\n", line);
|
log_debug ("ignoring gpg-agent inquiry '%s'\n", line);
|
||||||
|
|
||||||
@ -336,7 +367,7 @@ start_agent (ctrl_t ctrl, int flag_for_card)
|
|||||||
if (!(flag_for_card & FLAG_FOR_CARD_SUPPRESS_ERRORS))
|
if (!(flag_for_card & FLAG_FOR_CARD_SUPPRESS_ERRORS))
|
||||||
rc = warn_version_mismatch (agent_ctx, SCDAEMON_NAME, 2);
|
rc = warn_version_mismatch (agent_ctx, SCDAEMON_NAME, 2);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
|
rc = assuan_transact (agent_ctx, "SCD SERIALNO",
|
||||||
NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL,
|
||||||
learn_status_cb, &info);
|
learn_status_cb, &info);
|
||||||
if (rc && !(flag_for_card & FLAG_FOR_CARD_SUPPRESS_ERRORS))
|
if (rc && !(flag_for_card & FLAG_FOR_CARD_SUPPRESS_ERRORS))
|
||||||
@ -352,7 +383,7 @@ start_agent (ctrl_t ctrl, int flag_for_card)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
write_status_text (STATUS_CARDCTRL, "4");
|
write_status_text (STATUS_CARDCTRL, "4");
|
||||||
log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
|
log_info ("selecting card failed: %s\n", gpg_strerror (rc));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -726,7 +757,15 @@ learn_status_cb (void *opaque, const char *line)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call the scdaemon to learn about a smartcard */
|
|
||||||
|
/* Call the scdaemon to learn about a smartcard. Note that in
|
||||||
|
* contradiction to the function's name, gpg-agent's LEARN command is
|
||||||
|
* used and not the low-level "SCD LEARN".
|
||||||
|
* Used by:
|
||||||
|
* card-util.c
|
||||||
|
* keyedit_menu
|
||||||
|
* card_store_key_with_backup (Woth force to remove secret key data)
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
agent_scd_learn (struct agent_card_info_s *info, int force)
|
agent_scd_learn (struct agent_card_info_s *info, int force)
|
||||||
{
|
{
|
||||||
@ -759,10 +798,109 @@ agent_scd_learn (struct agent_card_info_s *info, int force)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Callback for the agent_scd_keypairinfo function. */
|
||||||
|
static gpg_error_t
|
||||||
|
scd_keypairinfo_status_cb (void *opaque, const char *line)
|
||||||
|
{
|
||||||
|
strlist_t *listaddr = opaque;
|
||||||
|
const char *keyword = line;
|
||||||
|
int keywordlen;
|
||||||
|
strlist_t sl;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
|
||||||
|
;
|
||||||
|
while (spacep (line))
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen))
|
||||||
|
{
|
||||||
|
sl = append_to_strlist (listaddr, line);
|
||||||
|
p = sl->d;
|
||||||
|
/* Make sure that we only have two tokens so that future
|
||||||
|
* extensions of the format won't change the format expected by
|
||||||
|
* the caller. */
|
||||||
|
while (*p && !spacep (p))
|
||||||
|
p++;
|
||||||
|
if (*p)
|
||||||
|
{
|
||||||
|
while (spacep (p))
|
||||||
|
p++;
|
||||||
|
while (*p && !spacep (p))
|
||||||
|
p++;
|
||||||
|
if (*p)
|
||||||
|
{
|
||||||
|
*p++ = 0;
|
||||||
|
while (spacep (p))
|
||||||
|
p++;
|
||||||
|
while (*p && !spacep (p))
|
||||||
|
{
|
||||||
|
switch (*p++)
|
||||||
|
{
|
||||||
|
case 'c': sl->flags |= GCRY_PK_USAGE_CERT; break;
|
||||||
|
case 's': sl->flags |= GCRY_PK_USAGE_SIGN; break;
|
||||||
|
case 'e': sl->flags |= GCRY_PK_USAGE_ENCR; break;
|
||||||
|
case 'a': sl->flags |= GCRY_PK_USAGE_AUTH; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read the keypairinfo lines of the current card directly from
|
||||||
|
* scdaemon. The list is returned as a string made up of the keygrip,
|
||||||
|
* a space and the keyref. The flags of the string carry the usage
|
||||||
|
* bits. If KEYREF is not NULL, only a single string is returned
|
||||||
|
* which matches the given keyref. */
|
||||||
|
gpg_error_t
|
||||||
|
agent_scd_keypairinfo (ctrl_t ctrl, const char *keyref, strlist_t *r_list)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
strlist_t list = NULL;
|
||||||
|
struct default_inq_parm_s inq_parm;
|
||||||
|
char line[ASSUAN_LINELENGTH];
|
||||||
|
|
||||||
|
*r_list = NULL;
|
||||||
|
err= start_agent (ctrl, 1);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
memset (&inq_parm, 0, sizeof inq_parm);
|
||||||
|
inq_parm.ctx = agent_ctx;
|
||||||
|
|
||||||
|
if (keyref)
|
||||||
|
snprintf (line, DIM(line), "SCD READKEY --info-only %s", keyref);
|
||||||
|
else
|
||||||
|
snprintf (line, DIM(line), "SCD LEARN --keypairinfo");
|
||||||
|
|
||||||
|
err = assuan_transact (agent_ctx, line,
|
||||||
|
NULL, NULL,
|
||||||
|
default_inq_cb, &inq_parm,
|
||||||
|
scd_keypairinfo_status_cb, &list);
|
||||||
|
if (!err && !list)
|
||||||
|
err = gpg_error (GPG_ERR_NO_DATA);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
free_strlist (list);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
*r_list = list;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Send an APDU to the current card. On success the status word is
|
/* Send an APDU to the current card. On success the status word is
|
||||||
stored at R_SW. With HEXAPDU being NULL only a RESET command is
|
* stored at R_SW. With HEXAPDU being NULL only a RESET command is
|
||||||
send to scd. With HEXAPDU being the string "undefined" the command
|
* send to scd. With HEXAPDU being the string "undefined" the command
|
||||||
"SERIALNO undefined" is send to scd. */
|
* "SERIALNO undefined" is send to scd.
|
||||||
|
* Used by:
|
||||||
|
* card-util.c
|
||||||
|
*/
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
agent_scd_apdu (const char *hexapdu, unsigned int *r_sw)
|
agent_scd_apdu (const char *hexapdu, unsigned int *r_sw)
|
||||||
{
|
{
|
||||||
@ -816,6 +954,10 @@ agent_scd_apdu (const char *hexapdu, unsigned int *r_sw)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Used by:
|
||||||
|
* card_store_subkey
|
||||||
|
* card_store_key_with_backup
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
agent_keytocard (const char *hexgrip, int keyno, int force,
|
agent_keytocard (const char *hexgrip, int keyno, int force,
|
||||||
const char *serialno, const char *timestamp)
|
const char *serialno, const char *timestamp)
|
||||||
@ -843,10 +985,100 @@ agent_keytocard (const char *hexgrip, int keyno, int force,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Object used with the agent_scd_getattr_one. */
|
||||||
|
struct getattr_one_parm_s {
|
||||||
|
const char *keyword; /* Keyword to look for. */
|
||||||
|
char *data; /* Malloced and unescaped data. */
|
||||||
|
gpg_error_t err; /* Error code or 0 on success. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Callback for agent_scd_getattr_one. */
|
||||||
|
static gpg_error_t
|
||||||
|
getattr_one_status_cb (void *opaque, const char *line)
|
||||||
|
{
|
||||||
|
struct getattr_one_parm_s *parm = opaque;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
if (parm->data)
|
||||||
|
return 0; /* We want only the first occurrence. */
|
||||||
|
|
||||||
|
if ((s=has_leading_keyword (line, parm->keyword)))
|
||||||
|
{
|
||||||
|
parm->data = percent_plus_unescape (s, 0xff);
|
||||||
|
if (!parm->data)
|
||||||
|
parm->err = gpg_error_from_syserror ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Simplified version of agent_scd_getattr. This function returns
|
||||||
|
* only the first occurance of the attribute NAME and stores it at
|
||||||
|
* R_VALUE. A nul in the result is silennly replaced by 0xff. On
|
||||||
|
* error NULL is stored at R_VALUE. */
|
||||||
|
gpg_error_t
|
||||||
|
agent_scd_getattr_one (const char *name, char **r_value)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
char line[ASSUAN_LINELENGTH];
|
||||||
|
struct default_inq_parm_s inqparm;
|
||||||
|
struct getattr_one_parm_s parm;
|
||||||
|
|
||||||
|
*r_value = NULL;
|
||||||
|
|
||||||
|
if (!*name)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
memset (&inqparm, 0, sizeof inqparm);
|
||||||
|
inqparm.ctx = agent_ctx;
|
||||||
|
|
||||||
|
memset (&parm, 0, sizeof parm);
|
||||||
|
parm.keyword = name;
|
||||||
|
|
||||||
|
/* We assume that NAME does not need escaping. */
|
||||||
|
if (12 + strlen (name) > DIM(line)-1)
|
||||||
|
return gpg_error (GPG_ERR_TOO_LARGE);
|
||||||
|
stpcpy (stpcpy (line, "SCD GETATTR "), name);
|
||||||
|
|
||||||
|
err = start_agent (NULL, 1);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = assuan_transact (agent_ctx, line,
|
||||||
|
NULL, NULL,
|
||||||
|
default_inq_cb, &inqparm,
|
||||||
|
getattr_one_status_cb, &parm);
|
||||||
|
if (!err && parm.err)
|
||||||
|
err = parm.err;
|
||||||
|
else if (!err && !parm.data)
|
||||||
|
err = gpg_error (GPG_ERR_NO_DATA);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
*r_value = parm.data;
|
||||||
|
else
|
||||||
|
xfree (parm.data);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Call the agent to retrieve a data object. This function returns
|
/* Call the agent to retrieve a data object. This function returns
|
||||||
the data in the same structure as used by the learn command. It is
|
* the data in the same structure as used by the learn command. It is
|
||||||
allowed to update such a structure using this command. */
|
* allowed to update such a structure using this command.
|
||||||
|
*
|
||||||
|
* Used by:
|
||||||
|
* build_sk_list
|
||||||
|
* enum_secret_keys
|
||||||
|
* get_signature_count
|
||||||
|
* card-util.c
|
||||||
|
* generate_keypair (KEY-ATTR)
|
||||||
|
* card_store_key_with_backup (SERIALNO)
|
||||||
|
* generate_card_subkeypair (KEY-ATTR)
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
agent_scd_getattr (const char *name, struct agent_card_info_s *info)
|
agent_scd_getattr (const char *name, struct agent_card_info_s *info)
|
||||||
{
|
{
|
||||||
@ -875,24 +1107,23 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Send an setattr command to the SCdaemon. SERIALNO is not actually
|
/* Send an setattr command to the SCdaemon.
|
||||||
used here but required by gpg 1.4's implementation of this code in
|
* Used by:
|
||||||
cardglue.c. */
|
* card-util.c
|
||||||
int
|
*/
|
||||||
agent_scd_setattr (const char *name,
|
gpg_error_t
|
||||||
const unsigned char *value, size_t valuelen,
|
agent_scd_setattr (const char *name, const void *value_arg, size_t valuelen)
|
||||||
const char *serialno)
|
|
||||||
{
|
{
|
||||||
int rc;
|
gpg_error_t err;
|
||||||
|
const unsigned char *value = value_arg;
|
||||||
char line[ASSUAN_LINELENGTH];
|
char line[ASSUAN_LINELENGTH];
|
||||||
char *p;
|
char *p;
|
||||||
struct default_inq_parm_s parm;
|
struct default_inq_parm_s parm;
|
||||||
|
|
||||||
memset (&parm, 0, sizeof parm);
|
memset (&parm, 0, sizeof parm);
|
||||||
|
|
||||||
(void)serialno;
|
|
||||||
|
|
||||||
if (!*name || !valuelen)
|
if (!*name || !valuelen)
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
@ -918,16 +1149,16 @@ agent_scd_setattr (const char *name,
|
|||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
|
||||||
rc = start_agent (NULL, 1);
|
err = start_agent (NULL, 1);
|
||||||
if (!rc)
|
if (!err)
|
||||||
{
|
{
|
||||||
parm.ctx = agent_ctx;
|
parm.ctx = agent_ctx;
|
||||||
rc = assuan_transact (agent_ctx, line, NULL, NULL,
|
err = assuan_transact (agent_ctx, line, NULL, NULL,
|
||||||
default_inq_cb, &parm, NULL, NULL);
|
default_inq_cb, &parm, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_sc_op_failure (rc);
|
status_sc_op_failure (err);
|
||||||
return rc;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -953,7 +1184,10 @@ inq_writecert_parms (void *opaque, const char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Send a WRITECERT command to the SCdaemon. */
|
/* Send a WRITECERT command to the SCdaemon.
|
||||||
|
* Used by:
|
||||||
|
* card-util.c
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
agent_scd_writecert (const char *certidstr,
|
agent_scd_writecert (const char *certidstr,
|
||||||
const unsigned char *certdata, size_t certdatalen)
|
const unsigned char *certdata, size_t certdatalen)
|
||||||
@ -984,60 +1218,6 @@ agent_scd_writecert (const char *certidstr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Handle a KEYDATA inquiry. Note, we only send the data,
|
|
||||||
assuan_transact takes care of flushing and writing the end */
|
|
||||||
static gpg_error_t
|
|
||||||
inq_writekey_parms (void *opaque, const char *line)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
struct writekey_parm_s *parm = opaque;
|
|
||||||
|
|
||||||
if (has_leading_keyword (line, "KEYDATA"))
|
|
||||||
{
|
|
||||||
rc = assuan_send_data (parm->dflt->ctx, parm->keydata, parm->keydatalen);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rc = default_inq_cb (parm->dflt, line);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Send a WRITEKEY command to the SCdaemon. */
|
|
||||||
int
|
|
||||||
agent_scd_writekey (int keyno, const char *serialno,
|
|
||||||
const unsigned char *keydata, size_t keydatalen)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
char line[ASSUAN_LINELENGTH];
|
|
||||||
struct writekey_parm_s parms;
|
|
||||||
struct default_inq_parm_s dfltparm;
|
|
||||||
|
|
||||||
memset (&dfltparm, 0, sizeof dfltparm);
|
|
||||||
|
|
||||||
(void)serialno;
|
|
||||||
|
|
||||||
rc = start_agent (NULL, 1);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
memset (&parms, 0, sizeof parms);
|
|
||||||
|
|
||||||
snprintf (line, DIM(line), "SCD WRITEKEY --force OPENPGP.%d", keyno);
|
|
||||||
dfltparm.ctx = agent_ctx;
|
|
||||||
parms.dflt = &dfltparm;
|
|
||||||
parms.keydata = keydata;
|
|
||||||
parms.keydatalen = keydatalen;
|
|
||||||
|
|
||||||
rc = assuan_transact (agent_ctx, line, NULL, NULL,
|
|
||||||
inq_writekey_parms, &parms, NULL, NULL);
|
|
||||||
|
|
||||||
status_sc_op_failure (rc);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Status callback for the SCD GENKEY command. */
|
/* Status callback for the SCD GENKEY command. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
@ -1065,10 +1245,13 @@ scd_genkey_cb (void *opaque, const char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Send a GENKEY command to the SCdaemon. If *CREATETIME is not 0,
|
/* Send a GENKEY command to the SCdaemon. If *CREATETIME is not 0,
|
||||||
the value will be passed to SCDAEMON with --timestamp option so that
|
* the value will be passed to SCDAEMON with --timestamp option so that
|
||||||
the key is created with this. Otherwise, timestamp was generated by
|
* the key is created with this. Otherwise, timestamp was generated by
|
||||||
SCDEAMON. On success, creation time is stored back to
|
* SCDEAMON. On success, creation time is stored back to
|
||||||
CREATETIME. */
|
* CREATETIME.
|
||||||
|
* Used by:
|
||||||
|
* gen_card_key
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
agent_scd_genkey (int keyno, int force, u32 *createtime)
|
agent_scd_genkey (int keyno, int force, u32 *createtime)
|
||||||
{
|
{
|
||||||
@ -1101,9 +1284,17 @@ agent_scd_genkey (int keyno, int force, u32 *createtime)
|
|||||||
status_sc_op_failure (rc);
|
status_sc_op_failure (rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Return the serial number of the card or an appropriate error. The
|
/* Return the serial number of the card or an appropriate error. The
|
||||||
serial number is returned as a hexstring. */
|
* serial number is returned as a hexstring. With DEMAND the active
|
||||||
|
* card is switched to the card with that serialno.
|
||||||
|
* Used by:
|
||||||
|
* card-util.c
|
||||||
|
* build_sk_list
|
||||||
|
* enum_secret_keys
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
agent_scd_serialno (char **r_serialno, const char *demand)
|
agent_scd_serialno (char **r_serialno, const char *demand)
|
||||||
{
|
{
|
||||||
@ -1111,7 +1302,7 @@ agent_scd_serialno (char **r_serialno, const char *demand)
|
|||||||
char *serialno = NULL;
|
char *serialno = NULL;
|
||||||
char line[ASSUAN_LINELENGTH];
|
char line[ASSUAN_LINELENGTH];
|
||||||
|
|
||||||
err = start_agent (NULL, 1 | FLAG_FOR_CARD_SUPPRESS_ERRORS);
|
err = start_agent (NULL, (1 | FLAG_FOR_CARD_SUPPRESS_ERRORS));
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -1132,8 +1323,13 @@ agent_scd_serialno (char **r_serialno, const char *demand)
|
|||||||
*r_serialno = serialno;
|
*r_serialno = serialno;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Send a READCERT command to the SCdaemon. */
|
/* Send a READCERT command to the SCdaemon.
|
||||||
|
* Used by:
|
||||||
|
* card-util.c
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
agent_scd_readcert (const char *certidstr,
|
agent_scd_readcert (const char *certidstr,
|
||||||
void **r_buf, size_t *r_buflen)
|
void **r_buf, size_t *r_buflen)
|
||||||
@ -1171,6 +1367,51 @@ agent_scd_readcert (const char *certidstr,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This is a variant of agent_readkey which sends a READKEY command
|
||||||
|
* directly Scdaemon. On success a new s-expression is stored at
|
||||||
|
* R_RESULT. */
|
||||||
|
gpg_error_t
|
||||||
|
agent_scd_readkey (const char *keyrefstr, gcry_sexp_t *r_result)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
char line[ASSUAN_LINELENGTH];
|
||||||
|
membuf_t data;
|
||||||
|
unsigned char *buf;
|
||||||
|
size_t len, buflen;
|
||||||
|
struct default_inq_parm_s dfltparm;
|
||||||
|
|
||||||
|
memset (&dfltparm, 0, sizeof dfltparm);
|
||||||
|
dfltparm.ctx = agent_ctx;
|
||||||
|
|
||||||
|
*r_result = NULL;
|
||||||
|
err = start_agent (NULL, 1);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
init_membuf (&data, 1024);
|
||||||
|
snprintf (line, DIM(line), "SCD READKEY %s", keyrefstr);
|
||||||
|
err = assuan_transact (agent_ctx, line,
|
||||||
|
put_membuf_cb, &data,
|
||||||
|
default_inq_cb, &dfltparm,
|
||||||
|
NULL, NULL);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
xfree (get_membuf (&data, &len));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
buf = get_membuf (&data, &buflen);
|
||||||
|
if (!buf)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
err = gcry_sexp_new (r_result, buf, buflen, 0);
|
||||||
|
xfree (buf);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct card_cardlist_parm_s {
|
struct card_cardlist_parm_s {
|
||||||
int error;
|
int error;
|
||||||
@ -1208,7 +1449,12 @@ card_cardlist_cb (void *opaque, const char *line)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return cardlist. */
|
|
||||||
|
/* Return a list of currently available cards.
|
||||||
|
* Used by:
|
||||||
|
* card-util.c
|
||||||
|
* skclist.c
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
agent_scd_cardlist (strlist_t *result)
|
agent_scd_cardlist (strlist_t *result)
|
||||||
{
|
{
|
||||||
@ -1237,16 +1483,20 @@ agent_scd_cardlist (strlist_t *result)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Change the PIN of an OpenPGP card or reset the retry counter.
|
/* Change the PIN of an OpenPGP card or reset the retry counter.
|
||||||
CHVNO 1: Change the PIN
|
* CHVNO 1: Change the PIN
|
||||||
2: For v1 cards: Same as 1.
|
* 2: For v1 cards: Same as 1.
|
||||||
For v2 cards: Reset the PIN using the Reset Code.
|
* For v2 cards: Reset the PIN using the Reset Code.
|
||||||
3: Change the admin PIN
|
* 3: Change the admin PIN
|
||||||
101: Set a new PIN and reset the retry counter
|
* 101: Set a new PIN and reset the retry counter
|
||||||
102: For v1 cars: Same as 101.
|
* 102: For v1 cars: Same as 101.
|
||||||
For v2 cards: Set a new Reset Code.
|
* For v2 cards: Set a new Reset Code.
|
||||||
SERIALNO is not used.
|
* SERIALNO is not used.
|
||||||
|
* Used by:
|
||||||
|
* card-util.c
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
agent_scd_change_pin (int chvno, const char *serialno)
|
agent_scd_change_pin (int chvno, const char *serialno)
|
||||||
@ -1280,8 +1530,11 @@ agent_scd_change_pin (int chvno, const char *serialno)
|
|||||||
|
|
||||||
|
|
||||||
/* Perform a CHECKPIN operation. SERIALNO should be the serial
|
/* Perform a CHECKPIN operation. SERIALNO should be the serial
|
||||||
number of the card - optionally followed by the fingerprint;
|
* number of the card - optionally followed by the fingerprint;
|
||||||
however the fingerprint is ignored here. */
|
* however the fingerprint is ignored here.
|
||||||
|
* Used by:
|
||||||
|
* card-util.c
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
agent_scd_checkpin (const char *serialno)
|
agent_scd_checkpin (const char *serialno)
|
||||||
{
|
{
|
||||||
@ -1306,15 +1559,6 @@ agent_scd_checkpin (const char *serialno)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Dummy function, only used by the gpg 1.4 implementation. */
|
|
||||||
void
|
|
||||||
agent_clear_pin_cache (const char *sn)
|
|
||||||
{
|
|
||||||
(void)sn;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Note: All strings shall be UTF-8. On success the caller needs to
|
/* Note: All strings shall be UTF-8. On success the caller needs to
|
||||||
free the string stored at R_PASSPHRASE. On error NULL will be
|
free the string stored at R_PASSPHRASE. On error NULL will be
|
||||||
@ -2299,6 +2543,31 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Status callback for handling confirmation. */
|
||||||
|
static gpg_error_t
|
||||||
|
confirm_status_cb (void *opaque, const char *line)
|
||||||
|
{
|
||||||
|
struct confirm_parm_s *parm = opaque;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
if ((s = has_leading_keyword (line, "SETDESC")))
|
||||||
|
{
|
||||||
|
xfree (parm->desc);
|
||||||
|
parm->desc = unescape_status_string (s);
|
||||||
|
}
|
||||||
|
else if ((s = has_leading_keyword (line, "SETOK")))
|
||||||
|
{
|
||||||
|
xfree (parm->ok);
|
||||||
|
parm->ok = unescape_status_string (s);
|
||||||
|
}
|
||||||
|
else if ((s = has_leading_keyword (line, "SETNOTOK")))
|
||||||
|
{
|
||||||
|
xfree (parm->notok);
|
||||||
|
parm->notok = unescape_status_string (s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Ask the agent to delete the key identified by HEXKEYGRIP. If DESC
|
/* Ask the agent to delete the key identified by HEXKEYGRIP. If DESC
|
||||||
is not NULL, display DESC instead of the default description
|
is not NULL, display DESC instead of the default description
|
||||||
@ -2311,9 +2580,12 @@ agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
|||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
char line[ASSUAN_LINELENGTH];
|
char line[ASSUAN_LINELENGTH];
|
||||||
struct default_inq_parm_s dfltparm;
|
struct default_inq_parm_s dfltparm;
|
||||||
|
struct confirm_parm_s confirm_parm;
|
||||||
|
|
||||||
|
memset (&confirm_parm, 0, sizeof confirm_parm);
|
||||||
memset (&dfltparm, 0, sizeof dfltparm);
|
memset (&dfltparm, 0, sizeof dfltparm);
|
||||||
dfltparm.ctrl = ctrl;
|
dfltparm.ctrl = ctrl;
|
||||||
|
dfltparm.confirm = &confirm_parm;
|
||||||
|
|
||||||
err = start_agent (ctrl, 0);
|
err = start_agent (ctrl, 0);
|
||||||
if (err)
|
if (err)
|
||||||
@ -2335,7 +2607,10 @@ agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
|||||||
force? " --force":"", hexkeygrip);
|
force? " --force":"", hexkeygrip);
|
||||||
err = assuan_transact (agent_ctx, line, NULL, NULL,
|
err = assuan_transact (agent_ctx, line, NULL, NULL,
|
||||||
default_inq_cb, &dfltparm,
|
default_inq_cb, &dfltparm,
|
||||||
NULL, NULL);
|
confirm_status_cb, &confirm_parm);
|
||||||
|
xfree (confirm_parm.desc);
|
||||||
|
xfree (confirm_parm.ok);
|
||||||
|
xfree (confirm_parm.notok);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +84,10 @@ void agent_release_card_info (struct agent_card_info_s *info);
|
|||||||
/* Return card info. */
|
/* Return card info. */
|
||||||
int agent_scd_learn (struct agent_card_info_s *info, int force);
|
int agent_scd_learn (struct agent_card_info_s *info, int force);
|
||||||
|
|
||||||
|
/* Get the keypariinfo directly from scdaemon. */
|
||||||
|
gpg_error_t agent_scd_keypairinfo (ctrl_t ctrl, const char *keyref,
|
||||||
|
strlist_t *r_list);
|
||||||
|
|
||||||
/* Return list of cards. */
|
/* Return list of cards. */
|
||||||
int agent_scd_cardlist (strlist_t *result);
|
int agent_scd_cardlist (strlist_t *result);
|
||||||
|
|
||||||
@ -93,6 +97,9 @@ int agent_scd_serialno (char **r_serialno, const char *demand);
|
|||||||
/* Send an APDU to the card. */
|
/* Send an APDU to the card. */
|
||||||
gpg_error_t agent_scd_apdu (const char *hexapdu, unsigned int *r_sw);
|
gpg_error_t agent_scd_apdu (const char *hexapdu, unsigned int *r_sw);
|
||||||
|
|
||||||
|
/* Get attribute NAME from the card and store at R_VALUE. */
|
||||||
|
gpg_error_t agent_scd_getattr_one (const char *name, char **r_value);
|
||||||
|
|
||||||
/* Update INFO with the attribute NAME. */
|
/* Update INFO with the attribute NAME. */
|
||||||
int agent_scd_getattr (const char *name, struct agent_card_info_s *info);
|
int agent_scd_getattr (const char *name, struct agent_card_info_s *info);
|
||||||
|
|
||||||
@ -101,35 +108,29 @@ int agent_keytocard (const char *hexgrip, int keyno, int force,
|
|||||||
const char *serialno, const char *timestamp);
|
const char *serialno, const char *timestamp);
|
||||||
|
|
||||||
/* Send a SETATTR command to the SCdaemon. */
|
/* Send a SETATTR command to the SCdaemon. */
|
||||||
int agent_scd_setattr (const char *name,
|
gpg_error_t agent_scd_setattr (const char *name,
|
||||||
const unsigned char *value, size_t valuelen,
|
const void *value, size_t valuelen);
|
||||||
const char *serialno);
|
|
||||||
|
|
||||||
/* Send a WRITECERT command to the SCdaemon. */
|
/* Send a WRITECERT command to the SCdaemon. */
|
||||||
int agent_scd_writecert (const char *certidstr,
|
int agent_scd_writecert (const char *certidstr,
|
||||||
const unsigned char *certdata, size_t certdatalen);
|
const unsigned char *certdata, size_t certdatalen);
|
||||||
|
|
||||||
/* Send a WRITEKEY command to the SCdaemon. */
|
|
||||||
int agent_scd_writekey (int keyno, const char *serialno,
|
|
||||||
const unsigned char *keydata, size_t keydatalen);
|
|
||||||
|
|
||||||
/* Send a GENKEY command to the SCdaemon. */
|
/* Send a GENKEY command to the SCdaemon. */
|
||||||
int agent_scd_genkey (int keyno, int force, u32 *createtime);
|
int agent_scd_genkey (int keyno, int force, u32 *createtime);
|
||||||
|
|
||||||
/* Send a READKEY command to the SCdaemon. */
|
/* Send a READCERT command to the SCdaemon. */
|
||||||
int agent_scd_readcert (const char *certidstr,
|
int agent_scd_readcert (const char *certidstr,
|
||||||
void **r_buf, size_t *r_buflen);
|
void **r_buf, size_t *r_buflen);
|
||||||
|
|
||||||
|
/* Send a READKEY command to the SCdaemon. */
|
||||||
|
gpg_error_t agent_scd_readkey (const char *keyrefstr, gcry_sexp_t *r_result);
|
||||||
|
|
||||||
/* Change the PIN of an OpenPGP card or reset the retry counter. */
|
/* Change the PIN of an OpenPGP card or reset the retry counter. */
|
||||||
int agent_scd_change_pin (int chvno, const char *serialno);
|
int agent_scd_change_pin (int chvno, const char *serialno);
|
||||||
|
|
||||||
/* Send the CHECKPIN command to the SCdaemon. */
|
/* Send the CHECKPIN command to the SCdaemon. */
|
||||||
int agent_scd_checkpin (const char *serialno);
|
int agent_scd_checkpin (const char *serialno);
|
||||||
|
|
||||||
/* Dummy function, only implemented by gpg 1.4. */
|
|
||||||
void agent_clear_pin_cache (const char *sn);
|
|
||||||
|
|
||||||
|
|
||||||
/* Send the GET_PASSPHRASE command to the agent. */
|
/* Send the GET_PASSPHRASE command to the agent. */
|
||||||
gpg_error_t agent_get_passphrase (const char *cache_id,
|
gpg_error_t agent_get_passphrase (const char *cache_id,
|
||||||
const char *err_msg,
|
const char *err_msg,
|
||||||
|
@ -91,8 +91,6 @@ change_pin (int unblock_v2, int allow_admin)
|
|||||||
log_info (_("OpenPGP card no. %s detected\n"),
|
log_info (_("OpenPGP card no. %s detected\n"),
|
||||||
info.serialno? info.serialno : "[none]");
|
info.serialno? info.serialno : "[none]");
|
||||||
|
|
||||||
agent_clear_pin_cache (info.serialno);
|
|
||||||
|
|
||||||
if (opt.batch)
|
if (opt.batch)
|
||||||
{
|
{
|
||||||
agent_release_card_info (&info);
|
agent_release_card_info (&info);
|
||||||
@ -421,36 +419,43 @@ current_card_status (ctrl_t ctrl, estream_t fp,
|
|||||||
if (!info.serialno || strncmp (info.serialno, "D27600012401", 12)
|
if (!info.serialno || strncmp (info.serialno, "D27600012401", 12)
|
||||||
|| strlen (info.serialno) != 32 )
|
|| strlen (info.serialno) != 32 )
|
||||||
{
|
{
|
||||||
|
const char *name1, *name2;
|
||||||
if (info.apptype && !strcmp (info.apptype, "NKS"))
|
if (info.apptype && !strcmp (info.apptype, "NKS"))
|
||||||
{
|
{
|
||||||
if (opt.with_colons)
|
name1 = "netkey";
|
||||||
es_fputs ("netkey-card:\n", fp);
|
name2 = "NetKey";
|
||||||
log_info ("this is a NetKey card\n");
|
|
||||||
}
|
}
|
||||||
else if (info.apptype && !strcmp (info.apptype, "DINSIG"))
|
else if (info.apptype && !strcmp (info.apptype, "DINSIG"))
|
||||||
{
|
{
|
||||||
if (opt.with_colons)
|
name1 = "dinsig";
|
||||||
es_fputs ("dinsig-card:\n", fp);
|
name2 = "DINSIG";
|
||||||
log_info ("this is a DINSIG compliant card\n");
|
|
||||||
}
|
}
|
||||||
else if (info.apptype && !strcmp (info.apptype, "P15"))
|
else if (info.apptype && !strcmp (info.apptype, "P15"))
|
||||||
{
|
{
|
||||||
if (opt.with_colons)
|
name1 = "pkcs15";
|
||||||
es_fputs ("pkcs15-card:\n", fp);
|
name2 = "PKCS#15";
|
||||||
log_info ("this is a PKCS#15 compliant card\n");
|
|
||||||
}
|
}
|
||||||
else if (info.apptype && !strcmp (info.apptype, "GELDKARTE"))
|
else if (info.apptype && !strcmp (info.apptype, "GELDKARTE"))
|
||||||
{
|
{
|
||||||
if (opt.with_colons)
|
name1 = "geldkarte";
|
||||||
es_fputs ("geldkarte-card:\n", fp);
|
name2 = "Geldkarte";
|
||||||
log_info ("this is a Geldkarte compliant card\n");
|
}
|
||||||
|
else if (info.apptype && !strcmp (info.apptype, "PIV"))
|
||||||
|
{
|
||||||
|
name1 = "piv";
|
||||||
|
name2 = "PIV";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (opt.with_colons)
|
name1 = "unknown";
|
||||||
es_fputs ("unknown:\n", fp);
|
name2 = "Unknown";
|
||||||
}
|
}
|
||||||
log_info ("not an OpenPGP card\n");
|
|
||||||
|
if (opt.with_colons)
|
||||||
|
es_fprintf (fp, "%s-card:\n", name1);
|
||||||
|
else
|
||||||
|
tty_fprintf (fp, "Application type .: %s\n", name2);
|
||||||
|
|
||||||
agent_release_card_info (&info);
|
agent_release_card_info (&info);
|
||||||
xfree (pk);
|
xfree (pk);
|
||||||
return;
|
return;
|
||||||
@ -465,6 +470,8 @@ current_card_status (ctrl_t ctrl, estream_t fp,
|
|||||||
|
|
||||||
if (opt.with_colons)
|
if (opt.with_colons)
|
||||||
es_fputs ("openpgp-card:\n", fp);
|
es_fputs ("openpgp-card:\n", fp);
|
||||||
|
else
|
||||||
|
tty_fprintf (fp, "Application type .: %s\n", "OpenPGP");
|
||||||
|
|
||||||
|
|
||||||
if (opt.with_colons)
|
if (opt.with_colons)
|
||||||
@ -673,9 +680,8 @@ current_card_status (ctrl_t ctrl, estream_t fp,
|
|||||||
if ( thefpr && !fpr_is_ff (thefpr, thefprlen)
|
if ( thefpr && !fpr_is_ff (thefpr, thefprlen)
|
||||||
&& !get_pubkey_byfprint (ctrl, pk, &keyblock, thefpr, thefprlen))
|
&& !get_pubkey_byfprint (ctrl, pk, &keyblock, thefpr, thefprlen))
|
||||||
{
|
{
|
||||||
print_pubkey_info (ctrl, fp, pk);
|
print_key_info (ctrl, fp, 0, pk, 0);
|
||||||
if (keyblock)
|
print_card_key_info (fp, keyblock);
|
||||||
print_card_key_info (fp, keyblock);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tty_fprintf (fp, "[none]\n");
|
tty_fprintf (fp, "[none]\n");
|
||||||
@ -697,6 +703,7 @@ card_status (ctrl_t ctrl, estream_t fp, const char *serialno)
|
|||||||
strlist_t card_list, sl;
|
strlist_t card_list, sl;
|
||||||
char *serialno0, *serialno1;
|
char *serialno0, *serialno1;
|
||||||
int all_cards = 0;
|
int all_cards = 0;
|
||||||
|
int any_card = 0;
|
||||||
|
|
||||||
if (serialno == NULL)
|
if (serialno == NULL)
|
||||||
{
|
{
|
||||||
@ -724,6 +731,10 @@ card_status (ctrl_t ctrl, estream_t fp, const char *serialno)
|
|||||||
if (!all_cards && strcmp (serialno, sl->d))
|
if (!all_cards && strcmp (serialno, sl->d))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (any_card && !opt.with_colons)
|
||||||
|
tty_fprintf (fp, "\n");
|
||||||
|
any_card = 1;
|
||||||
|
|
||||||
err = agent_scd_serialno (&serialno1, sl->d);
|
err = agent_scd_serialno (&serialno1, sl->d);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@ -816,7 +827,7 @@ change_name (void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname), NULL );
|
rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname));
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error ("error setting Name: %s\n", gpg_strerror (rc));
|
log_error ("error setting Name: %s\n", gpg_strerror (rc));
|
||||||
|
|
||||||
@ -837,7 +848,7 @@ change_url (void)
|
|||||||
trim_spaces (url);
|
trim_spaces (url);
|
||||||
cpr_kill_prompt ();
|
cpr_kill_prompt ();
|
||||||
|
|
||||||
rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url), NULL );
|
rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url));
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error ("error setting URL: %s\n", gpg_strerror (rc));
|
log_error ("error setting URL: %s\n", gpg_strerror (rc));
|
||||||
xfree (url);
|
xfree (url);
|
||||||
@ -995,7 +1006,7 @@ change_login (const char *args)
|
|||||||
n = strlen (data);
|
n = strlen (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = agent_scd_setattr ("LOGIN-DATA", data, n, NULL );
|
rc = agent_scd_setattr ("LOGIN-DATA", data, n);
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error ("error setting login data: %s\n", gpg_strerror (rc));
|
log_error ("error setting login data: %s\n", gpg_strerror (rc));
|
||||||
xfree (data);
|
xfree (data);
|
||||||
@ -1033,7 +1044,7 @@ change_private_do (const char *args, int nr)
|
|||||||
n = strlen (data);
|
n = strlen (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = agent_scd_setattr (do_name, data, n, NULL );
|
rc = agent_scd_setattr (do_name, data, n);
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error ("error setting private DO: %s\n", gpg_strerror (rc));
|
log_error ("error setting private DO: %s\n", gpg_strerror (rc));
|
||||||
xfree (data);
|
xfree (data);
|
||||||
@ -1132,7 +1143,7 @@ change_lang (void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = agent_scd_setattr ("DISP-LANG", data, strlen (data), NULL );
|
rc = agent_scd_setattr ("DISP-LANG", data, strlen (data));
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error ("error setting lang: %s\n", gpg_strerror (rc));
|
log_error ("error setting lang: %s\n", gpg_strerror (rc));
|
||||||
xfree (data);
|
xfree (data);
|
||||||
@ -1168,7 +1179,7 @@ change_sex (void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = agent_scd_setattr ("DISP-SEX", str, 1, NULL );
|
rc = agent_scd_setattr ("DISP-SEX", str, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error ("error setting salutation: %s\n", gpg_strerror (rc));
|
log_error ("error setting salutation: %s\n", gpg_strerror (rc));
|
||||||
xfree (data);
|
xfree (data);
|
||||||
@ -1216,7 +1227,7 @@ change_cafpr (int fprno)
|
|||||||
|
|
||||||
rc = agent_scd_setattr (fprno==1?"CA-FPR-1":
|
rc = agent_scd_setattr (fprno==1?"CA-FPR-1":
|
||||||
fprno==2?"CA-FPR-2":
|
fprno==2?"CA-FPR-2":
|
||||||
fprno==3?"CA-FPR-3":"x", fpr, fprlen, NULL );
|
fprno==3?"CA-FPR-3":"x", fpr, fprlen);
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error ("error setting cafpr: %s\n", gpg_strerror (rc));
|
log_error ("error setting cafpr: %s\n", gpg_strerror (rc));
|
||||||
write_sc_op_status (rc);
|
write_sc_op_status (rc);
|
||||||
@ -1242,7 +1253,7 @@ toggle_forcesig (void)
|
|||||||
newstate = !info.chv1_cached;
|
newstate = !info.chv1_cached;
|
||||||
agent_release_card_info (&info);
|
agent_release_card_info (&info);
|
||||||
|
|
||||||
rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1, NULL);
|
rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error ("error toggling signature PIN flag: %s\n", gpg_strerror (rc));
|
log_error ("error toggling signature PIN flag: %s\n", gpg_strerror (rc));
|
||||||
write_sc_op_status (rc);
|
write_sc_op_status (rc);
|
||||||
@ -1285,14 +1296,12 @@ check_pin_for_key_operation (struct agent_card_info_s *info, int *forced_chv1)
|
|||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
agent_clear_pin_cache (info->serialno);
|
|
||||||
|
|
||||||
*forced_chv1 = !info->chv1_cached;
|
*forced_chv1 = !info->chv1_cached;
|
||||||
if (*forced_chv1)
|
if (*forced_chv1)
|
||||||
{ /* Switch off the forced mode so that during key generation we
|
{ /* Switch off the forced mode so that during key generation we
|
||||||
don't get bothered with PIN queries for each
|
don't get bothered with PIN queries for each
|
||||||
self-signature. */
|
self-signature. */
|
||||||
rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1, info->serialno);
|
rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_error ("error clearing forced signature PIN flag: %s\n",
|
log_error ("error clearing forced signature PIN flag: %s\n",
|
||||||
@ -1323,7 +1332,7 @@ restore_forced_chv1 (int *forced_chv1)
|
|||||||
|
|
||||||
if (*forced_chv1)
|
if (*forced_chv1)
|
||||||
{ /* Switch back to forced state. */
|
{ /* Switch back to forced state. */
|
||||||
rc = agent_scd_setattr ("CHV-STATUS-1", "", 1, NULL);
|
rc = agent_scd_setattr ("CHV-STATUS-1", "", 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_error ("error setting forced signature PIN flag: %s\n",
|
log_error ("error setting forced signature PIN flag: %s\n",
|
||||||
@ -1570,7 +1579,7 @@ do_change_keyattr (int keyno, const struct key_attr *key_attr)
|
|||||||
return gpg_error (GPG_ERR_PUBKEY_ALGO);
|
return gpg_error (GPG_ERR_PUBKEY_ALGO);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = agent_scd_setattr ("KEY-ATTR", args, strlen (args), NULL);
|
err = agent_scd_setattr ("KEY-ATTR", args, strlen (args));
|
||||||
if (err)
|
if (err)
|
||||||
log_error (_("error changing key attribute for key %d: %s\n"),
|
log_error (_("error changing key attribute for key %d: %s\n"),
|
||||||
keyno+1, gpg_strerror (err));
|
keyno+1, gpg_strerror (err));
|
||||||
@ -2116,8 +2125,7 @@ kdf_setup (const char *args)
|
|||||||
goto leave_error;
|
goto leave_error;
|
||||||
|
|
||||||
err = agent_scd_setattr ("KDF", kdf_data,
|
err = agent_scd_setattr ("KDF", kdf_data,
|
||||||
single ? KDF_DATA_LENGTH_MIN : KDF_DATA_LENGTH_MAX,
|
single ? KDF_DATA_LENGTH_MIN : KDF_DATA_LENGTH_MAX);
|
||||||
NULL);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto leave_error;
|
goto leave_error;
|
||||||
|
|
||||||
@ -2169,7 +2177,7 @@ uif (int arg_number, const char *arg_rest)
|
|||||||
|
|
||||||
data[1] = 0x20;
|
data[1] = 0x20;
|
||||||
|
|
||||||
err = agent_scd_setattr (name, data, 2, NULL);
|
err = agent_scd_setattr (name, data, 2);
|
||||||
if (err)
|
if (err)
|
||||||
log_error (_("error for setup UIF: %s\n"), gpg_strerror (err));
|
log_error (_("error for setup UIF: %s\n"), gpg_strerror (err));
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ progress_cb (void *ctx, const char *what, int printchar,
|
|||||||
|
|
||||||
|
|
||||||
/* Return true if the status message NO may currently be issued. We
|
/* Return true if the status message NO may currently be issued. We
|
||||||
need this to avoid syncronisation problem while auto retrieving a
|
need this to avoid synchronization problem while auto retrieving a
|
||||||
key. There it may happen that a status NODATA is issued for a non
|
key. There it may happen that a status NODATA is issued for a non
|
||||||
available key and the user may falsely interpret this has a missing
|
available key and the user may falsely interpret this has a missing
|
||||||
signature. */
|
signature. */
|
||||||
|
@ -471,6 +471,7 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
|
|||||||
{
|
{
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
estream_t fp;
|
estream_t fp;
|
||||||
|
|
||||||
rc = get_output_file ("", 0, ed->buf, &filename, &fp);
|
rc = get_output_file ("", 0, ed->buf, &filename, &fp);
|
||||||
if (! rc)
|
if (! rc)
|
||||||
{
|
{
|
||||||
@ -492,8 +493,7 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
|
|||||||
filename, gpg_strerror (rc));
|
filename, gpg_strerror (rc));
|
||||||
|
|
||||||
iobuf_close (output);
|
iobuf_close (output);
|
||||||
if (afx)
|
release_armor_context (afx);
|
||||||
release_armor_context (afx);
|
|
||||||
}
|
}
|
||||||
xfree (filename);
|
xfree (filename);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,6 @@ decrypt_message (ctrl_t ctrl, const char *filename)
|
|||||||
armor_filter_context_t *afx = NULL;
|
armor_filter_context_t *afx = NULL;
|
||||||
progress_filter_context_t *pfx;
|
progress_filter_context_t *pfx;
|
||||||
int rc;
|
int rc;
|
||||||
int no_out = 0;
|
|
||||||
|
|
||||||
pfx = new_progress_context ();
|
pfx = new_progress_context ();
|
||||||
|
|
||||||
@ -82,11 +81,13 @@ decrypt_message (ctrl_t ctrl, const char *filename)
|
|||||||
|
|
||||||
if (!opt.outfile)
|
if (!opt.outfile)
|
||||||
{
|
{
|
||||||
no_out = 1;
|
|
||||||
opt.outfile = "-";
|
opt.outfile = "-";
|
||||||
|
opt.flags.dummy_outfile = 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
opt.flags.dummy_outfile = 0;
|
||||||
rc = proc_encryption_packets (ctrl, NULL, fp );
|
rc = proc_encryption_packets (ctrl, NULL, fp );
|
||||||
if (no_out)
|
if (opt.flags.dummy_outfile)
|
||||||
opt.outfile = NULL;
|
opt.outfile = NULL;
|
||||||
|
|
||||||
iobuf_close (fp);
|
iobuf_close (fp);
|
||||||
|
109
g10/delkey.c
109
g10/delkey.c
@ -1,7 +1,7 @@
|
|||||||
/* delkey.c - delete keys
|
/* delkey.c - delete keys
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004,
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004,
|
||||||
* 2005, 2006 Free Software Foundation, Inc.
|
* 2005, 2006 Free Software Foundation, Inc.
|
||||||
* Copyright (C) 2014 Werner Koch
|
* Copyright (C) 2014, 2019 Werner Koch
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -53,13 +53,15 @@ do_delete_key (ctrl_t ctrl, const char *username, int secret, int force,
|
|||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
kbnode_t keyblock = NULL;
|
kbnode_t keyblock = NULL;
|
||||||
kbnode_t node, kbctx;
|
kbnode_t node, kbctx;
|
||||||
|
kbnode_t targetnode;
|
||||||
KEYDB_HANDLE hd;
|
KEYDB_HANDLE hd;
|
||||||
PKT_public_key *pk = NULL;
|
PKT_public_key *pk = NULL;
|
||||||
u32 keyid[2];
|
u32 keyid[2];
|
||||||
int okay=0;
|
int okay=0;
|
||||||
int yes;
|
int yes;
|
||||||
KEYDB_SEARCH_DESC desc;
|
KEYDB_SEARCH_DESC desc;
|
||||||
int exactmatch;
|
int exactmatch; /* True if key was found by fingerprint. */
|
||||||
|
int thiskeyonly; /* 0 = false, 1 = is primary key, 2 = is a subkey. */
|
||||||
|
|
||||||
*r_sec_avail = 0;
|
*r_sec_avail = 0;
|
||||||
|
|
||||||
@ -70,6 +72,7 @@ do_delete_key (ctrl_t ctrl, const char *username, int secret, int force,
|
|||||||
/* Search the userid. */
|
/* Search the userid. */
|
||||||
err = classify_user_id (username, &desc, 1);
|
err = classify_user_id (username, &desc, 1);
|
||||||
exactmatch = (desc.mode == KEYDB_SEARCH_MODE_FPR);
|
exactmatch = (desc.mode == KEYDB_SEARCH_MODE_FPR);
|
||||||
|
thiskeyonly = desc.exact;
|
||||||
if (!err)
|
if (!err)
|
||||||
err = keydb_search (hd, &desc, 1, NULL);
|
err = keydb_search (hd, &desc, 1, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
@ -95,7 +98,35 @@ do_delete_key (ctrl_t ctrl, const char *username, int secret, int force,
|
|||||||
err = gpg_error (GPG_ERR_GENERAL);
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
pk = node->pkt->pkt.public_key;
|
|
||||||
|
/* If an operation only on a subkey is requested, find that subkey
|
||||||
|
* now. */
|
||||||
|
if (thiskeyonly)
|
||||||
|
{
|
||||||
|
kbnode_t tmpnode;
|
||||||
|
|
||||||
|
for (kbctx=NULL; (tmpnode = walk_kbnode (keyblock, &kbctx, 0)); )
|
||||||
|
{
|
||||||
|
if (!(tmpnode->pkt->pkttype == PKT_PUBLIC_KEY
|
||||||
|
|| tmpnode->pkt->pkttype == PKT_PUBLIC_SUBKEY))
|
||||||
|
continue;
|
||||||
|
if (exact_subkey_match_p (&desc, tmpnode))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!tmpnode)
|
||||||
|
{
|
||||||
|
log_error ("Oops; requested subkey not found anymore!\n");
|
||||||
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
/* Set NODE to this specific subkey or primary key. */
|
||||||
|
thiskeyonly = node == tmpnode? 1 : 2;
|
||||||
|
targetnode = tmpnode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
targetnode = node;
|
||||||
|
|
||||||
|
pk = targetnode->pkt->pkt.public_key;
|
||||||
keyid_from_pk (pk, keyid);
|
keyid_from_pk (pk, keyid);
|
||||||
|
|
||||||
if (!secret && !force)
|
if (!secret && !force)
|
||||||
@ -135,11 +166,33 @@ do_delete_key (ctrl_t ctrl, const char *username, int secret, int force,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (secret)
|
print_key_info (ctrl, NULL, 0, pk, secret);
|
||||||
print_seckey_info (ctrl, pk);
|
tty_printf ("\n");
|
||||||
else
|
if (thiskeyonly == 1 && !secret)
|
||||||
print_pubkey_info (ctrl, NULL, pk );
|
{
|
||||||
tty_printf( "\n" );
|
/* We need to delete the entire public key despite the use
|
||||||
|
* of the thiskeyonly request. */
|
||||||
|
tty_printf (_("Note: The public primary key and all its subkeys"
|
||||||
|
" will be deleted.\n"));
|
||||||
|
}
|
||||||
|
else if (thiskeyonly == 2 && !secret)
|
||||||
|
{
|
||||||
|
tty_printf (_("Note: Only the shown public subkey"
|
||||||
|
" will be deleted.\n"));
|
||||||
|
}
|
||||||
|
if (thiskeyonly == 1 && secret)
|
||||||
|
{
|
||||||
|
tty_printf (_("Note: Only the secret part of the shown primary"
|
||||||
|
" key will be deleted.\n"));
|
||||||
|
}
|
||||||
|
else if (thiskeyonly == 2 && secret)
|
||||||
|
{
|
||||||
|
tty_printf (_("Note: Only the secret part of the shown subkey"
|
||||||
|
" will be deleted.\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thiskeyonly)
|
||||||
|
tty_printf ("\n");
|
||||||
|
|
||||||
yes = cpr_get_answer_is_yes
|
yes = cpr_get_answer_is_yes
|
||||||
(secret? "delete_key.secret.okay": "delete_key.okay",
|
(secret? "delete_key.secret.okay": "delete_key.okay",
|
||||||
@ -176,6 +229,9 @@ do_delete_key (ctrl_t ctrl, const char *username, int secret, int force,
|
|||||||
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
|
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (thiskeyonly && targetnode != node)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (agent_probe_secret_key (NULL, node->pkt->pkt.public_key))
|
if (agent_probe_secret_key (NULL, node->pkt->pkt.public_key))
|
||||||
continue; /* No secret key for that public (sub)key. */
|
continue; /* No secret key for that public (sub)key. */
|
||||||
|
|
||||||
@ -188,7 +244,7 @@ do_delete_key (ctrl_t ctrl, const char *username, int secret, int force,
|
|||||||
* pre-caution is that since 2.1 the secret key may also
|
* pre-caution is that since 2.1 the secret key may also
|
||||||
* be used for other protocols and thus deleting it from
|
* be used for other protocols and thus deleting it from
|
||||||
* the gpg would also delete the key for other tools. */
|
* the gpg would also delete the key for other tools. */
|
||||||
if (!err)
|
if (!err && !opt.dry_run)
|
||||||
err = agent_delete_key (NULL, hexgrip, prompt,
|
err = agent_delete_key (NULL, hexgrip, prompt,
|
||||||
opt.answer_yes);
|
opt.answer_yes);
|
||||||
xfree (prompt);
|
xfree (prompt);
|
||||||
@ -217,6 +273,35 @@ do_delete_key (ctrl_t ctrl, const char *username, int secret, int force,
|
|||||||
if (firsterr)
|
if (firsterr)
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
else if (thiskeyonly == 2)
|
||||||
|
{
|
||||||
|
int selected = 0;
|
||||||
|
|
||||||
|
/* Delete the specified public subkey. */
|
||||||
|
for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
|
||||||
|
{
|
||||||
|
if (thiskeyonly && targetnode != node)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
||||||
|
{
|
||||||
|
selected = targetnode == node;
|
||||||
|
if (selected)
|
||||||
|
delete_kbnode (node);
|
||||||
|
}
|
||||||
|
else if (selected && node->pkt->pkttype == PKT_SIGNATURE)
|
||||||
|
delete_kbnode (node);
|
||||||
|
else
|
||||||
|
selected = 0;
|
||||||
|
}
|
||||||
|
commit_kbnode (&keyblock);
|
||||||
|
err = keydb_update_keyblock (ctrl, hd, keyblock);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error (_("update failed: %s\n"), gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
err = keydb_delete_keyblock (hd);
|
err = keydb_delete_keyblock (hd);
|
||||||
@ -232,7 +317,8 @@ do_delete_key (ctrl_t ctrl, const char *username, int secret, int force,
|
|||||||
revalidation_mark(). This makes sense - only deleting keys
|
revalidation_mark(). This makes sense - only deleting keys
|
||||||
that have ownertrust set should trigger this. */
|
that have ownertrust set should trigger this. */
|
||||||
|
|
||||||
if (!secret && pk && clear_ownertrusts (ctrl, pk))
|
if (!secret && pk && !opt.dry_run && thiskeyonly != 2
|
||||||
|
&& clear_ownertrusts (ctrl, pk))
|
||||||
{
|
{
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
log_info (_("ownertrust information cleared\n"));
|
log_info (_("ownertrust information cleared\n"));
|
||||||
@ -245,7 +331,8 @@ do_delete_key (ctrl_t ctrl, const char *username, int secret, int force,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************
|
|
||||||
|
/*
|
||||||
* Delete a public or secret key from a keyring.
|
* Delete a public or secret key from a keyring.
|
||||||
*/
|
*/
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
|
110
g10/exec.c
110
g10/exec.c
@ -77,37 +77,99 @@ set_exec_path(const char *path) { return GPG_ERR_GENERAL; }
|
|||||||
static int
|
static int
|
||||||
w32_system(const char *command)
|
w32_system(const char *command)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_W32CE_SYSTEM
|
if (!strncmp (command, "!ShellExecute ", 14))
|
||||||
#warning Change this code to use common/exechelp.c
|
{
|
||||||
#else
|
SHELLEXECUTEINFOW see;
|
||||||
PROCESS_INFORMATION pi;
|
wchar_t *wname;
|
||||||
STARTUPINFO si;
|
int waitms;
|
||||||
char *string;
|
|
||||||
|
|
||||||
/* We must use a copy of the command as CreateProcess modifies this
|
command = command + 14;
|
||||||
argument. */
|
while (spacep (command))
|
||||||
string=xstrdup(command);
|
command++;
|
||||||
|
waitms = atoi (command);
|
||||||
|
if (waitms < 0)
|
||||||
|
waitms = 0;
|
||||||
|
else if (waitms > 60*1000)
|
||||||
|
waitms = 60000;
|
||||||
|
while (*command && !spacep (command))
|
||||||
|
command++;
|
||||||
|
while (spacep (command))
|
||||||
|
command++;
|
||||||
|
|
||||||
memset(&pi,0,sizeof(pi));
|
wname = utf8_to_wchar (command);
|
||||||
memset(&si,0,sizeof(si));
|
if (!wname)
|
||||||
si.cb=sizeof(si);
|
return -1;
|
||||||
|
|
||||||
if(!CreateProcess(NULL,string,NULL,NULL,FALSE,
|
memset (&see, 0, sizeof see);
|
||||||
DETACHED_PROCESS,
|
see.cbSize = sizeof see;
|
||||||
NULL,NULL,&si,&pi))
|
see.fMask = (SEE_MASK_NOCLOSEPROCESS
|
||||||
return -1;
|
| SEE_MASK_NOASYNC
|
||||||
|
| SEE_MASK_FLAG_NO_UI
|
||||||
|
| SEE_MASK_NO_CONSOLE);
|
||||||
|
see.lpVerb = L"open";
|
||||||
|
see.lpFile = (LPCWSTR)wname;
|
||||||
|
see.nShow = SW_SHOW;
|
||||||
|
|
||||||
/* Wait for the child to exit */
|
if (DBG_EXTPROG)
|
||||||
WaitForSingleObject(pi.hProcess,INFINITE);
|
log_debug ("running ShellExecuteEx(open,'%s')\n", command);
|
||||||
|
if (!ShellExecuteExW (&see))
|
||||||
|
{
|
||||||
|
if (DBG_EXTPROG)
|
||||||
|
log_debug ("ShellExecuteEx failed: rc=%d\n", (int)GetLastError ());
|
||||||
|
xfree (wname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (DBG_EXTPROG)
|
||||||
|
log_debug ("ShellExecuteEx succeeded (hProcess=%p,hInstApp=%d)\n",
|
||||||
|
see.hProcess, (int)see.hInstApp);
|
||||||
|
|
||||||
CloseHandle(pi.hProcess);
|
if (!see.hProcess)
|
||||||
CloseHandle(pi.hThread);
|
{
|
||||||
xfree(string);
|
gnupg_usleep (waitms*1000);
|
||||||
|
if (DBG_EXTPROG)
|
||||||
|
log_debug ("ShellExecuteEx ready (wait=%dms)\n", waitms);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WaitForSingleObject (see.hProcess, INFINITE);
|
||||||
|
if (DBG_EXTPROG)
|
||||||
|
log_debug ("ShellExecuteEx ready\n");
|
||||||
|
}
|
||||||
|
CloseHandle (see.hProcess);
|
||||||
|
|
||||||
|
xfree (wname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *string;
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
STARTUPINFO si;
|
||||||
|
|
||||||
|
/* We must use a copy of the command as CreateProcess modifies
|
||||||
|
* this argument. */
|
||||||
|
string = xstrdup (command);
|
||||||
|
|
||||||
|
memset (&pi, 0, sizeof(pi));
|
||||||
|
memset (&si, 0, sizeof(si));
|
||||||
|
si.cb = sizeof (si);
|
||||||
|
|
||||||
|
if (!CreateProcess (NULL, string, NULL, NULL, FALSE,
|
||||||
|
DETACHED_PROCESS,
|
||||||
|
NULL, NULL, &si, &pi))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Wait for the child to exit */
|
||||||
|
WaitForSingleObject (pi.hProcess, INFINITE);
|
||||||
|
|
||||||
|
CloseHandle (pi.hProcess);
|
||||||
|
CloseHandle (pi.hThread);
|
||||||
|
xfree (string);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif /*_W32*/
|
||||||
|
|
||||||
|
|
||||||
/* Replaces current $PATH */
|
/* Replaces current $PATH */
|
||||||
int
|
int
|
||||||
@ -508,7 +570,7 @@ exec_read(struct exec_info *info)
|
|||||||
if(info->flags.use_temp_files)
|
if(info->flags.use_temp_files)
|
||||||
{
|
{
|
||||||
if(DBG_EXTPROG)
|
if(DBG_EXTPROG)
|
||||||
log_debug("system() command is %s\n",info->command);
|
log_debug ("running command: %s\n",info->command);
|
||||||
|
|
||||||
#if defined (_WIN32)
|
#if defined (_WIN32)
|
||||||
info->progreturn=w32_system(info->command);
|
info->progreturn=w32_system(info->command);
|
||||||
|
15
g10/export.c
15
g10/export.c
@ -436,8 +436,8 @@ new_subkey_list_item (KBNODE node)
|
|||||||
(keyID or fingerprint) and does match the one at NODE. It is
|
(keyID or fingerprint) and does match the one at NODE. It is
|
||||||
assumed that the packet at NODE is either a public or secret
|
assumed that the packet at NODE is either a public or secret
|
||||||
subkey. */
|
subkey. */
|
||||||
static int
|
int
|
||||||
exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
|
exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, kbnode_t node)
|
||||||
{
|
{
|
||||||
u32 kid[2];
|
u32 kid[2];
|
||||||
byte fpr[MAX_FINGERPRINT_LEN];
|
byte fpr[MAX_FINGERPRINT_LEN];
|
||||||
@ -596,7 +596,10 @@ cleartext_secret_key_to_openpgp (gcry_sexp_t s_key, PKT_public_key *pk)
|
|||||||
top_list = gcry_sexp_find_token (s_key, "private-key", 0);
|
top_list = gcry_sexp_find_token (s_key, "private-key", 0);
|
||||||
if (!top_list)
|
if (!top_list)
|
||||||
goto bad_seckey;
|
goto bad_seckey;
|
||||||
if (gcry_sexp_length(top_list) != 2)
|
|
||||||
|
/* ignore all S-expression after the first sublist -- we assume that
|
||||||
|
they are comments or otherwise irrelevant to OpenPGP */
|
||||||
|
if (gcry_sexp_length(top_list) < 2)
|
||||||
goto bad_seckey;
|
goto bad_seckey;
|
||||||
key = gcry_sexp_nth (top_list, 1);
|
key = gcry_sexp_nth (top_list, 1);
|
||||||
if (!key)
|
if (!key)
|
||||||
@ -2171,10 +2174,10 @@ export_ssh_key (ctrl_t ctrl, const char *userid)
|
|||||||
{
|
{
|
||||||
getkey_ctx_t getkeyctx;
|
getkey_ctx_t getkeyctx;
|
||||||
|
|
||||||
err = get_pubkey_byname (ctrl, &getkeyctx, NULL, userid, &keyblock,
|
err = get_pubkey_byname (ctrl, GET_PUBKEY_NO_AKL,
|
||||||
|
&getkeyctx, NULL, userid, &keyblock,
|
||||||
NULL,
|
NULL,
|
||||||
0 /* Only usable keys or given exact. */,
|
0 /* Only usable keys or given exact. */);
|
||||||
1 /* No AKL lookup. */);
|
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
err = getkey_next (ctrl, getkeyctx, NULL, NULL);
|
err = getkey_next (ctrl, getkeyctx, NULL, NULL);
|
||||||
|
379
g10/getkey.c
379
g10/getkey.c
@ -36,6 +36,7 @@
|
|||||||
#include "../common/i18n.h"
|
#include "../common/i18n.h"
|
||||||
#include "keyserver-internal.h"
|
#include "keyserver-internal.h"
|
||||||
#include "call-agent.h"
|
#include "call-agent.h"
|
||||||
|
#include "objcache.h"
|
||||||
#include "../common/host2net.h"
|
#include "../common/host2net.h"
|
||||||
#include "../common/mbox-util.h"
|
#include "../common/mbox-util.h"
|
||||||
#include "../common/status.h"
|
#include "../common/status.h"
|
||||||
@ -112,6 +113,7 @@ static struct
|
|||||||
typedef struct keyid_list
|
typedef struct keyid_list
|
||||||
{
|
{
|
||||||
struct keyid_list *next;
|
struct keyid_list *next;
|
||||||
|
byte fprlen;
|
||||||
char fpr[MAX_FINGERPRINT_LEN];
|
char fpr[MAX_FINGERPRINT_LEN];
|
||||||
u32 keyid[2];
|
u32 keyid[2];
|
||||||
} *keyid_list_t;
|
} *keyid_list_t;
|
||||||
@ -132,15 +134,6 @@ static int pk_cache_disabled;
|
|||||||
#if MAX_UID_CACHE_ENTRIES < 5
|
#if MAX_UID_CACHE_ENTRIES < 5
|
||||||
#error we really need the userid cache
|
#error we really need the userid cache
|
||||||
#endif
|
#endif
|
||||||
typedef struct user_id_db
|
|
||||||
{
|
|
||||||
struct user_id_db *next;
|
|
||||||
keyid_list_t keyids;
|
|
||||||
int len;
|
|
||||||
char name[1];
|
|
||||||
} *user_id_db_t;
|
|
||||||
static user_id_db_t user_id_db;
|
|
||||||
static int uid_cache_entries; /* Number of entries in uid cache. */
|
|
||||||
|
|
||||||
static void merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock);
|
static void merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock);
|
||||||
static int lookup (ctrl_t ctrl, getkey_ctx_t ctx, int want_secret,
|
static int lookup (ctrl_t ctrl, getkey_ctx_t ctx, int want_secret,
|
||||||
@ -262,112 +255,6 @@ user_id_not_found_utf8 (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Return the user ID from the given keyblock.
|
|
||||||
* We use the primary uid flag which has been set by the merge_selfsigs
|
|
||||||
* function. The returned value is only valid as long as the given
|
|
||||||
* keyblock is not changed. */
|
|
||||||
static const char *
|
|
||||||
get_primary_uid (KBNODE keyblock, size_t * uidlen)
|
|
||||||
{
|
|
||||||
KBNODE k;
|
|
||||||
const char *s;
|
|
||||||
|
|
||||||
for (k = keyblock; k; k = k->next)
|
|
||||||
{
|
|
||||||
if (k->pkt->pkttype == PKT_USER_ID
|
|
||||||
&& !k->pkt->pkt.user_id->attrib_data
|
|
||||||
&& k->pkt->pkt.user_id->flags.primary)
|
|
||||||
{
|
|
||||||
*uidlen = k->pkt->pkt.user_id->len;
|
|
||||||
return k->pkt->pkt.user_id->name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s = user_id_not_found_utf8 ();
|
|
||||||
*uidlen = strlen (s);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
release_keyid_list (keyid_list_t k)
|
|
||||||
{
|
|
||||||
while (k)
|
|
||||||
{
|
|
||||||
keyid_list_t k2 = k->next;
|
|
||||||
xfree (k);
|
|
||||||
k = k2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Store the association of keyid and userid
|
|
||||||
* Feed only public keys to this function.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
cache_user_id (KBNODE keyblock)
|
|
||||||
{
|
|
||||||
user_id_db_t r;
|
|
||||||
const char *uid;
|
|
||||||
size_t uidlen;
|
|
||||||
keyid_list_t keyids = NULL;
|
|
||||||
KBNODE k;
|
|
||||||
|
|
||||||
for (k = keyblock; k; k = k->next)
|
|
||||||
{
|
|
||||||
if (k->pkt->pkttype == PKT_PUBLIC_KEY
|
|
||||||
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
|
||||||
{
|
|
||||||
keyid_list_t a = xmalloc_clear (sizeof *a);
|
|
||||||
/* Hmmm: For a long list of keyids it might be an advantage
|
|
||||||
* to append the keys. */
|
|
||||||
fingerprint_from_pk (k->pkt->pkt.public_key, a->fpr, NULL);
|
|
||||||
keyid_from_pk (k->pkt->pkt.public_key, a->keyid);
|
|
||||||
/* First check for duplicates. */
|
|
||||||
for (r = user_id_db; r; r = r->next)
|
|
||||||
{
|
|
||||||
keyid_list_t b;
|
|
||||||
|
|
||||||
for (b = r->keyids; b; b = b->next)
|
|
||||||
{
|
|
||||||
if (!memcmp (b->fpr, a->fpr, MAX_FINGERPRINT_LEN))
|
|
||||||
{
|
|
||||||
if (DBG_CACHE)
|
|
||||||
log_debug ("cache_user_id: already in cache\n");
|
|
||||||
release_keyid_list (keyids);
|
|
||||||
xfree (a);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Now put it into the cache. */
|
|
||||||
a->next = keyids;
|
|
||||||
keyids = a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!keyids)
|
|
||||||
BUG (); /* No key no fun. */
|
|
||||||
|
|
||||||
|
|
||||||
uid = get_primary_uid (keyblock, &uidlen);
|
|
||||||
|
|
||||||
if (uid_cache_entries >= MAX_UID_CACHE_ENTRIES)
|
|
||||||
{
|
|
||||||
/* fixme: use another algorithm to free some cache slots */
|
|
||||||
r = user_id_db;
|
|
||||||
user_id_db = r->next;
|
|
||||||
release_keyid_list (r->keyids);
|
|
||||||
xfree (r);
|
|
||||||
uid_cache_entries--;
|
|
||||||
}
|
|
||||||
r = xmalloc (sizeof *r + uidlen - 1);
|
|
||||||
r->keyids = keyids;
|
|
||||||
r->len = uidlen;
|
|
||||||
memcpy (r->name, uid, r->len);
|
|
||||||
r->next = user_id_db;
|
|
||||||
user_id_db = r;
|
|
||||||
uid_cache_entries++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Disable and drop the public key cache (which is filled by
|
/* Disable and drop the public key cache (which is filled by
|
||||||
cache_public_key and get_pubkey). Note: there is currently no way
|
cache_public_key and get_pubkey). Note: there is currently no way
|
||||||
@ -948,11 +835,21 @@ key_byname (ctrl_t ctrl, GETKEY_CTX *retctx, strlist_t namelist,
|
|||||||
|
|
||||||
/* Find a public key identified by NAME.
|
/* Find a public key identified by NAME.
|
||||||
*
|
*
|
||||||
* If name appears to be a valid RFC822 mailbox (i.e., email
|
* If name appears to be a valid RFC822 mailbox (i.e., email address)
|
||||||
* address) and auto key lookup is enabled (no_akl == 0), then the
|
* and auto key lookup is enabled (mode != GET_PUBKEY_NO_AKL), then
|
||||||
* specified auto key lookup methods (--auto-key-lookup) are used to
|
* the specified auto key lookup methods (--auto-key-lookup) are used
|
||||||
* import the key into the local keyring. Otherwise, just the local
|
* to import the key into the local keyring. Otherwise, just the
|
||||||
* keyring is consulted.
|
* local keyring is consulted.
|
||||||
|
*
|
||||||
|
* MODE can be one of:
|
||||||
|
* GET_PUBKEY_NORMAL - The standard mode
|
||||||
|
* GET_PUBKEY_NO_AKL - The auto key locate functionality is
|
||||||
|
* disabled and only the local key ring is
|
||||||
|
* considered. Note: the local key ring is
|
||||||
|
* consulted even if local is not in the
|
||||||
|
* auto-key-locate option list!
|
||||||
|
* GET_PUBKEY_NO_LOCAL - Only the auto key locate functionaly is
|
||||||
|
* used and no local search is done.
|
||||||
*
|
*
|
||||||
* If RETCTX is not NULL, then the constructed context is returned in
|
* If RETCTX is not NULL, then the constructed context is returned in
|
||||||
* *RETCTX so that getpubkey_next can be used to get subsequent
|
* *RETCTX so that getpubkey_next can be used to get subsequent
|
||||||
@ -988,18 +885,14 @@ key_byname (ctrl_t ctrl, GETKEY_CTX *retctx, strlist_t namelist,
|
|||||||
* documentation for skip_unusable for an exact definition) are
|
* documentation for skip_unusable for an exact definition) are
|
||||||
* skipped unless they are looked up by key id or by fingerprint.
|
* skipped unless they are looked up by key id or by fingerprint.
|
||||||
*
|
*
|
||||||
* If NO_AKL is set, then the auto key locate functionality is
|
|
||||||
* disabled and only the local key ring is considered. Note: the
|
|
||||||
* local key ring is consulted even if local is not in the
|
|
||||||
* --auto-key-locate option list!
|
|
||||||
*
|
|
||||||
* This function returns 0 on success. Otherwise, an error code is
|
* This function returns 0 on success. Otherwise, an error code is
|
||||||
* returned. In particular, GPG_ERR_NO_PUBKEY or GPG_ERR_NO_SECKEY
|
* returned. In particular, GPG_ERR_NO_PUBKEY or GPG_ERR_NO_SECKEY
|
||||||
* (if want_secret is set) is returned if the key is not found. */
|
* (if want_secret is set) is returned if the key is not found. */
|
||||||
int
|
int
|
||||||
get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
|
get_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
||||||
|
GETKEY_CTX * retctx, PKT_public_key * pk,
|
||||||
const char *name, KBNODE * ret_keyblock,
|
const char *name, KBNODE * ret_keyblock,
|
||||||
KEYDB_HANDLE * ret_kdbhd, int include_unusable, int no_akl)
|
KEYDB_HANDLE * ret_kdbhd, int include_unusable)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
strlist_t namelist = NULL;
|
strlist_t namelist = NULL;
|
||||||
@ -1035,7 +928,9 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
|
|||||||
* Note: we only save the search context in RETCTX if the local
|
* Note: we only save the search context in RETCTX if the local
|
||||||
* method is the first method tried (either explicitly or
|
* method is the first method tried (either explicitly or
|
||||||
* implicitly). */
|
* implicitly). */
|
||||||
if (!no_akl)
|
if (mode == GET_PUBKEY_NO_LOCAL)
|
||||||
|
nodefault = 1; /* Auto-key-locate but ignore "local". */
|
||||||
|
else if (mode != GET_PUBKEY_NO_AKL)
|
||||||
{
|
{
|
||||||
/* auto-key-locate is enabled. */
|
/* auto-key-locate is enabled. */
|
||||||
|
|
||||||
@ -1064,7 +959,13 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
|
|||||||
anylocalfirst = 1;
|
anylocalfirst = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodefault && is_mbox)
|
if (mode == GET_PUBKEY_NO_LOCAL)
|
||||||
|
{
|
||||||
|
/* Force using the AKL. If IS_MBOX is not set this is the final
|
||||||
|
* error code. */
|
||||||
|
rc = GPG_ERR_NO_PUBKEY;
|
||||||
|
}
|
||||||
|
else if (nodefault && is_mbox)
|
||||||
{
|
{
|
||||||
/* Either "nodefault" or "local" (explicitly) appeared in the
|
/* Either "nodefault" or "local" (explicitly) appeared in the
|
||||||
* auto key locate list and NAME appears to be an email address.
|
* auto key locate list and NAME appears to be an email address.
|
||||||
@ -1085,7 +986,9 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
|
|||||||
|
|
||||||
/* If the requested name resembles a valid mailbox and automatic
|
/* If the requested name resembles a valid mailbox and automatic
|
||||||
retrieval has been enabled, we try to import the key. */
|
retrieval has been enabled, we try to import the key. */
|
||||||
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && !no_akl && is_mbox)
|
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
|
||||||
|
&& mode != GET_PUBKEY_NO_AKL
|
||||||
|
&& is_mbox)
|
||||||
{
|
{
|
||||||
/* NAME wasn't present in the local keyring (or we didn't try
|
/* NAME wasn't present in the local keyring (or we didn't try
|
||||||
* the local keyring). Since the auto key locate feature is
|
* the local keyring). Since the auto key locate feature is
|
||||||
@ -1104,22 +1007,30 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
|
|||||||
{
|
{
|
||||||
case AKL_NODEFAULT:
|
case AKL_NODEFAULT:
|
||||||
/* This is a dummy mechanism. */
|
/* This is a dummy mechanism. */
|
||||||
mechanism_string = "None";
|
mechanism_string = "";
|
||||||
rc = GPG_ERR_NO_PUBKEY;
|
rc = GPG_ERR_NO_PUBKEY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AKL_LOCAL:
|
case AKL_LOCAL:
|
||||||
mechanism_string = "Local";
|
if (mode == GET_PUBKEY_NO_LOCAL)
|
||||||
did_akl_local = 1;
|
{
|
||||||
if (retctx)
|
mechanism_string = "";
|
||||||
{
|
rc = GPG_ERR_NO_PUBKEY;
|
||||||
getkey_end (ctrl, *retctx);
|
}
|
||||||
*retctx = NULL;
|
else
|
||||||
}
|
{
|
||||||
add_to_strlist (&namelist, name);
|
mechanism_string = "Local";
|
||||||
rc = key_byname (ctrl, anylocalfirst ? retctx : NULL,
|
did_akl_local = 1;
|
||||||
namelist, pk, 0,
|
if (retctx)
|
||||||
include_unusable, ret_keyblock, ret_kdbhd);
|
{
|
||||||
|
getkey_end (ctrl, *retctx);
|
||||||
|
*retctx = NULL;
|
||||||
|
}
|
||||||
|
add_to_strlist (&namelist, name);
|
||||||
|
rc = key_byname (ctrl, anylocalfirst ? retctx : NULL,
|
||||||
|
namelist, pk, 0,
|
||||||
|
include_unusable, ret_keyblock, ret_kdbhd);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AKL_CERT:
|
case AKL_CERT:
|
||||||
@ -1246,15 +1157,14 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
|
|||||||
name, mechanism_string);
|
name, mechanism_string);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY
|
if ((gpg_err_code (rc) != GPG_ERR_NO_PUBKEY
|
||||||
|| opt.verbose || no_fingerprint)
|
|| opt.verbose || no_fingerprint) && *mechanism_string)
|
||||||
log_info (_("error retrieving '%s' via %s: %s\n"),
|
log_info (_("error retrieving '%s' via %s: %s\n"),
|
||||||
name, mechanism_string,
|
name, mechanism_string,
|
||||||
no_fingerprint ? _("No fingerprint") : gpg_strerror (rc));
|
no_fingerprint ? _("No fingerprint") : gpg_strerror (rc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (rc && retctx)
|
if (rc && retctx)
|
||||||
{
|
{
|
||||||
getkey_end (ctrl, *retctx);
|
getkey_end (ctrl, *retctx);
|
||||||
@ -1315,7 +1225,7 @@ subkey_is_ok (const PKT_public_key *sub)
|
|||||||
|
|
||||||
/* Return true if KEYBLOCK has only expired encryption subkyes. Note
|
/* Return true if KEYBLOCK has only expired encryption subkyes. Note
|
||||||
* that the function returns false if the key has no encryption
|
* that the function returns false if the key has no encryption
|
||||||
* subkeys at all or the subkecys are revoked. */
|
* subkeys at all or the subkeys are revoked. */
|
||||||
static int
|
static int
|
||||||
only_expired_enc_subkeys (kbnode_t keyblock)
|
only_expired_enc_subkeys (kbnode_t keyblock)
|
||||||
{
|
{
|
||||||
@ -1407,7 +1317,8 @@ pubkey_cmp (ctrl_t ctrl, const char *name, struct pubkey_cmp_cookie *old,
|
|||||||
* resembles a mail address, the results are ranked and only the best
|
* resembles a mail address, the results are ranked and only the best
|
||||||
* result is returned. */
|
* result is returned. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk,
|
get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
||||||
|
GETKEY_CTX *retctx, PKT_public_key *pk,
|
||||||
const char *name, KBNODE *ret_keyblock,
|
const char *name, KBNODE *ret_keyblock,
|
||||||
int include_unusable)
|
int include_unusable)
|
||||||
{
|
{
|
||||||
@ -1430,8 +1341,9 @@ get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk,
|
|||||||
getkey_end (ctrl, ctx);
|
getkey_end (ctrl, ctx);
|
||||||
ctx = NULL;
|
ctx = NULL;
|
||||||
}
|
}
|
||||||
err = get_pubkey_byname (ctrl, &ctx, pk, name, ret_keyblock,
|
err = get_pubkey_byname (ctrl, mode,
|
||||||
NULL, include_unusable, 0);
|
&ctx, pk, name, ret_keyblock,
|
||||||
|
NULL, include_unusable);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
getkey_end (ctrl, ctx);
|
getkey_end (ctrl, ctx);
|
||||||
@ -1493,15 +1405,14 @@ get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk,
|
|||||||
/* Old key is better. */
|
/* Old key is better. */
|
||||||
release_public_key_parts (&new.key);
|
release_public_key_parts (&new.key);
|
||||||
free_user_id (new.uid);
|
free_user_id (new.uid);
|
||||||
new.uid = NULL;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* A tie. Keep the old key. */
|
/* A tie. Keep the old key. */
|
||||||
release_public_key_parts (&new.key);
|
release_public_key_parts (&new.key);
|
||||||
free_user_id (new.uid);
|
free_user_id (new.uid);
|
||||||
new.uid = NULL;
|
|
||||||
}
|
}
|
||||||
|
new.uid = NULL;
|
||||||
}
|
}
|
||||||
getkey_end (ctrl, ctx);
|
getkey_end (ctrl, ctx);
|
||||||
ctx = NULL;
|
ctx = NULL;
|
||||||
@ -1637,7 +1548,7 @@ get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname)
|
|||||||
*
|
*
|
||||||
* FPRINT is a byte array whose contents is the fingerprint to use as
|
* FPRINT is a byte array whose contents is the fingerprint to use as
|
||||||
* the search term. FPRINT_LEN specifies the length of the
|
* the search term. FPRINT_LEN specifies the length of the
|
||||||
* fingerprint (in bytes). Currently, only 16 and 20-byte
|
* fingerprint (in bytes). Currently, only 16, 20, and 32-byte
|
||||||
* fingerprints are supported.
|
* fingerprints are supported.
|
||||||
*
|
*
|
||||||
* FIXME: We should replace this with the _byname function. This can
|
* FIXME: We should replace this with the _byname function. This can
|
||||||
@ -3291,7 +3202,11 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
|
|||||||
memcpy (&pk->revoked, &rinfo, sizeof (rinfo));
|
memcpy (&pk->revoked, &rinfo, sizeof (rinfo));
|
||||||
}
|
}
|
||||||
if (main_pk->has_expired)
|
if (main_pk->has_expired)
|
||||||
pk->has_expired = main_pk->has_expired;
|
{
|
||||||
|
pk->has_expired = main_pk->has_expired;
|
||||||
|
if (!pk->expiredate || pk->expiredate > main_pk->expiredate)
|
||||||
|
pk->expiredate = main_pk->expiredate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -3623,7 +3538,7 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
|
|||||||
xfree (tempkeystr);
|
xfree (tempkeystr);
|
||||||
}
|
}
|
||||||
|
|
||||||
cache_user_id (keyblock);
|
cache_put_keyblock (keyblock);
|
||||||
|
|
||||||
return latest_key ? latest_key : keyblock; /* Found. */
|
return latest_key ? latest_key : keyblock; /* Found. */
|
||||||
}
|
}
|
||||||
@ -3836,67 +3751,40 @@ get_seckey_default_or_card (ctrl_t ctrl, PKT_public_key *pk,
|
|||||||
* this string must be freed by xfree. If R_NOUID is not NULL it is
|
* this string must be freed by xfree. If R_NOUID is not NULL it is
|
||||||
* set to true if a user id was not found; otherwise to false. */
|
* set to true if a user id was not found; otherwise to false. */
|
||||||
static char *
|
static char *
|
||||||
get_user_id_string (ctrl_t ctrl, u32 * keyid, int mode, size_t *r_len,
|
get_user_id_string (ctrl_t ctrl, u32 * keyid, int mode)
|
||||||
int *r_nouid)
|
|
||||||
{
|
{
|
||||||
user_id_db_t r;
|
char *name;
|
||||||
keyid_list_t a;
|
unsigned int namelen;
|
||||||
int pass = 0;
|
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if (r_nouid)
|
log_assert (mode != 2);
|
||||||
*r_nouid = 0;
|
|
||||||
|
|
||||||
/* Try it two times; second pass reads from the database. */
|
name = cache_get_uid_bykid (keyid, &namelen);
|
||||||
do
|
if (!name)
|
||||||
{
|
{
|
||||||
for (r = user_id_db; r; r = r->next)
|
/* Get it so that the cache will be filled. */
|
||||||
{
|
if (!get_pubkey (ctrl, NULL, keyid))
|
||||||
for (a = r->keyids; a; a = a->next)
|
name = cache_get_uid_bykid (keyid, &namelen);
|
||||||
{
|
|
||||||
if (a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1])
|
|
||||||
{
|
|
||||||
if (mode == 2)
|
|
||||||
{
|
|
||||||
/* An empty string as user id is possible. Make
|
|
||||||
sure that the malloc allocates one byte and
|
|
||||||
does not bail out. */
|
|
||||||
p = xmalloc (r->len? r->len : 1);
|
|
||||||
memcpy (p, r->name, r->len);
|
|
||||||
if (r_len)
|
|
||||||
*r_len = r->len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (mode)
|
|
||||||
p = xasprintf ("%08lX%08lX %.*s",
|
|
||||||
(ulong) keyid[0], (ulong) keyid[1],
|
|
||||||
r->len, r->name);
|
|
||||||
else
|
|
||||||
p = xasprintf ("%s %.*s", keystr (keyid),
|
|
||||||
r->len, r->name);
|
|
||||||
if (r_len)
|
|
||||||
*r_len = strlen (p);
|
|
||||||
}
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
while (++pass < 2 && !get_pubkey (ctrl, NULL, keyid));
|
|
||||||
|
|
||||||
if (mode == 2)
|
if (name)
|
||||||
p = xstrdup (user_id_not_found_utf8 ());
|
{
|
||||||
else if (mode)
|
if (mode)
|
||||||
p = xasprintf ("%08lX%08lX [?]", (ulong) keyid[0], (ulong) keyid[1]);
|
p = xasprintf ("%08lX%08lX %.*s",
|
||||||
|
(ulong) keyid[0], (ulong) keyid[1], namelen, name);
|
||||||
|
else
|
||||||
|
p = xasprintf ("%s %.*s", keystr (keyid), namelen, name);
|
||||||
|
|
||||||
|
xfree (name);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
p = xasprintf ("%s [?]", keystr (keyid));
|
{
|
||||||
|
if (mode)
|
||||||
|
p = xasprintf ("%08lX%08lX [?]", (ulong) keyid[0], (ulong) keyid[1]);
|
||||||
|
else
|
||||||
|
p = xasprintf ("%s [?]", keystr (keyid));
|
||||||
|
}
|
||||||
|
|
||||||
if (r_nouid)
|
|
||||||
*r_nouid = 1;
|
|
||||||
if (r_len)
|
|
||||||
*r_len = strlen (p);
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3904,7 +3792,7 @@ get_user_id_string (ctrl_t ctrl, u32 * keyid, int mode, size_t *r_len,
|
|||||||
char *
|
char *
|
||||||
get_user_id_string_native (ctrl_t ctrl, u32 * keyid)
|
get_user_id_string_native (ctrl_t ctrl, u32 * keyid)
|
||||||
{
|
{
|
||||||
char *p = get_user_id_string (ctrl, keyid, 0, NULL, NULL);
|
char *p = get_user_id_string (ctrl, keyid, 0);
|
||||||
char *p2 = utf8_to_native (p, strlen (p), 0);
|
char *p2 = utf8_to_native (p, strlen (p), 0);
|
||||||
xfree (p);
|
xfree (p);
|
||||||
return p2;
|
return p2;
|
||||||
@ -3914,7 +3802,7 @@ get_user_id_string_native (ctrl_t ctrl, u32 * keyid)
|
|||||||
char *
|
char *
|
||||||
get_long_user_id_string (ctrl_t ctrl, u32 * keyid)
|
get_long_user_id_string (ctrl_t ctrl, u32 * keyid)
|
||||||
{
|
{
|
||||||
return get_user_id_string (ctrl, keyid, 1, NULL, NULL);
|
return get_user_id_string (ctrl, keyid, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3922,7 +3810,31 @@ get_long_user_id_string (ctrl_t ctrl, u32 * keyid)
|
|||||||
char *
|
char *
|
||||||
get_user_id (ctrl_t ctrl, u32 *keyid, size_t *rn, int *r_nouid)
|
get_user_id (ctrl_t ctrl, u32 *keyid, size_t *rn, int *r_nouid)
|
||||||
{
|
{
|
||||||
return get_user_id_string (ctrl, keyid, 2, rn, r_nouid);
|
char *name;
|
||||||
|
unsigned int namelen;
|
||||||
|
|
||||||
|
if (r_nouid)
|
||||||
|
*r_nouid = 0;
|
||||||
|
|
||||||
|
name = cache_get_uid_bykid (keyid, &namelen);
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
/* Get it so that the cache will be filled. */
|
||||||
|
if (!get_pubkey (ctrl, NULL, keyid))
|
||||||
|
name = cache_get_uid_bykid (keyid, &namelen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
name = xstrdup (user_id_not_found_utf8 ());
|
||||||
|
namelen = strlen (name);
|
||||||
|
if (r_nouid)
|
||||||
|
*r_nouid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rn && name)
|
||||||
|
*rn = namelen;
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3943,49 +3855,36 @@ get_user_id_native (ctrl_t ctrl, u32 *keyid)
|
|||||||
returned string, which must be freed using xfree, may not be NUL
|
returned string, which must be freed using xfree, may not be NUL
|
||||||
terminated. To determine the length of the string, you must use
|
terminated. To determine the length of the string, you must use
|
||||||
*RN. */
|
*RN. */
|
||||||
char *
|
static char *
|
||||||
get_user_id_byfpr (ctrl_t ctrl, const byte *fpr, size_t *rn)
|
get_user_id_byfpr (ctrl_t ctrl, const byte *fpr, size_t fprlen, size_t *rn)
|
||||||
{
|
{
|
||||||
user_id_db_t r;
|
char *name;
|
||||||
char *p;
|
|
||||||
int pass = 0;
|
|
||||||
|
|
||||||
/* Try it two times; second pass reads from the database. */
|
name = cache_get_uid_byfpr (fpr, fprlen, rn);
|
||||||
do
|
if (!name)
|
||||||
{
|
{
|
||||||
for (r = user_id_db; r; r = r->next)
|
/* Get it so that the cache will be filled. */
|
||||||
{
|
if (!get_pubkey_byfprint (ctrl, NULL, NULL, fpr, fprlen))
|
||||||
keyid_list_t a;
|
name = cache_get_uid_byfpr (fpr, fprlen, rn);
|
||||||
for (a = r->keyids; a; a = a->next)
|
|
||||||
{
|
|
||||||
if (!memcmp (a->fpr, fpr, MAX_FINGERPRINT_LEN))
|
|
||||||
{
|
|
||||||
/* An empty string as user id is possible. Make
|
|
||||||
sure that the malloc allocates one byte and does
|
|
||||||
not bail out. */
|
|
||||||
p = xmalloc (r->len? r->len : 1);
|
|
||||||
memcpy (p, r->name, r->len);
|
|
||||||
*rn = r->len;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
while (++pass < 2
|
|
||||||
&& !get_pubkey_byfprint (ctrl, NULL, NULL, fpr, MAX_FINGERPRINT_LEN));
|
if (!name)
|
||||||
p = xstrdup (user_id_not_found_utf8 ());
|
{
|
||||||
*rn = strlen (p);
|
name = xstrdup (user_id_not_found_utf8 ());
|
||||||
return p;
|
*rn = strlen (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Like get_user_id_byfpr, but convert the string to the native
|
/* Like get_user_id_byfpr, but convert the string to the native
|
||||||
encoding. The returned string needs to be freed. Unlike
|
encoding. The returned string needs to be freed. Unlike
|
||||||
get_user_id_byfpr, the returned string is NUL terminated. */
|
get_user_id_byfpr, the returned string is NUL terminated. */
|
||||||
char *
|
char *
|
||||||
get_user_id_byfpr_native (ctrl_t ctrl, const byte *fpr)
|
get_user_id_byfpr_native (ctrl_t ctrl, const byte *fpr, size_t fprlen)
|
||||||
{
|
{
|
||||||
size_t rn;
|
size_t rn;
|
||||||
char *p = get_user_id_byfpr (ctrl, fpr, &rn);
|
char *p = get_user_id_byfpr (ctrl, fpr, fprlen, &rn);
|
||||||
char *p2 = utf8_to_native (p, rn, 0);
|
char *p2 = utf8_to_native (p, rn, 0);
|
||||||
xfree (p);
|
xfree (p);
|
||||||
return p2;
|
return p2;
|
||||||
|
15
g10/gpg.c
15
g10/gpg.c
@ -59,6 +59,7 @@
|
|||||||
#include "../common/asshelp.h"
|
#include "../common/asshelp.h"
|
||||||
#include "call-dirmngr.h"
|
#include "call-dirmngr.h"
|
||||||
#include "tofu.h"
|
#include "tofu.h"
|
||||||
|
#include "objcache.h"
|
||||||
#include "../common/init.h"
|
#include "../common/init.h"
|
||||||
#include "../common/mbox-util.h"
|
#include "../common/mbox-util.h"
|
||||||
#include "../common/shareddefs.h"
|
#include "../common/shareddefs.h"
|
||||||
@ -148,6 +149,7 @@ enum cmd_and_opt_values
|
|||||||
aSendKeys,
|
aSendKeys,
|
||||||
aRecvKeys,
|
aRecvKeys,
|
||||||
aLocateKeys,
|
aLocateKeys,
|
||||||
|
aLocateExtKeys,
|
||||||
aSearchKeys,
|
aSearchKeys,
|
||||||
aRefreshKeys,
|
aRefreshKeys,
|
||||||
aFetchKeys,
|
aFetchKeys,
|
||||||
@ -502,6 +504,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
ARGPARSE_c (aRefreshKeys, "refresh-keys",
|
ARGPARSE_c (aRefreshKeys, "refresh-keys",
|
||||||
N_("update all keys from a keyserver")),
|
N_("update all keys from a keyserver")),
|
||||||
ARGPARSE_c (aLocateKeys, "locate-keys", "@"),
|
ARGPARSE_c (aLocateKeys, "locate-keys", "@"),
|
||||||
|
ARGPARSE_c (aLocateExtKeys, "locate-external-keys", "@"),
|
||||||
ARGPARSE_c (aFetchKeys, "fetch-keys" , "@" ),
|
ARGPARSE_c (aFetchKeys, "fetch-keys" , "@" ),
|
||||||
ARGPARSE_c (aShowKeys, "show-keys" , "@" ),
|
ARGPARSE_c (aShowKeys, "show-keys" , "@" ),
|
||||||
ARGPARSE_c (aExportSecret, "export-secret-keys" , "@" ),
|
ARGPARSE_c (aExportSecret, "export-secret-keys" , "@" ),
|
||||||
@ -2421,7 +2424,9 @@ main (int argc, char **argv)
|
|||||||
opt.import_options = IMPORT_REPAIR_KEYS;
|
opt.import_options = IMPORT_REPAIR_KEYS;
|
||||||
opt.export_options = EXPORT_ATTRIBUTES;
|
opt.export_options = EXPORT_ATTRIBUTES;
|
||||||
opt.keyserver_options.import_options = (IMPORT_REPAIR_KEYS
|
opt.keyserver_options.import_options = (IMPORT_REPAIR_KEYS
|
||||||
| IMPORT_REPAIR_PKS_SUBKEY_BUG);
|
| IMPORT_REPAIR_PKS_SUBKEY_BUG
|
||||||
|
| IMPORT_SELF_SIGS_ONLY
|
||||||
|
| IMPORT_CLEAN);
|
||||||
opt.keyserver_options.export_options = EXPORT_ATTRIBUTES;
|
opt.keyserver_options.export_options = EXPORT_ATTRIBUTES;
|
||||||
opt.keyserver_options.options = KEYSERVER_HONOR_PKA_RECORD;
|
opt.keyserver_options.options = KEYSERVER_HONOR_PKA_RECORD;
|
||||||
opt.verify_options = (LIST_SHOW_UID_VALIDITY
|
opt.verify_options = (LIST_SHOW_UID_VALIDITY
|
||||||
@ -2611,6 +2616,7 @@ main (int argc, char **argv)
|
|||||||
#endif /* ENABLE_CARD_SUPPORT*/
|
#endif /* ENABLE_CARD_SUPPORT*/
|
||||||
case aListKeys:
|
case aListKeys:
|
||||||
case aLocateKeys:
|
case aLocateKeys:
|
||||||
|
case aLocateExtKeys:
|
||||||
case aListSigs:
|
case aListSigs:
|
||||||
case aExportSecret:
|
case aExportSecret:
|
||||||
case aExportSecretSub:
|
case aExportSecretSub:
|
||||||
@ -4511,7 +4517,7 @@ main (int argc, char **argv)
|
|||||||
sl = NULL;
|
sl = NULL;
|
||||||
for( ; argc; argc--, argv++ )
|
for( ; argc; argc--, argv++ )
|
||||||
add_to_strlist2( &sl, *argv, utf8_strings );
|
add_to_strlist2( &sl, *argv, utf8_strings );
|
||||||
public_key_list (ctrl, sl, 0);
|
public_key_list (ctrl, sl, 0, 0);
|
||||||
free_strlist(sl);
|
free_strlist(sl);
|
||||||
break;
|
break;
|
||||||
case aListSecretKeys:
|
case aListSecretKeys:
|
||||||
@ -4522,10 +4528,11 @@ main (int argc, char **argv)
|
|||||||
free_strlist(sl);
|
free_strlist(sl);
|
||||||
break;
|
break;
|
||||||
case aLocateKeys:
|
case aLocateKeys:
|
||||||
|
case aLocateExtKeys:
|
||||||
sl = NULL;
|
sl = NULL;
|
||||||
for (; argc; argc--, argv++)
|
for (; argc; argc--, argv++)
|
||||||
add_to_strlist2( &sl, *argv, utf8_strings );
|
add_to_strlist2( &sl, *argv, utf8_strings );
|
||||||
public_key_list (ctrl, sl, 1);
|
public_key_list (ctrl, sl, 1, cmd == aLocateExtKeys);
|
||||||
free_strlist (sl);
|
free_strlist (sl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -5223,12 +5230,14 @@ g10_exit( int rc )
|
|||||||
{
|
{
|
||||||
keydb_dump_stats ();
|
keydb_dump_stats ();
|
||||||
sig_check_dump_stats ();
|
sig_check_dump_stats ();
|
||||||
|
objcache_dump_stats ();
|
||||||
gcry_control (GCRYCTL_DUMP_MEMORY_STATS);
|
gcry_control (GCRYCTL_DUMP_MEMORY_STATS);
|
||||||
gcry_control (GCRYCTL_DUMP_RANDOM_STATS);
|
gcry_control (GCRYCTL_DUMP_RANDOM_STATS);
|
||||||
}
|
}
|
||||||
if (opt.debug)
|
if (opt.debug)
|
||||||
gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
|
gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
|
||||||
|
|
||||||
|
gnupg_block_all_signals ();
|
||||||
emergency_cleanup ();
|
emergency_cleanup ();
|
||||||
|
|
||||||
rc = rc? rc : log_get_errorcount(0)? 2 : g10_errors_seen? 1 : 0;
|
rc = rc? rc : log_get_errorcount(0)? 2 : g10_errors_seen? 1 : 0;
|
||||||
|
@ -1200,7 +1200,8 @@ sig_revocation_key (const char *option, int argc, char *argv[], void *cookie)
|
|||||||
option, argv[0]);
|
option, argv[0]);
|
||||||
|
|
||||||
pk.req_usage = PUBKEY_USAGE_SIG;
|
pk.req_usage = PUBKEY_USAGE_SIG;
|
||||||
err = get_pubkey_byname (NULL, NULL, &pk, argv[1], NULL, NULL, 1, 1);
|
err = get_pubkey_byname (NULL, GET_PUBKEY_NO_AKL,
|
||||||
|
NULL, &pk, argv[1], NULL, NULL, 1);
|
||||||
if (err)
|
if (err)
|
||||||
log_fatal ("looking up key %s: %s\n", argv[1], gpg_strerror (err));
|
log_fatal ("looking up key %s: %s\n", argv[1], gpg_strerror (err));
|
||||||
|
|
||||||
@ -1799,12 +1800,19 @@ signature (const char *option, int argc, char *argv[], void *cookie)
|
|||||||
keyid_copy (si.issuer_pk->keyid, pk_keyid (pripk));
|
keyid_copy (si.issuer_pk->keyid, pk_keyid (pripk));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The reuse of core gpg stuff by this tool is questionable when it
|
||||||
|
* requires adding extra code to the actual gpg code. It does not
|
||||||
|
* make sense to pass an extra parameter and in particular not given
|
||||||
|
* that gpg already has opt.cert_digest_algo to override it. */
|
||||||
|
if (si.digest_algo)
|
||||||
|
log_info ("note: digest algo can't be passed to make_keysig_packet\n");
|
||||||
|
|
||||||
/* Changing the issuer's key id is fragile. Check to make sure
|
/* Changing the issuer's key id is fragile. Check to make sure
|
||||||
make_keysig_packet didn't recompute the keyid. */
|
make_keysig_packet didn't recompute the keyid. */
|
||||||
keyid_copy (keyid, si.issuer_pk->keyid);
|
keyid_copy (keyid, si.issuer_pk->keyid);
|
||||||
err = make_keysig_packet (global_ctrl,
|
err = make_keysig_packet (global_ctrl,
|
||||||
&sig, si.pk, si.uid, si.sk, si.issuer_pk,
|
&sig, si.pk, si.uid, si.sk, si.issuer_pk,
|
||||||
si.class, si.digest_algo,
|
si.class,
|
||||||
si.timestamp, si.expiration,
|
si.timestamp, si.expiration,
|
||||||
mksubpkt_callback, &si, NULL);
|
mksubpkt_callback, &si, NULL);
|
||||||
log_assert (keyid_cmp (keyid, si.issuer_pk->keyid) == 0);
|
log_assert (keyid_cmp (keyid, si.issuer_pk->keyid) == 0);
|
||||||
@ -2450,7 +2458,8 @@ pk_esk (const char *option, int argc, char *argv[], void *cookie)
|
|||||||
|
|
||||||
memset (&pk, 0, sizeof (pk));
|
memset (&pk, 0, sizeof (pk));
|
||||||
pk.req_usage = PUBKEY_USAGE_ENC;
|
pk.req_usage = PUBKEY_USAGE_ENC;
|
||||||
err = get_pubkey_byname (NULL, NULL, &pk, pi.keyid, NULL, NULL, 1, 1);
|
err = get_pubkey_byname (NULL, GET_PUBKEY_NO_AKL,
|
||||||
|
NULL, &pk, pi.keyid, NULL, NULL, 1);
|
||||||
if (err)
|
if (err)
|
||||||
log_fatal ("%s: looking up key %s: %s\n",
|
log_fatal ("%s: looking up key %s: %s\n",
|
||||||
option, pi.keyid, gpg_strerror (err));
|
option, pi.keyid, gpg_strerror (err));
|
||||||
|
254
g10/import.c
254
g10/import.c
@ -102,7 +102,7 @@ static int import (ctrl_t ctrl,
|
|||||||
unsigned char **fpr, size_t *fpr_len, unsigned int options,
|
unsigned char **fpr, size_t *fpr_len, unsigned int options,
|
||||||
import_screener_t screener, void *screener_arg,
|
import_screener_t screener, void *screener_arg,
|
||||||
int origin, const char *url);
|
int origin, const char *url);
|
||||||
static int read_block (IOBUF a, int with_meta,
|
static int read_block (IOBUF a, unsigned int options,
|
||||||
PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys);
|
PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys);
|
||||||
static void revocation_present (ctrl_t ctrl, kbnode_t keyblock);
|
static void revocation_present (ctrl_t ctrl, kbnode_t keyblock);
|
||||||
static gpg_error_t import_one (ctrl_t ctrl,
|
static gpg_error_t import_one (ctrl_t ctrl,
|
||||||
@ -129,6 +129,7 @@ static int delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock,
|
|||||||
u32 *keyid, unsigned int options);
|
u32 *keyid, unsigned int options);
|
||||||
static int any_uid_left (kbnode_t keyblock);
|
static int any_uid_left (kbnode_t keyblock);
|
||||||
static int remove_all_uids (kbnode_t *keyblock);
|
static int remove_all_uids (kbnode_t *keyblock);
|
||||||
|
static void remove_all_non_self_sigs (kbnode_t *keyblock, u32 *keyid);
|
||||||
static int merge_blocks (ctrl_t ctrl, unsigned int options,
|
static int merge_blocks (ctrl_t ctrl, unsigned int options,
|
||||||
kbnode_t keyblock_orig,
|
kbnode_t keyblock_orig,
|
||||||
kbnode_t keyblock, u32 *keyid,
|
kbnode_t keyblock, u32 *keyid,
|
||||||
@ -190,7 +191,10 @@ parse_import_options(char *str,unsigned int *options,int noisy)
|
|||||||
N_("remove as much as possible from key after import")},
|
N_("remove as much as possible from key after import")},
|
||||||
|
|
||||||
{"import-drop-uids", IMPORT_DROP_UIDS, NULL,
|
{"import-drop-uids", IMPORT_DROP_UIDS, NULL,
|
||||||
N_("Do not import user id or attribute packets")},
|
N_("do not import user id or attribute packets")},
|
||||||
|
|
||||||
|
{"self-sigs-only", IMPORT_SELF_SIGS_ONLY, NULL,
|
||||||
|
N_("ignore key-signatures which are not self-signatures")},
|
||||||
|
|
||||||
{"import-export", IMPORT_EXPORT, NULL,
|
{"import-export", IMPORT_EXPORT, NULL,
|
||||||
N_("run import filters and export key immediately")},
|
N_("run import filters and export key immediately")},
|
||||||
@ -589,8 +593,7 @@ import (ctrl_t ctrl, IOBUF inp, const char* fname,struct import_stats_s *stats,
|
|||||||
release_armor_context (afx);
|
release_armor_context (afx);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!(rc = read_block (inp, !!(options & IMPORT_RESTORE),
|
while (!(rc = read_block (inp, options, &pending_pkt, &keyblock, &v3keys)))
|
||||||
&pending_pkt, &keyblock, &v3keys)))
|
|
||||||
{
|
{
|
||||||
stats->v3keys += v3keys;
|
stats->v3keys += v3keys;
|
||||||
if (keyblock->pkt->pkttype == PKT_PUBLIC_KEY)
|
if (keyblock->pkt->pkttype == PKT_PUBLIC_KEY)
|
||||||
@ -669,6 +672,18 @@ import (ctrl_t ctrl, IOBUF inp, const char* fname,struct import_stats_s *stats,
|
|||||||
|
|
||||||
if (!(++stats->count % 100) && !opt.quiet)
|
if (!(++stats->count % 100) && !opt.quiet)
|
||||||
log_info (_("%lu keys processed so far\n"), stats->count );
|
log_info (_("%lu keys processed so far\n"), stats->count );
|
||||||
|
|
||||||
|
if (origin == KEYORG_WKD && stats->count >= 5)
|
||||||
|
{
|
||||||
|
/* We limit the number of keys _received_ from the WKD to 5.
|
||||||
|
* In fact there should be only one key but some sites want
|
||||||
|
* to store a few expired keys there also. gpg's key
|
||||||
|
* selection will later figure out which key to use. Note
|
||||||
|
* that for WKD we always return the fingerprint of the
|
||||||
|
* first imported key. */
|
||||||
|
log_info ("import from WKD stopped after %d keys\n", 5);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stats->v3keys += v3keys;
|
stats->v3keys += v3keys;
|
||||||
if (rc == -1)
|
if (rc == -1)
|
||||||
@ -677,6 +692,13 @@ import (ctrl_t ctrl, IOBUF inp, const char* fname,struct import_stats_s *stats,
|
|||||||
log_error (_("error reading '%s': %s\n"), fname, gpg_strerror (rc));
|
log_error (_("error reading '%s': %s\n"), fname, gpg_strerror (rc));
|
||||||
|
|
||||||
release_kbnode (secattic);
|
release_kbnode (secattic);
|
||||||
|
|
||||||
|
/* When read_block loop was stopped by error, we have PENDING_PKT left. */
|
||||||
|
if (pending_pkt)
|
||||||
|
{
|
||||||
|
free_packet (pending_pkt, NULL);
|
||||||
|
xfree (pending_pkt);
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -826,31 +848,39 @@ valid_keyblock_packet (int pkttype)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************
|
/* Read the next keyblock from stream A. Meta data (ring trust
|
||||||
* Read the next keyblock from stream A.
|
* packets) are only considered if OPTIONS has the IMPORT_RESTORE flag
|
||||||
* Meta data (ring trust packets) are only considered of WITH_META is set.
|
* set. PENDING_PKT should be initialized to NULL and not changed by
|
||||||
* PENDING_PKT should be initialized to NULL and not changed by the caller.
|
* the caller.
|
||||||
* Return: 0 = okay, -1 no more blocks or another errorcode.
|
*
|
||||||
* The int at R_V3KEY counts the number of unsupported v3
|
* Returns 0 for okay, -1 no more blocks, or any other errorcode. The
|
||||||
* keyblocks.
|
* integer at R_V3KEY counts the number of unsupported v3 keyblocks.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
read_block( IOBUF a, int with_meta,
|
read_block( IOBUF a, unsigned int options,
|
||||||
PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
|
PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct parse_packet_ctx_s parsectx;
|
struct parse_packet_ctx_s parsectx;
|
||||||
PACKET *pkt;
|
PACKET *pkt;
|
||||||
kbnode_t root = NULL;
|
kbnode_t root = NULL;
|
||||||
|
kbnode_t lastnode = NULL;
|
||||||
int in_cert, in_v3key, skip_sigs;
|
int in_cert, in_v3key, skip_sigs;
|
||||||
|
u32 keyid[2];
|
||||||
|
int got_keyid = 0;
|
||||||
|
unsigned int dropped_nonselfsigs = 0;
|
||||||
|
|
||||||
*r_v3keys = 0;
|
*r_v3keys = 0;
|
||||||
|
|
||||||
if (*pending_pkt)
|
if (*pending_pkt)
|
||||||
{
|
{
|
||||||
root = new_kbnode( *pending_pkt );
|
root = lastnode = new_kbnode( *pending_pkt );
|
||||||
*pending_pkt = NULL;
|
*pending_pkt = NULL;
|
||||||
|
log_assert (root->pkt->pkttype == PKT_PUBLIC_KEY
|
||||||
|
|| root->pkt->pkttype == PKT_SECRET_KEY);
|
||||||
in_cert = 1;
|
in_cert = 1;
|
||||||
|
keyid_from_pk (root->pkt->pkt.public_key, keyid);
|
||||||
|
got_keyid = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
in_cert = 0;
|
in_cert = 0;
|
||||||
@ -858,7 +888,7 @@ read_block( IOBUF a, int with_meta,
|
|||||||
pkt = xmalloc (sizeof *pkt);
|
pkt = xmalloc (sizeof *pkt);
|
||||||
init_packet (pkt);
|
init_packet (pkt);
|
||||||
init_parse_packet (&parsectx, a);
|
init_parse_packet (&parsectx, a);
|
||||||
if (!with_meta)
|
if (!(options & IMPORT_RESTORE))
|
||||||
parsectx.skip_meta = 1;
|
parsectx.skip_meta = 1;
|
||||||
in_v3key = 0;
|
in_v3key = 0;
|
||||||
skip_sigs = 0;
|
skip_sigs = 0;
|
||||||
@ -965,24 +995,59 @@ read_block( IOBUF a, int with_meta,
|
|||||||
init_packet(pkt);
|
init_packet(pkt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PKT_SIGNATURE:
|
||||||
|
if (!in_cert)
|
||||||
|
goto x_default;
|
||||||
|
if (!(options & IMPORT_SELF_SIGS_ONLY))
|
||||||
|
goto x_default;
|
||||||
|
log_assert (got_keyid);
|
||||||
|
if (pkt->pkt.signature->keyid[0] == keyid[0]
|
||||||
|
&& pkt->pkt.signature->keyid[1] == keyid[1])
|
||||||
|
{ /* This is likely a self-signature. We import this one.
|
||||||
|
* Eventually we should use the ISSUER_FPR to compare
|
||||||
|
* self-signatures, but that will work only for v5 keys
|
||||||
|
* which are currently not even deployed.
|
||||||
|
* Note that we do not do any crypto verify here because
|
||||||
|
* that would defeat this very mitigation of DoS by
|
||||||
|
* importing a key with a huge amount of faked
|
||||||
|
* key-signatures. A verification will be done later in
|
||||||
|
* the processing anyway. Here we want a cheap an early
|
||||||
|
* way to drop non-self-signatures. */
|
||||||
|
goto x_default;
|
||||||
|
}
|
||||||
|
/* Skip this signature. */
|
||||||
|
dropped_nonselfsigs++;
|
||||||
|
free_packet (pkt, &parsectx);
|
||||||
|
init_packet(pkt);
|
||||||
|
break;
|
||||||
|
|
||||||
case PKT_PUBLIC_KEY:
|
case PKT_PUBLIC_KEY:
|
||||||
case PKT_SECRET_KEY:
|
case PKT_SECRET_KEY:
|
||||||
if (in_cert ) /* Store this packet. */
|
if (!got_keyid)
|
||||||
|
{
|
||||||
|
keyid_from_pk (pkt->pkt.public_key, keyid);
|
||||||
|
got_keyid = 1;
|
||||||
|
}
|
||||||
|
if (in_cert) /* Store this packet. */
|
||||||
{
|
{
|
||||||
*pending_pkt = pkt;
|
*pending_pkt = pkt;
|
||||||
pkt = NULL;
|
pkt = NULL;
|
||||||
goto ready;
|
goto ready;
|
||||||
}
|
}
|
||||||
in_cert = 1;
|
in_cert = 1;
|
||||||
/* fall through */
|
goto x_default;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
x_default:
|
x_default:
|
||||||
if (in_cert && valid_keyblock_packet (pkt->pkttype))
|
if (in_cert && valid_keyblock_packet (pkt->pkttype))
|
||||||
{
|
{
|
||||||
if (!root )
|
if (!root )
|
||||||
root = new_kbnode (pkt);
|
root = lastnode = new_kbnode (pkt);
|
||||||
else
|
else
|
||||||
add_kbnode (root, new_kbnode (pkt));
|
{
|
||||||
|
lastnode->next = new_kbnode (pkt);
|
||||||
|
lastnode = lastnode->next;
|
||||||
|
}
|
||||||
pkt = xmalloc (sizeof *pkt);
|
pkt = xmalloc (sizeof *pkt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1003,6 +1068,10 @@ read_block( IOBUF a, int with_meta,
|
|||||||
free_packet (pkt, &parsectx);
|
free_packet (pkt, &parsectx);
|
||||||
deinit_parse_packet (&parsectx);
|
deinit_parse_packet (&parsectx);
|
||||||
xfree( pkt );
|
xfree( pkt );
|
||||||
|
if (!rc && dropped_nonselfsigs && opt.verbose)
|
||||||
|
log_info ("key %s: number of dropped non-self-signatures: %u\n",
|
||||||
|
keystr (keyid), dropped_nonselfsigs);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1729,12 +1798,12 @@ update_key_origin (kbnode_t keyblock, u32 curtime, int origin, const char *url)
|
|||||||
* has valid parts.
|
* has valid parts.
|
||||||
*/
|
*/
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
import_one (ctrl_t ctrl,
|
import_one_real (ctrl_t ctrl,
|
||||||
kbnode_t keyblock, struct import_stats_s *stats,
|
kbnode_t keyblock, struct import_stats_s *stats,
|
||||||
unsigned char **fpr, size_t *fpr_len, unsigned int options,
|
unsigned char **fpr, size_t *fpr_len, unsigned int options,
|
||||||
int from_sk, int silent,
|
int from_sk, int silent,
|
||||||
import_screener_t screener, void *screener_arg,
|
import_screener_t screener, void *screener_arg,
|
||||||
int origin, const char *url, int *r_valid)
|
int origin, const char *url, int *r_valid)
|
||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
PKT_public_key *pk;
|
PKT_public_key *pk;
|
||||||
@ -1817,6 +1886,13 @@ import_one (ctrl_t ctrl,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove all non-self-sigs if requested. Noe that this is a NOP if
|
||||||
|
* that option has been globally set but we may also be called
|
||||||
|
* latter with the already parsed keyblock and a locally changed
|
||||||
|
* option. This is why we need to remove them here as well. */
|
||||||
|
if ((options & IMPORT_SELF_SIGS_ONLY))
|
||||||
|
remove_all_non_self_sigs (&keyblock, keyid);
|
||||||
|
|
||||||
/* Remove or collapse the user ids. */
|
/* Remove or collapse the user ids. */
|
||||||
if ((options & IMPORT_DROP_UIDS))
|
if ((options & IMPORT_DROP_UIDS))
|
||||||
remove_all_uids (&keyblock);
|
remove_all_uids (&keyblock);
|
||||||
@ -2026,22 +2102,25 @@ import_one (ctrl_t ctrl,
|
|||||||
hd = NULL;
|
hd = NULL;
|
||||||
|
|
||||||
/* We are ready. */
|
/* We are ready. */
|
||||||
if (!opt.quiet && !silent)
|
if (!err && !opt.quiet && !silent)
|
||||||
{
|
{
|
||||||
char *p = get_user_id_byfpr_native (ctrl, fpr2);
|
char *p = get_user_id_byfpr_native (ctrl, fpr2, fpr2len);
|
||||||
log_info (_("key %s: public key \"%s\" imported\n"),
|
log_info (_("key %s: public key \"%s\" imported\n"),
|
||||||
keystr(keyid), p);
|
keystr(keyid), p);
|
||||||
xfree(p);
|
xfree(p);
|
||||||
}
|
}
|
||||||
if (is_status_enabled())
|
if (!err && is_status_enabled())
|
||||||
{
|
{
|
||||||
char *us = get_long_user_id_string (ctrl, keyid);
|
char *us = get_long_user_id_string (ctrl, keyid);
|
||||||
write_status_text( STATUS_IMPORTED, us );
|
write_status_text( STATUS_IMPORTED, us );
|
||||||
xfree(us);
|
xfree(us);
|
||||||
print_import_ok (pk, 1);
|
print_import_ok (pk, 1);
|
||||||
}
|
}
|
||||||
stats->imported++;
|
if (!err)
|
||||||
new_key = 1;
|
{
|
||||||
|
stats->imported++;
|
||||||
|
new_key = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else /* Key already exists - merge. */
|
else /* Key already exists - merge. */
|
||||||
{
|
{
|
||||||
@ -2111,10 +2190,12 @@ import_one (ctrl_t ctrl,
|
|||||||
keydb_release (hd);
|
keydb_release (hd);
|
||||||
hd = NULL;
|
hd = NULL;
|
||||||
|
|
||||||
/* We are ready. */
|
/* We are ready. Print and update stats if we got no error.
|
||||||
if (!opt.quiet && !silent)
|
* An error here comes from writing the keyblock and thus
|
||||||
|
* very likely means that no update happened. */
|
||||||
|
if (!err && !opt.quiet && !silent)
|
||||||
{
|
{
|
||||||
char *p = get_user_id_byfpr_native (ctrl, fpr2);
|
char *p = get_user_id_byfpr_native (ctrl, fpr2, fpr2len);
|
||||||
if (n_uids == 1 )
|
if (n_uids == 1 )
|
||||||
log_info( _("key %s: \"%s\" 1 new user ID\n"),
|
log_info( _("key %s: \"%s\" 1 new user ID\n"),
|
||||||
keystr(keyid),p);
|
keystr(keyid),p);
|
||||||
@ -2148,14 +2229,17 @@ import_one (ctrl_t ctrl,
|
|||||||
xfree(p);
|
xfree(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
stats->n_uids +=n_uids;
|
if (!err)
|
||||||
stats->n_sigs +=n_sigs;
|
{
|
||||||
stats->n_subk +=n_subk;
|
stats->n_uids +=n_uids;
|
||||||
stats->n_sigs_cleaned +=n_sigs_cleaned;
|
stats->n_sigs +=n_sigs;
|
||||||
stats->n_uids_cleaned +=n_uids_cleaned;
|
stats->n_subk +=n_subk;
|
||||||
|
stats->n_sigs_cleaned +=n_sigs_cleaned;
|
||||||
|
stats->n_uids_cleaned +=n_uids_cleaned;
|
||||||
|
|
||||||
if (is_status_enabled () && !silent)
|
if (is_status_enabled () && !silent)
|
||||||
print_import_ok (pk, ((n_uids?2:0)|(n_sigs?4:0)|(n_subk?8:0)));
|
print_import_ok (pk, ((n_uids?2:0)|(n_sigs?4:0)|(n_subk?8:0)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2175,7 +2259,7 @@ import_one (ctrl_t ctrl,
|
|||||||
|
|
||||||
if (!opt.quiet && !silent)
|
if (!opt.quiet && !silent)
|
||||||
{
|
{
|
||||||
char *p = get_user_id_byfpr_native (ctrl, fpr2);
|
char *p = get_user_id_byfpr_native (ctrl, fpr2, fpr2len);
|
||||||
log_info( _("key %s: \"%s\" not changed\n"),keystr(keyid),p);
|
log_info( _("key %s: \"%s\" not changed\n"),keystr(keyid),p);
|
||||||
xfree(p);
|
xfree(p);
|
||||||
}
|
}
|
||||||
@ -2203,14 +2287,19 @@ import_one (ctrl_t ctrl,
|
|||||||
fingerprint of the key in all cases. */
|
fingerprint of the key in all cases. */
|
||||||
if (fpr)
|
if (fpr)
|
||||||
{
|
{
|
||||||
xfree (*fpr);
|
|
||||||
/* Note that we need to compare against 0 here because
|
/* Note that we need to compare against 0 here because
|
||||||
COUNT gets only incremented after returning from this
|
COUNT gets only incremented after returning from this
|
||||||
function. */
|
function. */
|
||||||
if (!stats->count)
|
if (!stats->count)
|
||||||
*fpr = fingerprint_from_pk (pk, NULL, fpr_len);
|
{
|
||||||
else
|
xfree (*fpr);
|
||||||
*fpr = NULL;
|
*fpr = fingerprint_from_pk (pk, NULL, fpr_len);
|
||||||
|
}
|
||||||
|
else if (origin != KEYORG_WKD)
|
||||||
|
{
|
||||||
|
xfree (*fpr);
|
||||||
|
*fpr = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2237,6 +2326,41 @@ import_one (ctrl_t ctrl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Wrapper around import_one_real to retry the import in some cases. */
|
||||||
|
static gpg_error_t
|
||||||
|
import_one (ctrl_t ctrl,
|
||||||
|
kbnode_t keyblock, struct import_stats_s *stats,
|
||||||
|
unsigned char **fpr, size_t *fpr_len, unsigned int options,
|
||||||
|
int from_sk, int silent,
|
||||||
|
import_screener_t screener, void *screener_arg,
|
||||||
|
int origin, const char *url, int *r_valid)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
|
||||||
|
err = import_one_real (ctrl, keyblock, stats, fpr, fpr_len, options,
|
||||||
|
from_sk, silent, screener, screener_arg,
|
||||||
|
origin, url, r_valid);
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_TOO_LARGE
|
||||||
|
&& gpg_err_source (err) == GPG_ERR_SOURCE_KEYBOX
|
||||||
|
&& ((options & (IMPORT_SELF_SIGS_ONLY | IMPORT_CLEAN))
|
||||||
|
!= (IMPORT_SELF_SIGS_ONLY | IMPORT_CLEAN)))
|
||||||
|
{
|
||||||
|
/* We hit the maximum image length. Ask the wrapper to do
|
||||||
|
* everything again but this time with some extra options. */
|
||||||
|
u32 keyid[2];
|
||||||
|
|
||||||
|
keyid_from_pk (keyblock->pkt->pkt.public_key, keyid);
|
||||||
|
log_info ("key %s: keyblock too large, retrying with self-sigs-only\n",
|
||||||
|
keystr (keyid));
|
||||||
|
options |= IMPORT_SELF_SIGS_ONLY | IMPORT_CLEAN;
|
||||||
|
err = import_one_real (ctrl, keyblock, stats, fpr, fpr_len, options,
|
||||||
|
from_sk, silent, screener, screener_arg,
|
||||||
|
origin, url, r_valid);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Transfer all the secret keys in SEC_KEYBLOCK to the gpg-agent. The
|
/* Transfer all the secret keys in SEC_KEYBLOCK to the gpg-agent. The
|
||||||
* function prints diagnostics and returns an error code. If BATCH is
|
* function prints diagnostics and returns an error code. If BATCH is
|
||||||
* true the secret keys are stored by gpg-agent in the transfer format
|
* true the secret keys are stored by gpg-agent in the transfer format
|
||||||
@ -2544,6 +2668,7 @@ sec_to_pub_keyblock (kbnode_t sec_keyblock)
|
|||||||
kbnode_t pub_keyblock = NULL;
|
kbnode_t pub_keyblock = NULL;
|
||||||
kbnode_t ctx = NULL;
|
kbnode_t ctx = NULL;
|
||||||
kbnode_t secnode, pubnode;
|
kbnode_t secnode, pubnode;
|
||||||
|
kbnode_t lastnode = NULL;
|
||||||
unsigned int tag = 0;
|
unsigned int tag = 0;
|
||||||
|
|
||||||
/* Set a tag to all nodes. */
|
/* Set a tag to all nodes. */
|
||||||
@ -2583,9 +2708,12 @@ sec_to_pub_keyblock (kbnode_t sec_keyblock)
|
|||||||
pubnode->tag = secnode->tag;
|
pubnode->tag = secnode->tag;
|
||||||
|
|
||||||
if (!pub_keyblock)
|
if (!pub_keyblock)
|
||||||
pub_keyblock = pubnode;
|
pub_keyblock = lastnode = pubnode;
|
||||||
else
|
else
|
||||||
add_kbnode (pub_keyblock, pubnode);
|
{
|
||||||
|
lastnode->next = pubnode;
|
||||||
|
lastnode = pubnode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pub_keyblock;
|
return pub_keyblock;
|
||||||
@ -2915,7 +3043,7 @@ import_secret_one (ctrl_t ctrl, kbnode_t keyblock,
|
|||||||
/* The secret keyblock may not have nodes which are deleted in
|
/* The secret keyblock may not have nodes which are deleted in
|
||||||
* the public keyblock. Otherwise we would import just the
|
* the public keyblock. Otherwise we would import just the
|
||||||
* secret key without having the public key. That would be
|
* secret key without having the public key. That would be
|
||||||
* surprising and clutters out private-keys-v1.d. */
|
* surprising and clutters our private-keys-v1.d. */
|
||||||
err = resync_sec_with_pub_keyblock (&keyblock, pub_keyblock, &attic);
|
err = resync_sec_with_pub_keyblock (&keyblock, pub_keyblock, &attic);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -3764,6 +3892,38 @@ remove_all_uids (kbnode_t *keyblock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Delete all non-self-sigs from KEYBLOCK.
|
||||||
|
* Returns: True if the keyblock has changed. */
|
||||||
|
static void
|
||||||
|
remove_all_non_self_sigs (kbnode_t *keyblock, u32 *keyid)
|
||||||
|
{
|
||||||
|
kbnode_t node;
|
||||||
|
unsigned int dropped = 0;
|
||||||
|
|
||||||
|
for (node = *keyblock; node; node = node->next)
|
||||||
|
{
|
||||||
|
if (is_deleted_kbnode (node))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (node->pkt->pkttype != PKT_SIGNATURE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (node->pkt->pkt.signature->keyid[0] == keyid[0]
|
||||||
|
&& node->pkt->pkt.signature->keyid[1] == keyid[1])
|
||||||
|
continue;
|
||||||
|
delete_kbnode (node);
|
||||||
|
dropped++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dropped)
|
||||||
|
commit_kbnode (keyblock);
|
||||||
|
|
||||||
|
if (dropped && opt.verbose)
|
||||||
|
log_info ("key %s: number of dropped non-self-signatures: %u\n",
|
||||||
|
keystr (keyid), dropped);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It may happen that the imported keyblock has duplicated user IDs.
|
* It may happen that the imported keyblock has duplicated user IDs.
|
||||||
* We check this here and collapse those user IDs together with their
|
* We check this here and collapse those user IDs together with their
|
||||||
|
15
g10/keydb.c
15
g10/keydb.c
@ -1,6 +1,6 @@
|
|||||||
/* keydb.c - key database dispatcher
|
/* keydb.c - key database dispatcher
|
||||||
* Copyright (C) 2001-2013 Free Software Foundation, Inc.
|
* Copyright (C) 2001-2013 Free Software Foundation, Inc.
|
||||||
* Coyrright (C) 2001-2015 Werner Koch
|
* Copyright (C) 2001-2015 Werner Koch
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -1076,7 +1076,7 @@ lock_all (KEYDB_HANDLE hd)
|
|||||||
rc = keyring_lock (hd->active[i].u.kr, 1);
|
rc = keyring_lock (hd->active[i].u.kr, 1);
|
||||||
break;
|
break;
|
||||||
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
||||||
rc = keybox_lock (hd->active[i].u.kb, 1);
|
rc = keybox_lock (hd->active[i].u.kb, 1, -1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1094,7 +1094,7 @@ lock_all (KEYDB_HANDLE hd)
|
|||||||
keyring_lock (hd->active[i].u.kr, 0);
|
keyring_lock (hd->active[i].u.kr, 0);
|
||||||
break;
|
break;
|
||||||
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
||||||
keybox_lock (hd->active[i].u.kb, 0);
|
keybox_lock (hd->active[i].u.kb, 0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1127,7 +1127,7 @@ unlock_all (KEYDB_HANDLE hd)
|
|||||||
keyring_lock (hd->active[i].u.kr, 0);
|
keyring_lock (hd->active[i].u.kr, 0);
|
||||||
break;
|
break;
|
||||||
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
case KEYDB_RESOURCE_TYPE_KEYBOX:
|
||||||
keybox_lock (hd->active[i].u.kb, 0);
|
keybox_lock (hd->active[i].u.kb, 0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1242,8 +1242,15 @@ parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no,
|
|||||||
}
|
}
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
|
es_fflush (es_stdout);
|
||||||
log_error ("parse_keyblock_image: read error: %s\n",
|
log_error ("parse_keyblock_image: read error: %s\n",
|
||||||
gpg_strerror (err));
|
gpg_strerror (err));
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_INV_PACKET)
|
||||||
|
{
|
||||||
|
free_packet (pkt, &parsectx);
|
||||||
|
init_packet (pkt);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
err = gpg_error (GPG_ERR_INV_KEYRING);
|
err = gpg_error (GPG_ERR_INV_KEYRING);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
18
g10/keydb.h
18
g10/keydb.h
@ -345,16 +345,25 @@ typedef struct pubkey_s *pubkey_t;
|
|||||||
/* Free a list of public keys. */
|
/* Free a list of public keys. */
|
||||||
void pubkeys_free (pubkey_t keys);
|
void pubkeys_free (pubkey_t keys);
|
||||||
|
|
||||||
|
|
||||||
|
/* Mode flags for get_pubkey_byname. */
|
||||||
|
enum get_pubkey_modes
|
||||||
|
{
|
||||||
|
GET_PUBKEY_NORMAL = 0,
|
||||||
|
GET_PUBKEY_NO_AKL = 1,
|
||||||
|
GET_PUBKEY_NO_LOCAL = 2
|
||||||
|
};
|
||||||
|
|
||||||
/* Find a public key identified by NAME. */
|
/* Find a public key identified by NAME. */
|
||||||
int get_pubkey_byname (ctrl_t ctrl,
|
int get_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
||||||
GETKEY_CTX *retctx, PKT_public_key *pk,
|
GETKEY_CTX *retctx, PKT_public_key *pk,
|
||||||
const char *name,
|
const char *name,
|
||||||
KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd,
|
KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd,
|
||||||
int include_unusable, int no_akl );
|
int include_unusable);
|
||||||
|
|
||||||
/* Likewise, but only return the best match if NAME resembles a mail
|
/* Likewise, but only return the best match if NAME resembles a mail
|
||||||
* address. */
|
* address. */
|
||||||
gpg_error_t get_best_pubkey_byname (ctrl_t ctrl,
|
gpg_error_t get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
||||||
GETKEY_CTX *retctx, PKT_public_key *pk,
|
GETKEY_CTX *retctx, PKT_public_key *pk,
|
||||||
const char *name, KBNODE *ret_keyblock,
|
const char *name, KBNODE *ret_keyblock,
|
||||||
int include_unusable);
|
int include_unusable);
|
||||||
@ -436,8 +445,7 @@ char *get_user_id_string_native (ctrl_t ctrl, u32 *keyid);
|
|||||||
char *get_long_user_id_string (ctrl_t ctrl, u32 *keyid);
|
char *get_long_user_id_string (ctrl_t ctrl, u32 *keyid);
|
||||||
char *get_user_id (ctrl_t ctrl, u32 *keyid, size_t *rn, int *r_nouid);
|
char *get_user_id (ctrl_t ctrl, u32 *keyid, size_t *rn, int *r_nouid);
|
||||||
char *get_user_id_native (ctrl_t ctrl, u32 *keyid);
|
char *get_user_id_native (ctrl_t ctrl, u32 *keyid);
|
||||||
char *get_user_id_byfpr (ctrl_t ctrl, const byte *fpr, size_t *rn);
|
char *get_user_id_byfpr_native (ctrl_t ctrl, const byte *fpr, size_t fprlen);
|
||||||
char *get_user_id_byfpr_native (ctrl_t ctrl, const byte *fpr);
|
|
||||||
|
|
||||||
void release_akl(void);
|
void release_akl(void);
|
||||||
int parse_auto_key_locate(const char *options);
|
int parse_auto_key_locate(const char *options);
|
||||||
|
@ -1012,7 +1012,8 @@ sign_uids (ctrl_t ctrl, estream_t fp,
|
|||||||
node->pkt->pkt.user_id,
|
node->pkt->pkt.user_id,
|
||||||
NULL,
|
NULL,
|
||||||
pk,
|
pk,
|
||||||
0x13, 0, 0, 0,
|
0x13,
|
||||||
|
0, 0,
|
||||||
keygen_add_std_prefs, primary_pk,
|
keygen_add_std_prefs, primary_pk,
|
||||||
NULL);
|
NULL);
|
||||||
else
|
else
|
||||||
@ -1020,7 +1021,7 @@ sign_uids (ctrl_t ctrl, estream_t fp,
|
|||||||
node->pkt->pkt.user_id,
|
node->pkt->pkt.user_id,
|
||||||
NULL,
|
NULL,
|
||||||
pk,
|
pk,
|
||||||
class, 0,
|
class,
|
||||||
timestamp, duration,
|
timestamp, duration,
|
||||||
sign_mk_attrib, &attrib,
|
sign_mk_attrib, &attrib,
|
||||||
NULL);
|
NULL);
|
||||||
@ -1437,7 +1438,8 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Get the public key */
|
/* Get the public key */
|
||||||
err = get_pubkey_byname (ctrl, NULL, NULL, username, &keyblock, &kdbhd, 1, 1);
|
err = get_pubkey_byname (ctrl, GET_PUBKEY_NO_AKL,
|
||||||
|
NULL, NULL, username, &keyblock, &kdbhd, 1);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
log_error (_("key \"%s\" not found: %s\n"), username, gpg_strerror (err));
|
log_error (_("key \"%s\" not found: %s\n"), username, gpg_strerror (err));
|
||||||
@ -2570,7 +2572,8 @@ find_by_primary_fpr (ctrl_t ctrl, const char *fpr,
|
|||||||
err = gpg_error (GPG_ERR_INV_NAME);
|
err = gpg_error (GPG_ERR_INV_NAME);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
err = get_pubkey_byname (ctrl, NULL, NULL, fpr, &keyblock, &kdbhd, 1, 1);
|
err = get_pubkey_byname (ctrl, GET_PUBKEY_NO_AKL,
|
||||||
|
NULL, NULL, fpr, &keyblock, &kdbhd, 1);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
log_error (_("key \"%s\" not found: %s\n"), fpr, gpg_strerror (err));
|
log_error (_("key \"%s\" not found: %s\n"), fpr, gpg_strerror (err));
|
||||||
@ -3991,7 +3994,7 @@ menu_adduid (ctrl_t ctrl, kbnode_t pub_keyblock,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = make_keysig_packet (ctrl, &sig, pk, uid, NULL, pk, 0x13, 0, 0, 0,
|
err = make_keysig_packet (ctrl, &sig, pk, uid, NULL, pk, 0x13, 0, 0,
|
||||||
keygen_add_std_prefs, pk, NULL);
|
keygen_add_std_prefs, pk, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@ -4289,7 +4292,8 @@ menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive)
|
|||||||
primary keys only, but some casual testing shows that PGP and
|
primary keys only, but some casual testing shows that PGP and
|
||||||
GnuPG both can handle a designated revocation from a subkey. */
|
GnuPG both can handle a designated revocation from a subkey. */
|
||||||
revoker_pk->req_usage = PUBKEY_USAGE_CERT;
|
revoker_pk->req_usage = PUBKEY_USAGE_CERT;
|
||||||
rc = get_pubkey_byname (ctrl, NULL, revoker_pk, answer, NULL, NULL, 1, 1);
|
rc = get_pubkey_byname (ctrl, GET_PUBKEY_NO_AKL,
|
||||||
|
NULL, revoker_pk, answer, NULL, NULL, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_error (_("key \"%s\" not found: %s\n"), answer,
|
log_error (_("key \"%s\" not found: %s\n"), answer,
|
||||||
@ -4355,7 +4359,7 @@ menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
print_pubkey_info (ctrl, NULL, revoker_pk);
|
print_key_info (ctrl, NULL, 0, revoker_pk, 0);
|
||||||
print_fingerprint (ctrl, NULL, revoker_pk, 2);
|
print_fingerprint (ctrl, NULL, revoker_pk, 2);
|
||||||
tty_printf ("\n");
|
tty_printf ("\n");
|
||||||
|
|
||||||
@ -4374,7 +4378,7 @@ menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = make_keysig_packet (ctrl, &sig, pk, NULL, NULL, pk, 0x1F, 0, 0, 0,
|
rc = make_keysig_packet (ctrl, &sig, pk, NULL, NULL, pk, 0x1F, 0, 0,
|
||||||
keygen_add_revkey, &revkey, NULL);
|
keygen_add_revkey, &revkey, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
@ -5898,7 +5902,7 @@ reloop: /* (must use this, because we are modifying the list) */
|
|||||||
}
|
}
|
||||||
rc = make_keysig_packet (ctrl, &sig, primary_pk,
|
rc = make_keysig_packet (ctrl, &sig, primary_pk,
|
||||||
unode->pkt->pkt.user_id,
|
unode->pkt->pkt.user_id,
|
||||||
NULL, signerkey, 0x30, 0, 0, 0,
|
NULL, signerkey, 0x30, 0, 0,
|
||||||
sign_mk_attrib, &attrib, NULL);
|
sign_mk_attrib, &attrib, NULL);
|
||||||
free_public_key (signerkey);
|
free_public_key (signerkey);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -5977,11 +5981,11 @@ core_revuid (ctrl_t ctrl, kbnode_t keyblock, KBNODE node,
|
|||||||
memset (&attrib, 0, sizeof attrib);
|
memset (&attrib, 0, sizeof attrib);
|
||||||
/* should not need to cast away const here; but
|
/* should not need to cast away const here; but
|
||||||
revocation_reason_build_cb needs to take a non-const
|
revocation_reason_build_cb needs to take a non-const
|
||||||
void* in order to meet the function signtuare for the
|
void* in order to meet the function signutare for the
|
||||||
mksubpkt argument to make_keysig_packet */
|
mksubpkt argument to make_keysig_packet */
|
||||||
attrib.reason = (struct revocation_reason_info *)reason;
|
attrib.reason = (struct revocation_reason_info *)reason;
|
||||||
|
|
||||||
rc = make_keysig_packet (ctrl, &sig, pk, uid, NULL, pk, 0x30, 0,
|
rc = make_keysig_packet (ctrl, &sig, pk, uid, NULL, pk, 0x30,
|
||||||
timestamp, 0,
|
timestamp, 0,
|
||||||
sign_mk_attrib, &attrib, NULL);
|
sign_mk_attrib, &attrib, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -6111,7 +6115,7 @@ menu_revkey (ctrl_t ctrl, kbnode_t pub_keyblock)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rc = make_keysig_packet (ctrl, &sig, pk, NULL, NULL, pk,
|
rc = make_keysig_packet (ctrl, &sig, pk, NULL, NULL, pk,
|
||||||
0x20, 0, 0, 0,
|
0x20, 0, 0,
|
||||||
revocation_reason_build_cb, reason, NULL);
|
revocation_reason_build_cb, reason, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
@ -6173,7 +6177,7 @@ menu_revsubkey (ctrl_t ctrl, kbnode_t pub_keyblock)
|
|||||||
|
|
||||||
node->flag &= ~NODFLG_SELKEY;
|
node->flag &= ~NODFLG_SELKEY;
|
||||||
rc = make_keysig_packet (ctrl, &sig, mainpk, NULL, subpk, mainpk,
|
rc = make_keysig_packet (ctrl, &sig, mainpk, NULL, subpk, mainpk,
|
||||||
0x28, 0, 0, 0, sign_mk_attrib, &attrib,
|
0x28, 0, 0, sign_mk_attrib, &attrib,
|
||||||
NULL);
|
NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
|
244
g10/keygen.c
244
g10/keygen.c
@ -227,18 +227,22 @@ print_status_key_not_created (const char *handle)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static gpg_error_t
|
||||||
write_uid( KBNODE root, const char *s )
|
write_uid (kbnode_t root, const char *s)
|
||||||
{
|
{
|
||||||
PACKET *pkt = xmalloc_clear(sizeof *pkt );
|
PACKET *pkt = xmalloc_clear (sizeof *pkt);
|
||||||
size_t n = strlen(s);
|
size_t n = strlen (s);
|
||||||
|
|
||||||
pkt->pkttype = PKT_USER_ID;
|
if (n > MAX_UID_PACKET_LENGTH - 10)
|
||||||
pkt->pkt.user_id = xmalloc_clear (sizeof *pkt->pkt.user_id + n);
|
return gpg_error (GPG_ERR_INV_USER_ID);
|
||||||
pkt->pkt.user_id->len = n;
|
|
||||||
pkt->pkt.user_id->ref = 1;
|
pkt->pkttype = PKT_USER_ID;
|
||||||
strcpy(pkt->pkt.user_id->name, s);
|
pkt->pkt.user_id = xmalloc_clear (sizeof *pkt->pkt.user_id + n);
|
||||||
add_kbnode( root, new_kbnode( pkt ) );
|
pkt->pkt.user_id->len = n;
|
||||||
|
pkt->pkt.user_id->ref = 1;
|
||||||
|
strcpy (pkt->pkt.user_id->name, s);
|
||||||
|
add_kbnode (root, new_kbnode (pkt));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1022,7 +1026,7 @@ make_backsig (ctrl_t ctrl, PKT_signature *sig, PKT_public_key *pk,
|
|||||||
cache_public_key (sub_pk);
|
cache_public_key (sub_pk);
|
||||||
|
|
||||||
err = make_keysig_packet (ctrl, &backsig, pk, NULL, sub_pk, sub_psk, 0x19,
|
err = make_keysig_packet (ctrl, &backsig, pk, NULL, sub_pk, sub_psk, 0x19,
|
||||||
0, timestamp, 0, NULL, NULL, cache_nonce);
|
timestamp, 0, NULL, NULL, cache_nonce);
|
||||||
if (err)
|
if (err)
|
||||||
log_error ("make_keysig_packet failed for backsig: %s\n",
|
log_error ("make_keysig_packet failed for backsig: %s\n",
|
||||||
gpg_strerror (err));
|
gpg_strerror (err));
|
||||||
@ -1130,7 +1134,7 @@ write_direct_sig (ctrl_t ctrl, kbnode_t root, PKT_public_key *psk,
|
|||||||
|
|
||||||
/* Make the signature. */
|
/* Make the signature. */
|
||||||
err = make_keysig_packet (ctrl, &sig, pk, NULL,NULL, psk, 0x1F,
|
err = make_keysig_packet (ctrl, &sig, pk, NULL,NULL, psk, 0x1F,
|
||||||
0, timestamp, 0,
|
timestamp, 0,
|
||||||
keygen_add_revkey, revkey, cache_nonce);
|
keygen_add_revkey, revkey, cache_nonce);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@ -1185,7 +1189,7 @@ write_selfsigs (ctrl_t ctrl, kbnode_t root, PKT_public_key *psk,
|
|||||||
|
|
||||||
/* Make the signature. */
|
/* Make the signature. */
|
||||||
err = make_keysig_packet (ctrl, &sig, pk, uid, NULL, psk, 0x13,
|
err = make_keysig_packet (ctrl, &sig, pk, uid, NULL, psk, 0x13,
|
||||||
0, timestamp, 0,
|
timestamp, 0,
|
||||||
keygen_add_std_prefs, pk, cache_nonce);
|
keygen_add_std_prefs, pk, cache_nonce);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@ -1245,7 +1249,7 @@ write_keybinding (ctrl_t ctrl, kbnode_t root,
|
|||||||
oduap.usage = use;
|
oduap.usage = use;
|
||||||
oduap.pk = sub_pk;
|
oduap.pk = sub_pk;
|
||||||
err = make_keysig_packet (ctrl, &sig, pri_pk, NULL, sub_pk, pri_psk, 0x18,
|
err = make_keysig_packet (ctrl, &sig, pri_pk, NULL, sub_pk, pri_psk, 0x18,
|
||||||
0, timestamp, 0,
|
timestamp, 0,
|
||||||
keygen_add_key_flags_and_expire, &oduap,
|
keygen_add_key_flags_and_expire, &oduap,
|
||||||
cache_nonce);
|
cache_nonce);
|
||||||
if (err)
|
if (err)
|
||||||
@ -1881,24 +1885,26 @@ print_key_flags(int flags)
|
|||||||
|
|
||||||
|
|
||||||
/* Ask for the key flags and return them. CURRENT gives the current
|
/* Ask for the key flags and return them. CURRENT gives the current
|
||||||
* usage which should normally be given as 0. */
|
* usage which should normally be given as 0. MASK gives the allowed
|
||||||
|
* flags. */
|
||||||
unsigned int
|
unsigned int
|
||||||
ask_key_flags (int algo, int subkey, unsigned int current)
|
ask_key_flags_with_mask (int algo, int subkey, unsigned int current,
|
||||||
|
unsigned int mask)
|
||||||
{
|
{
|
||||||
/* TRANSLATORS: Please use only plain ASCII characters for the
|
/* TRANSLATORS: Please use only plain ASCII characters for the
|
||||||
translation. If this is not possible use single digits. The
|
* translation. If this is not possible use single digits. The
|
||||||
string needs to 8 bytes long. Here is a description of the
|
* string needs to 8 bytes long. Here is a description of the
|
||||||
functions:
|
* functions:
|
||||||
|
*
|
||||||
s = Toggle signing capability
|
* s = Toggle signing capability
|
||||||
e = Toggle encryption capability
|
* e = Toggle encryption capability
|
||||||
a = Toggle authentication capability
|
* a = Toggle authentication capability
|
||||||
q = Finish
|
* q = Finish
|
||||||
*/
|
*/
|
||||||
const char *togglers = _("SsEeAaQq");
|
const char *togglers = _("SsEeAaQq");
|
||||||
char *answer = NULL;
|
char *answer = NULL;
|
||||||
const char *s;
|
const char *s;
|
||||||
unsigned int possible = openpgp_pk_algo_usage(algo);
|
unsigned int possible;
|
||||||
|
|
||||||
if ( strlen(togglers) != 8 )
|
if ( strlen(togglers) != 8 )
|
||||||
{
|
{
|
||||||
@ -1907,22 +1913,26 @@ ask_key_flags (int algo, int subkey, unsigned int current)
|
|||||||
togglers = "11223300";
|
togglers = "11223300";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only primary keys may certify. */
|
/* Mask the possible usage flags. This is for example used for a
|
||||||
if(subkey)
|
* card based key. */
|
||||||
possible&=~PUBKEY_USAGE_CERT;
|
possible = (openpgp_pk_algo_usage (algo) & mask);
|
||||||
|
|
||||||
/* Preload the current set with the possible set, minus
|
/* However, only primary keys may certify. */
|
||||||
authentication if CURRENT has been given as 0. If CURRENT has
|
if (subkey)
|
||||||
been has non-zero we mask with all possible usages. */
|
possible &= ~PUBKEY_USAGE_CERT;
|
||||||
|
|
||||||
|
/* Preload the current set with the possible set, without
|
||||||
|
* authentication if CURRENT is 0. If CURRENT is non-zero we mask
|
||||||
|
* with all possible usages. */
|
||||||
if (current)
|
if (current)
|
||||||
current &= possible;
|
current &= possible;
|
||||||
else
|
else
|
||||||
current = (possible&~PUBKEY_USAGE_AUTH);
|
current = (possible&~PUBKEY_USAGE_AUTH);
|
||||||
|
|
||||||
for(;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
tty_printf("\n");
|
tty_printf("\n");
|
||||||
tty_printf(_("Possible actions for a %s key: "),
|
tty_printf(_("Possible actions for this %s key: "),
|
||||||
(algo == PUBKEY_ALGO_ECDSA
|
(algo == PUBKEY_ALGO_ECDSA
|
||||||
|| algo == PUBKEY_ALGO_EDDSA)
|
|| algo == PUBKEY_ALGO_EDDSA)
|
||||||
? "ECDSA/EdDSA" : openpgp_pk_algo_name (algo));
|
? "ECDSA/EdDSA" : openpgp_pk_algo_name (algo));
|
||||||
@ -2009,6 +2019,13 @@ ask_key_flags (int algo, int subkey, unsigned int current)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
ask_key_flags (int algo, int subkey, unsigned int current)
|
||||||
|
{
|
||||||
|
return ask_key_flags_with_mask (algo, subkey, current, ~0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check whether we have a key for the key with HEXGRIP. Returns 0 if
|
/* Check whether we have a key for the key with HEXGRIP. Returns 0 if
|
||||||
there is no such key or the OpenPGP algo number for the key. */
|
there is no such key or the OpenPGP algo number for the key. */
|
||||||
static int
|
static int
|
||||||
@ -2047,10 +2064,12 @@ static int
|
|||||||
ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
|
ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
|
||||||
char **r_keygrip)
|
char **r_keygrip)
|
||||||
{
|
{
|
||||||
|
gpg_error_t err;
|
||||||
char *keygrip = NULL;
|
char *keygrip = NULL;
|
||||||
char *answer = NULL;
|
char *answer = NULL;
|
||||||
int algo;
|
int algo;
|
||||||
int dummy_algo;
|
int dummy_algo;
|
||||||
|
char *p;
|
||||||
|
|
||||||
if (!r_subkey_algo)
|
if (!r_subkey_algo)
|
||||||
r_subkey_algo = &dummy_algo;
|
r_subkey_algo = &dummy_algo;
|
||||||
@ -2101,6 +2120,8 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
|
|||||||
|
|
||||||
if (opt.expert && r_keygrip)
|
if (opt.expert && r_keygrip)
|
||||||
tty_printf (_(" (%d) Existing key\n"), 13 );
|
tty_printf (_(" (%d) Existing key\n"), 13 );
|
||||||
|
if (r_keygrip)
|
||||||
|
tty_printf (_(" (%d) Existing key from card\n"), 14 );
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -2221,9 +2242,130 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
|
|||||||
*r_usage = ask_key_flags (algo, addmode, 0);
|
*r_usage = ask_key_flags (algo, addmode, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if ((algo == 14 || !strcmp (answer, "cardkey")) && r_keygrip)
|
||||||
|
{
|
||||||
|
char *serialno;
|
||||||
|
strlist_t keypairlist, sl;
|
||||||
|
int count, selection;
|
||||||
|
|
||||||
|
err = agent_scd_serialno (&serialno, NULL);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
tty_printf (_("error reading the card: %s\n"),
|
||||||
|
gpg_strerror (err));
|
||||||
|
goto ask_again;
|
||||||
|
}
|
||||||
|
tty_printf (_("Serial number of the card: %s\n"), serialno);
|
||||||
|
xfree (serialno);
|
||||||
|
|
||||||
|
err = agent_scd_keypairinfo (ctrl, NULL, &keypairlist);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
tty_printf (_("error reading the card: %s\n"),
|
||||||
|
gpg_strerror (err));
|
||||||
|
goto ask_again;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
tty_printf (_("Available keys:\n"));
|
||||||
|
for (count=1,sl=keypairlist; sl; sl = sl->next, count++)
|
||||||
|
{
|
||||||
|
gcry_sexp_t s_pkey;
|
||||||
|
char *algostr = NULL;
|
||||||
|
enum gcry_pk_algos algoid = 0;
|
||||||
|
const char *keyref;
|
||||||
|
int any = 0;
|
||||||
|
|
||||||
|
keyref = strchr (sl->d, ' ');
|
||||||
|
if (keyref)
|
||||||
|
{
|
||||||
|
keyref++;
|
||||||
|
if (!agent_scd_readkey (keyref, &s_pkey))
|
||||||
|
{
|
||||||
|
algostr = pubkey_algo_string (s_pkey, &algoid);
|
||||||
|
gcry_sexp_release (s_pkey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* We use the flags also encode the algo for use
|
||||||
|
* below. We need to tweak the algo in case
|
||||||
|
* GCRY_PK_ECC is returned becuase pubkey_algo_string
|
||||||
|
* is not aware of the OpenPGP algo mapping.
|
||||||
|
* FIXME: This is an ugly hack. */
|
||||||
|
sl->flags &= 0xff;
|
||||||
|
if (algoid == GCRY_PK_ECC
|
||||||
|
&& algostr && !strncmp (algostr, "nistp", 5)
|
||||||
|
&& !(sl->flags & GCRY_PK_USAGE_ENCR))
|
||||||
|
sl->flags |= (PUBKEY_ALGO_ECDSA << 8);
|
||||||
|
else
|
||||||
|
sl->flags |= (map_pk_gcry_to_openpgp (algoid) << 8);
|
||||||
|
|
||||||
|
tty_printf (" (%d) %s %s", count, sl->d, algostr);
|
||||||
|
if ((sl->flags & GCRY_PK_USAGE_CERT))
|
||||||
|
{
|
||||||
|
tty_printf ("%scert", any?",":" (");
|
||||||
|
any = 1;
|
||||||
|
}
|
||||||
|
if ((sl->flags & GCRY_PK_USAGE_SIGN))
|
||||||
|
{
|
||||||
|
tty_printf ("%ssign", any?",":" (");
|
||||||
|
any = 1;
|
||||||
|
}
|
||||||
|
if ((sl->flags & GCRY_PK_USAGE_AUTH))
|
||||||
|
{
|
||||||
|
tty_printf ("%sauth", any?",":" (");
|
||||||
|
any = 1;
|
||||||
|
}
|
||||||
|
if ((sl->flags & GCRY_PK_USAGE_ENCR))
|
||||||
|
{
|
||||||
|
tty_printf ("%sencr", any?",":" (");
|
||||||
|
any = 1;
|
||||||
|
}
|
||||||
|
tty_printf ("%s\n", any?")":"");
|
||||||
|
xfree (algostr);
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree (answer);
|
||||||
|
answer = cpr_get ("keygen.cardkey", _("Your selection? "));
|
||||||
|
cpr_kill_prompt ();
|
||||||
|
trim_spaces (answer);
|
||||||
|
selection = atoi (answer);
|
||||||
|
}
|
||||||
|
while (!(selection > 0 && selection < count));
|
||||||
|
|
||||||
|
for (count=1,sl=keypairlist; sl; sl = sl->next, count++)
|
||||||
|
if (count == selection)
|
||||||
|
break;
|
||||||
|
if (!sl)
|
||||||
|
{
|
||||||
|
/* Just in case COUNT is zero (no keys). */
|
||||||
|
free_strlist (keypairlist);
|
||||||
|
goto ask_again;
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree (keygrip);
|
||||||
|
keygrip = xstrdup (sl->d);
|
||||||
|
if ((p = strchr (keygrip, ' ')))
|
||||||
|
*p = 0;
|
||||||
|
algo = (sl->flags >>8);
|
||||||
|
if (opt.expert)
|
||||||
|
*r_usage = ask_key_flags_with_mask (algo, addmode,
|
||||||
|
(sl->flags & 0xff),
|
||||||
|
(sl->flags & 0xff));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*r_usage = (sl->flags & 0xff);
|
||||||
|
if (addmode)
|
||||||
|
*r_usage &= ~GCRY_PK_USAGE_CERT;
|
||||||
|
}
|
||||||
|
free_strlist (keypairlist);
|
||||||
|
break;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
tty_printf (_("Invalid selection.\n"));
|
tty_printf (_("Invalid selection.\n"));
|
||||||
|
|
||||||
|
ask_again:
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfree(answer);
|
xfree(answer);
|
||||||
@ -2507,14 +2649,25 @@ ask_curve (int *algo, int *subkey_algo, const char *current)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* If the user selected a signing algorithm and Curve25519
|
/* If the user selected a signing algorithm and Curve25519
|
||||||
we need to set the algo to EdDSA and update the curve name. */
|
we need to set the algo to EdDSA and update the curve name.
|
||||||
if ((*algo == PUBKEY_ALGO_ECDSA || *algo == PUBKEY_ALGO_EDDSA)
|
If switching away from EdDSA, we need to set the algo back
|
||||||
&& curves[idx].eddsa_curve)
|
to ECDSA. */
|
||||||
|
if (*algo == PUBKEY_ALGO_ECDSA || *algo == PUBKEY_ALGO_EDDSA)
|
||||||
{
|
{
|
||||||
if (subkey_algo && *subkey_algo == PUBKEY_ALGO_ECDSA)
|
if (curves[idx].eddsa_curve)
|
||||||
*subkey_algo = PUBKEY_ALGO_EDDSA;
|
{
|
||||||
*algo = PUBKEY_ALGO_EDDSA;
|
if (subkey_algo && *subkey_algo == PUBKEY_ALGO_ECDSA)
|
||||||
result = curves[idx].eddsa_curve;
|
*subkey_algo = PUBKEY_ALGO_EDDSA;
|
||||||
|
*algo = PUBKEY_ALGO_EDDSA;
|
||||||
|
result = curves[idx].eddsa_curve;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (subkey_algo && *subkey_algo == PUBKEY_ALGO_EDDSA)
|
||||||
|
*subkey_algo = PUBKEY_ALGO_ECDSA;
|
||||||
|
*algo = PUBKEY_ALGO_ECDSA;
|
||||||
|
result = curves[idx].name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = curves[idx].name;
|
result = curves[idx].name;
|
||||||
@ -4943,10 +5096,11 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
|||||||
|
|
||||||
if (!err && (s = get_parameter_value (para, pUSERID)))
|
if (!err && (s = get_parameter_value (para, pUSERID)))
|
||||||
{
|
{
|
||||||
write_uid (pub_root, s );
|
err = write_uid (pub_root, s );
|
||||||
err = write_selfsigs (ctrl, pub_root, pri_psk,
|
if (!err)
|
||||||
get_parameter_uint (para, pKEYUSAGE), timestamp,
|
err = write_selfsigs (ctrl, pub_root, pri_psk,
|
||||||
cache_nonce);
|
get_parameter_uint (para, pKEYUSAGE), timestamp,
|
||||||
|
cache_nonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the auth key to the card before the encryption key. This
|
/* Write the auth key to the card before the encryption key. This
|
||||||
|
120
g10/keyid.c
120
g10/keyid.c
@ -68,7 +68,7 @@ pubkey_letter( int algo )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return a string describing the public key algorithm and the
|
/* Return a string describing the public key algorithm and the
|
||||||
keysize. For elliptic curves the functions prints the name of the
|
keysize. For elliptic curves the function prints the name of the
|
||||||
curve because the keysize is a property of the curve. The string
|
curve because the keysize is a property of the curve. The string
|
||||||
is copied to the supplied buffer up a length of BUFSIZE-1.
|
is copied to the supplied buffer up a length of BUFSIZE-1.
|
||||||
Examples for the output are:
|
Examples for the output are:
|
||||||
@ -253,20 +253,6 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static gcry_md_hd_t
|
|
||||||
do_fingerprint_md( PKT_public_key *pk )
|
|
||||||
{
|
|
||||||
gcry_md_hd_t md;
|
|
||||||
|
|
||||||
if (gcry_md_open (&md, pk->version == 5 ? GCRY_MD_SHA256 : GCRY_MD_SHA1, 0))
|
|
||||||
BUG ();
|
|
||||||
hash_public_key (md,pk);
|
|
||||||
gcry_md_final (md);
|
|
||||||
|
|
||||||
return md;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* fixme: Check whether we can replace this function or if not
|
/* fixme: Check whether we can replace this function or if not
|
||||||
describe why we need it. */
|
describe why we need it. */
|
||||||
u32
|
u32
|
||||||
@ -520,6 +506,37 @@ keystr_from_desc(KEYDB_SEARCH_DESC *desc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Compute the fingerprint and keyid and store it in PK. */
|
||||||
|
static void
|
||||||
|
compute_fingerprint (PKT_public_key *pk)
|
||||||
|
{
|
||||||
|
const byte *dp;
|
||||||
|
gcry_md_hd_t md;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (gcry_md_open (&md, pk->version == 5 ? GCRY_MD_SHA256 : GCRY_MD_SHA1, 0))
|
||||||
|
BUG ();
|
||||||
|
hash_public_key (md, pk);
|
||||||
|
gcry_md_final (md);
|
||||||
|
dp = gcry_md_read (md, 0);
|
||||||
|
len = gcry_md_get_algo_dlen (gcry_md_get_algo (md));
|
||||||
|
log_assert (len <= MAX_FINGERPRINT_LEN);
|
||||||
|
memcpy (pk->fpr, dp, len);
|
||||||
|
pk->fprlen = len;
|
||||||
|
if (pk->version == 5)
|
||||||
|
{
|
||||||
|
pk->keyid[0] = buf32_to_u32 (dp);
|
||||||
|
pk->keyid[1] = buf32_to_u32 (dp+4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pk->keyid[0] = buf32_to_u32 (dp+12);
|
||||||
|
pk->keyid[1] = buf32_to_u32 (dp+16);
|
||||||
|
}
|
||||||
|
gcry_md_close( md);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the keyid from the public key PK and store it at KEYID unless
|
* Get the keyid from the public key PK and store it at KEYID unless
|
||||||
* this is NULL. Returns the 32 bit short keyid.
|
* this is NULL. Returns the 32 bit short keyid.
|
||||||
@ -532,37 +549,11 @@ keyid_from_pk (PKT_public_key *pk, u32 *keyid)
|
|||||||
if (!keyid)
|
if (!keyid)
|
||||||
keyid = dummy_keyid;
|
keyid = dummy_keyid;
|
||||||
|
|
||||||
if( pk->keyid[0] || pk->keyid[1] )
|
if (!pk->fprlen)
|
||||||
{
|
compute_fingerprint (pk);
|
||||||
keyid[0] = pk->keyid[0];
|
|
||||||
keyid[1] = pk->keyid[1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const byte *dp;
|
|
||||||
gcry_md_hd_t md;
|
|
||||||
|
|
||||||
md = do_fingerprint_md(pk);
|
keyid[0] = pk->keyid[0];
|
||||||
if(md)
|
keyid[1] = pk->keyid[1];
|
||||||
{
|
|
||||||
dp = gcry_md_read ( md, 0 );
|
|
||||||
if (pk->version == 5)
|
|
||||||
{
|
|
||||||
keyid[0] = buf32_to_u32 (dp);
|
|
||||||
keyid[1] = buf32_to_u32 (dp+4);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
keyid[0] = buf32_to_u32 (dp+12);
|
|
||||||
keyid[1] = buf32_to_u32 (dp+16);
|
|
||||||
}
|
|
||||||
gcry_md_close (md);
|
|
||||||
pk->keyid[0] = keyid[0];
|
|
||||||
pk->keyid[1] = keyid[1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
pk->keyid[0] = pk->keyid[1] = keyid[0]= keyid[1] = 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
return keyid[1]; /*FIXME:shortkeyid ist different for v5*/
|
return keyid[1]; /*FIXME:shortkeyid ist different for v5*/
|
||||||
}
|
}
|
||||||
@ -805,6 +796,7 @@ colon_expirestr_from_sig (PKT_signature *sig)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return a byte array with the fingerprint for the given PK/SK
|
* Return a byte array with the fingerprint for the given PK/SK
|
||||||
* The length of the array is returned in ret_len. Caller must free
|
* The length of the array is returned in ret_len. Caller must free
|
||||||
@ -813,31 +805,15 @@ colon_expirestr_from_sig (PKT_signature *sig)
|
|||||||
byte *
|
byte *
|
||||||
fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
|
fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
|
||||||
{
|
{
|
||||||
const byte *dp;
|
if (!pk->fprlen)
|
||||||
size_t len;
|
compute_fingerprint (pk);
|
||||||
gcry_md_hd_t md;
|
|
||||||
|
|
||||||
md = do_fingerprint_md (pk);
|
|
||||||
dp = gcry_md_read (md, 0);
|
|
||||||
len = gcry_md_get_algo_dlen (gcry_md_get_algo (md));
|
|
||||||
log_assert (len <= MAX_FINGERPRINT_LEN);
|
|
||||||
if (!array)
|
if (!array)
|
||||||
array = xmalloc ( len );
|
array = xmalloc (pk->fprlen);
|
||||||
memcpy (array, dp, len );
|
memcpy (array, pk->fpr, pk->fprlen);
|
||||||
if (pk->version == 5)
|
|
||||||
{
|
|
||||||
pk->keyid[0] = buf32_to_u32 (dp);
|
|
||||||
pk->keyid[1] = buf32_to_u32 (dp+4);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pk->keyid[0] = buf32_to_u32 (dp+12);
|
|
||||||
pk->keyid[1] = buf32_to_u32 (dp+16);
|
|
||||||
}
|
|
||||||
gcry_md_close( md);
|
|
||||||
|
|
||||||
if (ret_len)
|
if (ret_len)
|
||||||
*ret_len = len;
|
*ret_len = pk->fprlen;
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -852,19 +828,19 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
|
|||||||
char *
|
char *
|
||||||
hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen)
|
hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen)
|
||||||
{
|
{
|
||||||
unsigned char fpr[MAX_FINGERPRINT_LEN];
|
if (!pk->fprlen)
|
||||||
size_t len;
|
compute_fingerprint (pk);
|
||||||
|
|
||||||
fingerprint_from_pk (pk, fpr, &len);
|
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
{
|
{
|
||||||
buffer = xtrymalloc (2 * len + 1);
|
buffer = xtrymalloc (2 * pk->fprlen + 1);
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (buflen < 2*len+1)
|
else if (buflen < 2 * pk->fprlen + 1)
|
||||||
log_fatal ("%s: buffer too short (%zu)\n", __func__, buflen);
|
log_fatal ("%s: buffer too short (%zu)\n", __func__, buflen);
|
||||||
bin2hex (fpr, len, buffer);
|
|
||||||
|
bin2hex (pk->fpr, pk->fprlen, buffer);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
114
g10/keylist.c
114
g10/keylist.c
@ -51,7 +51,7 @@
|
|||||||
static void list_all (ctrl_t, int, int);
|
static void list_all (ctrl_t, int, int);
|
||||||
static void list_one (ctrl_t ctrl,
|
static void list_one (ctrl_t ctrl,
|
||||||
strlist_t names, int secret, int mark_secret);
|
strlist_t names, int secret, int mark_secret);
|
||||||
static void locate_one (ctrl_t ctrl, strlist_t names);
|
static void locate_one (ctrl_t ctrl, strlist_t names, int no_local);
|
||||||
static void print_card_serialno (const char *serialno);
|
static void print_card_serialno (const char *serialno);
|
||||||
|
|
||||||
struct keylist_context
|
struct keylist_context
|
||||||
@ -83,10 +83,11 @@ keylist_context_release (struct keylist_context *listctx)
|
|||||||
|
|
||||||
|
|
||||||
/* List the keys. If list is NULL, all available keys are listed.
|
/* List the keys. If list is NULL, all available keys are listed.
|
||||||
With LOCATE_MODE set the locate algorithm is used to find a
|
* With LOCATE_MODE set the locate algorithm is used to find a key; if
|
||||||
key. */
|
* in addition NO_LOCAL is set the locate does not look into the local
|
||||||
|
* keyring. */
|
||||||
void
|
void
|
||||||
public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode)
|
public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode, int no_local)
|
||||||
{
|
{
|
||||||
#ifndef NO_TRUST_MODELS
|
#ifndef NO_TRUST_MODELS
|
||||||
if (opt.with_colons)
|
if (opt.with_colons)
|
||||||
@ -140,7 +141,7 @@ public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (locate_mode)
|
if (locate_mode)
|
||||||
locate_one (ctrl, list);
|
locate_one (ctrl, list, no_local);
|
||||||
else if (!list)
|
else if (!list)
|
||||||
list_all (ctrl, 0, opt.with_secret);
|
list_all (ctrl, 0, opt.with_secret);
|
||||||
else
|
else
|
||||||
@ -165,43 +166,15 @@ secret_key_list (ctrl_t ctrl, strlist_t list)
|
|||||||
list_one (ctrl, list, 1, 0);
|
list_one (ctrl, list, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
|
||||||
format_seckey_info (ctrl_t ctrl, PKT_public_key *pk)
|
/* Helper for print_key_info and print_key_info_log. */
|
||||||
{
|
static char *
|
||||||
u32 keyid[2];
|
format_key_info (ctrl_t ctrl, PKT_public_key *pk, int secret)
|
||||||
char *p;
|
|
||||||
char pkstrbuf[PUBKEY_STRING_SIZE];
|
|
||||||
char *info;
|
|
||||||
|
|
||||||
keyid_from_pk (pk, keyid);
|
|
||||||
p = get_user_id_native (ctrl, keyid);
|
|
||||||
|
|
||||||
info = xtryasprintf ("sec %s/%s %s %s",
|
|
||||||
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
|
|
||||||
keystr (keyid), datestr_from_pk (pk), p);
|
|
||||||
|
|
||||||
xfree (p);
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
print_seckey_info (ctrl_t ctrl, PKT_public_key *pk)
|
|
||||||
{
|
|
||||||
char *p = format_seckey_info (ctrl, pk);
|
|
||||||
tty_printf ("\n%s\n", p);
|
|
||||||
xfree (p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print information about the public key. With FP passed as NULL,
|
|
||||||
the tty output interface is used, otherwise output is directed to
|
|
||||||
the given stream. */
|
|
||||||
void
|
|
||||||
print_pubkey_info (ctrl_t ctrl, estream_t fp, PKT_public_key *pk)
|
|
||||||
{
|
{
|
||||||
u32 keyid[2];
|
u32 keyid[2];
|
||||||
char *p;
|
char *p;
|
||||||
char pkstrbuf[PUBKEY_STRING_SIZE];
|
char pkstrbuf[PUBKEY_STRING_SIZE];
|
||||||
|
char *result;
|
||||||
|
|
||||||
keyid_from_pk (pk, keyid);
|
keyid_from_pk (pk, keyid);
|
||||||
|
|
||||||
@ -212,13 +185,59 @@ print_pubkey_info (ctrl_t ctrl, estream_t fp, PKT_public_key *pk)
|
|||||||
else
|
else
|
||||||
p = get_user_id_native (ctrl, keyid);
|
p = get_user_id_native (ctrl, keyid);
|
||||||
|
|
||||||
if (!fp)
|
result = xtryasprintf ("%s %s/%s %s %s",
|
||||||
tty_printf ("\n");
|
secret? (pk->flags.primary? "sec":"ssb")
|
||||||
tty_fprintf (fp, "%s %s/%s %s %s\n",
|
/* */ : (pk->flags.primary? "pub":"sub"),
|
||||||
pk->flags.primary? "pub":"sub",
|
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
|
||||||
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
|
keystr (keyid), datestr_from_pk (pk), p);
|
||||||
keystr (keyid), datestr_from_pk (pk), p);
|
|
||||||
xfree (p);
|
xfree (p);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Print basic information about a public or secret key. With FP
|
||||||
|
* passed as NULL, the tty output interface is used, otherwise output
|
||||||
|
* is directed to the given stream. INDENT gives the requested
|
||||||
|
* indentation; if that is a negative value indentation is suppressed
|
||||||
|
* for the first line. SECRET tells that the PK has a secret part.
|
||||||
|
* FIXME: This is similar in use to print_key_line and thus both
|
||||||
|
* functions should eventually be united.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
print_key_info (ctrl_t ctrl, estream_t fp,
|
||||||
|
int indent, PKT_public_key *pk, int secret)
|
||||||
|
{
|
||||||
|
int indentabs = indent >= 0? indent : -indent;
|
||||||
|
char *info;
|
||||||
|
|
||||||
|
/* Note: Negative values for INDENT are not yet needed. */
|
||||||
|
|
||||||
|
info = format_key_info (ctrl, pk, secret);
|
||||||
|
|
||||||
|
if (!fp && indent >= 0)
|
||||||
|
tty_printf ("\n"); /* (Backward compatibility to old code) */
|
||||||
|
tty_fprintf (fp, "%*s%s\n", indentabs, "",
|
||||||
|
info? info : "[Ooops - out of core]");
|
||||||
|
|
||||||
|
xfree (info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Same as print_key_info put print using the log functions at
|
||||||
|
* LOGLEVEL. */
|
||||||
|
void
|
||||||
|
print_key_info_log (ctrl_t ctrl, int loglevel,
|
||||||
|
int indent, PKT_public_key *pk, int secret)
|
||||||
|
{
|
||||||
|
int indentabs = indent >= 0? indent : -indent;
|
||||||
|
char *info;
|
||||||
|
|
||||||
|
info = format_key_info (ctrl, pk, secret);
|
||||||
|
|
||||||
|
log_log (loglevel, "%*s%s\n", indentabs, "",
|
||||||
|
info? info : "[Ooops - out of core]");
|
||||||
|
|
||||||
|
xfree (info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -640,7 +659,7 @@ list_one (ctrl_t ctrl, strlist_t names, int secret, int mark_secret)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
locate_one (ctrl_t ctrl, strlist_t names)
|
locate_one (ctrl_t ctrl, strlist_t names, int no_local)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
strlist_t sl;
|
strlist_t sl;
|
||||||
@ -654,7 +673,10 @@ locate_one (ctrl_t ctrl, strlist_t names)
|
|||||||
|
|
||||||
for (sl = names; sl; sl = sl->next)
|
for (sl = names; sl; sl = sl->next)
|
||||||
{
|
{
|
||||||
rc = get_best_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, 1);
|
rc = get_best_pubkey_byname (ctrl,
|
||||||
|
no_local? GET_PUBKEY_NO_LOCAL
|
||||||
|
/* */: GET_PUBKEY_NORMAL,
|
||||||
|
&ctx, NULL, sl->d, &keyblock, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
|
if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
|
||||||
|
@ -473,11 +473,14 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
in_cert = 1;
|
in_cert = 1;
|
||||||
node = lastnode = new_kbnode (pkt);
|
node = new_kbnode (pkt);
|
||||||
if (!keyblock)
|
if (!keyblock)
|
||||||
keyblock = node;
|
keyblock = lastnode = node;
|
||||||
else
|
else
|
||||||
add_kbnode (keyblock, node);
|
{
|
||||||
|
lastnode->next = node;
|
||||||
|
lastnode = node;
|
||||||
|
}
|
||||||
switch (pkt->pkttype)
|
switch (pkt->pkttype)
|
||||||
{
|
{
|
||||||
case PKT_PUBLIC_KEY:
|
case PKT_PUBLIC_KEY:
|
||||||
|
@ -333,7 +333,7 @@ parse_keyserver_uri (const char *string,int require_scheme)
|
|||||||
{
|
{
|
||||||
/* Three slashes means network path with a default host name.
|
/* Three slashes means network path with a default host name.
|
||||||
This is a hack because it does not crok all possible
|
This is a hack because it does not crok all possible
|
||||||
combiantions. We should better repalce all code bythe parser
|
combinations. We should better replace all code by the parser
|
||||||
from http.c. */
|
from http.c. */
|
||||||
keyserver->path = xstrdup (uri+2);
|
keyserver->path = xstrdup (uri+2);
|
||||||
}
|
}
|
||||||
@ -1519,9 +1519,7 @@ keyserver_search (ctrl_t ctrl, strlist_t tokens)
|
|||||||
log_info (_("key not found on keyserver\n"));
|
log_info (_("key not found on keyserver\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gpg_err_code (err) == GPG_ERR_NO_KEYSERVER)
|
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
|
||||||
log_error (_("no keyserver known (use option --keyserver)\n"));
|
|
||||||
else if (gpg_err_code (err) == GPG_ERR_NO_DATA)
|
|
||||||
err = gpg_error (GPG_ERR_NOT_FOUND);
|
err = gpg_error (GPG_ERR_NOT_FOUND);
|
||||||
else if (err)
|
else if (err)
|
||||||
log_error ("error searching keyserver: %s\n", gpg_strerror (err));
|
log_error ("error searching keyserver: %s\n", gpg_strerror (err));
|
||||||
@ -2051,8 +2049,9 @@ keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick,
|
|||||||
int armor_status = opt.no_armor;
|
int armor_status = opt.no_armor;
|
||||||
import_filter_t save_filt;
|
import_filter_t save_filt;
|
||||||
|
|
||||||
/* Keys returned via WKD are in binary format. */
|
/* Keys returned via WKD are in binary format. However, we
|
||||||
opt.no_armor = 1;
|
* relax that requirement and allow also for armored data. */
|
||||||
|
opt.no_armor = 0;
|
||||||
save_filt = save_and_clear_import_filter ();
|
save_filt = save_and_clear_import_filter ();
|
||||||
if (!save_filt)
|
if (!save_filt)
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
|
12
g10/main.h
12
g10/main.h
@ -414,6 +414,8 @@ void export_print_stats (export_stats_t stats);
|
|||||||
int parse_export_options(char *str,unsigned int *options,int noisy);
|
int parse_export_options(char *str,unsigned int *options,int noisy);
|
||||||
gpg_error_t parse_and_set_export_filter (const char *string);
|
gpg_error_t parse_and_set_export_filter (const char *string);
|
||||||
|
|
||||||
|
int exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, kbnode_t node);
|
||||||
|
|
||||||
int export_pubkeys (ctrl_t ctrl, strlist_t users, unsigned int options,
|
int export_pubkeys (ctrl_t ctrl, strlist_t users, unsigned int options,
|
||||||
export_stats_t stats);
|
export_stats_t stats);
|
||||||
int export_seckeys (ctrl_t ctrl, strlist_t users, unsigned int options,
|
int export_seckeys (ctrl_t ctrl, strlist_t users, unsigned int options,
|
||||||
@ -456,7 +458,8 @@ struct revocation_reason_info * get_default_uid_revocation_reason(void);
|
|||||||
void release_revocation_reason_info( struct revocation_reason_info *reason );
|
void release_revocation_reason_info( struct revocation_reason_info *reason );
|
||||||
|
|
||||||
/*-- keylist.c --*/
|
/*-- keylist.c --*/
|
||||||
void public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode );
|
void public_key_list (ctrl_t ctrl, strlist_t list,
|
||||||
|
int locate_mode, int no_local);
|
||||||
void secret_key_list (ctrl_t ctrl, strlist_t list );
|
void secret_key_list (ctrl_t ctrl, strlist_t list );
|
||||||
void print_subpackets_colon(PKT_signature *sig);
|
void print_subpackets_colon(PKT_signature *sig);
|
||||||
void reorder_keyblock (KBNODE keyblock);
|
void reorder_keyblock (KBNODE keyblock);
|
||||||
@ -470,9 +473,10 @@ void show_keyserver_url(PKT_signature *sig,int indent,int mode);
|
|||||||
void show_notation(PKT_signature *sig,int indent,int mode,int which);
|
void show_notation(PKT_signature *sig,int indent,int mode,int which);
|
||||||
void dump_attribs (const PKT_user_id *uid, PKT_public_key *pk);
|
void dump_attribs (const PKT_user_id *uid, PKT_public_key *pk);
|
||||||
void set_attrib_fd(int fd);
|
void set_attrib_fd(int fd);
|
||||||
char *format_seckey_info (ctrl_t ctrl, PKT_public_key *pk);
|
void print_key_info (ctrl_t ctrl, estream_t fp, int indent,
|
||||||
void print_seckey_info (ctrl_t ctrl, PKT_public_key *pk);
|
PKT_public_key *pk, int secret);
|
||||||
void print_pubkey_info (ctrl_t ctrl, estream_t fp, PKT_public_key *pk);
|
void print_key_info_log (ctrl_t ctrl, int loglevel, int indent,
|
||||||
|
PKT_public_key *pk, int secret);
|
||||||
void print_card_key_info (estream_t fp, KBNODE keyblock);
|
void print_card_key_info (estream_t fp, KBNODE keyblock);
|
||||||
void print_key_line (ctrl_t ctrl, estream_t fp, PKT_public_key *pk, int secret);
|
void print_key_line (ctrl_t ctrl, estream_t fp, PKT_public_key *pk, int secret);
|
||||||
|
|
||||||
|
146
g10/mainproc.c
146
g10/mainproc.c
@ -506,19 +506,18 @@ print_pkenc_list (ctrl_t ctrl, struct pubkey_enc_list *list)
|
|||||||
for (; list; list = list->next)
|
for (; list; list = list->next)
|
||||||
{
|
{
|
||||||
PKT_public_key *pk;
|
PKT_public_key *pk;
|
||||||
const char *algstr;
|
char pkstrbuf[PUBKEY_STRING_SIZE];
|
||||||
|
char *p;
|
||||||
|
|
||||||
algstr = openpgp_pk_algo_name (list->pubkey_algo);
|
|
||||||
pk = xmalloc_clear (sizeof *pk);
|
pk = xmalloc_clear (sizeof *pk);
|
||||||
|
|
||||||
if (!algstr)
|
|
||||||
algstr = "[?]";
|
|
||||||
pk->pubkey_algo = list->pubkey_algo;
|
pk->pubkey_algo = list->pubkey_algo;
|
||||||
if (!get_pubkey (ctrl, pk, list->keyid))
|
if (!get_pubkey (ctrl, pk, list->keyid))
|
||||||
{
|
{
|
||||||
char *p;
|
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf);
|
||||||
log_info (_("encrypted with %u-bit %s key, ID %s, created %s\n"),
|
|
||||||
nbits_from_pk (pk), algstr, keystr_from_pk(pk),
|
log_info (_("encrypted with %s key, ID %s, created %s\n"),
|
||||||
|
pkstrbuf, keystr_from_pk (pk),
|
||||||
strtimestamp (pk->timestamp));
|
strtimestamp (pk->timestamp));
|
||||||
p = get_user_id_native (ctrl, list->keyid);
|
p = get_user_id_native (ctrl, list->keyid);
|
||||||
log_printf (_(" \"%s\"\n"), p);
|
log_printf (_(" \"%s\"\n"), p);
|
||||||
@ -526,7 +525,8 @@ print_pkenc_list (ctrl_t ctrl, struct pubkey_enc_list *list)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
log_info (_("encrypted with %s key, ID %s\n"),
|
log_info (_("encrypted with %s key, ID %s\n"),
|
||||||
algstr, keystr(list->keyid));
|
openpgp_pk_algo_name (list->pubkey_algo),
|
||||||
|
keystr(list->keyid));
|
||||||
|
|
||||||
free_public_key (pk);
|
free_public_key (pk);
|
||||||
}
|
}
|
||||||
@ -574,7 +574,7 @@ proc_encrypted (CTX c, PACKET *pkt)
|
|||||||
write_status_error ("pkdecrypt_failed", result);
|
write_status_error ("pkdecrypt_failed", result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (c->pkenc_list)
|
||||||
{
|
{
|
||||||
c->dek = xmalloc_secure_clear (sizeof *c->dek);
|
c->dek = xmalloc_secure_clear (sizeof *c->dek);
|
||||||
result = get_session_key (c->ctrl, c->pkenc_list, c->dek);
|
result = get_session_key (c->ctrl, c->pkenc_list, c->dek);
|
||||||
@ -583,7 +583,7 @@ proc_encrypted (CTX c, PACKET *pkt)
|
|||||||
struct pubkey_enc_list *list;
|
struct pubkey_enc_list *list;
|
||||||
|
|
||||||
for (list = c->pkenc_list; list; list = list->next)
|
for (list = c->pkenc_list; list; list = list->next)
|
||||||
if (list->result == GPG_ERR_NO_SECKEY)
|
if (list->result != -1)
|
||||||
{
|
{
|
||||||
char buf[20];
|
char buf[20];
|
||||||
snprintf (buf, sizeof buf, "%08lX%08lX",
|
snprintf (buf, sizeof buf, "%08lX%08lX",
|
||||||
@ -668,7 +668,13 @@ proc_encrypted (CTX c, PACKET *pkt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!c->dek)
|
else if (!c->dek)
|
||||||
result = GPG_ERR_NO_SECKEY;
|
{
|
||||||
|
if (c->symkeys && !c->pkenc_list)
|
||||||
|
result = gpg_error (GPG_ERR_BAD_KEY);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
result = gpg_error (GPG_ERR_NO_SECKEY);
|
||||||
|
}
|
||||||
|
|
||||||
/* Compute compliance with CO_DE_VS. */
|
/* Compute compliance with CO_DE_VS. */
|
||||||
if (!result && is_status_enabled ()
|
if (!result && is_status_enabled ()
|
||||||
@ -780,7 +786,7 @@ proc_encrypted (CTX c, PACKET *pkt)
|
|||||||
if ((gpg_err_code (result) == GPG_ERR_BAD_KEY
|
if ((gpg_err_code (result) == GPG_ERR_BAD_KEY
|
||||||
|| gpg_err_code (result) == GPG_ERR_CHECKSUM
|
|| gpg_err_code (result) == GPG_ERR_CHECKSUM
|
||||||
|| gpg_err_code (result) == GPG_ERR_CIPHER_ALGO)
|
|| gpg_err_code (result) == GPG_ERR_CIPHER_ALGO)
|
||||||
&& *c->dek->s2k_cacheid != '\0')
|
&& c->dek && *c->dek->s2k_cacheid != '\0')
|
||||||
{
|
{
|
||||||
if (opt.debug)
|
if (opt.debug)
|
||||||
log_debug ("cleared passphrase cached with ID: %s\n",
|
log_debug ("cleared passphrase cached with ID: %s\n",
|
||||||
@ -1840,7 +1846,6 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||||||
int is_revkey = 0;
|
int is_revkey = 0;
|
||||||
char *issuer_fpr = NULL;
|
char *issuer_fpr = NULL;
|
||||||
PKT_public_key *pk = NULL; /* The public key for the signature or NULL. */
|
PKT_public_key *pk = NULL; /* The public key for the signature or NULL. */
|
||||||
int tried_ks_by_fpr;
|
|
||||||
const void *extrahash = NULL;
|
const void *extrahash = NULL;
|
||||||
size_t extrahashlen = 0;
|
size_t extrahashlen = 0;
|
||||||
|
|
||||||
@ -1999,12 +2004,17 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||||||
rc = do_check_sig (c, node, extrahash, extrahashlen,
|
rc = do_check_sig (c, node, extrahash, extrahashlen,
|
||||||
NULL, &is_expkey, &is_revkey, &pk);
|
NULL, &is_expkey, &is_revkey, &pk);
|
||||||
|
|
||||||
/* If the key isn't found, check for a preferred keyserver. */
|
/* If the key isn't found, check for a preferred keyserver. Note
|
||||||
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && sig->flags.pref_ks)
|
* that this is only done if honor-keyserver-url has been set. We
|
||||||
|
* test for this in the loop so that we can show info about the
|
||||||
|
* preferred keyservers. */
|
||||||
|
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
|
||||||
|
&& sig->flags.pref_ks)
|
||||||
{
|
{
|
||||||
const byte *p;
|
const byte *p;
|
||||||
int seq = 0;
|
int seq = 0;
|
||||||
size_t n;
|
size_t n;
|
||||||
|
int any_pref_ks = 0;
|
||||||
|
|
||||||
while ((p=enum_sig_subpkt (sig->hashed,SIGSUBPKT_PREF_KS,&n,&seq,NULL)))
|
while ((p=enum_sig_subpkt (sig->hashed,SIGSUBPKT_PREF_KS,&n,&seq,NULL)))
|
||||||
{
|
{
|
||||||
@ -2015,9 +2025,10 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||||||
log_info(_("Key available at: ") );
|
log_info(_("Key available at: ") );
|
||||||
print_utf8_buffer (log_get_stream(), p, n);
|
print_utf8_buffer (log_get_stream(), p, n);
|
||||||
log_printf ("\n");
|
log_printf ("\n");
|
||||||
|
any_pref_ks = 1;
|
||||||
|
|
||||||
if (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE
|
if ((opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)
|
||||||
&& opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL)
|
&& (opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL))
|
||||||
{
|
{
|
||||||
struct keyserver_spec *spec;
|
struct keyserver_spec *spec;
|
||||||
|
|
||||||
@ -2026,6 +2037,10 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
if (DBG_LOOKUP)
|
||||||
|
log_debug ("trying auto-key-retrieve method %s\n",
|
||||||
|
"Pref-KS");
|
||||||
|
|
||||||
free_public_key (pk);
|
free_public_key (pk);
|
||||||
pk = NULL;
|
pk = NULL;
|
||||||
glo_ctrl.in_auto_key_retrieve++;
|
glo_ctrl.in_auto_key_retrieve++;
|
||||||
@ -2034,6 +2049,9 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||||||
if (!res)
|
if (!res)
|
||||||
rc = do_check_sig (c, node, extrahash, extrahashlen,
|
rc = do_check_sig (c, node, extrahash, extrahashlen,
|
||||||
NULL, &is_expkey, &is_revkey, &pk);
|
NULL, &is_expkey, &is_revkey, &pk);
|
||||||
|
else if (DBG_LOOKUP)
|
||||||
|
log_debug ("lookup via %s failed: %s\n", "Pref-KS",
|
||||||
|
gpg_strerror (res));
|
||||||
free_keyserver_spec (spec);
|
free_keyserver_spec (spec);
|
||||||
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
@ -2041,10 +2059,44 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (any_pref_ks
|
||||||
|
&& (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)
|
||||||
|
&& !(opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL))
|
||||||
|
log_info (_("Note: Use '%s' to make use of this info\n"),
|
||||||
|
"--keyserver-option honor-keyserver-url");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the above methods didn't work, our next try is to retrieve the
|
||||||
|
* key from the WKD. This requires that WKD is in the AKL and the
|
||||||
|
* Signer's UID is in the signature. */
|
||||||
|
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
|
||||||
|
&& (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE)
|
||||||
|
&& !opt.flags.disable_signer_uid
|
||||||
|
&& akl_has_wkd_method ()
|
||||||
|
&& sig->signers_uid)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (DBG_LOOKUP)
|
||||||
|
log_debug ("trying auto-key-retrieve method %s\n", "WKD");
|
||||||
|
free_public_key (pk);
|
||||||
|
pk = NULL;
|
||||||
|
glo_ctrl.in_auto_key_retrieve++;
|
||||||
|
res = keyserver_import_wkd (c->ctrl, sig->signers_uid, 1, 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. */
|
||||||
|
if (!res)
|
||||||
|
rc = do_check_sig (c, node, extrahash, extrahashlen,
|
||||||
|
NULL, &is_expkey, &is_revkey, &pk);
|
||||||
|
else if (DBG_LOOKUP)
|
||||||
|
log_debug ("lookup via %s failed: %s\n", "WKD", gpg_strerror (res));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the avove methods didn't work, our next try is to use the URI
|
/* If the avove methods didn't work, our next try is to use the URI
|
||||||
* from a DNS PKA record. */
|
* from a DNS PKA record. This is a legacy method which will
|
||||||
|
* eventually be removed. */
|
||||||
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
|
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
|
||||||
&& (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE)
|
&& (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE)
|
||||||
&& (opt.keyserver_options.options & KEYSERVER_HONOR_PKA_RECORD))
|
&& (opt.keyserver_options.options & KEYSERVER_HONOR_PKA_RECORD))
|
||||||
@ -2061,6 +2113,9 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||||||
spec = parse_keyserver_uri (uri, 1);
|
spec = parse_keyserver_uri (uri, 1);
|
||||||
if (spec)
|
if (spec)
|
||||||
{
|
{
|
||||||
|
if (DBG_LOOKUP)
|
||||||
|
log_debug ("trying auto-key-retrieve method %s\n", "PKA");
|
||||||
|
|
||||||
free_public_key (pk);
|
free_public_key (pk);
|
||||||
pk = NULL;
|
pk = NULL;
|
||||||
glo_ctrl.in_auto_key_retrieve++;
|
glo_ctrl.in_auto_key_retrieve++;
|
||||||
@ -2070,16 +2125,16 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||||||
if (!res)
|
if (!res)
|
||||||
rc = do_check_sig (c, node, extrahash, extrahashlen,
|
rc = do_check_sig (c, node, extrahash, extrahashlen,
|
||||||
NULL, &is_expkey, &is_revkey, &pk);
|
NULL, &is_expkey, &is_revkey, &pk);
|
||||||
|
else if (DBG_LOOKUP)
|
||||||
|
log_debug ("lookup via %s failed: %s\n", "PKA",
|
||||||
|
gpg_strerror (res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the above methods didn't work, our next try is to locate
|
/* If the above methods didn't work, our next try is to locate
|
||||||
* the key via its fingerprint from a keyserver. This requires
|
* the key via its fingerprint from a keyserver. This requires
|
||||||
* that the signers fingerprint is encoded in the signature. We
|
* that the signers fingerprint is encoded in the signature. */
|
||||||
* favor this over the WKD method (to be tried next), because an
|
|
||||||
* arbitrary keyserver is less subject to web bug like monitoring. */
|
|
||||||
tried_ks_by_fpr = 0;
|
|
||||||
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
|
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
|
||||||
&& (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)
|
&& (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)
|
||||||
&& keyserver_any_configured (c->ctrl))
|
&& keyserver_any_configured (c->ctrl))
|
||||||
@ -2091,60 +2146,23 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||||||
p = issuer_fpr_raw (sig, &n);
|
p = issuer_fpr_raw (sig, &n);
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
|
if (DBG_LOOKUP)
|
||||||
|
log_debug ("trying auto-key-retrieve method %s\n", "KS");
|
||||||
|
|
||||||
/* v4 or v5 packet with a SHA-1/256 fingerprint. */
|
/* v4 or v5 packet with a SHA-1/256 fingerprint. */
|
||||||
free_public_key (pk);
|
free_public_key (pk);
|
||||||
pk = NULL;
|
pk = NULL;
|
||||||
glo_ctrl.in_auto_key_retrieve++;
|
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, 1);
|
||||||
tried_ks_by_fpr = 1;
|
|
||||||
glo_ctrl.in_auto_key_retrieve--;
|
glo_ctrl.in_auto_key_retrieve--;
|
||||||
if (!res)
|
if (!res)
|
||||||
rc = do_check_sig (c, node, extrahash, extrahashlen,
|
rc = do_check_sig (c, node, extrahash, extrahashlen,
|
||||||
NULL, &is_expkey, &is_revkey, &pk);
|
NULL, &is_expkey, &is_revkey, &pk);
|
||||||
|
else if (DBG_LOOKUP)
|
||||||
|
log_debug ("lookup via %s failed: %s\n", "KS", gpg_strerror (res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the above methods didn't work, our next try is to retrieve the
|
|
||||||
* key from the WKD. */
|
|
||||||
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
|
|
||||||
&& (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE)
|
|
||||||
&& !opt.flags.disable_signer_uid
|
|
||||||
&& akl_has_wkd_method ()
|
|
||||||
&& sig->signers_uid)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
|
|
||||||
free_public_key (pk);
|
|
||||||
pk = NULL;
|
|
||||||
glo_ctrl.in_auto_key_retrieve++;
|
|
||||||
res = keyserver_import_wkd (c->ctrl, sig->signers_uid, 1, 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. */
|
|
||||||
if (!res)
|
|
||||||
rc = do_check_sig (c, node, extrahash, extrahashlen,
|
|
||||||
NULL, &is_expkey, &is_revkey, &pk);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the above methods did't work, our next try is to use a
|
|
||||||
* keyserver. */
|
|
||||||
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
|
|
||||||
&& (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)
|
|
||||||
&& !tried_ks_by_fpr
|
|
||||||
&& keyserver_any_configured (c->ctrl))
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
|
|
||||||
free_public_key (pk);
|
|
||||||
pk = NULL;
|
|
||||||
glo_ctrl.in_auto_key_retrieve++;
|
|
||||||
res = keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver, 1);
|
|
||||||
glo_ctrl.in_auto_key_retrieve--;
|
|
||||||
if (!res)
|
|
||||||
rc = do_check_sig (c, node, extrahash, extrahashlen,
|
|
||||||
NULL, &is_expkey, &is_revkey, &pk);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rc || gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE)
|
if (!rc || gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE)
|
||||||
{
|
{
|
||||||
kbnode_t un, keyblock;
|
kbnode_t un, keyblock;
|
||||||
|
689
g10/objcache.c
Normal file
689
g10/objcache.c
Normal file
@ -0,0 +1,689 @@
|
|||||||
|
/* objcache.c - Caching functions for keys and user ids.
|
||||||
|
* Copyright (C) 2019 g10 Code GmbH
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG 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, see <https://www.gnu.org/licenses/>.
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gpg.h"
|
||||||
|
#include "../common/util.h"
|
||||||
|
#include "packet.h"
|
||||||
|
#include "keydb.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "objcache.h"
|
||||||
|
|
||||||
|
/* Note that max value for uid_items is actually a the threshold when
|
||||||
|
* we start to look for ietms which can be removed. */
|
||||||
|
#define NO_OF_UID_ITEM_BUCKETS 107
|
||||||
|
#define MAX_UID_ITEMS_PER_BUCKET 20
|
||||||
|
|
||||||
|
#define NO_OF_KEY_ITEM_BUCKETS 383
|
||||||
|
#define MAX_KEY_ITEMS_PER_BUCKET 20
|
||||||
|
|
||||||
|
|
||||||
|
/* An object to store a user id. This describes an item in the linked
|
||||||
|
* lists of a bucket in hash table. The reference count will
|
||||||
|
* eventually be used to remove items from the table. */
|
||||||
|
typedef struct uid_item_s
|
||||||
|
{
|
||||||
|
struct uid_item_s *next;
|
||||||
|
unsigned int refcount; /* The reference count for this item. */
|
||||||
|
unsigned int namelen; /* The length of the UID sans the nul. */
|
||||||
|
char name[1];
|
||||||
|
} *uid_item_t;
|
||||||
|
|
||||||
|
static uid_item_t *uid_table; /* Hash table for with user ids. */
|
||||||
|
static size_t uid_table_size; /* Number of allocated buckets. */
|
||||||
|
static unsigned int uid_table_max; /* Max. # of items in a bucket. */
|
||||||
|
static unsigned int uid_table_added; /* # of items added. */
|
||||||
|
static unsigned int uid_table_dropped;/* # of items dropped. */
|
||||||
|
|
||||||
|
|
||||||
|
/* An object to store properties of a key. Note that this can be used
|
||||||
|
* for a primary or a subkey. The key is linked to a user if that
|
||||||
|
* exists. */
|
||||||
|
typedef struct key_item_s
|
||||||
|
{
|
||||||
|
struct key_item_s *next;
|
||||||
|
unsigned int usecount;
|
||||||
|
byte fprlen;
|
||||||
|
char fpr[MAX_FINGERPRINT_LEN];
|
||||||
|
u32 keyid[2];
|
||||||
|
uid_item_t ui; /* NULL of a ref'ed user id item. */
|
||||||
|
} *key_item_t;
|
||||||
|
|
||||||
|
static key_item_t *key_table; /* Hash table with the keys. */
|
||||||
|
static size_t key_table_size; /* Number of allocated buckents. */
|
||||||
|
static unsigned int key_table_max; /* Max. # of items in a bucket. */
|
||||||
|
static unsigned int key_table_added; /* # of items added. */
|
||||||
|
static unsigned int key_table_dropped;/* # of items dropped. */
|
||||||
|
static key_item_t key_item_attic; /* List of freed items. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Dump stats. */
|
||||||
|
void
|
||||||
|
objcache_dump_stats (void)
|
||||||
|
{
|
||||||
|
unsigned int idx;
|
||||||
|
int len, minlen, maxlen;
|
||||||
|
unsigned int count, attic, empty;
|
||||||
|
key_item_t ki;
|
||||||
|
uid_item_t ui;
|
||||||
|
|
||||||
|
count = empty = 0;
|
||||||
|
minlen = -1;
|
||||||
|
maxlen = 0;
|
||||||
|
for (idx = 0; idx < key_table_size; idx++)
|
||||||
|
{
|
||||||
|
len = 0;
|
||||||
|
for (ki = key_table[idx]; ki; ki = ki->next)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
len++;
|
||||||
|
/* log_debug ("key bucket %u: kid=%08lX used=%u ui=%p\n", */
|
||||||
|
/* idx, (ulong)ki->keyid[0], ki->usecount, ki->ui); */
|
||||||
|
}
|
||||||
|
if (len > maxlen)
|
||||||
|
maxlen = len;
|
||||||
|
|
||||||
|
if (!len)
|
||||||
|
empty++;
|
||||||
|
else if (minlen == -1 || len < minlen)
|
||||||
|
minlen = len;
|
||||||
|
}
|
||||||
|
for (attic=0, ki = key_item_attic; ki; ki = ki->next)
|
||||||
|
attic++;
|
||||||
|
log_info ("objcache: keys=%u/%u/%u chains=%u,%d..%d buckets=%zu/%u"
|
||||||
|
" attic=%u\n",
|
||||||
|
count, key_table_added, key_table_dropped,
|
||||||
|
empty, minlen > 0? minlen : 0, maxlen,
|
||||||
|
key_table_size, key_table_max, attic);
|
||||||
|
|
||||||
|
count = empty = 0;
|
||||||
|
minlen = -1;
|
||||||
|
maxlen = 0;
|
||||||
|
for (idx = 0; idx < uid_table_size; idx++)
|
||||||
|
{
|
||||||
|
len = 0;
|
||||||
|
for (ui = uid_table[idx]; ui; ui = ui->next)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
len++;
|
||||||
|
/* log_debug ("uid bucket %u: %p ref=%u l=%u (%.20s)\n", */
|
||||||
|
/* idx, ui, ui->refcount, ui->namelen, ui->name); */
|
||||||
|
}
|
||||||
|
if (len > maxlen)
|
||||||
|
maxlen = len;
|
||||||
|
|
||||||
|
if (!len)
|
||||||
|
empty++;
|
||||||
|
else if (minlen == -1 || len < minlen)
|
||||||
|
minlen = len;
|
||||||
|
}
|
||||||
|
log_info ("objcache: uids=%u/%u/%u chains=%u,%d..%d buckets=%zu/%u\n",
|
||||||
|
count, uid_table_added, uid_table_dropped,
|
||||||
|
empty, minlen > 0? minlen : 0, maxlen,
|
||||||
|
uid_table_size, uid_table_max);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* The hash function we use for the uid_table. Must not call a system
|
||||||
|
* function. */
|
||||||
|
static inline unsigned int
|
||||||
|
uid_table_hasher (const char *name, unsigned namelen)
|
||||||
|
{
|
||||||
|
const unsigned char *s = (const unsigned char*)name;
|
||||||
|
unsigned int hashval = 0;
|
||||||
|
unsigned int carry;
|
||||||
|
|
||||||
|
for (; namelen; namelen--, s++)
|
||||||
|
{
|
||||||
|
hashval = (hashval << 4) + *s;
|
||||||
|
if ((carry = (hashval & 0xf0000000)))
|
||||||
|
{
|
||||||
|
hashval ^= (carry >> 24);
|
||||||
|
hashval ^= carry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashval % uid_table_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Run time allocation of the uid table. This allows us to eventually
|
||||||
|
* add an option to gpg to control the size. */
|
||||||
|
static void
|
||||||
|
uid_table_init (void)
|
||||||
|
{
|
||||||
|
if (uid_table)
|
||||||
|
return;
|
||||||
|
uid_table_size = NO_OF_UID_ITEM_BUCKETS;
|
||||||
|
uid_table_max = MAX_UID_ITEMS_PER_BUCKET;
|
||||||
|
uid_table = xcalloc (uid_table_size, sizeof *uid_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uid_item_t
|
||||||
|
uid_item_ref (uid_item_t ui)
|
||||||
|
{
|
||||||
|
if (ui)
|
||||||
|
ui->refcount++;
|
||||||
|
return ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
uid_item_unref (uid_item_t uid)
|
||||||
|
{
|
||||||
|
if (!uid)
|
||||||
|
return;
|
||||||
|
if (!uid->refcount)
|
||||||
|
log_fatal ("too many unrefs for uid_item\n");
|
||||||
|
|
||||||
|
uid->refcount--;
|
||||||
|
/* We do not release the item here because that would require that
|
||||||
|
* we locate the head of the list which has this item. This will
|
||||||
|
* take too long and thus the item is removed when we need to purge
|
||||||
|
* some items for the list during uid_item_put. */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Put (NAME,NAMELEN) into the UID_TABLE and return the item. The
|
||||||
|
* reference count for that item is incremented. NULL is return on an
|
||||||
|
* allocation error. The caller should release the returned item
|
||||||
|
* using uid_item_unref. */
|
||||||
|
static uid_item_t
|
||||||
|
uid_table_put (const char *name, unsigned int namelen)
|
||||||
|
{
|
||||||
|
unsigned int hash;
|
||||||
|
uid_item_t ui;
|
||||||
|
unsigned int count;
|
||||||
|
|
||||||
|
if (!uid_table)
|
||||||
|
uid_table_init ();
|
||||||
|
|
||||||
|
hash = uid_table_hasher (name, namelen);
|
||||||
|
for (ui = uid_table[hash], count = 0; ui; ui = ui->next, count++)
|
||||||
|
if (ui->namelen == namelen && !memcmp (ui->name, name, namelen))
|
||||||
|
return uid_item_ref (ui); /* Found. */
|
||||||
|
|
||||||
|
/* If the bucket is full remove all unrefed items. */
|
||||||
|
if (count >= uid_table_max)
|
||||||
|
{
|
||||||
|
uid_item_t ui_next, ui_prev, list_head, drop_head;
|
||||||
|
|
||||||
|
/* No syscalls from here .. */
|
||||||
|
list_head = uid_table[hash];
|
||||||
|
drop_head = NULL;
|
||||||
|
while (list_head && !list_head->refcount)
|
||||||
|
{
|
||||||
|
ui = list_head;
|
||||||
|
list_head = ui->next;
|
||||||
|
ui->next = drop_head;
|
||||||
|
drop_head = ui;
|
||||||
|
}
|
||||||
|
if ((ui_prev = list_head))
|
||||||
|
for (ui = ui_prev->next; ui; ui = ui_next)
|
||||||
|
{
|
||||||
|
ui_next = ui->next;
|
||||||
|
if (!ui->refcount)
|
||||||
|
{
|
||||||
|
ui->next = drop_head;
|
||||||
|
drop_head = ui;
|
||||||
|
ui_prev->next = ui_next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ui_prev = ui;
|
||||||
|
}
|
||||||
|
uid_table[hash] = list_head;
|
||||||
|
/* ... to here */
|
||||||
|
|
||||||
|
for (ui = drop_head; ui; ui = ui_next)
|
||||||
|
{
|
||||||
|
ui_next = ui->next;
|
||||||
|
xfree (ui);
|
||||||
|
uid_table_dropped++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count = uid_table_added + uid_table_dropped;
|
||||||
|
ui = xtrycalloc (1, sizeof *ui + namelen);
|
||||||
|
if (!ui)
|
||||||
|
return NULL; /* Out of core. */
|
||||||
|
if (count != uid_table_added + uid_table_dropped)
|
||||||
|
{
|
||||||
|
/* During the malloc another thread added an item. Thus we need
|
||||||
|
* to check again. */
|
||||||
|
uid_item_t ui_new = ui;
|
||||||
|
for (ui = uid_table[hash]; ui; ui = ui->next)
|
||||||
|
if (ui->namelen == namelen && !memcmp (ui->name, name, namelen))
|
||||||
|
{
|
||||||
|
/* Found. */
|
||||||
|
xfree (ui_new);
|
||||||
|
return uid_item_ref (ui);
|
||||||
|
}
|
||||||
|
ui = ui_new;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (ui->name, name, namelen);
|
||||||
|
ui->name[namelen] = 0; /* Extra Nul so we can use it as a string. */
|
||||||
|
ui->namelen = namelen;
|
||||||
|
ui->refcount = 1;
|
||||||
|
ui->next = uid_table[hash];
|
||||||
|
uid_table[hash] = ui;
|
||||||
|
uid_table_added++;
|
||||||
|
return ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* The hash function we use for the key_table. Must not call a system
|
||||||
|
* function. */
|
||||||
|
static inline unsigned int
|
||||||
|
key_table_hasher (u32 *keyid)
|
||||||
|
{
|
||||||
|
/* A fingerprint could be used directly as a hash value. However,
|
||||||
|
* we use the keyid here because it is used in encrypted packets and
|
||||||
|
* older signatures to identify a key. Since v4 keys the keyid is
|
||||||
|
* anyway a part of the fingerprint so it quickly extracted from a
|
||||||
|
* fingerprint. Note that v3 keys are not supported by gpg. */
|
||||||
|
return keyid[0] % key_table_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Run time allocation of the key table. This allows us to eventually
|
||||||
|
* add an option to gpg to control the size. */
|
||||||
|
static void
|
||||||
|
key_table_init (void)
|
||||||
|
{
|
||||||
|
if (key_table)
|
||||||
|
return;
|
||||||
|
key_table_size = NO_OF_KEY_ITEM_BUCKETS;
|
||||||
|
key_table_max = MAX_KEY_ITEMS_PER_BUCKET;
|
||||||
|
key_table = xcalloc (key_table_size, sizeof *key_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
key_item_free (key_item_t ki)
|
||||||
|
{
|
||||||
|
if (!ki)
|
||||||
|
return;
|
||||||
|
uid_item_unref (ki->ui);
|
||||||
|
ki->ui = NULL;
|
||||||
|
ki->next = key_item_attic;
|
||||||
|
key_item_attic = ki;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get a key item from PK or if that is NULL from KEYID. The
|
||||||
|
* reference count for that item is incremented. NULL is return if it
|
||||||
|
* was not found. */
|
||||||
|
static key_item_t
|
||||||
|
key_table_get (PKT_public_key *pk, u32 *keyid)
|
||||||
|
{
|
||||||
|
unsigned int hash;
|
||||||
|
key_item_t ki, ki2;
|
||||||
|
|
||||||
|
if (!key_table)
|
||||||
|
key_table_init ();
|
||||||
|
|
||||||
|
if (pk)
|
||||||
|
{
|
||||||
|
byte fpr[MAX_FINGERPRINT_LEN];
|
||||||
|
size_t fprlen;
|
||||||
|
u32 tmpkeyid[2];
|
||||||
|
|
||||||
|
fingerprint_from_pk (pk, fpr, &fprlen);
|
||||||
|
keyid_from_pk (pk, tmpkeyid);
|
||||||
|
hash = key_table_hasher (tmpkeyid);
|
||||||
|
for (ki = key_table[hash]; ki; ki = ki->next)
|
||||||
|
if (ki->fprlen == fprlen && !memcmp (ki->fpr, fpr, fprlen))
|
||||||
|
return ki; /* Found */
|
||||||
|
}
|
||||||
|
else if (keyid)
|
||||||
|
{
|
||||||
|
hash = key_table_hasher (keyid);
|
||||||
|
for (ki = key_table[hash]; ki; ki = ki->next)
|
||||||
|
if (ki->keyid[0] == keyid[0] && ki->keyid[1] == keyid[1])
|
||||||
|
{
|
||||||
|
/* Found. We need to check for dups. */
|
||||||
|
for (ki2 = ki->next; ki2; ki2 = ki2->next)
|
||||||
|
if (ki2->keyid[0] == keyid[0] && ki2->keyid[1] == keyid[1])
|
||||||
|
return NULL; /* Duplicated keyid - retrun NULL. */
|
||||||
|
|
||||||
|
/* This is the only one - return it. */
|
||||||
|
return ki;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper for the qsort in key_table_put. */
|
||||||
|
static int
|
||||||
|
compare_key_items (const void *arg_a, const void *arg_b)
|
||||||
|
{
|
||||||
|
const key_item_t a = *(const key_item_t *)arg_a;
|
||||||
|
const key_item_t b = *(const key_item_t *)arg_b;
|
||||||
|
|
||||||
|
/* Reverse sort on the usecount. */
|
||||||
|
if (a->usecount > b->usecount)
|
||||||
|
return -1;
|
||||||
|
else if (a->usecount == b->usecount)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Put PK into the KEY_TABLE and return a key item. The reference
|
||||||
|
* count for that item is incremented. If UI is given it is put into
|
||||||
|
* the entry. NULL is return on an allocation error. */
|
||||||
|
static key_item_t
|
||||||
|
key_table_put (PKT_public_key *pk, uid_item_t ui)
|
||||||
|
{
|
||||||
|
unsigned int hash;
|
||||||
|
key_item_t ki;
|
||||||
|
u32 keyid[2];
|
||||||
|
byte fpr[MAX_FINGERPRINT_LEN];
|
||||||
|
size_t fprlen;
|
||||||
|
unsigned int count, n;
|
||||||
|
|
||||||
|
if (!key_table)
|
||||||
|
key_table_init ();
|
||||||
|
|
||||||
|
fingerprint_from_pk (pk, fpr, &fprlen);
|
||||||
|
keyid_from_pk (pk, keyid);
|
||||||
|
hash = key_table_hasher (keyid);
|
||||||
|
for (ki = key_table[hash], count=0; ki; ki = ki->next, count++)
|
||||||
|
if (ki->fprlen == fprlen && !memcmp (ki->fpr, fpr, fprlen))
|
||||||
|
return ki; /* Found */
|
||||||
|
|
||||||
|
/* If the bucket is full remove a couple of items. */
|
||||||
|
if (count >= key_table_max)
|
||||||
|
{
|
||||||
|
key_item_t list_head, *list_tailp, ki_next;
|
||||||
|
key_item_t *array;
|
||||||
|
int narray, idx;
|
||||||
|
|
||||||
|
/* Unlink from the global list so that other threads don't
|
||||||
|
* disturb us. If another thread adds or removes something only
|
||||||
|
* one will be the winner. Bad luck for the drooped cache items
|
||||||
|
* but after all it is just a cache. */
|
||||||
|
list_head = key_table[hash];
|
||||||
|
key_table[hash] = NULL;
|
||||||
|
|
||||||
|
/* Put all items into an array for sorting. */
|
||||||
|
array = xtrycalloc (count, sizeof *array);
|
||||||
|
if (!array)
|
||||||
|
{
|
||||||
|
/* That's bad; give up all items of the bucket. */
|
||||||
|
log_info ("Note: malloc failed while purging from the key_tabe: %s\n",
|
||||||
|
gpg_strerror (gpg_error_from_syserror ()));
|
||||||
|
goto leave_drop;
|
||||||
|
}
|
||||||
|
narray = 0;
|
||||||
|
for (ki = list_head; ki; ki = ki_next)
|
||||||
|
{
|
||||||
|
ki_next = ki->next;
|
||||||
|
array[narray++] = ki;
|
||||||
|
ki->next = NULL;
|
||||||
|
}
|
||||||
|
log_assert (narray == count);
|
||||||
|
|
||||||
|
/* Sort the array and put half of it onto a new list. */
|
||||||
|
qsort (array, narray, sizeof *array, compare_key_items);
|
||||||
|
list_head = NULL;
|
||||||
|
list_tailp = &list_head;
|
||||||
|
for (idx=0; idx < narray/2; idx++)
|
||||||
|
{
|
||||||
|
*list_tailp = array[idx];
|
||||||
|
list_tailp = &array[idx]->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put the new list into the bucket. */
|
||||||
|
ki = key_table[hash];
|
||||||
|
key_table[hash] = list_head;
|
||||||
|
list_head = ki;
|
||||||
|
|
||||||
|
/* Free the remaining items and the array. */
|
||||||
|
for (; idx < narray; idx++)
|
||||||
|
{
|
||||||
|
key_item_free (array[idx]);
|
||||||
|
key_table_dropped++;
|
||||||
|
}
|
||||||
|
xfree (array);
|
||||||
|
|
||||||
|
leave_drop:
|
||||||
|
/* Free any items added in the meantime by other threads. This
|
||||||
|
* is also used in case of a malloc problem (which won't update
|
||||||
|
* the counters, though). */
|
||||||
|
for ( ; list_head; list_head = ki_next)
|
||||||
|
{
|
||||||
|
ki_next = list_head->next;
|
||||||
|
key_item_free (list_head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add an item to the bucket. We allocate a whole block of items
|
||||||
|
* for cache performace reasons. */
|
||||||
|
if (!key_item_attic)
|
||||||
|
{
|
||||||
|
key_item_t kiblock;
|
||||||
|
int kiblocksize = 256;
|
||||||
|
|
||||||
|
kiblock = xtrymalloc (kiblocksize * sizeof *kiblock);
|
||||||
|
if (!kiblock)
|
||||||
|
return NULL; /* Out of core. */
|
||||||
|
for (n = 0; n < kiblocksize; n++)
|
||||||
|
{
|
||||||
|
ki = kiblock + n;
|
||||||
|
ki->next = key_item_attic;
|
||||||
|
key_item_attic = ki;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* During the malloc another thread may have changed the bucket.
|
||||||
|
* Thus we need to check again. */
|
||||||
|
for (ki = key_table[hash]; ki; ki = ki->next)
|
||||||
|
if (ki->fprlen == fprlen && !memcmp (ki->fpr, fpr, fprlen))
|
||||||
|
return ki; /* Found */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We now know that there is an item in the attic. */
|
||||||
|
ki = key_item_attic;
|
||||||
|
key_item_attic = ki->next;
|
||||||
|
ki->next = NULL;
|
||||||
|
|
||||||
|
memcpy (ki->fpr, fpr, fprlen);
|
||||||
|
ki->fprlen = fprlen;
|
||||||
|
ki->keyid[0] = keyid[0];
|
||||||
|
ki->keyid[1] = keyid[1];
|
||||||
|
ki->ui = uid_item_ref (ui);
|
||||||
|
ki->usecount = 0;
|
||||||
|
ki->next = key_table[hash];
|
||||||
|
key_table[hash] = ki;
|
||||||
|
key_table_added++;
|
||||||
|
return ki;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the user ID from the given keyblock. We use the primary uid
|
||||||
|
* flag which should have already been set. The returned value is
|
||||||
|
* only valid as long as the given keyblock is not changed. */
|
||||||
|
static const char *
|
||||||
|
primary_uid_from_keyblock (kbnode_t keyblock, size_t *uidlen)
|
||||||
|
{
|
||||||
|
kbnode_t k;
|
||||||
|
|
||||||
|
for (k = keyblock; k; k = k->next)
|
||||||
|
{
|
||||||
|
if (k->pkt->pkttype == PKT_USER_ID
|
||||||
|
&& !k->pkt->pkt.user_id->attrib_data
|
||||||
|
&& k->pkt->pkt.user_id->flags.primary)
|
||||||
|
{
|
||||||
|
*uidlen = k->pkt->pkt.user_id->len;
|
||||||
|
return k->pkt->pkt.user_id->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Store the associations of keyid/fingerprint and userid. Only
|
||||||
|
* public keys should be fed to this function. */
|
||||||
|
void
|
||||||
|
cache_put_keyblock (kbnode_t keyblock)
|
||||||
|
{
|
||||||
|
uid_item_t ui = NULL;
|
||||||
|
kbnode_t k;
|
||||||
|
|
||||||
|
restart:
|
||||||
|
for (k = keyblock; k; k = k->next)
|
||||||
|
{
|
||||||
|
if (k->pkt->pkttype == PKT_PUBLIC_KEY
|
||||||
|
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
||||||
|
{
|
||||||
|
if (!ui)
|
||||||
|
{
|
||||||
|
/* Initially we just test for an entry to avoid the need
|
||||||
|
* to create a user id item for a put. Only if we miss
|
||||||
|
* key in the cache we create a user id and restart. */
|
||||||
|
if (!key_table_get (k->pkt->pkt.public_key, NULL))
|
||||||
|
{
|
||||||
|
const char *uid;
|
||||||
|
size_t uidlen;
|
||||||
|
|
||||||
|
uid = primary_uid_from_keyblock (keyblock, &uidlen);
|
||||||
|
if (uid)
|
||||||
|
{
|
||||||
|
ui = uid_table_put (uid, uidlen);
|
||||||
|
if (!ui)
|
||||||
|
{
|
||||||
|
log_info ("Note: failed to cache a user id: %s\n",
|
||||||
|
gpg_strerror (gpg_error_from_syserror ()));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* With a UID we use the update cache mode. */
|
||||||
|
{
|
||||||
|
if (!key_table_put (k->pkt->pkt.public_key, ui))
|
||||||
|
{
|
||||||
|
log_info ("Note: failed to cache a key: %s\n",
|
||||||
|
gpg_strerror (gpg_error_from_syserror ()));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
uid_item_unref (ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the user id string for KEYID. If a user id is not found (or
|
||||||
|
* on malloc error) NULL is returned. If R_LENGTH is not NULL the
|
||||||
|
* length of the user id is stored there; this does not included the
|
||||||
|
* always appended nul. Note that a user id may include an internal
|
||||||
|
* nul which can be detected by the caller by comparing to the
|
||||||
|
* returned length. */
|
||||||
|
char *
|
||||||
|
cache_get_uid_bykid (u32 *keyid, unsigned int *r_length)
|
||||||
|
{
|
||||||
|
key_item_t ki;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (r_length)
|
||||||
|
*r_length = 0;
|
||||||
|
|
||||||
|
ki = key_table_get (NULL, keyid);
|
||||||
|
if (!ki)
|
||||||
|
return NULL; /* Not found or duplicate keyid. */
|
||||||
|
|
||||||
|
if (!ki->ui)
|
||||||
|
p = NULL; /* No user id known for key. */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = xtrymalloc (ki->ui->namelen + 1);
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
memcpy (p, ki->ui->name, ki->ui->namelen + 1);
|
||||||
|
if (r_length)
|
||||||
|
*r_length = ki->ui->namelen;
|
||||||
|
ki->usecount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the user id string for FPR with FPRLEN. If a user id is not
|
||||||
|
* found (or on malloc error) NULL is returned. If R_LENGTH is not
|
||||||
|
* NULL the length of the user id is stored there; this does not
|
||||||
|
* included the always appended nul. Note that a user id may include
|
||||||
|
* an internal nul which can be detected by the caller by comparing to
|
||||||
|
* the returned length. */
|
||||||
|
char *
|
||||||
|
cache_get_uid_byfpr (const byte *fpr, size_t fprlen, size_t *r_length)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
unsigned int hash;
|
||||||
|
u32 keyid[2];
|
||||||
|
key_item_t ki;
|
||||||
|
|
||||||
|
if (r_length)
|
||||||
|
*r_length = 0;
|
||||||
|
|
||||||
|
if (!key_table)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
keyid_from_fingerprint (NULL, fpr, fprlen, keyid);
|
||||||
|
hash = key_table_hasher (keyid);
|
||||||
|
for (ki = key_table[hash]; ki; ki = ki->next)
|
||||||
|
if (ki->fprlen == fprlen && !memcmp (ki->fpr, fpr, fprlen))
|
||||||
|
break; /* Found */
|
||||||
|
|
||||||
|
if (!ki)
|
||||||
|
return NULL; /* Not found. */
|
||||||
|
|
||||||
|
if (!ki->ui)
|
||||||
|
p = NULL; /* No user id known for key. */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = xtrymalloc (ki->ui->namelen + 1);
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
memcpy (p, ki->ui->name, ki->ui->namelen + 1);
|
||||||
|
if (r_length)
|
||||||
|
*r_length = ki->ui->namelen;
|
||||||
|
ki->usecount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
29
g10/objcache.h
Normal file
29
g10/objcache.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/* objcache.h - Caching functions for keys and user ids.
|
||||||
|
* Copyright (C) 2019 g10 Code GmbH
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG 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, see <https://www.gnu.org/licenses/>.
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GNUPG_G10_OBJCACHE_H
|
||||||
|
#define GNUPG_G10_OBJCACHE_H
|
||||||
|
|
||||||
|
void objcache_dump_stats (void);
|
||||||
|
void cache_put_keyblock (kbnode_t keyblock);
|
||||||
|
char *cache_get_uid_bykid (u32 *keyid, unsigned int *r_length);
|
||||||
|
char *cache_get_uid_byfpr (const byte *fpr, size_t fprlen, size_t *r_length);
|
||||||
|
|
||||||
|
#endif /*GNUPG_G10_OBJCACHE_H*/
|
@ -249,6 +249,8 @@ struct
|
|||||||
unsigned int disable_signer_uid:1;
|
unsigned int disable_signer_uid:1;
|
||||||
/* Flag to enable experimental features from RFC4880bis. */
|
/* Flag to enable experimental features from RFC4880bis. */
|
||||||
unsigned int rfc4880bis:1;
|
unsigned int rfc4880bis:1;
|
||||||
|
/* Hack: --output is not given but OUTFILE was temporary set to "-". */
|
||||||
|
unsigned int dummy_outfile:1;
|
||||||
} flags;
|
} flags;
|
||||||
|
|
||||||
/* Linked list of ways to find a key if the key isn't on the local
|
/* Linked list of ways to find a key if the key isn't on the local
|
||||||
@ -361,6 +363,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
|
|||||||
#define IMPORT_REPAIR_KEYS (1<<11)
|
#define IMPORT_REPAIR_KEYS (1<<11)
|
||||||
#define IMPORT_DRY_RUN (1<<12)
|
#define IMPORT_DRY_RUN (1<<12)
|
||||||
#define IMPORT_DROP_UIDS (1<<13)
|
#define IMPORT_DROP_UIDS (1<<13)
|
||||||
|
#define IMPORT_SELF_SIGS_ONLY (1<<14)
|
||||||
|
|
||||||
#define EXPORT_LOCAL_SIGS (1<<0)
|
#define EXPORT_LOCAL_SIGS (1<<0)
|
||||||
#define EXPORT_ATTRIBUTES (1<<1)
|
#define EXPORT_ATTRIBUTES (1<<1)
|
||||||
|
10
g10/packet.h
10
g10/packet.h
@ -33,6 +33,11 @@
|
|||||||
|
|
||||||
#define DEBUG_PARSE_PACKET 1
|
#define DEBUG_PARSE_PACKET 1
|
||||||
|
|
||||||
|
/* Maximum length of packets to avoid excessive memory allocation. */
|
||||||
|
#define MAX_KEY_PACKET_LENGTH (256 * 1024)
|
||||||
|
#define MAX_UID_PACKET_LENGTH ( 2 * 1024)
|
||||||
|
#define MAX_COMMENT_PACKET_LENGTH ( 64 * 1024)
|
||||||
|
#define MAX_ATTR_PACKET_LENGTH ( 16 * 1024*1024)
|
||||||
|
|
||||||
/* Constants to allocate static MPI arrays. */
|
/* Constants to allocate static MPI arrays. */
|
||||||
#define PUBKEY_MAX_NPKEY OPENPGP_MAX_NPKEY
|
#define PUBKEY_MAX_NPKEY OPENPGP_MAX_NPKEY
|
||||||
@ -394,6 +399,7 @@ typedef struct
|
|||||||
byte pubkey_algo;
|
byte pubkey_algo;
|
||||||
byte pubkey_usage; /* for now only used to pass it to getkey() */
|
byte pubkey_usage; /* for now only used to pass it to getkey() */
|
||||||
byte req_usage; /* hack to pass a request to getkey() */
|
byte req_usage; /* hack to pass a request to getkey() */
|
||||||
|
byte fprlen; /* 0 or length of FPR. */
|
||||||
u32 has_expired; /* set to the expiration date if expired */
|
u32 has_expired; /* set to the expiration date if expired */
|
||||||
/* keyid of the primary key. Never access this value directly.
|
/* keyid of the primary key. Never access this value directly.
|
||||||
Instead, use pk_main_keyid(). */
|
Instead, use pk_main_keyid(). */
|
||||||
@ -401,6 +407,8 @@ typedef struct
|
|||||||
/* keyid of this key. Never access this value directly! Instead,
|
/* keyid of this key. Never access this value directly! Instead,
|
||||||
use pk_keyid(). */
|
use pk_keyid(). */
|
||||||
u32 keyid[2];
|
u32 keyid[2];
|
||||||
|
/* Fingerprint of the key. Only valid if FPRLEN is not 0. */
|
||||||
|
byte fpr[MAX_FINGERPRINT_LEN];
|
||||||
prefitem_t *prefs; /* list of preferences (may be NULL) */
|
prefitem_t *prefs; /* list of preferences (may be NULL) */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@ -928,7 +936,7 @@ int ask_for_detached_datafile( gcry_md_hd_t md, gcry_md_hd_t md2,
|
|||||||
int make_keysig_packet (ctrl_t ctrl,
|
int make_keysig_packet (ctrl_t ctrl,
|
||||||
PKT_signature **ret_sig, PKT_public_key *pk,
|
PKT_signature **ret_sig, PKT_public_key *pk,
|
||||||
PKT_user_id *uid, PKT_public_key *subpk,
|
PKT_user_id *uid, PKT_public_key *subpk,
|
||||||
PKT_public_key *pksk, int sigclass, int digest_algo,
|
PKT_public_key *pksk, int sigclass,
|
||||||
u32 timestamp, u32 duration,
|
u32 timestamp, u32 duration,
|
||||||
int (*mksubpkt)(PKT_signature *, void *),
|
int (*mksubpkt)(PKT_signature *, void *),
|
||||||
void *opaque,
|
void *opaque,
|
||||||
|
@ -35,14 +35,9 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "../common/i18n.h"
|
#include "../common/i18n.h"
|
||||||
#include "../common/host2net.h"
|
#include "../common/host2net.h"
|
||||||
|
#include "../common/mbox-util.h"
|
||||||
|
|
||||||
|
|
||||||
/* Maximum length of packets to avoid excessive memory allocation. */
|
|
||||||
#define MAX_KEY_PACKET_LENGTH (256 * 1024)
|
|
||||||
#define MAX_UID_PACKET_LENGTH ( 2 * 1024)
|
|
||||||
#define MAX_COMMENT_PACKET_LENGTH ( 64 * 1024)
|
|
||||||
#define MAX_ATTR_PACKET_LENGTH ( 16 * 1024*1024)
|
|
||||||
|
|
||||||
static int mpi_print_mode;
|
static int mpi_print_mode;
|
||||||
static int list_mode;
|
static int list_mode;
|
||||||
static estream_t listfp;
|
static estream_t listfp;
|
||||||
@ -2118,12 +2113,20 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
|
|||||||
p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIGNERS_UID, &len);
|
p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIGNERS_UID, &len);
|
||||||
if (p && len)
|
if (p && len)
|
||||||
{
|
{
|
||||||
|
char *mbox;
|
||||||
|
|
||||||
sig->signers_uid = try_make_printable_string (p, len, 0);
|
sig->signers_uid = try_make_printable_string (p, len, 0);
|
||||||
if (!sig->signers_uid)
|
if (!sig->signers_uid)
|
||||||
{
|
{
|
||||||
rc = gpg_error_from_syserror ();
|
rc = gpg_error_from_syserror ();
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
mbox = mailbox_from_userid (sig->signers_uid, 0);
|
||||||
|
if (mbox)
|
||||||
|
{
|
||||||
|
xfree (sig->signers_uid);
|
||||||
|
sig->signers_uid = mbox;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_NOTATION, NULL);
|
p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_NOTATION, NULL);
|
||||||
|
@ -262,7 +262,8 @@ char *image_type_to_string(byte type,int style)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(FIXED_PHOTO_VIEWER) && !defined(DISABLE_PHOTO_VIEWER)
|
#if !defined(FIXED_PHOTO_VIEWER) && !defined(DISABLE_PHOTO_VIEWER)
|
||||||
static const char *get_default_photo_command(void)
|
static const char *
|
||||||
|
get_default_photo_command(void)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
OSVERSIONINFO osvi;
|
OSVERSIONINFO osvi;
|
||||||
@ -274,14 +275,21 @@ static const char *get_default_photo_command(void)
|
|||||||
if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
|
if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
|
||||||
return "start /w %i";
|
return "start /w %i";
|
||||||
else
|
else
|
||||||
return "cmd /c start /w %i";
|
return "!ShellExecute 400 %i";
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
/* OS X. This really needs more than just __APPLE__. */
|
/* OS X. This really needs more than just __APPLE__. */
|
||||||
return "open %I";
|
return "open %I";
|
||||||
#elif defined(__riscos__)
|
#elif defined(__riscos__)
|
||||||
return "Filer_Run %I";
|
return "Filer_Run %I";
|
||||||
#else
|
#else
|
||||||
return "xloadimage -fork -quiet -title 'KeyID 0x%k' stdin";
|
if (!path_access ("xloadimage", X_OK))
|
||||||
|
return "xloadimage -fork -quiet -title 'KeyID 0x%k' stdin";
|
||||||
|
else if (!path_access ("display",X_OK))
|
||||||
|
return "display -title 'KeyID 0x%k' %i";
|
||||||
|
else if (getuid () && !path_access ("xdg-open", X_OK))
|
||||||
|
return "xdg-open %i";
|
||||||
|
else
|
||||||
|
return "/bin/true";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -312,6 +320,8 @@ show_photos (ctrl_t ctrl, const struct user_attribute *attrs, int count,
|
|||||||
if (pk)
|
if (pk)
|
||||||
keyid_from_pk (pk, kid);
|
keyid_from_pk (pk, kid);
|
||||||
|
|
||||||
|
es_fflush (es_stdout);
|
||||||
|
|
||||||
for(i=0;i<count;i++)
|
for(i=0;i<count;i++)
|
||||||
if(attrs[i].type==ATTRIB_IMAGE &&
|
if(attrs[i].type==ATTRIB_IMAGE &&
|
||||||
parse_image_header(&attrs[i],&args.imagetype,&len))
|
parse_image_header(&attrs[i],&args.imagetype,&len))
|
||||||
|
@ -475,7 +475,7 @@ do_we_trust_pre (ctrl_t ctrl, PKT_public_key *pk, unsigned int trustlevel )
|
|||||||
|
|
||||||
if( !opt.batch && !rc )
|
if( !opt.batch && !rc )
|
||||||
{
|
{
|
||||||
print_pubkey_info (ctrl, NULL,pk);
|
print_key_info (ctrl, NULL, 0, pk, 0);
|
||||||
print_fingerprint (ctrl, NULL, pk, 2);
|
print_fingerprint (ctrl, NULL, pk, 2);
|
||||||
tty_printf("\n");
|
tty_printf("\n");
|
||||||
|
|
||||||
@ -834,7 +834,8 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
|
|||||||
if (from_file)
|
if (from_file)
|
||||||
rc = get_pubkey_fromfile (ctrl, pk, name);
|
rc = get_pubkey_fromfile (ctrl, pk, name);
|
||||||
else
|
else
|
||||||
rc = get_best_pubkey_byname (ctrl, NULL, pk, name, &keyblock, 0);
|
rc = get_best_pubkey_byname (ctrl, GET_PUBKEY_NORMAL,
|
||||||
|
NULL, pk, name, &keyblock, 0);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
int code;
|
int code;
|
||||||
@ -975,8 +976,8 @@ build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list)
|
|||||||
r->pk = xmalloc_clear (sizeof *r->pk);
|
r->pk = xmalloc_clear (sizeof *r->pk);
|
||||||
r->pk->req_usage = PUBKEY_USAGE_ENC;
|
r->pk->req_usage = PUBKEY_USAGE_ENC;
|
||||||
|
|
||||||
rc = get_pubkey_byname (ctrl, NULL, r->pk, default_key,
|
rc = get_pubkey_byname (ctrl, GET_PUBKEY_NO_AKL,
|
||||||
NULL, NULL, 0, 1);
|
NULL, r->pk, default_key, NULL, NULL, 0);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
xfree (r->pk);
|
xfree (r->pk);
|
||||||
@ -1041,8 +1042,8 @@ build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list)
|
|||||||
/* We explicitly allow encrypt-to to an disabled key; thus
|
/* We explicitly allow encrypt-to to an disabled key; thus
|
||||||
we pass 1 for the second last argument and 1 as the last
|
we pass 1 for the second last argument and 1 as the last
|
||||||
argument to disable AKL. */
|
argument to disable AKL. */
|
||||||
if ( (rc = get_pubkey_byname (ctrl,
|
if ((rc = get_pubkey_byname (ctrl, GET_PUBKEY_NO_AKL,
|
||||||
NULL, pk, rov->d, NULL, NULL, 1, 1)) )
|
NULL, pk, rov->d, NULL, NULL, 1)))
|
||||||
{
|
{
|
||||||
free_public_key ( pk ); pk = NULL;
|
free_public_key ( pk ); pk = NULL;
|
||||||
log_error (_("%s: skipped: %s\n"), rov->d, gpg_strerror (rc) );
|
log_error (_("%s: skipped: %s\n"), rov->d, gpg_strerror (rc) );
|
||||||
@ -1179,7 +1180,8 @@ build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list)
|
|||||||
free_public_key (pk);
|
free_public_key (pk);
|
||||||
pk = xmalloc_clear( sizeof *pk );
|
pk = xmalloc_clear( sizeof *pk );
|
||||||
pk->req_usage = PUBKEY_USAGE_ENC;
|
pk->req_usage = PUBKEY_USAGE_ENC;
|
||||||
rc = get_pubkey_byname (ctrl, NULL, pk, answer, NULL, NULL, 0, 0 );
|
rc = get_pubkey_byname (ctrl, GET_PUBKEY_NORMAL,
|
||||||
|
NULL, pk, answer, NULL, NULL, 0);
|
||||||
if (rc)
|
if (rc)
|
||||||
tty_printf(_("No such user ID.\n"));
|
tty_printf(_("No such user ID.\n"));
|
||||||
else if ( !(rc=openpgp_pk_test_algo2 (pk->pubkey_algo,
|
else if ( !(rc=openpgp_pk_test_algo2 (pk->pubkey_algo,
|
||||||
@ -1257,7 +1259,8 @@ build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list)
|
|||||||
|
|
||||||
/* The default recipient is allowed to be disabled; thus pass 1
|
/* The default recipient is allowed to be disabled; thus pass 1
|
||||||
as second last argument. We also don't want an AKL. */
|
as second last argument. We also don't want an AKL. */
|
||||||
rc = get_pubkey_byname (ctrl, NULL, pk, def_rec, NULL, NULL, 1, 1);
|
rc = get_pubkey_byname (ctrl, GET_PUBKEY_NO_AKL,
|
||||||
|
NULL, pk, def_rec, NULL, NULL, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error(_("unknown default recipient \"%s\"\n"), def_rec );
|
log_error(_("unknown default recipient \"%s\"\n"), def_rec );
|
||||||
else if ( !(rc=openpgp_pk_test_algo2(pk->pubkey_algo,
|
else if ( !(rc=openpgp_pk_test_algo2(pk->pubkey_algo,
|
||||||
|
@ -70,7 +70,8 @@ get_output_file (const byte *embedded_name, int embedded_namelen,
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (opt.outfile)
|
else if (opt.outfile
|
||||||
|
&& !(opt.flags.use_embedded_filename && opt.flags.dummy_outfile))
|
||||||
{
|
{
|
||||||
fname = xtrystrdup (opt.outfile);
|
fname = xtrystrdup (opt.outfile);
|
||||||
if (!fname)
|
if (!fname)
|
||||||
|
@ -75,25 +75,21 @@ gpg_error_t
|
|||||||
get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek)
|
get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek)
|
||||||
{
|
{
|
||||||
PKT_public_key *sk = NULL;
|
PKT_public_key *sk = NULL;
|
||||||
int rc;
|
gpg_error_t err;
|
||||||
void *enum_context = NULL;
|
void *enum_context = NULL;
|
||||||
u32 keyid[2];
|
u32 keyid[2];
|
||||||
int search_for_secret_keys = 1;
|
int search_for_secret_keys = 1;
|
||||||
|
struct pubkey_enc_list *k;
|
||||||
|
|
||||||
if (DBG_CLOCK)
|
if (DBG_CLOCK)
|
||||||
log_clock ("get_session_key enter");
|
log_clock ("get_session_key enter");
|
||||||
|
|
||||||
while (search_for_secret_keys)
|
while (search_for_secret_keys)
|
||||||
{
|
{
|
||||||
struct pubkey_enc_list *k;
|
|
||||||
|
|
||||||
sk = xmalloc_clear (sizeof *sk);
|
sk = xmalloc_clear (sizeof *sk);
|
||||||
rc = enum_secret_keys (ctrl, &enum_context, sk);
|
err = enum_secret_keys (ctrl, &enum_context, sk);
|
||||||
if (rc)
|
if (err)
|
||||||
{
|
break;
|
||||||
rc = GPG_ERR_NO_SECKEY;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(sk->pubkey_usage & PUBKEY_USAGE_ENC))
|
if (!(sk->pubkey_usage & PUBKEY_USAGE_ENC))
|
||||||
continue;
|
continue;
|
||||||
@ -132,8 +128,6 @@ get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek)
|
|||||||
if (openpgp_pk_test_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC))
|
if (openpgp_pk_test_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
k->result = GPG_ERR_NO_SECKEY;
|
|
||||||
|
|
||||||
if (sk->pubkey_algo != k->pubkey_algo)
|
if (sk->pubkey_algo != k->pubkey_algo)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -154,16 +148,16 @@ get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek)
|
|||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rc = get_it (ctrl, k, dek, sk, keyid);
|
err = get_it (ctrl, k, dek, sk, keyid);
|
||||||
if (!rc)
|
k->result = err;
|
||||||
|
if (!err)
|
||||||
{
|
{
|
||||||
k->result = 0;
|
|
||||||
if (!opt.quiet && !k->keyid[0] && !k->keyid[1])
|
if (!opt.quiet && !k->keyid[0] && !k->keyid[1])
|
||||||
log_info (_("okay, we are the anonymous recipient.\n"));
|
log_info (_("okay, we are the anonymous recipient.\n"));
|
||||||
search_for_secret_keys = 0;
|
search_for_secret_keys = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
|
else if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
|
||||||
{
|
{
|
||||||
search_for_secret_keys = 0;
|
search_for_secret_keys = 0;
|
||||||
break; /* Don't try any more secret keys. */
|
break; /* Don't try any more secret keys. */
|
||||||
@ -172,9 +166,19 @@ get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek)
|
|||||||
}
|
}
|
||||||
enum_secret_keys (ctrl, &enum_context, NULL); /* free context */
|
enum_secret_keys (ctrl, &enum_context, NULL); /* free context */
|
||||||
|
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_EOF)
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_NO_SECKEY);
|
||||||
|
|
||||||
|
/* Return the last specific error, if any. */
|
||||||
|
for (k = list; k; k = k->next)
|
||||||
|
if (k->result != -1)
|
||||||
|
err = k->result;
|
||||||
|
}
|
||||||
|
|
||||||
if (DBG_CLOCK)
|
if (DBG_CLOCK)
|
||||||
log_clock ("get_session_key leave");
|
log_clock ("get_session_key leave");
|
||||||
return rc;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -319,6 +323,16 @@ get_it (ctrl_t ctrl,
|
|||||||
err = gpg_error (GPG_ERR_WRONG_SECKEY);
|
err = gpg_error (GPG_ERR_WRONG_SECKEY);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: Actually the leading zero is required but due to
|
||||||
|
* the way we encode the output in libgcrypt as an MPI we
|
||||||
|
* are not able to encode that leading zero. However, when
|
||||||
|
* using a Smartcard we are doing it the right way and
|
||||||
|
* therefore we have to skip the zero. This should be fixed
|
||||||
|
* in gpg-agent of course. */
|
||||||
|
if (!frame[n])
|
||||||
|
n++;
|
||||||
|
|
||||||
if (frame[n] == 1 && frame[nframe - 1] == 2)
|
if (frame[n] == 1 && frame[nframe - 1] == 2)
|
||||||
{
|
{
|
||||||
log_info (_("old encoding of the DEK is not supported\n"));
|
log_info (_("old encoding of the DEK is not supported\n"));
|
||||||
|
26
g10/revoke.c
26
g10/revoke.c
@ -305,11 +305,11 @@ gen_desig_revoke (ctrl_t ctrl, const char *uname, strlist_t locusr)
|
|||||||
|
|
||||||
any = 1;
|
any = 1;
|
||||||
|
|
||||||
print_pubkey_info (ctrl, NULL, pk);
|
print_key_info (ctrl, NULL, 0, pk, 0);
|
||||||
tty_printf ("\n");
|
tty_printf ("\n");
|
||||||
|
|
||||||
tty_printf (_("To be revoked by:\n"));
|
tty_printf (_("To be revoked by:\n"));
|
||||||
print_seckey_info (ctrl, pk2);
|
print_key_info (ctrl, NULL, 0, pk2, 1);
|
||||||
|
|
||||||
if(pk->revkey[i].class&0x40)
|
if(pk->revkey[i].class&0x40)
|
||||||
tty_printf(_("(This is a sensitive revocation key)\n"));
|
tty_printf(_("(This is a sensitive revocation key)\n"));
|
||||||
@ -343,7 +343,7 @@ gen_desig_revoke (ctrl_t ctrl, const char *uname, strlist_t locusr)
|
|||||||
push_armor_filter (afx, out);
|
push_armor_filter (afx, out);
|
||||||
|
|
||||||
/* create it */
|
/* create it */
|
||||||
rc = make_keysig_packet (ctrl, &sig, pk, NULL, NULL, pk2, 0x20, 0,
|
rc = make_keysig_packet (ctrl, &sig, pk, NULL, NULL, pk2, 0x20,
|
||||||
0, 0,
|
0, 0,
|
||||||
revocation_reason_build_cb, reason,
|
revocation_reason_build_cb, reason,
|
||||||
NULL);
|
NULL);
|
||||||
@ -474,7 +474,7 @@ create_revocation (ctrl_t ctrl,
|
|||||||
afx->hdrlines = "Comment: This is a revocation certificate\n";
|
afx->hdrlines = "Comment: This is a revocation certificate\n";
|
||||||
push_armor_filter (afx, out);
|
push_armor_filter (afx, out);
|
||||||
|
|
||||||
rc = make_keysig_packet (ctrl, &sig, psk, NULL, NULL, psk, 0x20, 0,
|
rc = make_keysig_packet (ctrl, &sig, psk, NULL, NULL, psk, 0x20,
|
||||||
0, 0,
|
0, 0,
|
||||||
revocation_reason_build_cb, reason, cache_nonce);
|
revocation_reason_build_cb, reason, cache_nonce);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -669,30 +669,26 @@ gen_revoke (ctrl_t ctrl, const char *uname)
|
|||||||
|
|
||||||
rc = keydb_search (kdbhd, &desc, 1, NULL);
|
rc = keydb_search (kdbhd, &desc, 1, NULL);
|
||||||
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
|
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
|
||||||
/* Not ambiguous. */
|
|
||||||
{
|
{
|
||||||
|
/* Not ambiguous. */
|
||||||
}
|
}
|
||||||
else if (rc == 0)
|
else if (rc == 0)
|
||||||
/* Ambiguous. */
|
|
||||||
{
|
{
|
||||||
char *info;
|
/* Ambiguous. */
|
||||||
|
|
||||||
/* TRANSLATORS: The %s prints a key specification which
|
/* TRANSLATORS: The %s prints a key specification which
|
||||||
for example has been given at the command line. Several lines
|
for example has been given at the command line. Several lines
|
||||||
lines with secret key infos are printed after this message. */
|
lines with secret key infos are printed after this message. */
|
||||||
log_error (_("'%s' matches multiple secret keys:\n"), uname);
|
log_error (_("'%s' matches multiple secret keys:\n"), uname);
|
||||||
|
|
||||||
info = format_seckey_info (ctrl, keyblock->pkt->pkt.public_key);
|
print_key_info_log (ctrl, GPGRT_LOGLVL_ERROR, 2,
|
||||||
log_error (" %s\n", info);
|
keyblock->pkt->pkt.public_key, 1);
|
||||||
xfree (info);
|
|
||||||
release_kbnode (keyblock);
|
release_kbnode (keyblock);
|
||||||
|
|
||||||
rc = keydb_get_keyblock (kdbhd, &keyblock);
|
rc = keydb_get_keyblock (kdbhd, &keyblock);
|
||||||
while (! rc)
|
while (! rc)
|
||||||
{
|
{
|
||||||
info = format_seckey_info (ctrl, keyblock->pkt->pkt.public_key);
|
print_key_info_log (ctrl, GPGRT_LOGLVL_INFO, 2,
|
||||||
log_info (" %s\n", info);
|
keyblock->pkt->pkt.public_key, 1);
|
||||||
xfree (info);
|
|
||||||
release_kbnode (keyblock);
|
release_kbnode (keyblock);
|
||||||
keyblock = NULL;
|
keyblock = NULL;
|
||||||
|
|
||||||
@ -726,7 +722,7 @@ gen_revoke (ctrl_t ctrl, const char *uname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
keyid_from_pk (psk, keyid );
|
keyid_from_pk (psk, keyid );
|
||||||
print_seckey_info (ctrl, psk);
|
print_key_info (ctrl, NULL, 0, psk, 1);
|
||||||
|
|
||||||
tty_printf("\n");
|
tty_printf("\n");
|
||||||
if (!cpr_get_answer_is_yes ("gen_revoke.okay",
|
if (!cpr_get_answer_is_yes ("gen_revoke.okay",
|
||||||
|
@ -1076,7 +1076,7 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer,
|
|||||||
* signature packet's data structure.
|
* signature packet's data structure.
|
||||||
*
|
*
|
||||||
* TODO: add r_revoked here as well. It has the same problems as
|
* TODO: add r_revoked here as well. It has the same problems as
|
||||||
* r_expiredate and r_expired and the cache. */
|
* r_expiredate and r_expired and the cache [nw]. Which problems [wk]? */
|
||||||
int
|
int
|
||||||
check_key_signature2 (ctrl_t ctrl,
|
check_key_signature2 (ctrl_t ctrl,
|
||||||
kbnode_t root, kbnode_t node, PKT_public_key *check_pk,
|
kbnode_t root, kbnode_t node, PKT_public_key *check_pk,
|
||||||
|
49
g10/sign.c
49
g10/sign.c
@ -1593,7 +1593,7 @@ make_keysig_packet (ctrl_t ctrl,
|
|||||||
PKT_signature **ret_sig, PKT_public_key *pk,
|
PKT_signature **ret_sig, PKT_public_key *pk,
|
||||||
PKT_user_id *uid, PKT_public_key *subpk,
|
PKT_user_id *uid, PKT_public_key *subpk,
|
||||||
PKT_public_key *pksk,
|
PKT_public_key *pksk,
|
||||||
int sigclass, int digest_algo,
|
int sigclass,
|
||||||
u32 timestamp, u32 duration,
|
u32 timestamp, u32 duration,
|
||||||
int (*mksubpkt)(PKT_signature *, void *), void *opaque,
|
int (*mksubpkt)(PKT_signature *, void *), void *opaque,
|
||||||
const char *cache_nonce)
|
const char *cache_nonce)
|
||||||
@ -1601,6 +1601,7 @@ make_keysig_packet (ctrl_t ctrl,
|
|||||||
PKT_signature *sig;
|
PKT_signature *sig;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int sigversion;
|
int sigversion;
|
||||||
|
int digest_algo;
|
||||||
gcry_md_hd_t md;
|
gcry_md_hd_t md;
|
||||||
|
|
||||||
log_assert ((sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F
|
log_assert ((sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F
|
||||||
@ -1612,31 +1613,22 @@ make_keysig_packet (ctrl_t ctrl,
|
|||||||
else
|
else
|
||||||
sigversion = 4;
|
sigversion = 4;
|
||||||
|
|
||||||
if (!digest_algo)
|
/* Select the digest algo to use. */
|
||||||
|
if (opt.cert_digest_algo) /* Forceful override by the user. */
|
||||||
|
digest_algo = opt.cert_digest_algo;
|
||||||
|
else if (pksk->pubkey_algo == PUBKEY_ALGO_DSA) /* Meet DSA requirements. */
|
||||||
|
digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8);
|
||||||
|
else if (pksk->pubkey_algo == PUBKEY_ALGO_ECDSA /* Meet ECDSA requirements. */
|
||||||
|
|| pksk->pubkey_algo == PUBKEY_ALGO_EDDSA)
|
||||||
{
|
{
|
||||||
/* Basically, this means use SHA1 always unless the user
|
if (openpgp_oid_is_ed25519 (pksk->pkey[0]))
|
||||||
* specified something (use whatever they said), or it's DSA
|
digest_algo = DIGEST_ALGO_SHA256;
|
||||||
* (use the best match). They still can't pick an inappropriate
|
|
||||||
* hash for DSA or the signature will fail. Note that this
|
|
||||||
* still allows the caller of make_keysig_packet to override the
|
|
||||||
* user setting if it must. */
|
|
||||||
|
|
||||||
if (opt.cert_digest_algo)
|
|
||||||
digest_algo = opt.cert_digest_algo;
|
|
||||||
else if (pksk->pubkey_algo == PUBKEY_ALGO_DSA)
|
|
||||||
digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8);
|
|
||||||
else if (pksk->pubkey_algo == PUBKEY_ALGO_ECDSA
|
|
||||||
|| pksk->pubkey_algo == PUBKEY_ALGO_EDDSA)
|
|
||||||
{
|
|
||||||
if (openpgp_oid_is_ed25519 (pksk->pkey[0]))
|
|
||||||
digest_algo = DIGEST_ALGO_SHA256;
|
|
||||||
else
|
|
||||||
digest_algo = match_dsa_hash
|
|
||||||
(ecdsa_qbits_from_Q (gcry_mpi_get_nbits (pksk->pkey[1]))/8);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
digest_algo = DEFAULT_DIGEST_ALGO;
|
digest_algo = match_dsa_hash
|
||||||
|
(ecdsa_qbits_from_Q (gcry_mpi_get_nbits (pksk->pkey[1]))/8);
|
||||||
}
|
}
|
||||||
|
else /* Use the default. */
|
||||||
|
digest_algo = DEFAULT_DIGEST_ALGO;
|
||||||
|
|
||||||
if (gcry_md_open (&md, digest_algo, 0))
|
if (gcry_md_open (&md, digest_algo, 0))
|
||||||
BUG ();
|
BUG ();
|
||||||
@ -1722,8 +1714,19 @@ update_keysig_packet (ctrl_t ctrl,
|
|||||||
|| (orig_sig->sig_class == 0x18 && !subpk))
|
|| (orig_sig->sig_class == 0x18 && !subpk))
|
||||||
return GPG_ERR_GENERAL;
|
return GPG_ERR_GENERAL;
|
||||||
|
|
||||||
|
/* Either use the override digest algo or in the normal case the
|
||||||
|
* original digest algorithm. However, iff the original digest
|
||||||
|
* algorithms is SHA-1 and we are in gnupg or de-vs compliance mode
|
||||||
|
* we switch to SHA-256 (done by the macro). */
|
||||||
if (opt.cert_digest_algo)
|
if (opt.cert_digest_algo)
|
||||||
digest_algo = opt.cert_digest_algo;
|
digest_algo = opt.cert_digest_algo;
|
||||||
|
else if (pksk->pubkey_algo == PUBKEY_ALGO_DSA
|
||||||
|
|| pksk->pubkey_algo == PUBKEY_ALGO_ECDSA
|
||||||
|
|| pksk->pubkey_algo == PUBKEY_ALGO_EDDSA)
|
||||||
|
digest_algo = orig_sig->digest_algo;
|
||||||
|
else if (orig_sig->digest_algo == DIGEST_ALGO_SHA1
|
||||||
|
|| orig_sig->digest_algo == DIGEST_ALGO_RMD160)
|
||||||
|
digest_algo = DEFAULT_DIGEST_ALGO;
|
||||||
else
|
else
|
||||||
digest_algo = orig_sig->digest_algo;
|
digest_algo = orig_sig->digest_algo;
|
||||||
|
|
||||||
|
@ -340,6 +340,10 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
|
|||||||
SK_LIST results;
|
SK_LIST results;
|
||||||
} *c = *context;
|
} *c = *context;
|
||||||
|
|
||||||
|
#if MAX_FINGERPRINT_LEN < KEYGRIP_LEN
|
||||||
|
# error buffer too short for this configuration
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!c)
|
if (!c)
|
||||||
{
|
{
|
||||||
/* Make a new context. */
|
/* Make a new context. */
|
||||||
@ -423,23 +427,58 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
|
|||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
log_info (_("error getting serial number of card: %s\n"),
|
log_info (_("error getting serial number of card: %s\n"),
|
||||||
gpg_strerror (err));
|
gpg_strerror (err));
|
||||||
|
c->sl = c->sl->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfree (serialno);
|
xfree (serialno);
|
||||||
c->info.fpr2len = 0;
|
c->info.fpr2len = 0;
|
||||||
err = agent_scd_getattr ("KEY-FPR", &c->info);
|
err = agent_scd_getattr ("KEY-FPR", &c->info);
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
if (c->info.fpr2len)
|
||||||
|
{
|
||||||
|
c->fpr2[0] = '0';
|
||||||
|
c->fpr2[1] = 'x';
|
||||||
|
bin2hex (c->info.fpr2, sizeof c->info.fpr2,
|
||||||
|
c->fpr2 + 2);
|
||||||
|
name = c->fpr2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (gpg_err_code (err) == GPG_ERR_INV_NAME)
|
||||||
|
{
|
||||||
|
/* KEY-FPR not supported by the card - get
|
||||||
|
* the key using the keygrip. */
|
||||||
|
char *keyref;
|
||||||
|
strlist_t kplist;
|
||||||
|
const char *s;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
err = agent_scd_getattr_one ("$ENCRKEYID", &keyref);
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
err = agent_scd_keypairinfo (ctrl, keyref,
|
||||||
|
&kplist);
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
c->fpr2[0] = '&';
|
||||||
|
for (i=1, s=kplist->d;
|
||||||
|
(*s && *s != ' '
|
||||||
|
&& i < sizeof c->fpr2 - 3);
|
||||||
|
s++, i++)
|
||||||
|
c->fpr2[i] = *s;
|
||||||
|
c->fpr2[i] = 0;
|
||||||
|
name = c->fpr2;
|
||||||
|
free_strlist (kplist);
|
||||||
|
}
|
||||||
|
xfree (keyref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
log_error ("error retrieving key fingerprint from card: %s\n",
|
log_error ("error retrieving key from card: %s\n",
|
||||||
gpg_strerror (err));
|
gpg_strerror (err));
|
||||||
|
|
||||||
if (c->info.fpr2len)
|
|
||||||
{
|
|
||||||
c->fpr2[0] = '0';
|
|
||||||
c->fpr2[1] = 'x';
|
|
||||||
bin2hex (c->info.fpr2, sizeof c->info.fpr2,c->fpr2+2);
|
|
||||||
name = c->fpr2;
|
|
||||||
}
|
|
||||||
c->sl = c->sl->next;
|
c->sl = c->sl->next;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
32
g10/tofu.c
32
g10/tofu.c
@ -534,7 +534,7 @@ check_utks (sqlite3 *db)
|
|||||||
NULL, NULL, &err);
|
NULL, NULL, &err);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_error (_("error creating 'ultimately_trusted_keys' TOFU table: %s\n"),
|
log_error ("error creating 'ultimately_trusted_keys' TOFU table: %s\n",
|
||||||
err);
|
err);
|
||||||
sqlite3_free (err);
|
sqlite3_free (err);
|
||||||
goto out;
|
goto out;
|
||||||
@ -840,7 +840,7 @@ initdb (sqlite3 *db)
|
|||||||
NULL, NULL, &err);
|
NULL, NULL, &err);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_error (_("error creating 'encryptions' TOFU table: %s\n"),
|
log_error ("error creating 'encryptions' TOFU table: %s\n",
|
||||||
err);
|
err);
|
||||||
sqlite3_free (err);
|
sqlite3_free (err);
|
||||||
}
|
}
|
||||||
@ -870,7 +870,7 @@ initdb (sqlite3 *db)
|
|||||||
* safely ignore. */
|
* safely ignore. */
|
||||||
rc = 0;
|
rc = 0;
|
||||||
else
|
else
|
||||||
log_error (_("adding column effective_policy to bindings DB: %s\n"),
|
log_error ("adding column effective_policy to bindings DB: %s\n",
|
||||||
err);
|
err);
|
||||||
sqlite3_free (err);
|
sqlite3_free (err);
|
||||||
}
|
}
|
||||||
@ -2146,8 +2146,7 @@ build_conflict_set (ctrl_t ctrl, tofu_dbs_t dbs,
|
|||||||
rc = keydb_search_reset (hd);
|
rc = keydb_search_reset (hd);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_error (_("resetting keydb: %s\n"),
|
log_error ("resetting keydb failed: %s\n", gpg_strerror (rc));
|
||||||
gpg_strerror (rc));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2614,8 +2613,8 @@ get_policy (ctrl_t ctrl, tofu_dbs_t dbs, PKT_public_key *pk,
|
|||||||
if (record_binding (dbs, fingerprint, email, user_id,
|
if (record_binding (dbs, fingerprint, email, user_id,
|
||||||
policy == TOFU_POLICY_NONE ? TOFU_POLICY_AUTO : policy,
|
policy == TOFU_POLICY_NONE ? TOFU_POLICY_AUTO : policy,
|
||||||
effective_policy, conflict, 1, 0, now) != 0)
|
effective_policy, conflict, 1, 0, now) != 0)
|
||||||
log_error (_("error setting TOFU binding's policy"
|
log_error ("error setting TOFU binding's policy"
|
||||||
" to %s\n"), tofu_policy_str (policy));
|
" to %s\n", tofu_policy_str (policy));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the caller wants the set of conflicts, return it. */
|
/* If the caller wants the set of conflicts, return it. */
|
||||||
@ -3152,14 +3151,10 @@ show_statistics (tofu_dbs_t dbs,
|
|||||||
es_fprintf (fp, _("%s: Verified 0 signatures."), email);
|
es_fprintf (fp, _("%s: Verified 0 signatures."), email);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* TRANSLATORS: The final %s is replaced by a string like
|
/* Note: Translation not possible with that wording. */
|
||||||
"7~months". */
|
|
||||||
char *ago_str = time_ago_str (now - signature_first_seen);
|
char *ago_str = time_ago_str (now - signature_first_seen);
|
||||||
es_fprintf
|
es_fprintf
|
||||||
(fp,
|
(fp, "%s: Verified %ld~signatures in the past %s.",
|
||||||
ngettext("%s: Verified %ld~signature in the past %s.",
|
|
||||||
"%s: Verified %ld~signatures in the past %s.",
|
|
||||||
signature_count),
|
|
||||||
email, signature_count, ago_str);
|
email, signature_count, ago_str);
|
||||||
xfree (ago_str);
|
xfree (ago_str);
|
||||||
}
|
}
|
||||||
@ -3172,12 +3167,9 @@ show_statistics (tofu_dbs_t dbs,
|
|||||||
{
|
{
|
||||||
char *ago_str = time_ago_str (now - encryption_first_done);
|
char *ago_str = time_ago_str (now - encryption_first_done);
|
||||||
|
|
||||||
/* TRANSLATORS: The final %s is replaced by a string like
|
/* Note: Translation not possible with this kind of
|
||||||
"7~months". */
|
* composition. */
|
||||||
es_fprintf (fp,
|
es_fprintf (fp, "Encrypted %ld~messages in the past %s.",
|
||||||
ngettext("Encrypted %ld~message in the past %s.",
|
|
||||||
"Encrypted %ld~messages in the past %s.",
|
|
||||||
encryption_count),
|
|
||||||
encryption_count, ago_str);
|
encryption_count, ago_str);
|
||||||
xfree (ago_str);
|
xfree (ago_str);
|
||||||
}
|
}
|
||||||
@ -3944,7 +3936,7 @@ tofu_set_policy (ctrl_t ctrl, kbnode_t kb, enum tofu_policy policy)
|
|||||||
policy, TOFU_POLICY_NONE, NULL, 0, 1, now);
|
policy, TOFU_POLICY_NONE, NULL, 0, 1, now);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
log_error (_("error setting policy for key %s, user id \"%s\": %s"),
|
log_error ("error setting policy for key %s, user id \"%s\": %s",
|
||||||
fingerprint, email, gpg_strerror (err));
|
fingerprint, email, gpg_strerror (err));
|
||||||
xfree (email);
|
xfree (email);
|
||||||
break;
|
break;
|
||||||
|
@ -530,7 +530,7 @@ cmd_getinfo (assuan_context_t ctx, char *line)
|
|||||||
{
|
{
|
||||||
cmdopt = line;
|
cmdopt = line;
|
||||||
if (!command_has_option (cmd, cmdopt))
|
if (!command_has_option (cmd, cmdopt))
|
||||||
err = gpg_error (GPG_ERR_GENERAL);
|
err = gpg_error (GPG_ERR_FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@
|
|||||||
Note that this value matches TRUST_FLAG_REVOKED
|
Note that this value matches TRUST_FLAG_REVOKED
|
||||||
- u16 RFU
|
- u16 RFU
|
||||||
- u32 Recheck_after
|
- u32 Recheck_after
|
||||||
- u32 Latest timestamp in the keyblock (useful for KS syncronsiation?)
|
- u32 Latest timestamp in the keyblock (useful for KS synchronization?)
|
||||||
- u32 Blob created at
|
- u32 Blob created at
|
||||||
- u32 [NRES] Size of reserved space (not including this field)
|
- u32 [NRES] Size of reserved space (not including this field)
|
||||||
- bN Reserved space of size NRES for future use.
|
- bN Reserved space of size NRES for future use.
|
||||||
@ -144,7 +144,7 @@
|
|||||||
- bN Space for the keyblock or certificate.
|
- bN Space for the keyblock or certificate.
|
||||||
- bN RFU. This is the remaining space after keyblock and before
|
- bN RFU. This is the remaining space after keyblock and before
|
||||||
the checksum. It is not covered by the checksum.
|
the checksum. It is not covered by the checksum.
|
||||||
- b20 SHA-1 checksum (useful for KS syncronisation?)
|
- b20 SHA-1 checksum (useful for KS synchronization?)
|
||||||
Note, that KBX versions before GnuPG 2.1 used an MD5
|
Note, that KBX versions before GnuPG 2.1 used an MD5
|
||||||
checksum. However it was only created but never checked.
|
checksum. However it was only created but never checked.
|
||||||
Thus we do not expect problems if we switch to SHA-1. If
|
Thus we do not expect problems if we switch to SHA-1. If
|
||||||
|
@ -261,10 +261,12 @@ _keybox_close_file (KEYBOX_HANDLE hd)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lock the keybox at handle HD, or unlock if YES is false.
|
* Lock the keybox at handle HD, or unlock if YES is false. TIMEOUT
|
||||||
|
* is the value used for dotlock_take. In general -1 should be used
|
||||||
|
* when taking a lock; use 0 when releasing a lock.
|
||||||
*/
|
*/
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
keybox_lock (KEYBOX_HANDLE hd, int yes)
|
keybox_lock (KEYBOX_HANDLE hd, int yes, long timeout)
|
||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
KB_NAME kb = hd->kb;
|
KB_NAME kb = hd->kb;
|
||||||
@ -289,23 +291,22 @@ keybox_lock (KEYBOX_HANDLE hd, int yes)
|
|||||||
if (!kb->is_locked)
|
if (!kb->is_locked)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
/* Under Windows we need to close the file before we try
|
/* Under Windows we need to close the file before we try
|
||||||
* to lock it. This is because another process might have
|
* to lock it. This is because another process might have
|
||||||
* taken the lock and is using keybox_file_rename to
|
* taken the lock and is using keybox_file_rename to
|
||||||
* rename the base file. How if our dotlock_take below is
|
* rename the base file. Now if our dotlock_take below is
|
||||||
* waiting for the lock but we have the base file still
|
* waiting for the lock but we have the base file still
|
||||||
* open, keybox_file_rename will never succeed as we are
|
* open, keybox_file_rename will never succeed as we are
|
||||||
* in a deadlock. */
|
* in a deadlock. */
|
||||||
if (hd->fp)
|
_keybox_close_file (hd);
|
||||||
{
|
|
||||||
fclose (hd->fp);
|
|
||||||
hd->fp = NULL;
|
|
||||||
}
|
|
||||||
#endif /*HAVE_W32_SYSTEM*/
|
#endif /*HAVE_W32_SYSTEM*/
|
||||||
if (dotlock_take (kb->lockhd, -1))
|
if (dotlock_take (kb->lockhd, timeout))
|
||||||
{
|
{
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
log_info ("can't lock '%s'\n", kb->fname );
|
if (!timeout && gpg_err_code (err) == GPG_ERR_EACCES)
|
||||||
|
; /* No diagnostic if we only tried to lock. */
|
||||||
|
else
|
||||||
|
log_info ("can't lock '%s'\n", kb->fname );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
kb->is_locked = 1;
|
kb->is_locked = 1;
|
||||||
|
@ -873,16 +873,21 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
|
|||||||
KEYBOXBLOB blob = NULL;
|
KEYBOXBLOB blob = NULL;
|
||||||
struct sn_array_s *sn_array = NULL;
|
struct sn_array_s *sn_array = NULL;
|
||||||
int pk_no, uid_no;
|
int pk_no, uid_no;
|
||||||
|
off_t lastfoundoff;
|
||||||
|
|
||||||
if (!hd)
|
if (!hd)
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
/* clear last found result */
|
/* Clear last found result but reord the offset of the last found
|
||||||
|
* blob which we may need later. */
|
||||||
if (hd->found.blob)
|
if (hd->found.blob)
|
||||||
{
|
{
|
||||||
|
lastfoundoff = _keybox_get_blob_fileoffset (hd->found.blob);
|
||||||
_keybox_release_blob (hd->found.blob);
|
_keybox_release_blob (hd->found.blob);
|
||||||
hd->found.blob = NULL;
|
hd->found.blob = NULL;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
lastfoundoff = 0;
|
||||||
|
|
||||||
if (hd->error)
|
if (hd->error)
|
||||||
return hd->error; /* still in error state */
|
return hd->error; /* still in error state */
|
||||||
@ -901,6 +906,7 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
|
|||||||
case KEYDB_SEARCH_MODE_FIRST:
|
case KEYDB_SEARCH_MODE_FIRST:
|
||||||
/* always restart the search in this mode */
|
/* always restart the search in this mode */
|
||||||
keybox_search_reset (hd);
|
keybox_search_reset (hd);
|
||||||
|
lastfoundoff = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -925,6 +931,32 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
|
|||||||
xfree (sn_array);
|
xfree (sn_array);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
/* log_debug ("%s: re-opened file\n", __func__); */
|
||||||
|
if (ndesc && desc[0].mode != KEYDB_SEARCH_MODE_FIRST && lastfoundoff)
|
||||||
|
{
|
||||||
|
/* Search mode is not first and the last search operation
|
||||||
|
* returned a blob which also was not the first one. We now
|
||||||
|
* need to skip over that blob and hope that the file has
|
||||||
|
* not changed. */
|
||||||
|
if (fseeko (hd->fp, lastfoundoff, SEEK_SET))
|
||||||
|
{
|
||||||
|
rc = gpg_error_from_syserror ();
|
||||||
|
log_debug ("%s: seeking to last found offset failed: %s\n",
|
||||||
|
__func__, gpg_strerror (rc));
|
||||||
|
xfree (sn_array);
|
||||||
|
return gpg_error (GPG_ERR_NOTHING_FOUND);
|
||||||
|
}
|
||||||
|
/* log_debug ("%s: re-opened file and sought to last offset\n", */
|
||||||
|
/* __func__); */
|
||||||
|
rc = _keybox_read_blob (NULL, hd->fp, NULL);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
log_debug ("%s: skipping last found blob failed: %s\n",
|
||||||
|
__func__, gpg_strerror (rc));
|
||||||
|
xfree (sn_array);
|
||||||
|
return gpg_error (GPG_ERR_NOTHING_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Kludge: We need to convert an SN given as hexstring to its binary
|
/* Kludge: We need to convert an SN given as hexstring to its binary
|
||||||
|
@ -423,7 +423,7 @@ keybox_update_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen)
|
|||||||
if (off == (off_t)-1)
|
if (off == (off_t)-1)
|
||||||
return gpg_error (GPG_ERR_GENERAL);
|
return gpg_error (GPG_ERR_GENERAL);
|
||||||
|
|
||||||
/* Close this the file so that we do no mess up the position for a
|
/* Close the file so that we do no mess up the position for a
|
||||||
next search. */
|
next search. */
|
||||||
_keybox_close_file (hd);
|
_keybox_close_file (hd);
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ void keybox_pop_found_state (KEYBOX_HANDLE hd);
|
|||||||
const char *keybox_get_resource_name (KEYBOX_HANDLE hd);
|
const char *keybox_get_resource_name (KEYBOX_HANDLE hd);
|
||||||
int keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes);
|
int keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes);
|
||||||
|
|
||||||
gpg_error_t keybox_lock (KEYBOX_HANDLE hd, int yes);
|
gpg_error_t keybox_lock (KEYBOX_HANDLE hd, int yes, long timeout);
|
||||||
|
|
||||||
/*-- keybox-file.c --*/
|
/*-- keybox-file.c --*/
|
||||||
/* Fixme: This function does not belong here: Provide a better
|
/* Fixme: This function does not belong here: Provide a better
|
||||||
|
222
m4/iconv.m4
222
m4/iconv.m4
@ -1,5 +1,6 @@
|
|||||||
# iconv.m4 serial AM6 (gettext-0.17)
|
# iconv.m4 serial 21
|
||||||
dnl Copyright (C) 2000-2002, 2007 Free Software Foundation, Inc.
|
dnl Copyright (C) 2000-2002, 2007-2014, 2016-2019 Free Software Foundation,
|
||||||
|
dnl Inc.
|
||||||
dnl This file is free software; the Free Software Foundation
|
dnl This file is free software; the Free Software Foundation
|
||||||
dnl gives unlimited permission to copy and/or distribute it,
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
dnl with or without modifications, as long as this notice is preserved.
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
@ -30,61 +31,118 @@ AC_DEFUN([AM_ICONV_LINK],
|
|||||||
dnl Add $INCICONV to CPPFLAGS before performing the following checks,
|
dnl Add $INCICONV to CPPFLAGS before performing the following checks,
|
||||||
dnl because if the user has installed libiconv and not disabled its use
|
dnl because if the user has installed libiconv and not disabled its use
|
||||||
dnl via --without-libiconv-prefix, he wants to use it. The first
|
dnl via --without-libiconv-prefix, he wants to use it. The first
|
||||||
dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed.
|
dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed.
|
||||||
am_save_CPPFLAGS="$CPPFLAGS"
|
am_save_CPPFLAGS="$CPPFLAGS"
|
||||||
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
|
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
|
||||||
|
|
||||||
AC_CACHE_CHECK([for iconv], am_cv_func_iconv, [
|
AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [
|
||||||
am_cv_func_iconv="no, consider installing GNU libiconv"
|
am_cv_func_iconv="no, consider installing GNU libiconv"
|
||||||
am_cv_lib_iconv=no
|
am_cv_lib_iconv=no
|
||||||
AC_TRY_LINK([#include <stdlib.h>
|
AC_LINK_IFELSE(
|
||||||
#include <iconv.h>],
|
[AC_LANG_PROGRAM(
|
||||||
[iconv_t cd = iconv_open("","");
|
[[
|
||||||
iconv(cd,NULL,NULL,NULL,NULL);
|
#include <stdlib.h>
|
||||||
iconv_close(cd);],
|
#include <iconv.h>
|
||||||
am_cv_func_iconv=yes)
|
]],
|
||||||
|
[[iconv_t cd = iconv_open("","");
|
||||||
|
iconv(cd,NULL,NULL,NULL,NULL);
|
||||||
|
iconv_close(cd);]])],
|
||||||
|
[am_cv_func_iconv=yes])
|
||||||
if test "$am_cv_func_iconv" != yes; then
|
if test "$am_cv_func_iconv" != yes; then
|
||||||
am_save_LIBS="$LIBS"
|
am_save_LIBS="$LIBS"
|
||||||
LIBS="$LIBS $LIBICONV"
|
LIBS="$LIBS $LIBICONV"
|
||||||
AC_TRY_LINK([#include <stdlib.h>
|
AC_LINK_IFELSE(
|
||||||
#include <iconv.h>],
|
[AC_LANG_PROGRAM(
|
||||||
[iconv_t cd = iconv_open("","");
|
[[
|
||||||
iconv(cd,NULL,NULL,NULL,NULL);
|
#include <stdlib.h>
|
||||||
iconv_close(cd);],
|
#include <iconv.h>
|
||||||
am_cv_lib_iconv=yes
|
]],
|
||||||
am_cv_func_iconv=yes)
|
[[iconv_t cd = iconv_open("","");
|
||||||
|
iconv(cd,NULL,NULL,NULL,NULL);
|
||||||
|
iconv_close(cd);]])],
|
||||||
|
[am_cv_lib_iconv=yes]
|
||||||
|
[am_cv_func_iconv=yes])
|
||||||
LIBS="$am_save_LIBS"
|
LIBS="$am_save_LIBS"
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
if test "$am_cv_func_iconv" = yes; then
|
if test "$am_cv_func_iconv" = yes; then
|
||||||
AC_CACHE_CHECK([for working iconv], am_cv_func_iconv_works, [
|
AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [
|
||||||
dnl This tests against bugs in AIX 5.1 and HP-UX 11.11.
|
dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11,
|
||||||
|
dnl Solaris 10.
|
||||||
am_save_LIBS="$LIBS"
|
am_save_LIBS="$LIBS"
|
||||||
if test $am_cv_lib_iconv = yes; then
|
if test $am_cv_lib_iconv = yes; then
|
||||||
LIBS="$LIBS $LIBICONV"
|
LIBS="$LIBS $LIBICONV"
|
||||||
fi
|
fi
|
||||||
AC_TRY_RUN([
|
am_cv_func_iconv_works=no
|
||||||
|
for ac_iconv_const in '' 'const'; do
|
||||||
|
AC_RUN_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM(
|
||||||
|
[[
|
||||||
#include <iconv.h>
|
#include <iconv.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
int main ()
|
|
||||||
{
|
#ifndef ICONV_CONST
|
||||||
|
# define ICONV_CONST $ac_iconv_const
|
||||||
|
#endif
|
||||||
|
]],
|
||||||
|
[[int result = 0;
|
||||||
/* Test against AIX 5.1 bug: Failures are not distinguishable from successful
|
/* Test against AIX 5.1 bug: Failures are not distinguishable from successful
|
||||||
returns. */
|
returns. */
|
||||||
{
|
{
|
||||||
iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
|
iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
|
||||||
if (cd_utf8_to_88591 != (iconv_t)(-1))
|
if (cd_utf8_to_88591 != (iconv_t)(-1))
|
||||||
{
|
{
|
||||||
static const char input[] = "\342\202\254"; /* EURO SIGN */
|
static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */
|
||||||
char buf[10];
|
char buf[10];
|
||||||
const char *inptr = input;
|
ICONV_CONST char *inptr = input;
|
||||||
size_t inbytesleft = strlen (input);
|
size_t inbytesleft = strlen (input);
|
||||||
char *outptr = buf;
|
char *outptr = buf;
|
||||||
size_t outbytesleft = sizeof (buf);
|
size_t outbytesleft = sizeof (buf);
|
||||||
size_t res = iconv (cd_utf8_to_88591,
|
size_t res = iconv (cd_utf8_to_88591,
|
||||||
(char **) &inptr, &inbytesleft,
|
&inptr, &inbytesleft,
|
||||||
&outptr, &outbytesleft);
|
&outptr, &outbytesleft);
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
return 1;
|
result |= 1;
|
||||||
|
iconv_close (cd_utf8_to_88591);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Test against Solaris 10 bug: Failures are not distinguishable from
|
||||||
|
successful returns. */
|
||||||
|
{
|
||||||
|
iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646");
|
||||||
|
if (cd_ascii_to_88591 != (iconv_t)(-1))
|
||||||
|
{
|
||||||
|
static ICONV_CONST char input[] = "\263";
|
||||||
|
char buf[10];
|
||||||
|
ICONV_CONST char *inptr = input;
|
||||||
|
size_t inbytesleft = strlen (input);
|
||||||
|
char *outptr = buf;
|
||||||
|
size_t outbytesleft = sizeof (buf);
|
||||||
|
size_t res = iconv (cd_ascii_to_88591,
|
||||||
|
&inptr, &inbytesleft,
|
||||||
|
&outptr, &outbytesleft);
|
||||||
|
if (res == 0)
|
||||||
|
result |= 2;
|
||||||
|
iconv_close (cd_ascii_to_88591);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Test against AIX 6.1..7.1 bug: Buffer overrun. */
|
||||||
|
{
|
||||||
|
iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1");
|
||||||
|
if (cd_88591_to_utf8 != (iconv_t)(-1))
|
||||||
|
{
|
||||||
|
static ICONV_CONST char input[] = "\304";
|
||||||
|
static char buf[2] = { (char)0xDE, (char)0xAD };
|
||||||
|
ICONV_CONST char *inptr = input;
|
||||||
|
size_t inbytesleft = 1;
|
||||||
|
char *outptr = buf;
|
||||||
|
size_t outbytesleft = 1;
|
||||||
|
size_t res = iconv (cd_88591_to_utf8,
|
||||||
|
&inptr, &inbytesleft,
|
||||||
|
&outptr, &outbytesleft);
|
||||||
|
if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD)
|
||||||
|
result |= 4;
|
||||||
|
iconv_close (cd_88591_to_utf8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if 0 /* This bug could be worked around by the caller. */
|
#if 0 /* This bug could be worked around by the caller. */
|
||||||
@ -93,37 +151,53 @@ int main ()
|
|||||||
iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
|
iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
|
||||||
if (cd_88591_to_utf8 != (iconv_t)(-1))
|
if (cd_88591_to_utf8 != (iconv_t)(-1))
|
||||||
{
|
{
|
||||||
static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
|
static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
|
||||||
char buf[50];
|
char buf[50];
|
||||||
const char *inptr = input;
|
ICONV_CONST char *inptr = input;
|
||||||
size_t inbytesleft = strlen (input);
|
size_t inbytesleft = strlen (input);
|
||||||
char *outptr = buf;
|
char *outptr = buf;
|
||||||
size_t outbytesleft = sizeof (buf);
|
size_t outbytesleft = sizeof (buf);
|
||||||
size_t res = iconv (cd_88591_to_utf8,
|
size_t res = iconv (cd_88591_to_utf8,
|
||||||
(char **) &inptr, &inbytesleft,
|
&inptr, &inbytesleft,
|
||||||
&outptr, &outbytesleft);
|
&outptr, &outbytesleft);
|
||||||
if ((int)res > 0)
|
if ((int)res > 0)
|
||||||
return 1;
|
result |= 8;
|
||||||
|
iconv_close (cd_88591_to_utf8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
|
/* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
|
||||||
provided. */
|
provided. */
|
||||||
if (/* Try standardized names. */
|
{
|
||||||
iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
|
/* Try standardized names. */
|
||||||
/* Try IRIX, OSF/1 names. */
|
iconv_t cd1 = iconv_open ("UTF-8", "EUC-JP");
|
||||||
&& iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
|
/* Try IRIX, OSF/1 names. */
|
||||||
/* Try AIX names. */
|
iconv_t cd2 = iconv_open ("UTF-8", "eucJP");
|
||||||
&& iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
|
/* Try AIX names. */
|
||||||
/* Try HP-UX names. */
|
iconv_t cd3 = iconv_open ("UTF-8", "IBM-eucJP");
|
||||||
&& iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
|
/* Try HP-UX names. */
|
||||||
return 1;
|
iconv_t cd4 = iconv_open ("utf8", "eucJP");
|
||||||
return 0;
|
if (cd1 == (iconv_t)(-1) && cd2 == (iconv_t)(-1)
|
||||||
}], [am_cv_func_iconv_works=yes], [am_cv_func_iconv_works=no],
|
&& cd3 == (iconv_t)(-1) && cd4 == (iconv_t)(-1))
|
||||||
[case "$host_os" in
|
result |= 16;
|
||||||
aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
|
if (cd1 != (iconv_t)(-1))
|
||||||
*) am_cv_func_iconv_works="guessing yes" ;;
|
iconv_close (cd1);
|
||||||
esac])
|
if (cd2 != (iconv_t)(-1))
|
||||||
|
iconv_close (cd2);
|
||||||
|
if (cd3 != (iconv_t)(-1))
|
||||||
|
iconv_close (cd3);
|
||||||
|
if (cd4 != (iconv_t)(-1))
|
||||||
|
iconv_close (cd4);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
]])],
|
||||||
|
[am_cv_func_iconv_works=yes], ,
|
||||||
|
[case "$host_os" in
|
||||||
|
aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
|
||||||
|
*) am_cv_func_iconv_works="guessing yes" ;;
|
||||||
|
esac])
|
||||||
|
test "$am_cv_func_iconv_works" = no || break
|
||||||
|
done
|
||||||
LIBS="$am_save_LIBS"
|
LIBS="$am_save_LIBS"
|
||||||
])
|
])
|
||||||
case "$am_cv_func_iconv_works" in
|
case "$am_cv_func_iconv_works" in
|
||||||
@ -134,7 +208,7 @@ int main ()
|
|||||||
am_func_iconv=no am_cv_lib_iconv=no
|
am_func_iconv=no am_cv_lib_iconv=no
|
||||||
fi
|
fi
|
||||||
if test "$am_func_iconv" = yes; then
|
if test "$am_func_iconv" = yes; then
|
||||||
AC_DEFINE(HAVE_ICONV, 1,
|
AC_DEFINE([HAVE_ICONV], [1],
|
||||||
[Define if you have the iconv() function and it works.])
|
[Define if you have the iconv() function and it works.])
|
||||||
fi
|
fi
|
||||||
if test "$am_cv_lib_iconv" = yes; then
|
if test "$am_cv_lib_iconv" = yes; then
|
||||||
@ -147,34 +221,68 @@ int main ()
|
|||||||
LIBICONV=
|
LIBICONV=
|
||||||
LTLIBICONV=
|
LTLIBICONV=
|
||||||
fi
|
fi
|
||||||
AC_SUBST(LIBICONV)
|
AC_SUBST([LIBICONV])
|
||||||
AC_SUBST(LTLIBICONV)
|
AC_SUBST([LTLIBICONV])
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN([AM_ICONV],
|
dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to
|
||||||
|
dnl avoid warnings like
|
||||||
|
dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required".
|
||||||
|
dnl This is tricky because of the way 'aclocal' is implemented:
|
||||||
|
dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN.
|
||||||
|
dnl Otherwise aclocal's initial scan pass would miss the macro definition.
|
||||||
|
dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions.
|
||||||
|
dnl Otherwise aclocal would emit many "Use of uninitialized value $1"
|
||||||
|
dnl warnings.
|
||||||
|
m4_define([gl_iconv_AC_DEFUN],
|
||||||
|
m4_version_prereq([2.64],
|
||||||
|
[[AC_DEFUN_ONCE(
|
||||||
|
[$1], [$2])]],
|
||||||
|
[m4_ifdef([gl_00GNULIB],
|
||||||
|
[[AC_DEFUN_ONCE(
|
||||||
|
[$1], [$2])]],
|
||||||
|
[[AC_DEFUN(
|
||||||
|
[$1], [$2])]])]))
|
||||||
|
gl_iconv_AC_DEFUN([AM_ICONV],
|
||||||
[
|
[
|
||||||
AM_ICONV_LINK
|
AM_ICONV_LINK
|
||||||
if test "$am_cv_func_iconv" = yes; then
|
if test "$am_cv_func_iconv" = yes; then
|
||||||
AC_MSG_CHECKING([for iconv declaration])
|
AC_MSG_CHECKING([for iconv declaration])
|
||||||
AC_CACHE_VAL(am_cv_proto_iconv, [
|
AC_CACHE_VAL([am_cv_proto_iconv], [
|
||||||
AC_TRY_COMPILE([
|
AC_COMPILE_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM(
|
||||||
|
[[
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <iconv.h>
|
#include <iconv.h>
|
||||||
extern
|
extern
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
"C"
|
"C"
|
||||||
#endif
|
#endif
|
||||||
#if defined(__STDC__) || defined(__cplusplus)
|
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus)
|
||||||
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
|
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
|
||||||
#else
|
#else
|
||||||
size_t iconv();
|
size_t iconv();
|
||||||
#endif
|
#endif
|
||||||
], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
|
]],
|
||||||
|
[[]])],
|
||||||
|
[am_cv_proto_iconv_arg1=""],
|
||||||
|
[am_cv_proto_iconv_arg1="const"])
|
||||||
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
|
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
|
||||||
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
|
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
|
||||||
AC_MSG_RESULT([$]{ac_t:-
|
AC_MSG_RESULT([
|
||||||
}[$]am_cv_proto_iconv)
|
$am_cv_proto_iconv])
|
||||||
AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
|
else
|
||||||
[Define as const if the declaration of iconv() needs const.])
|
dnl When compiling GNU libiconv on a system that does not have iconv yet,
|
||||||
|
dnl pick the POSIX compliant declaration without 'const'.
|
||||||
|
am_cv_proto_iconv_arg1=""
|
||||||
fi
|
fi
|
||||||
|
AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1],
|
||||||
|
[Define as const if the declaration of iconv() needs const.])
|
||||||
|
dnl Also substitute ICONV_CONST in the gnulib generated <iconv.h>.
|
||||||
|
m4_ifdef([gl_ICONV_H_DEFAULTS],
|
||||||
|
[AC_REQUIRE([gl_ICONV_H_DEFAULTS])
|
||||||
|
if test -n "$am_cv_proto_iconv_arg1"; then
|
||||||
|
ICONV_CONST="const"
|
||||||
|
fi
|
||||||
|
])
|
||||||
])
|
])
|
||||||
|
541
po/ja.po
541
po/ja.po
@ -4,13 +4,13 @@
|
|||||||
# IIDA Yosiaki <iida@gnu.org>, 1999, 2000, 2002, 2003, 2004.
|
# IIDA Yosiaki <iida@gnu.org>, 1999, 2000, 2002, 2003, 2004.
|
||||||
# Yoshihiro Kajiki <kajiki@ylug.org>, 1999.
|
# Yoshihiro Kajiki <kajiki@ylug.org>, 1999.
|
||||||
# Takashi P.KATOH, 2002.
|
# Takashi P.KATOH, 2002.
|
||||||
# NIIBE Yutaka <gniibe@fsij.org>, 2013, 2014, 2015, 2016, 2017, 2018.
|
# NIIBE Yutaka <gniibe@fsij.org>, 2013, 2014, 2015, 2016, 2017, 2018, 2019.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnupg 2.2.6\n"
|
"Project-Id-Version: gnupg 2.2.16\n"
|
||||||
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
|
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
|
||||||
"PO-Revision-Date: 2018-04-12 10:51+0900\n"
|
"PO-Revision-Date: 2019-06-27 08:29+0900\n"
|
||||||
"Last-Translator: NIIBE Yutaka <gniibe@fsij.org>\n"
|
"Last-Translator: NIIBE Yutaka <gniibe@fsij.org>\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: none\n"
|
||||||
"Language: ja\n"
|
"Language: ja\n"
|
||||||
@ -23,12 +23,12 @@ msgstr ""
|
|||||||
msgid "failed to acquire the pinentry lock: %s\n"
|
msgid "failed to acquire the pinentry lock: %s\n"
|
||||||
msgstr "pinentryのロックの獲得に失敗しました: %s\n"
|
msgstr "pinentryのロックの獲得に失敗しました: %s\n"
|
||||||
|
|
||||||
#. TRANSLATORS: These are labels for buttons etc used in
|
#. TRANSLATORS: These are labels for buttons etc as used in
|
||||||
#. Pinentries. An underscore indicates that the next letter
|
#. * Pinentries. In your translation copy the text before the
|
||||||
#. should be used as an accelerator. Double the underscore for
|
#. * second vertical bar verbatim; translate only the following
|
||||||
#. a literal one. The actual to be translated text starts after
|
#. * text. An underscore indicates that the next letter should be
|
||||||
#. the second vertical bar. Note that gpg-agent has been set to
|
#. * used as an accelerator. Double the underscore to have
|
||||||
#. utf-8 so that the strings are in the expected encoding.
|
#. * pinentry display a literal underscore.
|
||||||
msgid "|pinentry-label|_OK"
|
msgid "|pinentry-label|_OK"
|
||||||
msgstr "|pinentry-label|_OK"
|
msgstr "|pinentry-label|_OK"
|
||||||
|
|
||||||
@ -203,9 +203,11 @@ msgstr "PUK"
|
|||||||
msgid "Reset Code"
|
msgid "Reset Code"
|
||||||
msgstr "リセット・コード"
|
msgstr "リセット・コード"
|
||||||
|
|
||||||
#, c-format
|
msgid "Push ACK button on card/token."
|
||||||
msgid "%s%%0A%%0AUse the reader's pinpad for input."
|
msgstr "カード/トークンのACKボタンを押してください。"
|
||||||
msgstr "%s%%0A%%0Aリーダーのピンパッドを入力に使ってください。"
|
|
||||||
|
msgid "Use the reader's pinpad for input."
|
||||||
|
msgstr "リーダーのピンパッドを入力に使ってください。"
|
||||||
|
|
||||||
msgid "Repeat this Reset Code"
|
msgid "Repeat this Reset Code"
|
||||||
msgstr "このリセット・コードをもう一度入力してください"
|
msgstr "このリセット・コードをもう一度入力してください"
|
||||||
@ -240,9 +242,6 @@ msgstr "一時ファイルの書き込みエラー: %s\n"
|
|||||||
msgid "Enter new passphrase"
|
msgid "Enter new passphrase"
|
||||||
msgstr "新しいパスフレーズを入力してください"
|
msgstr "新しいパスフレーズを入力してください"
|
||||||
|
|
||||||
msgid "Take this one anyway"
|
|
||||||
msgstr "それでもこれを使います"
|
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"You have not entered a passphrase!%0AAn empty passphrase is not allowed."
|
"You have not entered a passphrase!%0AAn empty passphrase is not allowed."
|
||||||
@ -280,6 +279,9 @@ msgstr ""
|
|||||||
msgid "Warning: You have entered an insecure passphrase."
|
msgid "Warning: You have entered an insecure passphrase."
|
||||||
msgstr "警告: 安全とは言えないパスフレーズが入力されました。"
|
msgstr "警告: 安全とは言えないパスフレーズが入力されました。"
|
||||||
|
|
||||||
|
msgid "Take this one anyway"
|
||||||
|
msgstr "それでもこれを使います"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Please enter the passphrase to%0Aprotect your new key"
|
msgid "Please enter the passphrase to%0Aprotect your new key"
|
||||||
msgstr "新しい鍵を保護するために、%0Aパスフレーズを入力してください。"
|
msgstr "新しい鍵を保護するために、%0Aパスフレーズを入力してください。"
|
||||||
@ -577,7 +579,7 @@ msgid "error reading '%s', line %d: %s\n"
|
|||||||
msgstr "'%s'の読み込みエラー(行 %d): %s\n"
|
msgstr "'%s'の読み込みエラー(行 %d): %s\n"
|
||||||
|
|
||||||
msgid "error reading list of trusted root certificates\n"
|
msgid "error reading list of trusted root certificates\n"
|
||||||
msgstr "信用されたルート証明書のリストの読み込みエラ−\n"
|
msgstr "信用されたルート証明書のリストの読み込みエラー\n"
|
||||||
|
|
||||||
#. TRANSLATORS: This prompt is shown by the Pinentry
|
#. TRANSLATORS: This prompt is shown by the Pinentry
|
||||||
#. and has one special property: A "%%0A" is used by
|
#. and has one special property: A "%%0A" is used by
|
||||||
@ -674,7 +676,7 @@ msgid "checking created signature failed: %s\n"
|
|||||||
msgstr "作成された署名の検査に失敗しました: %s\n"
|
msgstr "作成された署名の検査に失敗しました: %s\n"
|
||||||
|
|
||||||
msgid "secret key parts are not available\n"
|
msgid "secret key parts are not available\n"
|
||||||
msgstr "秘密部分が得られません\n"
|
msgstr "秘密鍵部分が利用できません\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "public key algorithm %d (%s) is not supported\n"
|
msgid "public key algorithm %d (%s) is not supported\n"
|
||||||
@ -729,7 +731,7 @@ msgid "can't connect to '%s': %s\n"
|
|||||||
msgstr "'%s'へ接続できません: %s\n"
|
msgstr "'%s'へ接続できません: %s\n"
|
||||||
|
|
||||||
msgid "problem setting the gpg-agent options\n"
|
msgid "problem setting the gpg-agent options\n"
|
||||||
msgstr "gpg-agentオプションの設定の問題\n"
|
msgstr "gpg-agentのオプション設定の問題\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "can't disable core dumps: %s\n"
|
msgid "can't disable core dumps: %s\n"
|
||||||
@ -813,30 +815,30 @@ msgid "unknown debug flag '%s' ignored\n"
|
|||||||
msgstr "未知のdebugフラグ'%s'は無視されました\n"
|
msgstr "未知のdebugフラグ'%s'は無視されました\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "no running gpg-agent - starting '%s'\n"
|
msgid "waiting for the dirmngr to come up ... (%ds)\n"
|
||||||
msgstr "gpg-agentが実行されていません - '%s'を開始します\n"
|
msgstr "dirmngrの起動のため、%d秒待ちます\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "waiting for the agent to come up ... (%ds)\n"
|
msgid "waiting for the agent to come up ... (%ds)\n"
|
||||||
msgstr "agentの起動のため、%d秒待ちます\n"
|
msgstr "agentの起動のため、%d秒待ちます\n"
|
||||||
|
|
||||||
msgid "connection to agent established\n"
|
msgid "connection to the dirmngr established\n"
|
||||||
|
msgstr "dirmngrへの接続が確立しました\n"
|
||||||
|
|
||||||
|
msgid "connection to the agent established\n"
|
||||||
msgstr "エージェントへの接続が確立しました。\n"
|
msgstr "エージェントへの接続が確立しました。\n"
|
||||||
|
|
||||||
msgid "connection to agent is in restricted mode\n"
|
#, c-format
|
||||||
|
msgid "no running gpg-agent - starting '%s'\n"
|
||||||
|
msgstr "gpg-agentが実行されていません - '%s'を開始します\n"
|
||||||
|
|
||||||
|
msgid "connection to the agent is in restricted mode\n"
|
||||||
msgstr "エージェントへの接続は制限モードです。\n"
|
msgstr "エージェントへの接続は制限モードです。\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "no running Dirmngr - starting '%s'\n"
|
msgid "no running dirmngr - starting '%s'\n"
|
||||||
msgstr "dirmngrが動いていません - 開始します'%s'\n"
|
msgstr "dirmngrが動いていません - 開始します'%s'\n"
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "waiting for the dirmngr to come up ... (%ds)\n"
|
|
||||||
msgstr "dirmngrの起動のため、%d秒待ちます\n"
|
|
||||||
|
|
||||||
msgid "connection to the dirmngr established\n"
|
|
||||||
msgstr "dirmngrへの接続が確立しました\n"
|
|
||||||
|
|
||||||
#. TRANSLATORS: Copy the prefix between the vertical bars
|
#. TRANSLATORS: Copy the prefix between the vertical bars
|
||||||
#. verbatim. It will not be printed.
|
#. verbatim. It will not be printed.
|
||||||
msgid "|audit-log-result|Good"
|
msgid "|audit-log-result|Good"
|
||||||
@ -1128,7 +1130,7 @@ msgid "CRC error; %06lX - %06lX\n"
|
|||||||
msgstr "CRCエラー。%06lX - %06lX\n"
|
msgstr "CRCエラー。%06lX - %06lX\n"
|
||||||
|
|
||||||
msgid "premature eof (in trailer)\n"
|
msgid "premature eof (in trailer)\n"
|
||||||
msgstr "ファイル末尾が早すぎます (後尾部の中にあります)\n"
|
msgstr "ファイル終端が早すぎます (後尾部の中にあります)\n"
|
||||||
|
|
||||||
msgid "error in trailer line\n"
|
msgid "error in trailer line\n"
|
||||||
msgstr "後尾の行にエラーがあります\n"
|
msgstr "後尾の行にエラーがあります\n"
|
||||||
@ -1205,6 +1207,10 @@ msgstr "注意: \"%s\"コマンドを使って再起動してください。\n"
|
|||||||
msgid "%s is not compliant with %s mode\n"
|
msgid "%s is not compliant with %s mode\n"
|
||||||
msgstr "%sは%sモードに準拠しません\n"
|
msgstr "%sは%sモードに準拠しません\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "problem with the agent: %s\n"
|
||||||
|
msgstr "エージェントに問題: %s\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "OpenPGP card not available: %s\n"
|
msgid "OpenPGP card not available: %s\n"
|
||||||
msgstr "OpenPGPカードが利用できません: %s\n"
|
msgstr "OpenPGPカードが利用できません: %s\n"
|
||||||
@ -1228,14 +1234,11 @@ msgstr "あなたの選択は? "
|
|||||||
msgid "[not set]"
|
msgid "[not set]"
|
||||||
msgstr "[未設定]"
|
msgstr "[未設定]"
|
||||||
|
|
||||||
msgid "male"
|
msgid "Mr."
|
||||||
msgstr "男"
|
msgstr "Mr."
|
||||||
|
|
||||||
msgid "female"
|
msgid "Mrs."
|
||||||
msgstr "女"
|
msgstr "Mrs"
|
||||||
|
|
||||||
msgid "unspecified"
|
|
||||||
msgstr "無指定"
|
|
||||||
|
|
||||||
msgid "not forced"
|
msgid "not forced"
|
||||||
msgstr "強制なし"
|
msgstr "強制なし"
|
||||||
@ -1288,8 +1291,8 @@ msgstr "エラー: 優先指定の文字列の長さが無効です。\n"
|
|||||||
msgid "Error: invalid characters in preference string.\n"
|
msgid "Error: invalid characters in preference string.\n"
|
||||||
msgstr "エラー: 優先指定の文字列に無効な文字があります。\n"
|
msgstr "エラー: 優先指定の文字列に無効な文字があります。\n"
|
||||||
|
|
||||||
msgid "Sex ((M)ale, (F)emale or space): "
|
msgid "Salutation (M = Mr., F = Mrs., or space): "
|
||||||
msgstr "性別 ((M)男、(F)女、または空白): "
|
msgstr "敬称 (M = Mr., F = Mrs, あるいは空白): "
|
||||||
|
|
||||||
msgid "Error: invalid response.\n"
|
msgid "Error: invalid response.\n"
|
||||||
msgstr "エラー: 無効な応答。\n"
|
msgstr "エラー: 無効な応答。\n"
|
||||||
@ -1315,13 +1318,15 @@ msgid "Replace existing key? (y/N) "
|
|||||||
msgstr "既存の鍵を置き換えしますか? (y/N) "
|
msgstr "既存の鍵を置き換えしますか? (y/N) "
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Note: There is no guarantee that the card supports the requested size.\n"
|
"Note: There is no guarantee that the card supports the requested\n"
|
||||||
" If the key generation does not succeed, please check the\n"
|
" key type or size. If the key generation does not succeed,\n"
|
||||||
" documentation of your card to see what sizes are allowed.\n"
|
" please check the documentation of your card to see which\n"
|
||||||
|
" key types and sizes are supported.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"注意: カードが要求された鍵長をサポートしているという保証はありません。\n"
|
"注意: カードが要求された鍵のタイプもしくは鍵長をサポートしている保証は\n"
|
||||||
" 鍵生成が成功しない場合、あなたのカードに関する技術文書を確認し、\n"
|
" ありません。鍵生成が成功しない場合、あなたのカードに関する技術文書を\n"
|
||||||
" 利用できる鍵長について確認ください。\n"
|
" 確認し、どの鍵のタイプと鍵長がサポートされているかについて確認して\n"
|
||||||
|
" ください。\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "What keysize do you want? (%u) "
|
msgid "What keysize do you want? (%u) "
|
||||||
@ -1432,6 +1437,10 @@ msgstr "工場出荷リセットを行いますか? (本当なら \"yes\" と入
|
|||||||
msgid "error for setup KDF: %s\n"
|
msgid "error for setup KDF: %s\n"
|
||||||
msgstr "KDF設定のエラー: %s\n"
|
msgstr "KDF設定のエラー: %s\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "error for setup UIF: %s\n"
|
||||||
|
msgstr "UIF設定のエラー: %s\n"
|
||||||
|
|
||||||
msgid "quit this menu"
|
msgid "quit this menu"
|
||||||
msgstr "このメニューを終了"
|
msgstr "このメニューを終了"
|
||||||
|
|
||||||
@ -1459,8 +1468,8 @@ msgstr "ログイン名の変更"
|
|||||||
msgid "change the language preferences"
|
msgid "change the language preferences"
|
||||||
msgstr "言語の優先指定の変更"
|
msgstr "言語の優先指定の変更"
|
||||||
|
|
||||||
msgid "change card holder's sex"
|
msgid "change card holder's salutation"
|
||||||
msgstr "カード所有者の性別の変更"
|
msgstr "カード所有者の敬称の変更"
|
||||||
|
|
||||||
msgid "change a CA fingerprint"
|
msgid "change a CA fingerprint"
|
||||||
msgstr "CAフィンガープリントの変更"
|
msgstr "CAフィンガープリントの変更"
|
||||||
@ -1489,6 +1498,9 @@ msgstr "PIN認証のKDFを設定する"
|
|||||||
msgid "change the key attribute"
|
msgid "change the key attribute"
|
||||||
msgstr "鍵の属性の変更"
|
msgstr "鍵の属性の変更"
|
||||||
|
|
||||||
|
msgid "change the User Interaction Flag"
|
||||||
|
msgstr "ユーザ・インタラクション・フラグの変更"
|
||||||
|
|
||||||
msgid "gpg/card> "
|
msgid "gpg/card> "
|
||||||
msgstr "gpg/card> "
|
msgstr "gpg/card> "
|
||||||
|
|
||||||
@ -1527,7 +1539,19 @@ msgid "(unless you specify the key by fingerprint)\n"
|
|||||||
msgstr "(フィンガー・プリントで鍵を指定してない限り)\n"
|
msgstr "(フィンガー・プリントで鍵を指定してない限り)\n"
|
||||||
|
|
||||||
msgid "can't do this in batch mode without \"--yes\"\n"
|
msgid "can't do this in batch mode without \"--yes\"\n"
|
||||||
msgstr "\"--yes\"なしでバッチ・モードではできません\n"
|
msgstr "これは\"--yes\"なしでバッチ・モードではできません\n"
|
||||||
|
|
||||||
|
msgid "Note: The public primary key and all its subkeys will be deleted.\n"
|
||||||
|
msgstr "注意: 主鍵とすべての副鍵の公開鍵が削除されます。\n"
|
||||||
|
|
||||||
|
msgid "Note: Only the shown public subkey will be deleted.\n"
|
||||||
|
msgstr "注意: 表示されている副鍵の公開鍵だけが削除されます。\n"
|
||||||
|
|
||||||
|
msgid "Note: Only the secret part of the shown primary key will be deleted.\n"
|
||||||
|
msgstr "注意: 表示されている主鍵の秘密鍵だけが削除されます。\n"
|
||||||
|
|
||||||
|
msgid "Note: Only the secret part of the shown subkey will be deleted.\n"
|
||||||
|
msgstr "注意: 表示されている副鍵の秘密鍵だけが削除されます。\n"
|
||||||
|
|
||||||
msgid "Delete this key from the keyring? (y/N) "
|
msgid "Delete this key from the keyring? (y/N) "
|
||||||
msgstr "この鍵を鍵リングから削除しますか? (y/N) "
|
msgstr "この鍵を鍵リングから削除しますか? (y/N) "
|
||||||
@ -1545,6 +1569,10 @@ msgstr "鍵"
|
|||||||
msgid "subkey"
|
msgid "subkey"
|
||||||
msgstr "副鍵: "
|
msgstr "副鍵: "
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "update failed: %s\n"
|
||||||
|
msgstr "更新に失敗しました: %s\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "deleting keyblock failed: %s\n"
|
msgid "deleting keyblock failed: %s\n"
|
||||||
msgstr "鍵ブロックの削除に失敗しました: %s\n"
|
msgstr "鍵ブロックの削除に失敗しました: %s\n"
|
||||||
@ -1567,8 +1595,8 @@ msgid "can't use a symmetric ESK packet due to the S2K mode\n"
|
|||||||
msgstr "S2Kモードのため、共通鍵ESKパケットを使えません\n"
|
msgstr "S2Kモードのため、共通鍵ESKパケットを使えません\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "using cipher %s\n"
|
msgid "using cipher %s.%s\n"
|
||||||
msgstr "暗号方式 %s を使います\n"
|
msgstr "暗号方式 %s.%s を使います\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "'%s' already compressed\n"
|
msgid "'%s' already compressed\n"
|
||||||
@ -1608,16 +1636,16 @@ msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n"
|
|||||||
msgstr "共通鍵暗号方式 %s (%d) の強制が、受取人の優先指定をそむきます\n"
|
msgstr "共通鍵暗号方式 %s (%d) の強制が、受取人の優先指定をそむきます\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s/%s encrypted for: \"%s\"\n"
|
msgid "%s/%s.%s encrypted for: \"%s\"\n"
|
||||||
msgstr "%s/%s暗号化 受信者:\"%s\"\n"
|
msgstr "%s/%s.%s 暗号化 受信者:\"%s\"\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "option '%s' may not be used in %s mode\n"
|
msgid "option '%s' may not be used in %s mode\n"
|
||||||
msgstr "オプション'%s'を%sモードで使うことはできません\n"
|
msgstr "オプション'%s'を%sモードで使うことはできません\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s encrypted data\n"
|
msgid "%s.%s encrypted data\n"
|
||||||
msgstr "%s暗号化済みデータ\n"
|
msgstr "%s.%s 暗号化データ\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "encrypted with unknown algorithm %d\n"
|
msgid "encrypted with unknown algorithm %d\n"
|
||||||
@ -1688,6 +1716,9 @@ msgstr "エクスポートの際、利用できない部分を除去する"
|
|||||||
msgid "remove as much as possible from key during export"
|
msgid "remove as much as possible from key during export"
|
||||||
msgstr "エクスポートの際、できるだけ除去する"
|
msgstr "エクスポートの際、できるだけ除去する"
|
||||||
|
|
||||||
|
msgid "Do not export user id or attribute packets"
|
||||||
|
msgstr "ユーザIDもしくは属性パケットをエクスポートしない"
|
||||||
|
|
||||||
msgid "use the GnuPG key backup format"
|
msgid "use the GnuPG key backup format"
|
||||||
msgstr "GnuPGの鍵のバックアップフォーマットを使います"
|
msgstr "GnuPGの鍵のバックアップフォーマットを使います"
|
||||||
|
|
||||||
@ -1719,22 +1750,6 @@ msgstr "'%s'の作成エラー: %s\n"
|
|||||||
msgid "[User ID not found]"
|
msgid "[User ID not found]"
|
||||||
msgstr "[ユーザIDが見つかりません]"
|
msgstr "[ユーザIDが見つかりません]"
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "(check argument of option '%s')\n"
|
|
||||||
msgstr "(オプション'%s'の引数を確認ください)\n"
|
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "Warning: '%s' should be a long key ID or a fingerprint\n"
|
|
||||||
msgstr "警告: '%s'は長い鍵IDかフィンガープリントであるべきです。\n"
|
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "error looking up: %s\n"
|
|
||||||
msgstr "検索のエラー: %s\n"
|
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "Warning: %s appears in the keyring %d times\n"
|
|
||||||
msgstr "警告: %sは鍵リングに%d回出現します\n"
|
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "automatically retrieved '%s' via %s\n"
|
msgid "automatically retrieved '%s' via %s\n"
|
||||||
msgstr "'%s'を %s から自動取得\n"
|
msgstr "'%s'を %s から自動取得\n"
|
||||||
@ -1746,10 +1761,18 @@ msgstr "'%s'を %s から取得する際のエラー: %s\n"
|
|||||||
msgid "No fingerprint"
|
msgid "No fingerprint"
|
||||||
msgstr "フィンガープリントがありません"
|
msgstr "フィンガープリントがありません"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "checking for a fresh copy of an expired key via %s\n"
|
||||||
|
msgstr "%s から失効した鍵の新しいコピーを確認します。\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "secret key \"%s\" not found: %s\n"
|
msgid "secret key \"%s\" not found: %s\n"
|
||||||
msgstr "秘密鍵\"%s\"が見つかりません: %s\n"
|
msgstr "秘密鍵\"%s\"が見つかりません: %s\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "(check argument of option '%s')\n"
|
||||||
|
msgstr "(オプション'%s'の引数を確認ください)\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Warning: not using '%s' as default key: %s\n"
|
msgid "Warning: not using '%s' as default key: %s\n"
|
||||||
msgstr "警告: デフォルトの秘密鍵として '%s' を用いません: %s\n"
|
msgstr "警告: デフォルトの秘密鍵として '%s' を用いません: %s\n"
|
||||||
@ -2225,7 +2248,10 @@ msgid "will not run with insecure memory due to %s\n"
|
|||||||
msgstr "%s のため、セキュアでないメモリで実行しません\n"
|
msgstr "%s のため、セキュアでないメモリで実行しません\n"
|
||||||
|
|
||||||
msgid "selected cipher algorithm is invalid\n"
|
msgid "selected cipher algorithm is invalid\n"
|
||||||
msgstr "選択された暗号アルゴリズムは、無効です\n"
|
msgstr "選択された暗号アルゴリズムは無効です\n"
|
||||||
|
|
||||||
|
msgid "selected AEAD algorithm is invalid\n"
|
||||||
|
msgstr "選択された AEAD アルゴリズムは無効です\n"
|
||||||
|
|
||||||
msgid "selected compression algorithm is invalid\n"
|
msgid "selected compression algorithm is invalid\n"
|
||||||
msgstr "選択された圧縮アルゴリズムは、無効です\n"
|
msgstr "選択された圧縮アルゴリズムは、無効です\n"
|
||||||
@ -2260,16 +2286,27 @@ msgstr "無効なデフォルトの優先指定\n"
|
|||||||
msgid "invalid personal cipher preferences\n"
|
msgid "invalid personal cipher preferences\n"
|
||||||
msgstr "無効な個人用暗号方式の優先指定\n"
|
msgstr "無効な個人用暗号方式の優先指定\n"
|
||||||
|
|
||||||
|
msgid "invalid personal AEAD preferences\n"
|
||||||
|
msgstr "無効な個人用 AEAD 方式の優先指定\n"
|
||||||
|
|
||||||
msgid "invalid personal digest preferences\n"
|
msgid "invalid personal digest preferences\n"
|
||||||
msgstr "無効な個人用ダイジェストの優先指定\n"
|
msgstr "無効な個人用ダイジェストの優先指定\n"
|
||||||
|
|
||||||
msgid "invalid personal compress preferences\n"
|
msgid "invalid personal compress preferences\n"
|
||||||
msgstr "無効な個人用圧縮の優先指定\n"
|
msgstr "無効な個人用圧縮の優先指定\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "chunk size invalid - using %d\n"
|
||||||
|
msgstr "無効なチャンク長です - %dにします\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s does not yet work with %s\n"
|
msgid "%s does not yet work with %s\n"
|
||||||
msgstr "%sは%sではまだ機能しません\n"
|
msgstr "%sは%sではまだ機能しません\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "AEAD algorithm '%s' may not be used in %s mode\n"
|
||||||
|
msgstr "AEAD アルゴリズム'%s'を%sモードで使うことはできません\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
msgid "digest algorithm '%s' may not be used in %s mode\n"
|
||||||
msgstr "ダイジェスト・アルゴリズム'%s'を%sモードで使うことはできません\n"
|
msgstr "ダイジェスト・アルゴリズム'%s'を%sモードで使うことはできません\n"
|
||||||
@ -2417,6 +2454,9 @@ msgstr "インポート後、利用できない部分を鍵から除去します
|
|||||||
msgid "remove as much as possible from key after import"
|
msgid "remove as much as possible from key after import"
|
||||||
msgstr "インポート後、できるだけ除去します"
|
msgstr "インポート後、できるだけ除去します"
|
||||||
|
|
||||||
|
msgid "Do not import user id or attribute packets"
|
||||||
|
msgstr "ユーザIDもしくは属性パケットをインポートしない"
|
||||||
|
|
||||||
msgid "run import filters and export key immediately"
|
msgid "run import filters and export key immediately"
|
||||||
msgstr "インポート・フィルタを実行し鍵をすぐにエクスポートします"
|
msgstr "インポート・フィルタを実行し鍵をすぐにエクスポートします"
|
||||||
|
|
||||||
@ -2510,6 +2550,10 @@ msgstr ""
|
|||||||
msgid " \"%s\": preference for cipher algorithm %s\n"
|
msgid " \"%s\": preference for cipher algorithm %s\n"
|
||||||
msgstr " \"%s\": 暗号アルゴリズムの優先指定 %s\n"
|
msgstr " \"%s\": 暗号アルゴリズムの優先指定 %s\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid " \"%s\": preference for AEAD algorithm %s\n"
|
||||||
|
msgstr " \"%s\": AEADアルゴリズムの優先指定 %s\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid " \"%s\": preference for digest algorithm %s\n"
|
msgid " \"%s\": preference for digest algorithm %s\n"
|
||||||
msgstr " \"%s\": ダイジェスト・アルゴリズムの優先指定 %s\n"
|
msgstr " \"%s\": ダイジェスト・アルゴリズムの優先指定 %s\n"
|
||||||
@ -2634,6 +2678,18 @@ msgstr "鍵 %s: 秘密鍵はもうあります\n"
|
|||||||
msgid "key %s: error sending to agent: %s\n"
|
msgid "key %s: error sending to agent: %s\n"
|
||||||
msgstr "鍵 %s: エージェントへの送信エラー: %s\n"
|
msgstr "鍵 %s: エージェントへの送信エラー: %s\n"
|
||||||
|
|
||||||
|
#. TRANSLATORS: For a smartcard, each private key on host has a
|
||||||
|
#. * reference (stub) to a smartcard and actual private key data
|
||||||
|
#. * is stored on the card. A single smartcard can have up to
|
||||||
|
#. * three private key data. Importing private key stub is always
|
||||||
|
#. * skipped in 2.1, and it returns GPG_ERR_NOT_PROCESSED.
|
||||||
|
#. * Instead, user should be suggested to run 'gpg --card-status',
|
||||||
|
#. * then, references to a card will be automatically created
|
||||||
|
#. * again.
|
||||||
|
#, c-format
|
||||||
|
msgid "To migrate '%s', with each smartcard, run: %s\n"
|
||||||
|
msgstr "'%s'の移行には、スマードカードそれぞれで、以下を実行してください: %s\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "secret key %s: %s\n"
|
msgid "secret key %s: %s\n"
|
||||||
msgstr "秘密鍵 %s: %s\n"
|
msgstr "秘密鍵 %s: %s\n"
|
||||||
@ -2645,19 +2701,26 @@ msgstr "秘密鍵のインポートは禁止です\n"
|
|||||||
msgid "key %s: secret key with invalid cipher %d - skipped\n"
|
msgid "key %s: secret key with invalid cipher %d - skipped\n"
|
||||||
msgstr "鍵%s: 無効な暗号方式%dの秘密鍵です - スキップします\n"
|
msgstr "鍵%s: 無効な暗号方式%dの秘密鍵です - スキップします\n"
|
||||||
|
|
||||||
#. TRANSLATORS: For smartcard, each private key on
|
msgid "No reason specified"
|
||||||
#. host has a reference (stub) to a smartcard and
|
msgstr "理由は指定されていません"
|
||||||
#. actual private key data is stored on the card. A
|
|
||||||
#. single smartcard can have up to three private key
|
msgid "Key is superseded"
|
||||||
#. data. Importing private key stub is always
|
msgstr "鍵がとりかわっています"
|
||||||
#. skipped in 2.1, and it returns
|
|
||||||
#. GPG_ERR_NOT_PROCESSED. Instead, user should be
|
msgid "Key has been compromised"
|
||||||
#. suggested to run 'gpg --card-status', then,
|
msgstr "鍵(の信頼性)が損なわれています"
|
||||||
#. references to a card will be automatically
|
|
||||||
#. created again.
|
msgid "Key is no longer used"
|
||||||
#, c-format
|
msgstr "鍵はもはや使われていません"
|
||||||
msgid "To migrate '%s', with each smartcard, run: %s\n"
|
|
||||||
msgstr "'%s'の移行には、スマードカードそれぞれで、以下を実行してください: %s\n"
|
msgid "User ID is no longer valid"
|
||||||
|
msgstr "ユーザIDがもはや有効でありません"
|
||||||
|
|
||||||
|
msgid "reason for revocation: "
|
||||||
|
msgstr "失効理由: "
|
||||||
|
|
||||||
|
msgid "revocation comment: "
|
||||||
|
msgstr "失効のコメント: "
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "key %s: no public key - can't apply revocation certificate\n"
|
msgid "key %s: no public key - can't apply revocation certificate\n"
|
||||||
@ -3227,10 +3290,6 @@ msgstr "変更を保存しますか? (y/N) "
|
|||||||
msgid "Quit without saving? (y/N) "
|
msgid "Quit without saving? (y/N) "
|
||||||
msgstr "保存せずに終了しますか? (y/N) "
|
msgstr "保存せずに終了しますか? (y/N) "
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "update failed: %s\n"
|
|
||||||
msgstr "更新に失敗しました: %s\n"
|
|
||||||
|
|
||||||
msgid "Key not changed so no update needed.\n"
|
msgid "Key not changed so no update needed.\n"
|
||||||
msgstr "鍵は無変更なので更新は不要です。\n"
|
msgstr "鍵は無変更なので更新は不要です。\n"
|
||||||
|
|
||||||
@ -3269,12 +3328,15 @@ msgstr "'%s'は、有効な有効期限ではありません\n"
|
|||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "\"%s\" is not a proper fingerprint\n"
|
msgid "\"%s\" is not a proper fingerprint\n"
|
||||||
msgstr "\"%s\"はフ正しいィンガープリントではありません\n"
|
msgstr "\"%s\"は正しいフィンガープリントではありません\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "subkey \"%s\" not found\n"
|
msgid "subkey \"%s\" not found\n"
|
||||||
msgstr "副鍵\"%s\"が見つかりません\n"
|
msgstr "副鍵\"%s\"が見つかりません\n"
|
||||||
|
|
||||||
|
msgid "AEAD: "
|
||||||
|
msgstr "AEAD: "
|
||||||
|
|
||||||
msgid "Digest: "
|
msgid "Digest: "
|
||||||
msgstr "ダイジェスト: "
|
msgstr "ダイジェスト: "
|
||||||
|
|
||||||
@ -3607,6 +3669,9 @@ msgstr "ダイジェストの優先指定が多すぎます\n"
|
|||||||
msgid "too many compression preferences\n"
|
msgid "too many compression preferences\n"
|
||||||
msgstr "圧縮の優先指定が多すぎます\n"
|
msgstr "圧縮の優先指定が多すぎます\n"
|
||||||
|
|
||||||
|
msgid "too many AEAD preferences\n"
|
||||||
|
msgstr "AEAD方式の優先指定が多すぎます\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "invalid item '%s' in preference string\n"
|
msgid "invalid item '%s' in preference string\n"
|
||||||
msgstr "優先指定の文字列に無効な項目'%s'があります\n"
|
msgstr "優先指定の文字列に無効な項目'%s'があります\n"
|
||||||
@ -3647,21 +3712,21 @@ msgid "Authenticate"
|
|||||||
msgstr "Authenticate"
|
msgstr "Authenticate"
|
||||||
|
|
||||||
#. TRANSLATORS: Please use only plain ASCII characters for the
|
#. TRANSLATORS: Please use only plain ASCII characters for the
|
||||||
#. translation. If this is not possible use single digits. The
|
#. * translation. If this is not possible use single digits. The
|
||||||
#. string needs to 8 bytes long. Here is a description of the
|
#. * string needs to 8 bytes long. Here is a description of the
|
||||||
#. functions:
|
#. * functions:
|
||||||
#.
|
#. *
|
||||||
#. s = Toggle signing capability
|
#. * s = Toggle signing capability
|
||||||
#. e = Toggle encryption capability
|
#. * e = Toggle encryption capability
|
||||||
#. a = Toggle authentication capability
|
#. * a = Toggle authentication capability
|
||||||
#. q = Finish
|
#. * q = Finish
|
||||||
#.
|
#.
|
||||||
msgid "SsEeAaQq"
|
msgid "SsEeAaQq"
|
||||||
msgstr "SsEeAaQq"
|
msgstr "SsEeAaQq"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Possible actions for a %s key: "
|
msgid "Possible actions for this %s key: "
|
||||||
msgstr "鍵%sに認められた操作: "
|
msgstr "この鍵%sにありうる操作: "
|
||||||
|
|
||||||
msgid "Current allowed actions: "
|
msgid "Current allowed actions: "
|
||||||
msgstr "現在の認められた操作: "
|
msgstr "現在の認められた操作: "
|
||||||
@ -3734,6 +3799,10 @@ msgstr " (%d) ECC (暗号化のみ)\n"
|
|||||||
msgid " (%d) Existing key\n"
|
msgid " (%d) Existing key\n"
|
||||||
msgstr " (%d) 既存の鍵\n"
|
msgstr " (%d) 既存の鍵\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid " (%d) Existing key from card\n"
|
||||||
|
msgstr " (%d) カードに存在する鍵\n"
|
||||||
|
|
||||||
msgid "Enter the keygrip: "
|
msgid "Enter the keygrip: "
|
||||||
msgstr "keygripを入力: "
|
msgstr "keygripを入力: "
|
||||||
|
|
||||||
@ -3743,6 +3812,17 @@ msgstr "有効なkeygrip (40桁の16進数字)ではありません\n"
|
|||||||
msgid "No key with this keygrip\n"
|
msgid "No key with this keygrip\n"
|
||||||
msgstr "このkeygripの鍵はありません\n"
|
msgstr "このkeygripの鍵はありません\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "error reading the card: %s\n"
|
||||||
|
msgstr "カードの読み込みエラー: %s\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "Serial number of the card: %s\n"
|
||||||
|
msgstr "カードのシリアル番号: %s\n"
|
||||||
|
|
||||||
|
msgid "Available keys:\n"
|
||||||
|
msgstr "利用可能な鍵:\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "rounded to %u bits\n"
|
msgid "rounded to %u bits\n"
|
||||||
msgstr "%uビットに切り上げます\n"
|
msgstr "%uビットに切り上げます\n"
|
||||||
@ -4164,9 +4244,6 @@ msgstr "鍵\"%s\"が鍵サーバに見つかりません\n"
|
|||||||
msgid "key not found on keyserver\n"
|
msgid "key not found on keyserver\n"
|
||||||
msgstr "鍵が鍵サーバに見つかりません\n"
|
msgstr "鍵が鍵サーバに見つかりません\n"
|
||||||
|
|
||||||
msgid "no keyserver known (use option --keyserver)\n"
|
|
||||||
msgstr "既知の鍵サーバがありません (オプション--keyserverを使いましょう)\n"
|
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "requesting key %s from %s server %s\n"
|
msgid "requesting key %s from %s server %s\n"
|
||||||
msgstr "鍵%sを%sからサーバ%sに要求\n"
|
msgstr "鍵%sを%sからサーバ%sに要求\n"
|
||||||
@ -4196,11 +4273,15 @@ msgstr "*警告*: URI %s からデータを取れません: %s\n"
|
|||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "weird size for an encrypted session key (%d)\n"
|
msgid "weird size for an encrypted session key (%d)\n"
|
||||||
msgstr "変な長さの暗号化済みセッション鍵 (%d)\n"
|
msgstr "変な長さの暗号化セッション鍵 (%d)\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s encrypted session key\n"
|
msgid "%s.%s encrypted session key\n"
|
||||||
msgstr "%s 暗号化済みセッション鍵\n"
|
msgstr "%s.%s 暗号化セッション鍵\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "encrypted with unknown algorithm %d.%s\n"
|
||||||
|
msgstr "不明のアルゴリズム%d.%sによる暗号化\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "passphrase generated with unknown digest algorithm %d\n"
|
msgid "passphrase generated with unknown digest algorithm %d\n"
|
||||||
@ -4210,12 +4291,9 @@ msgstr "不明のダイジェスト・アルゴリズムで生成されたパス
|
|||||||
msgid "public key is %s\n"
|
msgid "public key is %s\n"
|
||||||
msgstr "公開鍵は%sです\n"
|
msgstr "公開鍵は%sです\n"
|
||||||
|
|
||||||
msgid "public key encrypted data: good DEK\n"
|
|
||||||
msgstr "公開鍵による暗号化済みデータ: 正しいDEKです\n"
|
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "encrypted with %u-bit %s key, ID %s, created %s\n"
|
msgid "encrypted with %s key, ID %s, created %s\n"
|
||||||
msgstr "%u-ビット%s鍵, ID %s, 日付%sに暗号化されました\n"
|
msgstr "%s鍵, ID %s, 作成日付%s により暗号化されました\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid " \"%s\"\n"
|
msgid " \"%s\"\n"
|
||||||
@ -4225,9 +4303,8 @@ msgstr " \"%s\"\n"
|
|||||||
msgid "encrypted with %s key, ID %s\n"
|
msgid "encrypted with %s key, ID %s\n"
|
||||||
msgstr "%s鍵, ID %sで暗号化されました\n"
|
msgstr "%s鍵, ID %sで暗号化されました\n"
|
||||||
|
|
||||||
#, c-format
|
msgid "WARNING: multiple plaintexts seen\n"
|
||||||
msgid "public key decryption failed: %s\n"
|
msgstr "*警告*: 複数のプレインテクストが見られます\n"
|
||||||
msgstr "公開鍵の復号に失敗しました: %s\n"
|
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "encrypted with %lu passphrases\n"
|
msgid "encrypted with %lu passphrases\n"
|
||||||
@ -4236,9 +4313,16 @@ msgstr "%lu 個のパスフレーズで暗号化\n"
|
|||||||
msgid "encrypted with 1 passphrase\n"
|
msgid "encrypted with 1 passphrase\n"
|
||||||
msgstr "1 個のパスフレーズで暗号化\n"
|
msgstr "1 個のパスフレーズで暗号化\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "public key decryption failed: %s\n"
|
||||||
|
msgstr "公開鍵の復号に失敗しました: %s\n"
|
||||||
|
|
||||||
|
msgid "public key encrypted data: good DEK\n"
|
||||||
|
msgstr "公開鍵による暗号化データ: 正しいDEKです\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "assuming %s encrypted data\n"
|
msgid "assuming %s encrypted data\n"
|
||||||
msgstr "%s暗号化済みデータを仮定\n"
|
msgstr "%s暗号化データを仮定\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n"
|
msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n"
|
||||||
@ -4247,6 +4331,22 @@ msgstr "IDEA暗号方式は利用不能なので、楽天的ですが%sで代用
|
|||||||
msgid "WARNING: message was not integrity protected\n"
|
msgid "WARNING: message was not integrity protected\n"
|
||||||
msgstr "*警告*: メッセージの完全性は保護されていません\n"
|
msgstr "*警告*: メッセージの完全性は保護されていません\n"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Hint: If this message was created before the year 2003 it is\n"
|
||||||
|
"likely that this message is legitimate. This is because back\n"
|
||||||
|
"then integrity protection was not widely used.\n"
|
||||||
|
msgstr ""
|
||||||
|
"ヒント: もし、このメッセージが2003年以前に作成されたのであれば、\n"
|
||||||
|
"このメッセージはおそらく正当でしょう。当時、整合性の保護機能は\n"
|
||||||
|
"広く使われてはいなかったためです。\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "Use the option '%s' to decrypt anyway.\n"
|
||||||
|
msgstr "それでも復号するにはオプション '%s' を使います。\n"
|
||||||
|
|
||||||
|
msgid "decryption forced to fail!\n"
|
||||||
|
msgstr "復号は強制的に失敗とされました!\n"
|
||||||
|
|
||||||
msgid "decryption okay\n"
|
msgid "decryption okay\n"
|
||||||
msgstr "復号に成功\n"
|
msgstr "復号に成功\n"
|
||||||
|
|
||||||
@ -4264,9 +4364,6 @@ msgstr "注意: 送信者は\"極秘とする\"ように求めています\n"
|
|||||||
msgid "original file name='%.*s'\n"
|
msgid "original file name='%.*s'\n"
|
||||||
msgstr "元のファイル名='%.*s'\n"
|
msgstr "元のファイル名='%.*s'\n"
|
||||||
|
|
||||||
msgid "WARNING: multiple plaintexts seen\n"
|
|
||||||
msgstr "*警告*: 複数のプレインテクストが見られます\n"
|
|
||||||
|
|
||||||
msgid "standalone revocation - use \"gpg --import\" to apply\n"
|
msgid "standalone revocation - use \"gpg --import\" to apply\n"
|
||||||
msgstr "スタンドアロン失効 - \"gpg --import\"を使って適用してください\n"
|
msgstr "スタンドアロン失効 - \"gpg --import\"を使って適用してください\n"
|
||||||
|
|
||||||
@ -4493,14 +4590,13 @@ msgstr "公開鍵のアルゴリズム%dは、取り扱えません\n"
|
|||||||
msgid "WARNING: potentially insecure symmetrically encrypted session key\n"
|
msgid "WARNING: potentially insecure symmetrically encrypted session key\n"
|
||||||
msgstr "*警告*: 潜在的にセキュアでない共通鍵暗号化セッション鍵です\n"
|
msgstr "*警告*: 潜在的にセキュアでない共通鍵暗号化セッション鍵です\n"
|
||||||
|
|
||||||
|
msgid "Unknown critical signature notation: "
|
||||||
|
msgstr "不明なクリティカルな署名注釈: "
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "subpacket of type %d has critical bit set\n"
|
msgid "subpacket of type %d has critical bit set\n"
|
||||||
msgstr "型%dの下位パケットにクリティカル・ビットを発見\n"
|
msgstr "型%dの下位パケットにクリティカル・ビットを発見\n"
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "problem with the agent: %s\n"
|
|
||||||
msgstr "エージェントに問題: %s\n"
|
|
||||||
|
|
||||||
msgid "Enter passphrase\n"
|
msgid "Enter passphrase\n"
|
||||||
msgstr "パスフレーズを入力\n"
|
msgstr "パスフレーズを入力\n"
|
||||||
|
|
||||||
@ -4581,27 +4677,6 @@ msgstr "この写真は正しいですか (y/N/q)? "
|
|||||||
msgid "unable to display photo ID!\n"
|
msgid "unable to display photo ID!\n"
|
||||||
msgstr "フォトIDが表示不能!\n"
|
msgstr "フォトIDが表示不能!\n"
|
||||||
|
|
||||||
msgid "No reason specified"
|
|
||||||
msgstr "理由は指定されていません"
|
|
||||||
|
|
||||||
msgid "Key is superseded"
|
|
||||||
msgstr "鍵がとりかわっています"
|
|
||||||
|
|
||||||
msgid "Key has been compromised"
|
|
||||||
msgstr "鍵(の信頼性)が損なわれています"
|
|
||||||
|
|
||||||
msgid "Key is no longer used"
|
|
||||||
msgstr "鍵はもはや使われていません"
|
|
||||||
|
|
||||||
msgid "User ID is no longer valid"
|
|
||||||
msgstr "ユーザIDがもはや有効でありません"
|
|
||||||
|
|
||||||
msgid "reason for revocation: "
|
|
||||||
msgstr "失効理由: "
|
|
||||||
|
|
||||||
msgid "revocation comment: "
|
|
||||||
msgstr "失効のコメント: "
|
|
||||||
|
|
||||||
#. TRANSLATORS: These are the allowed answers in lower and
|
#. TRANSLATORS: These are the allowed answers in lower and
|
||||||
#. uppercase. Below you will find the matching strings which
|
#. uppercase. Below you will find the matching strings which
|
||||||
#. should be translated accordingly and the letter changed to
|
#. should be translated accordingly and the letter changed to
|
||||||
@ -5080,6 +5155,10 @@ msgstr "注意: 鍵 %s は失効済みです\n"
|
|||||||
msgid "bad key signature from key %s: %s (0x%02x, 0x%x)\n"
|
msgid "bad key signature from key %s: %s (0x%02x, 0x%x)\n"
|
||||||
msgstr "鍵%sによる不正な鍵への署名: %s (0x%02x, 0x%x)\n"
|
msgstr "鍵%sによる不正な鍵への署名: %s (0x%02x, 0x%x)\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "bad data signature from key %s: %s (0x%02x, 0x%x)\n"
|
||||||
|
msgstr "鍵%sによる不正なデータへの署名: %s (0x%02x, 0x%x)\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "assuming bad signature from key %s due to an unknown critical bit\n"
|
msgid "assuming bad signature from key %s due to an unknown critical bit\n"
|
||||||
msgstr "不明のクリティカル・ビットのため、鍵%sによる署名を不正とみなします\n"
|
msgstr "不明のクリティカル・ビットのため、鍵%sによる署名を不正とみなします\n"
|
||||||
@ -5122,8 +5201,8 @@ msgid "signing:"
|
|||||||
msgstr "署名:"
|
msgstr "署名:"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s encryption will be used\n"
|
msgid "%s.%s encryption will be used\n"
|
||||||
msgstr "%s暗号化を使用します\n"
|
msgstr "%s.%s 暗号化を使用します\n"
|
||||||
|
|
||||||
msgid "key is not flagged as insecure - can't use it with the faked RNG!\n"
|
msgid "key is not flagged as insecure - can't use it with the faked RNG!\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -5306,9 +5385,6 @@ msgid "unsupported TOFU database version: %s\n"
|
|||||||
msgstr "サポートされていないTOFUデータベースバージョン: %s\n"
|
msgstr "サポートされていないTOFUデータベースバージョン: %s\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "error creating 'ultimately_trusted_keys' TOFU table: %s\n"
|
|
||||||
msgstr "'ultimately_trusted_keys' TOFUテーブル作成エラー: %s\n"
|
|
||||||
|
|
||||||
msgid "TOFU DB error"
|
msgid "TOFU DB error"
|
||||||
msgstr "TOFU DBエラー"
|
msgstr "TOFU DBエラー"
|
||||||
|
|
||||||
@ -5324,14 +5400,6 @@ msgstr "TOFUデータベースのバージョン判定エラー: %s\n"
|
|||||||
msgid "error initializing TOFU database: %s\n"
|
msgid "error initializing TOFU database: %s\n"
|
||||||
msgstr "TOFUデータベースの初期化エラー: %s\n"
|
msgstr "TOFUデータベースの初期化エラー: %s\n"
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "error creating 'encryptions' TOFU table: %s\n"
|
|
||||||
msgstr "'encryptions' TOFUデータベースの作成エラー: %s\n"
|
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "adding column effective_policy to bindings DB: %s\n"
|
|
||||||
msgstr "バインディングDBにカラムeffective_policyを追加: %s\n"
|
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "error opening TOFU database '%s': %s\n"
|
msgid "error opening TOFU database '%s': %s\n"
|
||||||
msgstr "TOFUデータベースのオープンでエラー '%s': %s\n"
|
msgstr "TOFUデータベースのオープンでエラー '%s': %s\n"
|
||||||
@ -5470,14 +5538,6 @@ msgstr "不明をデフォルトとします。\n"
|
|||||||
msgid "TOFU db corruption detected.\n"
|
msgid "TOFU db corruption detected.\n"
|
||||||
msgstr "TOFU dbが壊れていることが検出されました。\n"
|
msgstr "TOFU dbが壊れていることが検出されました。\n"
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "resetting keydb: %s\n"
|
|
||||||
msgstr "keydbをリセット: %s\n"
|
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "error setting TOFU binding's policy to %s\n"
|
|
||||||
msgstr "TOFUバインディングのポリシーを %s に設定エラー\n"
|
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "error changing TOFU policy: %s\n"
|
msgid "error changing TOFU policy: %s\n"
|
||||||
msgstr "TOFUポリシーの作成エラー: %s\n"
|
msgstr "TOFUポリシーの作成エラー: %s\n"
|
||||||
@ -5525,19 +5585,9 @@ msgstr "%s: 0個の署名を検証、0個のメッセージを暗号化しまし
|
|||||||
msgid "%s: Verified 0 signatures."
|
msgid "%s: Verified 0 signatures."
|
||||||
msgstr "%s: 0個の署名を検証しました。"
|
msgstr "%s: 0個の署名を検証しました。"
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "%s: Verified %ld~signature in the past %s."
|
|
||||||
msgid_plural "%s: Verified %ld~signatures in the past %s."
|
|
||||||
msgstr[0] "%s: 署名を%ld個検証しました(これまで %s に)。"
|
|
||||||
|
|
||||||
msgid "Encrypted 0 messages."
|
msgid "Encrypted 0 messages."
|
||||||
msgstr "0 個のメッセージを暗号化しました。"
|
msgstr "0 個のメッセージを暗号化しました。"
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "Encrypted %ld~message in the past %s."
|
|
||||||
msgid_plural "Encrypted %ld~messages in the past %s."
|
|
||||||
msgstr[0] "メッセージを%ld個暗号化しました(これまで %s に)。"
|
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "(policy: %s)"
|
msgid "(policy: %s)"
|
||||||
msgstr "(ポリシー: %s)"
|
msgstr "(ポリシー: %s)"
|
||||||
@ -5585,10 +5635,6 @@ msgid "WARNING: Encrypting to %s, which has no non-revoked user ids\n"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"*警告*: %s に暗号化します。失効していないユーザIDが一つもないものです\n"
|
"*警告*: %s に暗号化します。失効していないユーザIDが一つもないものです\n"
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "error setting policy for key %s, user id \"%s\": %s"
|
|
||||||
msgstr "鍵%s, ユーザID \"%s\"のポリシーの設定エラー: %s"
|
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "'%s' is not a valid long keyID\n"
|
msgid "'%s' is not a valid long keyID\n"
|
||||||
msgstr "'%s'は、有効な大型鍵IDでありません\n"
|
msgstr "'%s'は、有効な大型鍵IDでありません\n"
|
||||||
@ -5751,6 +5797,13 @@ msgstr "入力の%u行目が長すぎるか、LFがないようです\n"
|
|||||||
msgid "can't open fd %d: %s\n"
|
msgid "can't open fd %d: %s\n"
|
||||||
msgstr "fd %dが開けません: %s\n"
|
msgstr "fd %dが開けません: %s\n"
|
||||||
|
|
||||||
|
msgid "WARNING: encrypting without integrity protection is dangerous\n"
|
||||||
|
msgstr "*警告*: 完全性保護なしでの暗号化は危険です\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "Hint: Do not use option %s\n"
|
||||||
|
msgstr "ヒント: オプション %s を使わない\n"
|
||||||
|
|
||||||
msgid "set debugging flags"
|
msgid "set debugging flags"
|
||||||
msgstr "デバッグ・フラグを設定"
|
msgstr "デバッグ・フラグを設定"
|
||||||
|
|
||||||
@ -6030,6 +6083,9 @@ msgstr "リーダのピンパッドを使わない"
|
|||||||
msgid "deny the use of admin card commands"
|
msgid "deny the use of admin card commands"
|
||||||
msgstr "管理カード・コマンドの使用を拒否"
|
msgstr "管理カード・コマンドの使用を拒否"
|
||||||
|
|
||||||
|
msgid "|LIST|Change the application priority to LIST"
|
||||||
|
msgstr "|LIST|アプリケーションの優先順位をLISTに変更します"
|
||||||
|
|
||||||
msgid "use variable length input for pinpad"
|
msgid "use variable length input for pinpad"
|
||||||
msgstr "ピンパッドの可変長入力を使う"
|
msgstr "ピンパッドの可変長入力を使う"
|
||||||
|
|
||||||
@ -6298,6 +6354,9 @@ msgstr "証明書は暗号化のために使えません\n"
|
|||||||
msgid "certificate is not usable for signing\n"
|
msgid "certificate is not usable for signing\n"
|
||||||
msgstr "証明書は署名のために使えません\n"
|
msgstr "証明書は署名のために使えません\n"
|
||||||
|
|
||||||
|
msgid "looking for another certificate\n"
|
||||||
|
msgstr "別の証明書を探索する\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "line %d: invalid algorithm\n"
|
msgid "line %d: invalid algorithm\n"
|
||||||
msgstr "行 %d: 無効なアルゴリズムです\n"
|
msgstr "行 %d: 無効なアルゴリズムです\n"
|
||||||
@ -6385,17 +6444,6 @@ msgstr " (%d) 既存の鍵\n"
|
|||||||
msgid " (%d) Existing key from card\n"
|
msgid " (%d) Existing key from card\n"
|
||||||
msgstr " (%d) カードに存在する鍵\n"
|
msgstr " (%d) カードに存在する鍵\n"
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "error reading the card: %s\n"
|
|
||||||
msgstr "カードの読み込みエラー: %s\n"
|
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "Serial number of the card: %s\n"
|
|
||||||
msgstr "カードのシリアル番号: %s\n"
|
|
||||||
|
|
||||||
msgid "Available keys:\n"
|
|
||||||
msgstr "利用可能な鍵:\n"
|
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Possible actions for a %s key:\n"
|
msgid "Possible actions for a %s key:\n"
|
||||||
msgstr "%s鍵に可能な操作:\n"
|
msgstr "%s鍵に可能な操作:\n"
|
||||||
@ -7641,6 +7689,17 @@ msgstr "'%s' は無効なLDAP URLです\n"
|
|||||||
msgid "error accessing '%s': http status %u\n"
|
msgid "error accessing '%s': http status %u\n"
|
||||||
msgstr "'%s'へアクセスのエラー: httpステイタス %u\n"
|
msgstr "'%s'へアクセスのエラー: httpステイタス %u\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "URL '%s' redirected to '%s' (%u)\n"
|
||||||
|
msgstr "URL'%s' は '%s' (%u) へリダイレクトされました\n"
|
||||||
|
|
||||||
|
msgid "too many redirections\n"
|
||||||
|
msgstr "リダイレクトが多すぎます\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "redirection changed to '%s'\n"
|
||||||
|
msgstr "リダイレクトが'%s'に変更されました\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "error allocating memory: %s\n"
|
msgid "error allocating memory: %s\n"
|
||||||
msgstr "メモリの確保のエラー: %s\n"
|
msgstr "メモリの確保のエラー: %s\n"
|
||||||
@ -7736,13 +7795,6 @@ msgstr "'%s'の接続エラー: %s\n"
|
|||||||
msgid "error reading HTTP response for '%s': %s\n"
|
msgid "error reading HTTP response for '%s': %s\n"
|
||||||
msgstr "'%s'のHTTP応答の読み込みエラー: %s\n"
|
msgstr "'%s'のHTTP応答の読み込みエラー: %s\n"
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "URL '%s' redirected to '%s' (%u)\n"
|
|
||||||
msgstr "URL'%s' は '%s' (%u) へリダイレクトされました\n"
|
|
||||||
|
|
||||||
msgid "too many redirections\n"
|
|
||||||
msgstr "リダイレクトが多すぎます\n"
|
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "error parsing OCSP response for '%s': %s\n"
|
msgid "error parsing OCSP response for '%s': %s\n"
|
||||||
msgstr "'%s'に対するOCSP応答構文解析エラー: %s\n"
|
msgstr "'%s'に対するOCSP応答構文解析エラー: %s\n"
|
||||||
@ -7751,6 +7803,10 @@ msgstr "'%s'に対するOCSP応答構文解析エラー: %s\n"
|
|||||||
msgid "OCSP responder at '%s' status: %s\n"
|
msgid "OCSP responder at '%s' status: %s\n"
|
||||||
msgstr "OSCP応答が '%s' でステイタス: %s\n"
|
msgstr "OSCP応答が '%s' でステイタス: %s\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "failed to establish a hashing context for OCSP: %s\n"
|
||||||
|
msgstr "OCSPのハッシュ・コンテクストを確立するのに失敗しました: %s\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "hashing the OCSP response for '%s' failed: %s\n"
|
msgid "hashing the OCSP response for '%s' failed: %s\n"
|
||||||
msgstr "'%s'に対するOCSP応答のハッシングに失敗しました: %s\n"
|
msgstr "'%s'に対するOCSP応答のハッシングに失敗しました: %s\n"
|
||||||
@ -7758,9 +7814,6 @@ msgstr "'%s'に対するOCSP応答のハッシングに失敗しました: %s\n"
|
|||||||
msgid "not signed by a default OCSP signer's certificate"
|
msgid "not signed by a default OCSP signer's certificate"
|
||||||
msgstr "デフォルトOCSP署名者の証明で署名されていません"
|
msgstr "デフォルトOCSP署名者の証明で署名されていません"
|
||||||
|
|
||||||
msgid "only SHA-1 is supported for OCSP responses\n"
|
|
||||||
msgstr "SHA-1だけがOCSPレスポンスとしてサポートされています\n"
|
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "allocating list item failed: %s\n"
|
msgid "allocating list item failed: %s\n"
|
||||||
msgstr "リスト項目の確保に失敗しました: %s\n"
|
msgstr "リスト項目の確保に失敗しました: %s\n"
|
||||||
@ -7804,10 +7857,6 @@ msgstr "デフォルトOCSP応答'%s'を使います\n"
|
|||||||
msgid "using OCSP responder '%s'\n"
|
msgid "using OCSP responder '%s'\n"
|
||||||
msgstr "OCSP応答'%s'を使います\n"
|
msgstr "OCSP応答'%s'を使います\n"
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "failed to establish a hashing context for OCSP: %s\n"
|
|
||||||
msgstr "OCSPのハッシュ・コンテクストを確立するのに失敗しました: %s\n"
|
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "error getting OCSP status for target certificate: %s\n"
|
msgid "error getting OCSP status for target certificate: %s\n"
|
||||||
msgstr "対象の証明書のOCSPステイタスの取得エラー: %s\n"
|
msgstr "対象の証明書のOCSPステイタスの取得エラー: %s\n"
|
||||||
@ -8106,6 +8155,14 @@ msgstr "パスフレーズ入力"
|
|||||||
msgid "Component not suitable for launching"
|
msgid "Component not suitable for launching"
|
||||||
msgstr "コンポーネントが起動するために適切ではありません"
|
msgstr "コンポーネントが起動するために適切ではありません"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "Configuration file of component %s is broken\n"
|
||||||
|
msgstr "コンポーネント%sのコンフィグレーション・ファイルが壊れています\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "Note: Use the command \"%s%s\" to get details.\n"
|
||||||
|
msgstr "注意: \"%s%s\"コマンドを使って詳細を得てください。\n"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "External verification of component %s failed"
|
msgid "External verification of component %s failed"
|
||||||
msgstr "コンポーネント%sの外部の検証が失敗しました"
|
msgstr "コンポーネント%sの外部の検証が失敗しました"
|
||||||
@ -8332,6 +8389,84 @@ msgstr ""
|
|||||||
"形式: gpg-check-pattern [オプション] パターンファイル\n"
|
"形式: gpg-check-pattern [オプション] パターンファイル\n"
|
||||||
"パターンファイルに対して標準入力のパスフレーズを確認する\n"
|
"パターンファイルに対して標準入力のパスフレーズを確認する\n"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "%s card no. %s detected\n"
|
||||||
|
msgstr "%s カード番号 %sを検出しました\n"
|
||||||
|
|
||||||
|
msgid "authenticate to the card"
|
||||||
|
msgstr "カードに対して認証します"
|
||||||
|
|
||||||
|
msgid "send a reset to the card daemon"
|
||||||
|
msgstr "リセットをカードデーモンに送ります"
|
||||||
|
|
||||||
|
msgid "change a private data object"
|
||||||
|
msgstr "プライベート・データオブジェクトを変更します"
|
||||||
|
|
||||||
|
msgid "read a certificate from a data object"
|
||||||
|
msgstr "証明書をデータオブジェクトから読み出します"
|
||||||
|
|
||||||
|
msgid "store a certificate to a data object"
|
||||||
|
msgstr "証明書をデータオブジェクトに保管します"
|
||||||
|
|
||||||
|
msgid "store a private key to a data object"
|
||||||
|
msgstr "プライベート鍵をデータオブジェクトに保管します"
|
||||||
|
|
||||||
|
msgid "Yubikey management commands"
|
||||||
|
msgstr "Yubikey管理コマンド"
|
||||||
|
|
||||||
|
#~ msgid "no keyserver known (use option --keyserver)\n"
|
||||||
|
#~ msgstr "既知の鍵サーバがありません (オプション--keyserverを使いましょう)\n"
|
||||||
|
|
||||||
|
#~ msgid "error creating 'ultimately_trusted_keys' TOFU table: %s\n"
|
||||||
|
#~ msgstr "'ultimately_trusted_keys' TOFUテーブル作成エラー: %s\n"
|
||||||
|
|
||||||
|
#~ msgid "error creating 'encryptions' TOFU table: %s\n"
|
||||||
|
#~ msgstr "'encryptions' TOFUデータベースの作成エラー: %s\n"
|
||||||
|
|
||||||
|
#~ msgid "adding column effective_policy to bindings DB: %s\n"
|
||||||
|
#~ msgstr "バインディングDBにカラムeffective_policyを追加: %s\n"
|
||||||
|
|
||||||
|
#~ msgid "resetting keydb: %s\n"
|
||||||
|
#~ msgstr "keydbをリセット: %s\n"
|
||||||
|
|
||||||
|
#~ msgid "error setting TOFU binding's policy to %s\n"
|
||||||
|
#~ msgstr "TOFUバインディングのポリシーを %s に設定エラー\n"
|
||||||
|
|
||||||
|
#~ msgid "%s: Verified %ld~signature in the past %s."
|
||||||
|
#~ msgid_plural "%s: Verified %ld~signatures in the past %s."
|
||||||
|
#~ msgstr[0] "%s: 署名を%ld個検証しました(これまで %s に)。"
|
||||||
|
|
||||||
|
#~ msgid "Encrypted %ld~message in the past %s."
|
||||||
|
#~ msgid_plural "Encrypted %ld~messages in the past %s."
|
||||||
|
#~ msgstr[0] "メッセージを%ld個暗号化しました(これまで %s に)。"
|
||||||
|
|
||||||
|
#~ msgid "error setting policy for key %s, user id \"%s\": %s"
|
||||||
|
#~ msgstr "鍵%s, ユーザID \"%s\"のポリシーの設定エラー: %s"
|
||||||
|
|
||||||
|
#~ msgid "only SHA-1 is supported for OCSP responses\n"
|
||||||
|
#~ msgstr "SHA-1だけがOCSPレスポンスとしてサポートされています\n"
|
||||||
|
|
||||||
|
#~ msgid "male"
|
||||||
|
#~ msgstr "男"
|
||||||
|
|
||||||
|
#~ msgid "female"
|
||||||
|
#~ msgstr "女"
|
||||||
|
|
||||||
|
#~ msgid "unspecified"
|
||||||
|
#~ msgstr "無指定"
|
||||||
|
|
||||||
|
#~ msgid "Sex ((M)ale, (F)emale or space): "
|
||||||
|
#~ msgstr "性別 ((M)男、(F)女、または空白): "
|
||||||
|
|
||||||
|
#~ msgid "Warning: '%s' should be a long key ID or a fingerprint\n"
|
||||||
|
#~ msgstr "警告: '%s'は長い鍵IDかフィンガープリントであるべきです。\n"
|
||||||
|
|
||||||
|
#~ msgid "error looking up: %s\n"
|
||||||
|
#~ msgstr "検索のエラー: %s\n"
|
||||||
|
|
||||||
|
#~ msgid "Warning: %s appears in the keyring %d times\n"
|
||||||
|
#~ msgstr "警告: %sは鍵リングに%d回出現します\n"
|
||||||
|
|
||||||
#~ msgid "using \"http\" instead of \"https\"\n"
|
#~ msgid "using \"http\" instead of \"https\"\n"
|
||||||
#~ msgstr "\"http\" を \"https\" の代わりに使います\n"
|
#~ msgstr "\"http\" を \"https\" の代わりに使います\n"
|
||||||
|
|
||||||
|
27
scd/apdu.c
27
scd/apdu.c
@ -42,23 +42,11 @@
|
|||||||
#include "rapdu.h"
|
#include "rapdu.h"
|
||||||
#endif /*USE_G10CODE_RAPDU*/
|
#endif /*USE_G10CODE_RAPDU*/
|
||||||
|
|
||||||
#if defined(GNUPG_SCD_MAIN_HEADER)
|
#if defined(GNUPG_MAJOR_VERSION)
|
||||||
#include GNUPG_SCD_MAIN_HEADER
|
# include "scdaemon.h"
|
||||||
#elif GNUPG_MAJOR_VERSION == 1
|
# include "../common/exechelp.h"
|
||||||
/* This is used with GnuPG version < 1.9. The code has been source
|
#endif /*GNUPG_MAJOR_VERSION*/
|
||||||
copied from the current GnuPG >= 1.9 and is maintained over
|
|
||||||
there. */
|
|
||||||
#include "../common/options.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "../common/util.h"
|
|
||||||
#include "../common/i18n.h"
|
|
||||||
#include "dynload.h"
|
|
||||||
#include "cardglue.h"
|
|
||||||
#else /* GNUPG_MAJOR_VERSION != 1 */
|
|
||||||
#include "scdaemon.h"
|
|
||||||
#include "../common/exechelp.h"
|
|
||||||
#endif /* GNUPG_MAJOR_VERSION != 1 */
|
|
||||||
#include "../common/host2net.h"
|
#include "../common/host2net.h"
|
||||||
|
|
||||||
#include "iso7816.h"
|
#include "iso7816.h"
|
||||||
@ -266,8 +254,13 @@ static npth_mutex_t reader_table_lock;
|
|||||||
|
|
||||||
struct pcsc_io_request_s
|
struct pcsc_io_request_s
|
||||||
{
|
{
|
||||||
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||||
|
pcsc_dword_t protocol;
|
||||||
|
pcsc_dword_t pci_len;
|
||||||
|
#else
|
||||||
unsigned long protocol;
|
unsigned long protocol;
|
||||||
unsigned long pci_len;
|
unsigned long pci_len;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct pcsc_io_request_s *pcsc_io_request_t;
|
typedef struct pcsc_io_request_s *pcsc_io_request_t;
|
||||||
|
187
scd/app-common.h
187
scd/app-common.h
@ -36,35 +36,95 @@
|
|||||||
/* Flags used with app_writekey. */
|
/* Flags used with app_writekey. */
|
||||||
#define APP_WRITEKEY_FLAG_FORCE 1 /* Force overwriting existing key. */
|
#define APP_WRITEKEY_FLAG_FORCE 1 /* Force overwriting existing key. */
|
||||||
|
|
||||||
|
/* Flags used with app_readkey. */
|
||||||
|
#define APP_READKEY_FLAG_INFO 1 /* Send also a KEYPAIRINFO line. */
|
||||||
|
|
||||||
/* Bit flags set by the decipher function into R_INFO. */
|
/* Bit flags set by the decipher function into R_INFO. */
|
||||||
#define APP_DECIPHER_INFO_NOPAD 1 /* Padding has been removed. */
|
#define APP_DECIPHER_INFO_NOPAD 1 /* Padding has been removed. */
|
||||||
|
|
||||||
|
|
||||||
|
/* List of supported card types. Generic is the usual ISO7817-4
|
||||||
|
* compliant card. More specific card or token versions can be given
|
||||||
|
* here. Use strcardtype() to map them to a string. */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CARDTYPE_GENERIC = 0,
|
||||||
|
CARDTYPE_YUBIKEY
|
||||||
|
|
||||||
|
} cardtype_t;
|
||||||
|
|
||||||
|
/* List of supported card applications. The source code for each
|
||||||
|
* application can usually be found in an app-NAME.c file. Use
|
||||||
|
* strapptype() to map them to a string. */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
APPTYPE_NONE = 0,
|
||||||
|
APPTYPE_UNDEFINED,
|
||||||
|
APPTYPE_OPENPGP,
|
||||||
|
APPTYPE_PIV,
|
||||||
|
APPTYPE_NKS,
|
||||||
|
APPTYPE_P15,
|
||||||
|
APPTYPE_GELDKARTE,
|
||||||
|
APPTYPE_DINSIG,
|
||||||
|
APPTYPE_SC_HSM
|
||||||
|
} apptype_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward declarations. */
|
||||||
|
struct card_ctx_s;
|
||||||
|
struct app_ctx_s;
|
||||||
struct app_local_s; /* Defined by all app-*.c. */
|
struct app_local_s; /* Defined by all app-*.c. */
|
||||||
|
|
||||||
struct app_ctx_s {
|
|
||||||
struct app_ctx_s *next;
|
typedef struct card_ctx_s *card_t;
|
||||||
|
typedef struct app_ctx_s *app_t;
|
||||||
|
|
||||||
|
/* The object describing a card. */
|
||||||
|
struct card_ctx_s {
|
||||||
|
card_t next;
|
||||||
|
|
||||||
npth_mutex_t lock;
|
npth_mutex_t lock;
|
||||||
|
|
||||||
/* Number of connections currently using this application context.
|
/* Number of connections currently using this application context. */
|
||||||
If this is not 0 the application has been initialized and the
|
|
||||||
function pointers may be used. Note that for unsupported
|
|
||||||
operations the particular function pointer is set to NULL */
|
|
||||||
unsigned int ref_count;
|
unsigned int ref_count;
|
||||||
|
|
||||||
/* Used reader slot. */
|
/* Used reader slot. */
|
||||||
int slot;
|
int slot;
|
||||||
|
|
||||||
|
cardtype_t cardtype; /* The token's type. */
|
||||||
|
unsigned int cardversion;/* Firmware version of the token or 0. */
|
||||||
|
|
||||||
|
unsigned int card_status;
|
||||||
|
|
||||||
|
/* The serial number is associated with the card and not with a
|
||||||
|
* specific app. If a card uses different serial numbers for its
|
||||||
|
* applications, our code picks the serial number of a specific
|
||||||
|
* application and uses that. */
|
||||||
unsigned char *serialno; /* Serialnumber in raw form, allocated. */
|
unsigned char *serialno; /* Serialnumber in raw form, allocated. */
|
||||||
size_t serialnolen; /* Length in octets of serialnumber. */
|
size_t serialnolen; /* Length in octets of serialnumber. */
|
||||||
const char *cardtype; /* NULL or string with the token's type. */
|
|
||||||
const char *apptype;
|
/* A linked list of applications used on this card. The app at the
|
||||||
unsigned int cardversion;/* Firmware version of the token or 0. */
|
* head of the list is the currently active app; To work with the
|
||||||
unsigned int appversion; /* Version of the application or 0. */
|
* other apps, switching to that app might be needed. Switching will
|
||||||
unsigned int card_status;
|
* put the active app at the head of the list. */
|
||||||
|
app_t app;
|
||||||
|
|
||||||
|
/* Various flags. */
|
||||||
unsigned int reset_requested:1;
|
unsigned int reset_requested:1;
|
||||||
unsigned int periodical_check_needed:1;
|
unsigned int periodical_check_needed:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* The object describing a card's applications. A card may have
|
||||||
|
* several applications and it is usuallay required to explicity
|
||||||
|
* switch between applications. */
|
||||||
|
struct app_ctx_s {
|
||||||
|
app_t next;
|
||||||
|
|
||||||
|
card_t card; /* Link back to the card. */
|
||||||
|
|
||||||
|
apptype_t apptype; /* The type of the application. */
|
||||||
|
unsigned int appversion; /* Version of the application or 0. */
|
||||||
unsigned int did_chv1:1;
|
unsigned int did_chv1:1;
|
||||||
unsigned int force_chv1:1; /* True if the card does not cache CHV1. */
|
unsigned int force_chv1:1; /* True if the card does not cache CHV1. */
|
||||||
unsigned int did_chv2:1;
|
unsigned int did_chv2:1;
|
||||||
@ -72,11 +132,13 @@ struct app_ctx_s {
|
|||||||
struct app_local_s *app_local; /* Local to the application. */
|
struct app_local_s *app_local; /* Local to the application. */
|
||||||
struct {
|
struct {
|
||||||
void (*deinit) (app_t app);
|
void (*deinit) (app_t app);
|
||||||
|
gpg_error_t (*reselect) (app_t app, ctrl_t ctrl);
|
||||||
gpg_error_t (*learn_status) (app_t app, ctrl_t ctrl, unsigned int flags);
|
gpg_error_t (*learn_status) (app_t app, ctrl_t ctrl, unsigned int flags);
|
||||||
gpg_error_t (*readcert) (app_t app, const char *certid,
|
gpg_error_t (*readcert) (app_t app, const char *certid,
|
||||||
unsigned char **cert, size_t *certlen);
|
unsigned char **cert, size_t *certlen);
|
||||||
gpg_error_t (*readkey) (app_t app, const char *certid,
|
gpg_error_t (*readkey) (app_t app, ctrl_t ctrl,
|
||||||
unsigned char **pk, size_t *pklen);
|
const char *certid, unsigned int flags,
|
||||||
|
unsigned char **pk, size_t *pklen);
|
||||||
gpg_error_t (*getattr) (app_t app, ctrl_t ctrl, const char *name);
|
gpg_error_t (*getattr) (app_t app, ctrl_t ctrl, const char *name);
|
||||||
gpg_error_t (*setattr) (app_t app, const char *name,
|
gpg_error_t (*setattr) (app_t app, const char *name,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
@ -121,11 +183,35 @@ struct app_ctx_s {
|
|||||||
gpg_error_t (*check_pin) (app_t app, const char *keyidstr,
|
gpg_error_t (*check_pin) (app_t app, const char *keyidstr,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg);
|
void *pincb_arg);
|
||||||
|
gpg_error_t (*with_keygrip) (app_t app, ctrl_t ctrl, int action,
|
||||||
|
const char *keygrip_str);
|
||||||
} fnc;
|
} fnc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Action values for app_do_with_keygrip. */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
KEYGRIP_ACTION_SEND_DATA,
|
||||||
|
KEYGRIP_ACTION_WRITE_STATUS,
|
||||||
|
KEYGRIP_ACTION_LOOKUP
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper to get the slot from an APP object. */
|
||||||
|
static inline int
|
||||||
|
app_get_slot (app_t app)
|
||||||
|
{
|
||||||
|
if (app && app->card)
|
||||||
|
return app->card->slot;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-- app-help.c --*/
|
/*-- app-help.c --*/
|
||||||
unsigned int app_help_count_bits (const unsigned char *a, size_t len);
|
unsigned int app_help_count_bits (const unsigned char *a, size_t len);
|
||||||
|
gpg_error_t app_help_get_keygrip_string_pk (const void *pk, size_t pklen,
|
||||||
|
char *hexkeygrip);
|
||||||
gpg_error_t app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip);
|
gpg_error_t app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip);
|
||||||
gpg_error_t app_help_pubkey_from_cert (const void *cert, size_t certlen,
|
gpg_error_t app_help_pubkey_from_cert (const void *cert, size_t certlen,
|
||||||
unsigned char **r_pk, size_t *r_pklen);
|
unsigned char **r_pk, size_t *r_pklen);
|
||||||
@ -133,70 +219,85 @@ size_t app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff);
|
|||||||
|
|
||||||
|
|
||||||
/*-- app.c --*/
|
/*-- app.c --*/
|
||||||
void app_send_card_list (ctrl_t ctrl);
|
const char *strcardtype (cardtype_t t);
|
||||||
|
const char *strapptype (apptype_t t);
|
||||||
|
|
||||||
|
void app_update_priority_list (const char *arg);
|
||||||
|
gpg_error_t app_send_card_list (ctrl_t ctrl);
|
||||||
|
char *card_get_serialno (card_t card);
|
||||||
char *app_get_serialno (app_t app);
|
char *app_get_serialno (app_t app);
|
||||||
|
|
||||||
void app_dump_state (void);
|
void app_dump_state (void);
|
||||||
void application_notify_card_reset (int slot);
|
void application_notify_card_reset (int slot);
|
||||||
gpg_error_t check_application_conflict (const char *name, app_t app);
|
gpg_error_t check_application_conflict (card_t card, const char *name,
|
||||||
gpg_error_t app_reset (app_t app, ctrl_t ctrl, int send_reset);
|
const unsigned char *serialno_bin,
|
||||||
gpg_error_t select_application (ctrl_t ctrl, const char *name, app_t *r_app,
|
size_t serialno_bin_len);
|
||||||
|
gpg_error_t card_reset (card_t card, ctrl_t ctrl, int send_reset);
|
||||||
|
gpg_error_t select_application (ctrl_t ctrl, const char *name, card_t *r_app,
|
||||||
int scan, const unsigned char *serialno_bin,
|
int scan, const unsigned char *serialno_bin,
|
||||||
size_t serialno_bin_len);
|
size_t serialno_bin_len);
|
||||||
|
gpg_error_t select_additional_application (ctrl_t ctrl, const char *name);
|
||||||
char *get_supported_applications (void);
|
char *get_supported_applications (void);
|
||||||
void release_application (app_t app, int locked_already);
|
|
||||||
gpg_error_t app_munge_serialno (app_t app);
|
card_t card_ref (card_t card);
|
||||||
gpg_error_t app_write_learn_status (app_t app, ctrl_t ctrl,
|
void card_unref (card_t card);
|
||||||
|
void card_unref_locked (card_t card);
|
||||||
|
|
||||||
|
gpg_error_t app_munge_serialno (card_t card);
|
||||||
|
gpg_error_t app_write_learn_status (card_t card, ctrl_t ctrl,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
gpg_error_t app_readcert (app_t app, ctrl_t ctrl, const char *certid,
|
gpg_error_t app_readcert (card_t card, ctrl_t ctrl, const char *certid,
|
||||||
unsigned char **cert, size_t *certlen);
|
unsigned char **cert, size_t *certlen);
|
||||||
gpg_error_t app_readkey (app_t app, ctrl_t ctrl,
|
gpg_error_t app_readkey (card_t card, ctrl_t ctrl,
|
||||||
const char *keyid, unsigned char **pk, size_t *pklen);
|
const char *keyid, unsigned int flags,
|
||||||
gpg_error_t app_getattr (app_t app, ctrl_t ctrl, const char *name);
|
unsigned char **pk, size_t *pklen);
|
||||||
gpg_error_t app_setattr (app_t app, ctrl_t ctrl, const char *name,
|
gpg_error_t app_getattr (card_t card, ctrl_t ctrl, const char *name);
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t app_setattr (card_t card, ctrl_t ctrl, const char *name,
|
||||||
void *pincb_arg,
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
const unsigned char *value, size_t valuelen);
|
void *pincb_arg,
|
||||||
gpg_error_t app_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
|
const unsigned char *value, size_t valuelen);
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t app_sign (card_t card, ctrl_t ctrl,
|
||||||
void *pincb_arg,
|
const char *keyidstr, int hashalgo,
|
||||||
const void *indata, size_t indatalen,
|
|
||||||
unsigned char **outdata, size_t *outdatalen );
|
|
||||||
gpg_error_t app_auth (app_t app, ctrl_t ctrl, const char *keyidstr,
|
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg,
|
void *pincb_arg,
|
||||||
const void *indata, size_t indatalen,
|
const void *indata, size_t indatalen,
|
||||||
unsigned char **outdata, size_t *outdatalen);
|
unsigned char **outdata, size_t *outdatalen);
|
||||||
gpg_error_t app_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
|
gpg_error_t app_auth (card_t card, ctrl_t ctrl, const char *keyidstr,
|
||||||
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
|
void *pincb_arg,
|
||||||
|
const void *indata, size_t indatalen,
|
||||||
|
unsigned char **outdata, size_t *outdatalen);
|
||||||
|
gpg_error_t app_decipher (card_t card, ctrl_t ctrl, const char *keyidstr,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg,
|
void *pincb_arg,
|
||||||
const void *indata, size_t indatalen,
|
const void *indata, size_t indatalen,
|
||||||
unsigned char **outdata, size_t *outdatalen,
|
unsigned char **outdata, size_t *outdatalen,
|
||||||
unsigned int *r_info);
|
unsigned int *r_info);
|
||||||
gpg_error_t app_writecert (app_t app, ctrl_t ctrl,
|
gpg_error_t app_writecert (card_t card, ctrl_t ctrl,
|
||||||
const char *certidstr,
|
const char *certidstr,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg,
|
void *pincb_arg,
|
||||||
const unsigned char *keydata, size_t keydatalen);
|
const unsigned char *keydata, size_t keydatalen);
|
||||||
gpg_error_t app_writekey (app_t app, ctrl_t ctrl,
|
gpg_error_t app_writekey (card_t card, ctrl_t ctrl,
|
||||||
const char *keyidstr, unsigned int flags,
|
const char *keyidstr, unsigned int flags,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg,
|
void *pincb_arg,
|
||||||
const unsigned char *keydata, size_t keydatalen);
|
const unsigned char *keydata, size_t keydatalen);
|
||||||
gpg_error_t app_genkey (app_t app, ctrl_t ctrl,
|
gpg_error_t app_genkey (card_t card, ctrl_t ctrl,
|
||||||
const char *keynostr, const char *keytype,
|
const char *keynostr, const char *keytype,
|
||||||
unsigned int flags, time_t createtime,
|
unsigned int flags, time_t createtime,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg);
|
void *pincb_arg);
|
||||||
gpg_error_t app_get_challenge (app_t app, ctrl_t ctrl, size_t nbytes,
|
gpg_error_t app_get_challenge (card_t card, ctrl_t ctrl, size_t nbytes,
|
||||||
unsigned char *buffer);
|
unsigned char *buffer);
|
||||||
gpg_error_t app_change_pin (app_t app, ctrl_t ctrl,
|
gpg_error_t app_change_pin (card_t card, ctrl_t ctrl,
|
||||||
const char *chvnostr, unsigned int flags,
|
const char *chvnostr, unsigned int flags,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg);
|
void *pincb_arg);
|
||||||
gpg_error_t app_check_pin (app_t app, ctrl_t ctrl, const char *keyidstr,
|
gpg_error_t app_check_pin (card_t card, ctrl_t ctrl, const char *keyidstr,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg);
|
void *pincb_arg);
|
||||||
|
card_t app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str);
|
||||||
|
|
||||||
|
|
||||||
/*-- app-openpgp.c --*/
|
/*-- app-openpgp.c --*/
|
||||||
|
@ -81,7 +81,6 @@
|
|||||||
|
|
||||||
#include "../common/i18n.h"
|
#include "../common/i18n.h"
|
||||||
#include "iso7816.h"
|
#include "iso7816.h"
|
||||||
#include "app-common.h"
|
|
||||||
#include "../common/tlv.h"
|
#include "../common/tlv.h"
|
||||||
|
|
||||||
|
|
||||||
@ -101,7 +100,7 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
|
|||||||
|
|
||||||
/* Return the certificate of the card holder. */
|
/* Return the certificate of the card holder. */
|
||||||
fid = 0xC000;
|
fid = 0xC000;
|
||||||
len = app_help_read_length_of_cert (app->slot, fid, &certoff);
|
len = app_help_read_length_of_cert (app_get_slot (app), fid, &certoff);
|
||||||
if (!len)
|
if (!len)
|
||||||
return 0; /* Card has not been personalized. */
|
return 0; /* Card has not been personalized. */
|
||||||
|
|
||||||
@ -114,7 +113,8 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
|
|||||||
|
|
||||||
/* Now we need to read the certificate, so that we can get the
|
/* Now we need to read the certificate, so that we can get the
|
||||||
public key out of it. */
|
public key out of it. */
|
||||||
err = iso7816_read_binary (app->slot, certoff, len-certoff, &der, &derlen);
|
err = iso7816_read_binary (app_get_slot (app), certoff, len-certoff,
|
||||||
|
&der, &derlen);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
log_info ("error reading entire certificate from FID 0x%04X: %s\n",
|
log_info ("error reading entire certificate from FID 0x%04X: %s\n",
|
||||||
@ -193,14 +193,14 @@ do_readcert (app_t app, const char *certid,
|
|||||||
/* Read the entire file. fixme: This could be optimized by first
|
/* Read the entire file. fixme: This could be optimized by first
|
||||||
reading the header to figure out how long the certificate
|
reading the header to figure out how long the certificate
|
||||||
actually is. */
|
actually is. */
|
||||||
err = iso7816_select_file (app->slot, fid, 0);
|
err = iso7816_select_file (app_get_slot (app), fid, 0);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
log_error ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err));
|
log_error ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = iso7816_read_binary (app->slot, 0, 0, &buffer, &buflen);
|
err = iso7816_read_binary (app_get_slot (app), 0, 0, &buffer, &buflen);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
log_error ("error reading certificate from FID 0x%04X: %s\n",
|
log_error ("error reading certificate from FID 0x%04X: %s\n",
|
||||||
@ -293,7 +293,7 @@ verify_pin (app_t app,
|
|||||||
pininfo.maxlen = 8;
|
pininfo.maxlen = 8;
|
||||||
|
|
||||||
if (!opt.disable_pinpad
|
if (!opt.disable_pinpad
|
||||||
&& !iso7816_check_pinpad (app->slot, ISO7816_VERIFY, &pininfo) )
|
&& !iso7816_check_pinpad (app_get_slot (app), ISO7816_VERIFY, &pininfo) )
|
||||||
{
|
{
|
||||||
rc = pincb (pincb_arg,
|
rc = pincb (pincb_arg,
|
||||||
_("||Please enter your PIN at the reader's pinpad"),
|
_("||Please enter your PIN at the reader's pinpad"),
|
||||||
@ -304,7 +304,7 @@ verify_pin (app_t app,
|
|||||||
gpg_strerror (rc));
|
gpg_strerror (rc));
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
rc = iso7816_verify_kp (app->slot, 0x81, &pininfo);
|
rc = iso7816_verify_kp (app_get_slot (app), 0x81, &pininfo);
|
||||||
/* Dismiss the prompt. */
|
/* Dismiss the prompt. */
|
||||||
pincb (pincb_arg, NULL, NULL);
|
pincb (pincb_arg, NULL, NULL);
|
||||||
}
|
}
|
||||||
@ -345,7 +345,8 @@ verify_pin (app_t app,
|
|||||||
return gpg_error (GPG_ERR_BAD_PIN);
|
return gpg_error (GPG_ERR_BAD_PIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
|
rc = iso7816_verify (app_get_slot (app), 0x81,
|
||||||
|
pinvalue, strlen (pinvalue));
|
||||||
if (gpg_err_code (rc) == GPG_ERR_INV_VALUE)
|
if (gpg_err_code (rc) == GPG_ERR_INV_VALUE)
|
||||||
{
|
{
|
||||||
/* We assume that ISO 9564-1 encoding is used and we failed
|
/* We assume that ISO 9564-1 encoding is used and we failed
|
||||||
@ -366,7 +367,8 @@ verify_pin (app_t app,
|
|||||||
paddedpin[i++] = (((*s - '0') << 4) | 0x0f);
|
paddedpin[i++] = (((*s - '0') << 4) | 0x0f);
|
||||||
while (i < sizeof paddedpin)
|
while (i < sizeof paddedpin)
|
||||||
paddedpin[i++] = 0xff;
|
paddedpin[i++] = 0xff;
|
||||||
rc = iso7816_verify (app->slot, 0x81, paddedpin, sizeof paddedpin);
|
rc = iso7816_verify (app_get_slot (app), 0x81,
|
||||||
|
paddedpin, sizeof paddedpin);
|
||||||
}
|
}
|
||||||
xfree (pinvalue);
|
xfree (pinvalue);
|
||||||
}
|
}
|
||||||
@ -482,7 +484,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||||||
|
|
||||||
rc = verify_pin (app, pincb, pincb_arg);
|
rc = verify_pin (app, pincb, pincb_arg);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = iso7816_compute_ds (app->slot, 0, data, datalen, 0,
|
rc = iso7816_compute_ds (app_get_slot (app), 0, data, datalen, 0,
|
||||||
outdata, outdatalen);
|
outdata, outdatalen);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -532,7 +534,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = iso7816_change_reference_data (app->slot, 0x81,
|
err = iso7816_change_reference_data (app_get_slot (app), 0x81,
|
||||||
oldpin, oldpinlen,
|
oldpin, oldpinlen,
|
||||||
pinvalue, strlen (pinvalue));
|
pinvalue, strlen (pinvalue));
|
||||||
xfree (pinvalue);
|
xfree (pinvalue);
|
||||||
@ -547,14 +549,15 @@ gpg_error_t
|
|||||||
app_select_dinsig (app_t app)
|
app_select_dinsig (app_t app)
|
||||||
{
|
{
|
||||||
static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x66, 0x01 };
|
static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x66, 0x01 };
|
||||||
int slot = app->slot;
|
int slot = app_get_slot (app);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = iso7816_select_application (slot, aid, sizeof aid, 0);
|
rc = iso7816_select_application (slot, aid, sizeof aid, 0);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
app->apptype = "DINSIG";
|
app->apptype = APPTYPE_DINSIG;
|
||||||
|
|
||||||
|
app->fnc.reselect = NULL;
|
||||||
app->fnc.learn_status = do_learn_status;
|
app->fnc.learn_status = do_learn_status;
|
||||||
app->fnc.readcert = do_readcert;
|
app->fnc.readcert = do_readcert;
|
||||||
app->fnc.getattr = NULL;
|
app->fnc.getattr = NULL;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user