+Noteworthy changes in version 2.1.13 (2016-06-16)
+-------------------------------------------------
+
+ * gpg: New command --quick-addkey. Extend the --quick-gen-key
+ command.
+
+ * gpg: New --keyid-format "none" which is now also the default.
+
+ * gpg: New option --with-subkey-fingerprint.
+
+ * gpg: Include Signer's UID subpacket in signatures if the secret key
+ has been specified using a mail address and the new option
+ --disable-signer-uid is not used.
+
+ * gpg: Allow unattended deletion of a secret key.
+
+ * gpg: Allow export of non-passphrase protected secret keys.
+
+ * gpg: New status lines KEY_CONSIDERED and NOTATION_FLAGS.
+
+ * gpg: Change status line TOFU_STATS_LONG to use '~' as
+ a non-breaking-space character.
+
+ * gpg: Speedup key listings in Tofu mode.
+
+ * gpg: Make sure that the current and total values of a PROGRESS
+ status line are small enough.
+
+ * gpgsm: Allow the use of AES192 and SERPENT ciphers.
+
+ * dirmngr: Adjust WKD lookup to current specs.
+
+ * dirmngr: Fallback to LDAP v3 if v2 is is not supported.
+
+ * gpgconf: New commands --create-socketdir and --remove-socketdir,
+ new option --homedir.
+
+ * If a /run/user/$UID directory exists, that directory is now used
+ for IPC sockets instead of the GNUPGHOME directory. This fixes
+ problems with NFS and too long socket names and thus avoids the
+ need for redirection files.
+
+ * The Speedo build systems now uses the new versions.gnupg.org server
+ to retrieve the default package versions.
+
+ * Fix detection of libusb on FreeBSD.
+
+ * Speedup fd closing after a fork.
+
+
Noteworthy changes in version 2.1.12 (2016-05-04)
-------------------------------------------------
int quiet; /* Be as quiet as possible */
int dry_run; /* Don't change any persistent data */
int batch; /* Batch mode */
- const char *homedir; /* Configuration directory name */
/* True if we handle sigusr2. */
int sigusr2_enabled;
/* Note: As soon as we start to use non blocking functions here
(i.e. where Pth might switch threads) we need to employ a
mutex. */
- cf->fname = make_filename_try (opt.homedir, SSH_CONTROL_FILE_NAME, NULL);
+ cf->fname = make_filename_try (gnupg_homedir (), SSH_CONTROL_FILE_NAME, NULL);
if (!cf->fname)
{
err = gpg_error_from_syserror ();
{
char *dname;
- dname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL);
+ dname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR, NULL);
if (!dname)
{
err = gpg_err_code_from_syserror ();
}
-/* This function is called by Libassuan whenever thee client sends a
+/* This function is called by Libassuan whenever the client sends a
reset. It has been registered similar to the other Assuan
commands. */
static gpg_error_t
static const char hlp_genkey[] =
- "GENKEY [--no-protection] [--preset] [--inq-passwd] [<cache_nonce>]\n"
+ "GENKEY [--no-protection] [--preset] [--inq-passwd]\n"
+ " [--passwd-nonce=<s>] [<cache_nonce>]\n"
"\n"
"Generate a new key, store the secret part and return the public\n"
"part. Here is an example transaction:\n"
"When the --preset option is used the passphrase for the generated\n"
"key will be added to the cache. When --inq-passwd is used an inquire\n"
"with the keyword NEWPASSWD is used to request the passphrase for the\n"
- "new key.\n";
+ "new key. When a --passwd-nonce is used, the corresponding cached\n"
+ "passphrase is used to protect the new key.";
static gpg_error_t
cmd_genkey (assuan_context_t ctx, char *line)
{
unsigned char *newpasswd = NULL;
membuf_t outbuf;
char *cache_nonce = NULL;
+ char *passwd_nonce = NULL;
int opt_preset;
int opt_inq_passwd;
size_t n;
- char *p;
+ char *p, *pend;
+ int c;
if (ctrl->restricted)
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
no_protection = has_option (line, "--no-protection");
opt_preset = has_option (line, "--preset");
opt_inq_passwd = has_option (line, "--inq-passwd");
+ passwd_nonce = option_value (line, "--passwd-nonce");
+ if (passwd_nonce)
+ {
+ for (pend = passwd_nonce; *pend && !spacep (pend); pend++)
+ ;
+ c = *pend;
+ *pend = '\0';
+ passwd_nonce = xtrystrdup (passwd_nonce);
+ *pend = c;
+ if (!passwd_nonce)
+ {
+ rc = gpg_error_from_syserror ();
+ goto leave;
+ }
+ }
line = skip_options (line);
p = line;
}
}
+ else if (passwd_nonce)
+ newpasswd = agent_get_cache (passwd_nonce, CACHE_MODE_NONCE);
rc = agent_genkey (ctrl, cache_nonce, (char*)value, valuelen, no_protection,
newpasswd, opt_preset, &outbuf);
else
rc = write_and_clear_outbuf (ctx, &outbuf);
xfree (cache_nonce);
+ xfree (passwd_nonce);
return leave_cmd (ctx, rc);
}
char *dirname;
struct dirent *dir_entry;
- dirname = make_filename_try (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL);
+ dirname = make_filename_try (gnupg_homedir (),
+ GNUPG_PRIVATE_KEYS_DIR, NULL);
if (!dirname)
{
err = gpg_error_from_syserror ();
else if (opt_verify)
{
/* All done. */
+ if (passphrase)
+ {
+ if (!passwd_nonce)
+ {
+ char buf[12];
+ gcry_create_nonce (buf, 12);
+ passwd_nonce = bin2hex (buf, 12, NULL);
+ }
+ if (passwd_nonce
+ && !agent_put_cache (passwd_nonce, CACHE_MODE_NONCE,
+ passphrase, CACHE_TTL_NONCE))
+ {
+ assuan_write_status (ctx, "PASSWD_NONCE", passwd_nonce);
+ xfree (ctrl->server_local->last_passwd_nonce);
+ ctrl->server_local->last_passwd_nonce = passwd_nonce;
+ passwd_nonce = NULL;
+ }
+ }
}
else
{
gcry_sexp_release (s_skey);
xfree (shadow_info);
xfree (cache_nonce);
+ xfree (passwd_nonce);
return leave_cmd (ctx, err);
}
"Export a secret key from the key store. The key will be encrypted\n"
"using the current session's key wrapping key (cf. command KEYWRAP_KEY)\n"
"using the AESWRAP-128 algorithm. The caller needs to retrieve that key\n"
- "prior to using this command. The function takes the keygrip as argument.\n";
+ "prior to using this command. The function takes the keygrip as argument.\n"
+ "\n"
+ "If --openpgp is used, the secret key material will be exported in RFC 4880\n"
+ "compatible passphrase-protected form. Without --openpgp, the secret key\n"
+ "material will be exported in the clear (after prompting the user to unlock\n"
+ "it, if needed).\n";
static gpg_error_t
cmd_export_key (assuan_context_t ctx, char *line)
{
static const char hlp_delete_key[] =
"DELETE_KEY [--force] <hexstring_with_keygrip>\n"
"\n"
- "Delete a secret key from the key store.\n"
- "Unless --force is used the agent asks the user for confirmation.\n";
+ "Delete a secret key from the key store. If --force is used\n"
+ "and a loopback pinentry is allowed, the agent will not ask\n"
+ "the user for confirmation.";
static gpg_error_t
cmd_delete_key (assuan_context_t ctx, char *line)
{
force = has_option (line, "--force");
line = skip_options (line);
+ /* If the use of a loopback pinentry has been disabled, we assume
+ * that a silent deletion of keys shall also not be allowed. */
+ if (!opt.allow_loopback_pinentry)
+ force = 0;
+
err = parse_keygrip (ctx, line, grip);
if (err)
goto leave;
bin2hex (grip, 20, hexgrip);
strcpy (hexgrip+40, ".key");
- fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
+ fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
+ hexgrip, NULL);
/* FIXME: Write to a temp file first so that write failures during
key updates won't lead to a key loss. */
bin2hex (grip, 20, hexgrip);
strcpy (hexgrip+40, ".key");
- fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
+ fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
+ hexgrip, NULL);
fp = es_fopen (fname, "rb");
if (!fp)
{
bin2hex (grip, 20, hexgrip);
strcpy (hexgrip+40, ".key");
- fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
+ fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
+ hexgrip, NULL);
if (gnupg_remove (fname))
err = gpg_error_from_syserror ();
xfree (fname);
bin2hex (grip, 20, hexgrip);
strcpy (hexgrip+40, ".key");
- fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
+ fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
+ hexgrip, NULL);
result = !access (fname, R_OK)? 0 : -1;
xfree (fname);
return result;
/* gpg-agent.c - The GnuPG Agent
* Copyright (C) 2000-2007, 2009-2010 Free Software Foundation, Inc.
- * Copyright (C) 2000-2014 Werner Koch
+ * Copyright (C) 2000-2016 Werner Koch
*
* This file is part of GnuPG.
*
{
if (name && *name)
{
- char *p;
-
if (redir_name)
name = redir_name;
gnupg_remove (name);
- p = strrchr (name, '/');
- if (p)
- {
- *p = 0;
- rmdir (name);
- *p = '/';
- }
*name = 0;
}
}
if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
csh_style = 1;
- opt.homedir = default_homedir ();
-
/* Record some of the original environment strings. */
{
const char *s;
else if (pargs.r_opt == oNoOptions)
default_config = 0; /* --no-options */
else if (pargs.r_opt == oHomedir)
- opt.homedir = pargs.r.ret_str;
+ gnupg_set_homedir (pargs.r.ret_str);
else if (pargs.r_opt == oDebugQuickRandom)
{
gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
*/
if (default_config)
- configname = make_filename (opt.homedir, GPG_AGENT_NAME EXTSEP_S "conf",
- NULL );
+ configname = make_filename (gnupg_homedir (),
+ GPG_AGENT_NAME EXTSEP_S "conf", NULL);
argc = orig_argc;
argv = orig_argv;
case oNoGreeting: /* Dummy option. */ break;
case oNoVerbose: opt.verbose = 0; break;
case oNoOptions: break; /* no-options */
- case oHomedir: opt.homedir = pargs.r.ret_str; break;
+ case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
case oNoDetach: nodetach = 1; break;
case oLogFile: logfile = pargs.r.ret_str; break;
case oCsh: csh_style = 1; break;
finalize_rereadable_options ();
- /* Turn the homedir into an absolute one. */
- opt.homedir = make_absfilename (opt.homedir, NULL);
-
/* Print a warning if an argument looks like an option. */
if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
{
char *filename_esc;
/* List options and default values in the GPG Conf format. */
- filename = make_filename (opt.homedir, GPG_AGENT_NAME EXTSEP_S "conf",
- NULL );
+ filename = make_filename (gnupg_homedir (),
+ GPG_AGENT_NAME EXTSEP_S "conf", NULL);
filename_esc = percent_escape (filename, NULL);
es_printf ("%s-%s.conf:%lu:\"%s\n",
char *name;
if (with_homedir)
- name = make_filename (opt.homedir, standard_name, NULL);
+ name = make_filename (gnupg_socketdir (), standard_name, NULL);
else
name = make_filename (standard_name, NULL);
if (strchr (name, PATHSEP_C))
agent_exit (2);
}
+ if (gnupg_chmod (unaddr->sun_path, "-rwx"))
+ log_error (_("can't set permissions of '%s': %s\n"),
+ unaddr->sun_path, strerror (errno));
+
if (listen (FD2INT(fd), 5 ) == -1)
{
log_error (_("listen() failed: %s\n"), strerror (errno));
const char *defhome = standard_homedir ();
char *home;
- home = make_filename (opt.homedir, NULL);
+ home = make_filename (gnupg_homedir (), NULL);
if ( stat (home, &statbuf) )
{
if (errno == ENOENT)
if (check_own_socket_running || shutdown_pending)
return; /* Still running or already shutting down. */
- sockname = make_filename (opt.homedir, GPG_AGENT_SOCK_NAME, NULL);
+ sockname = make_filename_try (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
if (!sockname)
return; /* Out of memory. */
char *sockname;
assuan_context_t ctx = NULL;
- sockname = make_filename (opt.homedir, GPG_AGENT_SOCK_NAME, NULL);
+ sockname = make_filename_try (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
+ if (!sockname)
+ return gpg_error_from_syserror ();
err = assuan_new (&ctx);
if (!err)
aTest };
-static const char *opt_homedir;
static const char *opt_passphrase;
static ARGPARSE_OPTS opts[] = {
i18n_init ();
init_common_subsystems (&argc, &argv);
- opt_homedir = default_homedir ();
-
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1; /* (do not remove the args) */
switch (pargs.r_opt)
{
case oVerbose: opt.verbose++; break;
- case oHomedir: opt_homedir = pargs.r.ret_str; break;
+ case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
case oPreset: cmd = oPreset; break;
case oForget: cmd = oForget; break;
/* Tell simple-pwquery about the the standard socket name. */
{
- char *tmp = make_filename (opt_homedir, GPG_AGENT_SOCK_NAME, NULL);
+ char *tmp = make_filename (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
simple_pw_set_socket (tmp);
xfree (tmp);
}
};
-static const char *opt_homedir;
static int opt_armor;
static int opt_canonical;
static int opt_store;
gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
- opt_homedir = default_homedir ();
-
-
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1; /* (do not remove the args) */
case oVerbose: opt.verbose++; break;
case oArmor: opt_armor=1; break;
case oCanonical: opt_canonical=1; break;
- case oHomedir: opt_homedir = pargs.r.ret_str; break;
+ case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
case oAgentProgram: opt_agent_program = pargs.r.ret_str; break;
/* Set the information which can't be taken from envvars. */
gnupg_prepare_get_passphrase (GPG_ERR_SOURCE_DEFAULT,
opt.verbose,
- opt_homedir,
opt_agent_program,
NULL, NULL, NULL);
return gpg_error_from_syserror ();
tableidx = 0;
- fname = make_filename (opt.homedir, "trustlist.txt", NULL);
+ fname = make_filename_try (gnupg_homedir (), "trustlist.txt", NULL);
+ if (!fname)
+ {
+ err = gpg_error_from_syserror ();
+ xfree (table);
+ return err;
+ }
+
if ( access (fname, F_OK) )
{
if ( errno == ENOENT )
trustlist with only admin priviliges to modify it. Of course
this is not a secure way of denying access, but it avoids the
usual clicking on an Okay button most users are used to. */
- fname = make_filename (opt.homedir, "trustlist.txt", NULL);
+ fname = make_filename_try (gnupg_homedir (), "trustlist.txt", NULL);
+ if (!fname)
+ return gpg_error_from_syserror ();
+
if ( access (fname, W_OK) && errno != ENOENT)
{
xfree (fname);
return is_disabled? gpg_error (GPG_ERR_NOT_TRUSTED) : 0;
}
- fname = make_filename (opt.homedir, "trustlist.txt", NULL);
+ fname = make_filename_try (gnupg_homedir (), "trustlist.txt", NULL);
+ if (!fname)
+ {
+ err = gpg_error_from_syserror ();
+ unlock_trusttable ();
+ xfree (fprformatted);
+ xfree (nameformatted);
+ return err;
+ }
if ( access (fname, F_OK) && errno == ENOENT)
{
fp = es_fopen (fname, "wx,mode=-rw-r");
[ -z "${SILENT}" ] && cat <<EOF
*** Activating trailing whitespace git pre-commit hook. ***
For more information see this thread:
- http://mail.gnome.org/archives/desktop-devel-list/2009-May/msg00084html
+ http://mail.gnome.org/archives/desktop-devel-list/2009-May/msg00084.html
To deactivate this pre-commit hook again move .git/hooks/pre-commit
and .git/hooks/pre-commit.sample out of the way.
EOF
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# The URL of the file to retrieve.
-# (some wget versions seem to have problems with SubjectAltName, thus
-# we do not use www.gnupg.org)
-urlbase="https://gnupg.org/"
+urlbase="https://versions.gnupg.org/"
WGET=wget
GPGV=gpgv
speedo_pkg_libksba_configure = --disable-static
ifeq ($(TARGETOS),w32)
-speedo_pkg_gnupg_configure = --enable-gpg2-is-gpg --disable-g13 --disable-ntbtls
+speedo_pkg_gnupg_configure = \
+ --enable-gpg2-is-gpg --disable-g13 --disable-ntbtls \
+ --enable-build-timestamp
else
speedo_pkg_gnupg_configure = --disable-g13
endif
File "bin/gpgconf.exe"
File "bin/gpg-connect-agent.exe"
File "bin/gpgtar.exe"
+ File "libexec/gpg-preset-passphrase.exe"
ClearErrors
SetOverwrite try
Delete "$INSTDIR\bin\gpgconf.exe"
Delete "$INSTDIR\bin\gpg-connect-agent.exe"
Delete "$INSTDIR\bin\gpgtar.exe"
+ Delete "$INSTDIR\bin\gpg-preset-passphrase.exe"
Delete "$INSTDIR\share\gnupg\dirmngr-conf.skel"
Delete "$INSTDIR\share\gnupg\distsigkey.gpg"
xasprintf.c \
xreadline.c \
membuf.c membuf.h \
+ ccparray.c ccparray.h \
iobuf.c iobuf.h \
ttyio.c ttyio.h \
asshelp.c asshelp2.c asshelp.h \
t-convert t-percent t-gettime t-sysutils t-sexputil \
t-session-env t-openpgp-oid t-ssh-utils \
t-mapstrings t-zb32 t-mbox-util t-iobuf t-strlist \
- t-private-keys
+ t-private-keys t-ccparray
if !HAVE_W32CE_SYSTEM
module_tests += t-exechelp
endif
t_iobuf_LDADD = $(t_common_ldadd)
t_strlist_LDADD = $(t_common_ldadd)
t_private_keys_LDADD = $(t_common_ldadd)
+t_ccparray_LDADD = $(t_common_ldadd)
# System specific test
if HAVE_W32_SYSTEM
gpg_error_t
start_new_gpg_agent (assuan_context_t *r_ctx,
gpg_err_source_t errsource,
- const char *homedir,
const char *agent_program,
const char *opt_lc_ctype,
const char *opt_lc_messages,
return err;
}
- sockname = make_absfilename (homedir, GPG_AGENT_SOCK_NAME, NULL);
+ sockname = make_filename_try (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
+ if (!sockname)
+ {
+ err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
+ assuan_release (ctx);
+ return err;
+ }
+
err = assuan_socket_connect (ctx, sockname, 0, 0);
if (err && autostart)
{
/* We better pass an absolute home directory to the agent just
in case gpg-agent does not convert the passed name to an
absolute one (which it should do). */
- abs_homedir = make_absfilename_try (homedir, NULL);
+ abs_homedir = make_absfilename_try (gnupg_homedir (), NULL);
if (!abs_homedir)
{
gpg_error_t tmperr = gpg_err_make (errsource,
argv[i++] = "--daemon";
argv[i++] = NULL;
- if (!(err = lock_spawning (&lock, homedir, "agent", verbose))
+ if (!(err = lock_spawning (&lock, gnupg_homedir (), "agent", verbose))
&& assuan_socket_connect (ctx, sockname, 0, 0))
{
err = gnupg_spawn_process_detached (program? program : agent_program,
gpg_error_t
start_new_dirmngr (assuan_context_t *r_ctx,
gpg_err_source_t errsource,
- const char *homedir,
const char *dirmngr_program,
int autostart,
int verbose, int debug,
status_cb (status_cb_arg, STATUS_PROGRESS,
"starting_dirmngr ? 0 0", NULL);
- abs_homedir = make_absfilename (homedir, NULL);
+ abs_homedir = make_absfilename (gnupg_homedir (), NULL);
if (!abs_homedir)
{
gpg_error_t tmperr = gpg_err_make (errsource,
TRY_SYSTEM_DAEMON should never be true because
dirmngr_user_socket_name() won't return NULL. */
- if (!(err = lock_spawning (&lock, homedir, "dirmngr", verbose))
+ if (!(err = lock_spawning (&lock, gnupg_homedir (), "dirmngr", verbose))
&& assuan_socket_connect (ctx, sockname, 0, 0))
{
err = gnupg_spawn_process_detached (dirmngr_program, argv, NULL);
xfree (abs_homedir);
}
#else
- (void)homedir;
(void)dirmngr_program;
(void)verbose;
(void)status_cb;
gpg_error_t
start_new_gpg_agent (assuan_context_t *r_ctx,
gpg_err_source_t errsource,
- const char *homedir,
const char *agent_program,
const char *opt_lc_ctype,
const char *opt_lc_messages,
gpg_error_t
start_new_dirmngr (assuan_context_t *r_ctx,
gpg_err_source_t errsource,
- const char *homedir,
const char *dirmngr_program,
int autostart, int verbose, int debug,
gpg_error_t (*status_cb)(ctrl_t, int, ...),
assert ((reader_mb == NULL) != (cipher_stream == NULL));
/* Create two pipes. */
- err = gnupg_create_outbound_pipe (outbound_fds);
+ err = gnupg_create_outbound_pipe (outbound_fds, NULL, 0);
if (!err)
- err = gnupg_create_inbound_pipe (inbound_fds);
+ err = gnupg_create_inbound_pipe (inbound_fds, NULL, 0);
if (err)
{
log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
assert ((reader_mb == NULL) != (plain_stream == NULL));
/* Create two pipes. */
- err = gnupg_create_outbound_pipe (outbound_fds);
+ err = gnupg_create_outbound_pipe (outbound_fds, NULL, 0);
if (!err)
- err = gnupg_create_inbound_pipe (inbound_fds);
+ err = gnupg_create_inbound_pipe (inbound_fds, NULL, 0);
if (err)
{
log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
--- /dev/null
+/* ccparray.c - A simple dynamic array for character pointer.
+ * Copyright (C) 2016 g10 Code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either
+ *
+ * - the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * or
+ *
+ * - the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * or both in parallel, as here.
+ *
+ * This file 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include "util.h"
+#include "ccparray.h"
+
+
+/* A simple implementation of a dynamic array of const char pointers.
+ * The example code:
+ *
+ * ccparray_t ccp;
+ * const char **argv;
+ * int i;
+ *
+ * ccparray_init (&ccp, 0);
+ * ccparray_put (&ccp, "First arg");
+ * ccparray_put (&ccp, "Second arg");
+ * ccparray_put (&ccp, NULL);
+ * ccparray_put (&ccp, "Fourth arg");
+ * argv = ccparray_get (&ccp, NULL);
+ * if (!argv)
+ * die ("error building array: %s\n", strerror (errno));
+ * for (i=0; argv[i]; i++)
+ * printf ("[%d] = '%s'\n", i, argv[i]);
+ * xfree (argv);
+ *
+ * will result in this output:
+ *
+ * [0] = 'First arg'
+ * [1] = 'Second arg'
+ *
+ * Note that allocation errors are detected but only returned with the
+ * final ccparray_get(); this helps not to clutter the code with out
+ * of core checks.
+ */
+
+void
+ccparray_init (ccparray_t *cpa, unsigned int initialsize)
+{
+ if (!initialsize)
+ cpa->size = 16;
+ else if (initialsize < (1<<16))
+ cpa->size = initialsize;
+ else
+ cpa->size = (1<<16);
+
+ cpa->count = 0;
+ cpa->out_of_core = 0;
+ cpa->array = xtrycalloc (cpa->size, sizeof *cpa->array);
+ if (!cpa->array)
+ cpa->out_of_core = errno;
+}
+
+
+void
+ccparray_put (ccparray_t *cpa, const char *value)
+{
+ if (cpa->out_of_core)
+ return;
+
+ if (cpa->count + 1 >= cpa->size)
+ {
+ const char **newarray;
+ size_t n, newsize;
+
+ if (cpa->size < 8)
+ newsize = 16;
+ else if (cpa->size < 4096)
+ newsize = 2 * cpa->size;
+ else if (cpa->size < (1<<16))
+ newsize = cpa->size + 2048;
+ else
+ {
+ cpa->out_of_core = ENOMEM;
+ return;
+ }
+
+ newarray = xtrycalloc (newsize, sizeof *newarray);
+ if (!newarray)
+ {
+ cpa->out_of_core = errno ? errno : ENOMEM;
+ return;
+ }
+ for (n=0; n < cpa->size; n++)
+ newarray[n] = cpa->array[n];
+ cpa->array = newarray;
+ cpa->size = newsize;
+
+ }
+ cpa->array[cpa->count++] = value;
+}
+
+
+const char **
+ccparray_get (ccparray_t *cpa, size_t *r_count)
+{
+ const char **result;
+
+ if (cpa->out_of_core)
+ {
+ if (cpa->array)
+ {
+ xfree (cpa->array);
+ cpa->array = NULL;
+ }
+ gpg_err_set_errno (cpa->out_of_core);
+ return NULL;
+ }
+
+ result= cpa->array;
+ if (r_count)
+ *r_count = cpa->count;
+ cpa->array = NULL;
+ cpa->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */
+ return result;
+}
--- /dev/null
+/* ccparray.c - A simple dynamic array for character pointer.
+ * Copyright (C) 2016 g10 Code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either
+ *
+ * - the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * or
+ *
+ * - the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * or both in parallel, as here.
+ *
+ * This file 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GNUPG_COMMON_CCPARRAY_H
+#define GNUPG_COMMON_CCPARRAY_H
+
+/* The definition of the structure is private, we only need it here,
+ * so it can be allocated on the stack. */
+struct _ccparray_private_s
+{
+ unsigned int count;
+ unsigned int size;
+ int out_of_core;
+ const char **array;
+};
+
+typedef struct _ccparray_private_s ccparray_t;
+
+
+void ccparray_init (ccparray_t *cpa, unsigned int initialsize);
+void ccparray_put (ccparray_t *cpa, const char *value);
+const char **ccparray_get (ccparray_t *cpa, size_t *r_nelems);
+
+
+#endif /*GNUPG_COMMON_CCPARRAY_H*/
# include <sys/stat.h>
#endif
+#if __linux__
+# include <sys/types.h>
+# include <dirent.h>
+#endif /*__linux__ */
+
#include "util.h"
#include "i18n.h"
#include "sysutils.h"
#include "exechelp.h"
+/* Helper */
+static inline gpg_error_t
+my_error_from_syserror (void)
+{
+ return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
+}
+
+static inline gpg_error_t
+my_error (int errcode)
+{
+ return gpg_err_make (default_errsource, errcode);
+}
+
+
/* Return the maximum number of currently allowed open file
descriptors. Only useful on POSIX systems but returns a value on
other systems too. */
#ifdef HAVE_GETRLIMIT
struct rlimit rl;
+ /* Under Linux we can figure out the highest used file descriptor by
+ * reading /proc/PID/fd. This is in the common cases much fast than
+ * for example doing 4096 close calls where almost all of them will
+ * fail. On a system with a limit of 4096 files and only 8 files
+ * open with the highest number being 10, we speedup close_all_fds
+ * from 125ms to 0.4ms including readdir.
+ *
+ * Another option would be to close the file descriptors as returned
+ * from reading that directory - however then we need to snapshot
+ * that list before starting to close them. */
+#ifdef __linux__
+ {
+ DIR *dir = NULL;
+ struct dirent *dir_entry;
+ const char *s;
+ int x;
+
+ dir = opendir ("/proc/self/fd");
+ if (dir)
+ {
+ while ((dir_entry = readdir (dir)))
+ {
+ s = dir_entry->d_name;
+ if ( *s < '0' || *s > '9')
+ continue;
+ x = atoi (s);
+ if (x > max_fds)
+ max_fds = x;
+ }
+ closedir (dir);
+ }
+ if (max_fds != -1)
+ return max_fds + 1;
+ }
+#endif /* __linux__ */
+
+
# ifdef RLIMIT_NOFILE
if (!getrlimit (RLIMIT_NOFILE, &rl))
max_fds = rl.rlim_max;
static void
do_exec (const char *pgmname, const char *argv[],
int fd_in, int fd_out, int fd_err,
- void (*preexec)(void) )
+ int *except, void (*preexec)(void) )
{
char **arg_list;
int i, j;
}
/* Close all other files. */
- close_all_fds (3, NULL);
+ close_all_fds (3, except);
if (preexec)
preexec ();
if (pipe (filedes) == -1)
{
- err = gpg_error_from_syserror ();
+ err = my_error_from_syserror ();
filedes[0] = filedes[1] = -1;
}
return err;
}
-/* Portable function to create a pipe. Under Windows the write end is
- inheritable. */
-gpg_error_t
-gnupg_create_inbound_pipe (int filedes[2])
-{
- return do_create_pipe (filedes);
-}
-
-
-/* Portable function to create a pipe. Under Windows the read end is
- inheritable. */
-gpg_error_t
-gnupg_create_outbound_pipe (int filedes[2])
-{
- return do_create_pipe (filedes);
-}
-
-
-/* Portable function to create a pipe. Under Windows both ends are
- inheritable. */
-gpg_error_t
-gnupg_create_pipe (int filedes[2])
-{
- return do_create_pipe (filedes);
-}
-
-
static gpg_error_t
create_pipe_and_estream (int filedes[2], estream_t *r_fp,
- int outbound, int nonblock,
- gpg_err_source_t errsource)
+ int outbound, int nonblock)
{
gpg_error_t err;
if (pipe (filedes) == -1)
{
- err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
+ err = my_error_from_syserror ();
log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
filedes[0] = filedes[1] = -1;
*r_fp = NULL;
return err;
}
- if (outbound)
+ if (!outbound)
*r_fp = es_fdopen (filedes[0], nonblock? "r,nonblock" : "r");
else
*r_fp = es_fdopen (filedes[1], nonblock? "w,nonblock" : "w");
if (!*r_fp)
{
- err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
+ err = my_error_from_syserror ();
log_error (_("error creating a stream for a pipe: %s\n"),
gpg_strerror (err));
close (filedes[0]);
}
+/* Portable function to create a pipe. Under Windows the write end is
+ inheritable. If R_FP is not NULL, an estream is created for the
+ read end and stored at R_FP. */
+gpg_error_t
+gnupg_create_inbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
+{
+ if (r_fp)
+ return create_pipe_and_estream (filedes, r_fp, 0, nonblock);
+ else
+ return do_create_pipe (filedes);
+}
+
+
+/* Portable function to create a pipe. Under Windows the read end is
+ inheritable. If R_FP is not NULL, an estream is created for the
+ write end and stored at R_FP. */
+gpg_error_t
+gnupg_create_outbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
+{
+ if (r_fp)
+ return create_pipe_and_estream (filedes, r_fp, 1, nonblock);
+ else
+ return do_create_pipe (filedes);
+}
+
+
+/* Portable function to create a pipe. Under Windows both ends are
+ inheritable. */
+gpg_error_t
+gnupg_create_pipe (int filedes[2])
+{
+ return do_create_pipe (filedes);
+}
+
/* Fork and exec the PGMNAME, see exechelp.h for details. */
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
- gpg_err_source_t errsource,
- void (*preexec)(void), unsigned int flags,
+ int *except, void (*preexec)(void), unsigned int flags,
estream_t *r_infp,
estream_t *r_outfp,
estream_t *r_errfp,
if (r_infp)
{
- err = create_pipe_and_estream (inpipe, &infp, 0, nonblock, errsource);
+ err = create_pipe_and_estream (inpipe, &infp, 1, nonblock);
if (err)
return err;
}
if (r_outfp)
{
- err = create_pipe_and_estream (outpipe, &outfp, 1, nonblock, errsource);
+ err = create_pipe_and_estream (outpipe, &outfp, 0, nonblock);
if (err)
{
if (infp)
if (r_errfp)
{
- err = create_pipe_and_estream (errpipe, &errfp, 1, nonblock, errsource);
+ err = create_pipe_and_estream (errpipe, &errfp, 0, nonblock);
if (err)
{
if (infp)
*pid = fork ();
if (*pid == (pid_t)(-1))
{
- err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
+ err = my_error_from_syserror ();
log_error (_("error forking process: %s\n"), gpg_strerror (err));
if (infp)
gcry_control (GCRYCTL_TERM_SECMEM);
es_fclose (outfp);
es_fclose (errfp);
- do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1], preexec);
+ do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1],
+ except, preexec);
/*NOTREACHED*/
}
*pid = fork ();
if (*pid == (pid_t)(-1))
{
- err = gpg_error_from_syserror ();
+ err = my_error_from_syserror ();
log_error (_("error forking process: %s\n"), strerror (errno));
return err;
}
{
gcry_control (GCRYCTL_TERM_SECMEM);
/* Run child. */
- do_exec (pgmname, argv, infd, outfd, errfd, NULL);
+ do_exec (pgmname, argv, infd, outfd, errfd, NULL, NULL);
/*NOTREACHED*/
}
r_exitcodes[i] = -1;
if (pids[i] == (pid_t)(-1))
- return gpg_error (GPG_ERR_INV_VALUE);
+ return my_error (GPG_ERR_INV_VALUE);
}
left = count;
int i;
if (getuid() != geteuid())
- return gpg_error (GPG_ERR_BUG);
+ return my_error (GPG_ERR_BUG);
if (access (pgmname, X_OK))
- return gpg_error_from_syserror ();
+ return my_error_from_syserror ();
pid = fork ();
if (pid == (pid_t)(-1))
{
log_error (_("error forking process: %s\n"), strerror (errno));
- return gpg_error_from_syserror ();
+ return my_error_from_syserror ();
}
if (!pid)
{
for (i=0; envp[i]; i++)
putenv (xstrdup (envp[i]));
- do_exec (pgmname, argv, -1, -1, -1, NULL);
+ do_exec (pgmname, argv, -1, -1, -1, NULL, NULL);
/*NOTREACHED*/
}
}
/* Portable function to create a pipe. Under Windows the write end is
- inheritable. */
+ inheritable. If R_FP is not NULL, an estream is created for the
+ read end and stored at R_FP. */
gpg_error_t
-gnupg_create_inbound_pipe (int filedes[2])
+gnupg_create_inbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
{
- return do_create_pipe (filedes, INHERIT_WRITE);
+ if (r_fp)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ else
+ return do_create_pipe (filedes, INHERIT_WRITE);
}
/* Portable function to create a pipe. Under Windows the read end is
- inheritable. */
+ inheritable. If R_FP is not NULL, an estream is created for the
+ write end and stored at R_FP. */
gpg_error_t
-gnupg_create_outbound_pipe (int filedes[2])
+gnupg_create_outbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
{
- return do_create_pipe (filedes, INHERIT_READ);
+ if (r_fp)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ else
+ return do_create_pipe (filedes, INHERIT_READ);
}
/* Fork and exec the PGMNAME, see exechelp.h for details. */
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
- gpg_err_source_t errsource,
- void (*preexec)(void), unsigned int flags,
+ int *except, void (*preexec)(void), unsigned int flags,
estream_t *r_infp,
estream_t *r_outfp,
estream_t *r_errfp,
INVALID_HANDLE_VALUE};
int i;
es_syshd_t syshd;
+ gpg_err_source_t errsource = default_errsource;
+
+ (void)except; /* Not yet used. */
if (r_infp)
*r_infp = NULL;
/* Portable function to create a pipe. Under Windows the write end is
inheritable (i.e. an rendezvous id). */
gpg_error_t
-gnupg_create_inbound_pipe (int filedes[2])
+gnupg_create_inbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
{
- return create_inheritable_pipe (filedes, 1);
+ if (r_fp)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ else
+ return create_inheritable_pipe (filedes, 1);
}
/* Portable function to create a pipe. Under Windows the read end is
inheritable (i.e. an rendezvous id). */
gpg_error_t
-gnupg_create_outbound_pipe (int filedes[2])
+gnupg_create_outbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
{
- return create_inheritable_pipe (filedes, 0);
+ if (r_fp)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ else
+ return create_inheritable_pipe (filedes, 0);
}
/* Fork and exec the PGMNAME, see exechelp.h for details. */
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
- gpg_err_source_t errsource,
- void (*preexec)(void), unsigned int flags,
+ int *except, void (*preexec)(void), unsigned int flags,
estream_t *r_infp,
estream_t *r_outfp,
estream_t *r_errfp,
} errpipe = {INVALID_HANDLE_VALUE, 0};
estream_t outfp = NULL;
estream_t errfp = NULL;
+ gpg_err_source_t errsource = default_errsource;
+ (void)except; /* Not yet used. */
(void)preexec;
(void)flags;
/* Portable function to create a pipe. Under Windows the write end is
- inheritable. */
-gpg_error_t gnupg_create_inbound_pipe (int filedes[2]);
+ inheritable. If R_FP is not NULL, an estream is created for the
+ write end and stored at R_FP. */
+gpg_error_t gnupg_create_inbound_pipe (int filedes[2],
+ estream_t *r_fp, int nonblock);
/* Portable function to create a pipe. Under Windows the read end is
- inheritable. */
-gpg_error_t gnupg_create_outbound_pipe (int filedes[2]);
+ inheritable. If R_FP is not NULL, an estream is created for the
+ write end and stored at R_FP. */
+gpg_error_t gnupg_create_outbound_pipe (int filedes[2],
+ estream_t *r_fp, int nonblock);
/* Portable function to create a pipe. Under Windows both ends are
inheritable. */
If PREEXEC is not NULL, the given function will be called right
before the exec.
+ IF EXCEPT is not NULL, it is expected to be an ordered list of file
+ descriptors, terminated by an entry with the value (-1). These
+ file descriptors won't be closed before spawning a new program.
+
Returns 0 on success or an error code. Calling gnupg_wait_process
and gnupg_release_process is required if the function succeeded.
*/
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
- gpg_err_source_t errsource,
- void (*preexec)(void), unsigned int flags,
+ int *execpt, void (*preexec)(void), unsigned int flags,
estream_t *r_infp,
estream_t *r_outfp,
estream_t *r_errfp,
#include "exechelp.h"
#include "sysutils.h"
#include "util.h"
+#include "exectool.h"
typedef struct
{
const char *pgmname;
+ exec_tool_status_cb_t status_cb;
+ void *status_cb_value;
int cont;
- int used;
- char buffer[256];
+ size_t used;
+ size_t buffer_size;
+ char *buffer;
} read_and_log_buffer_t;
pname++;
else
pname = state->pgmname;
- /* If our pgmname plus colon is identical to the start of
- the output, print only the output. */
len = strlen (pname);
- if (!state->cont
+
+ if (state->status_cb
+ && !strncmp (state->buffer, "[GNUPG:] ", 9)
+ && state->buffer[9] >= 'A' && state->buffer[9] <= 'Z')
+ {
+ char *rest;
+
+ rest = strchr (state->buffer + 9, ' ');
+ if (!rest)
+ {
+ /* Set REST to an empty string. */
+ rest = state->buffer + strlen (state->buffer);
+ }
+ else
+ {
+ *rest++ = 0;
+ trim_spaces (rest);
+ }
+ state->status_cb (state->status_cb_value,
+ state->buffer + 9, rest);
+ }
+ else if (!state->cont
&& !strncmp (state->buffer, pname, len)
&& strlen (state->buffer) > strlen (pname)
&& state->buffer[len] == ':' )
- log_info ("%s\n", state->buffer);
+ {
+ /* PGMNAME plus colon is identical to the start of
+ the output: print only the output. */
+ log_info ("%s\n", state->buffer);
+ }
else
log_info ("%s%c %s\n",
pname, state->cont? '+':':', state->buffer);
}
else
{
- if (state->used >= sizeof state->buffer - 1)
+ if (state->used >= state->buffer_size - 1)
{
- read_and_log_stderr (state, NULL);
- state->cont = 1;
+ if (state->status_cb)
+ {
+ /* A status callback requires that we have a full
+ * line. Thus we need to enlarget the buffer in
+ * this case. */
+ char *newbuffer;
+ size_t newsize = state->buffer_size + 256;
+
+ newbuffer = xtrymalloc (newsize);
+ if (!newbuffer)
+ {
+ log_error ("error allocating memory for status cb: %s\n",
+ gpg_strerror (my_error_from_syserror ()));
+ /* We better disable the status CB in this case. */
+ state->status_cb = NULL;
+ read_and_log_stderr (state, NULL);
+ state->cont = 1;
+ }
+ else
+ {
+ memcpy (newbuffer, state->buffer, state->used);
+ xfree (state->buffer);
+ state->buffer = newbuffer;
+ state->buffer_size = newsize;
+ }
+ }
+ else
+ {
+ read_and_log_stderr (state, NULL);
+ state->cont = 1;
+ }
}
state->buffer[state->used++] = c;
}
if (c->nread == 0)
return 0; /* Done copying. */
- err = es_write (sink, c->writep, c->nread, &nwritten);
+
+ err = sink? es_write (sink, c->writep, c->nread, &nwritten) : 0;
if (err)
{
if (errno == EAGAIN)
c->nread -= nwritten;
assert (c->writep - c->buffer <= sizeof c->buffer);
- if (es_fflush (sink) && errno != EAGAIN)
+ if (sink && es_fflush (sink) && errno != EAGAIN)
err = my_error_from_syserror ();
return err;
\f
/* Run the program PGMNAME with the command line arguments given in
- the NULL terminates array ARGV. If INPUT is not NULL it will be
- fed to stdin of the process. stderr is logged using log_info and
- the process' stdout is written to OUTPUT. On error a diagnostic is
- printed, and an error code returned. */
+ * the NULL terminates array ARGV. If INPUT is not NULL it will be
+ * fed to stdin of the process. stderr is logged using log_info and
+ * the process' stdout is written to OUTPUT. If OUTPUT is NULL the
+ * output is discarded. If INEXTRA is given, an additional input
+ * stream will be passed to the child; to tell the child about this
+ * ARGV is scanned and the first occurrence of an argument
+ * "-&@INEXTRA@" is replaced by the concatenation of "-&" and the
+ * child's file descriptor of the pipe created for the INEXTRA stream.
+ *
+ * On error a diagnostic is printed and an error code returned. */
gpg_error_t
gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
- estream_t input,
- estream_t output)
+ estream_t input, estream_t inextra,
+ estream_t output,
+ exec_tool_status_cb_t status_cb,
+ void *status_cb_value)
{
gpg_error_t err;
pid_t pid;
estream_t infp = NULL;
+ estream_t extrafp = NULL;
estream_t outfp, errfp;
- es_poll_t fds[3];
+ es_poll_t fds[4];
+ int exceptclose[2];
+ int extrapipe[2] = {-1, -1};
+ char extrafdbuf[20];
+ const char *argsave = NULL;
+ int argsaveidx;
int count;
read_and_log_buffer_t fderrstate;
- struct copy_buffer cpbuf[2];
+ struct copy_buffer cpbuf_in, cpbuf_out, cpbuf_extra; /* Fixme: malloc them. */
memset (fds, 0, sizeof fds);
memset (&fderrstate, 0, sizeof fderrstate);
- copy_buffer_init (&cpbuf[0]);
- copy_buffer_init (&cpbuf[1]);
+ copy_buffer_init (&cpbuf_in);
+ copy_buffer_init (&cpbuf_out);
+ copy_buffer_init (&cpbuf_extra);
+
+ fderrstate.pgmname = pgmname;
+ fderrstate.status_cb = status_cb;
+ fderrstate.status_cb_value = status_cb_value;
+ fderrstate.buffer_size = 256;
+ fderrstate.buffer = xtrymalloc (fderrstate.buffer_size);
+ if (!fderrstate.buffer)
+ return my_error_from_syserror ();
+
+ if (inextra)
+ {
+ err = gnupg_create_outbound_pipe (extrapipe, &extrafp, 1);
+ if (err)
+ {
+ log_error ("error running outbound pipe for extra fp: %s\n",
+ gpg_strerror (err));
+ xfree (fderrstate.buffer);
+ return err;
+ }
+ exceptclose[0] = extrapipe[0]; /* Do not close in child. */
+ exceptclose[1] = -1;
+ /* Now find the argument marker and replace by the pipe's fd.
+ Yeah, that is an ugly non-thread safe hack but it safes us to
+ create a copy of the array. */
+ snprintf (extrafdbuf, sizeof extrafdbuf, "-&%d", extrapipe[0]);
+ for (argsaveidx=0; argv[argsaveidx]; argsaveidx++)
+ if (!strcmp (argv[argsaveidx], "-&@INEXTRA@"))
+ {
+ argsave = argv[argsaveidx];
+ argv[argsaveidx] = extrafdbuf;
+ break;
+ }
+ }
+ else
+ exceptclose[0] = -1;
- err = gnupg_spawn_process (pgmname, argv, GPG_ERR_SOURCE_DEFAULT,
- NULL, GNUPG_SPAWN_NONBLOCK,
+ err = gnupg_spawn_process (pgmname, argv,
+ exceptclose, NULL, GNUPG_SPAWN_NONBLOCK,
input? &infp : NULL,
&outfp, &errfp, &pid);
+ if (extrapipe[0] != -1)
+ close (extrapipe[0]);
+ if (argsave)
+ argv[argsaveidx] = argsave;
if (err)
{
log_error ("error running '%s': %s\n", pgmname, gpg_strerror (err));
+ es_fclose (extrafp);
+ xfree (fderrstate.buffer);
return err;
}
- fderrstate.pgmname = pgmname;
-
fds[0].stream = infp;
fds[0].want_write = 1;
if (!input)
fds[1].want_read = 1;
fds[2].stream = errfp;
fds[2].want_read = 1;
+ fds[3].stream = extrafp;
+ fds[3].want_write = 1;
+ if (!inextra)
+ fds[3].ignore = 1;
+
/* Now read as long as we have something to poll. We continue
reading even after EOF or error on stdout so that we get the
other error messages or remaining outut. */
if (fds[0].got_write)
{
- err = copy_buffer_do_copy (&cpbuf[0], input, fds[0].stream);
+ err = copy_buffer_do_copy (&cpbuf_in, input, fds[0].stream);
if (err)
{
log_error ("error feeding data to '%s': %s\n",
if (es_feof (input))
{
- err = copy_buffer_flush (&cpbuf[0], fds[0].stream);
+ err = copy_buffer_flush (&cpbuf_in, fds[0].stream);
if (err)
{
log_error ("error feeding data to '%s': %s\n",
}
}
+ if (fds[3].got_write)
+ {
+ log_assert (inextra);
+ err = copy_buffer_do_copy (&cpbuf_extra, inextra, fds[3].stream);
+ if (err)
+ {
+ log_error ("error feeding data to '%s': %s\n",
+ pgmname, gpg_strerror (err));
+ goto leave;
+ }
+
+ if (es_feof (inextra))
+ {
+ err = copy_buffer_flush (&cpbuf_extra, fds[3].stream);
+ if (err)
+ {
+ log_error ("error feeding data to '%s': %s\n",
+ pgmname, gpg_strerror (err));
+ goto leave;
+ }
+
+ fds[3].ignore = 1; /* ready. */
+ es_fclose (extrafp); extrafp = NULL;
+ }
+ }
+
if (fds[1].got_read)
{
- err = copy_buffer_do_copy (&cpbuf[1], fds[1].stream, output);
+ err = copy_buffer_do_copy (&cpbuf_out, fds[1].stream, output);
if (err)
{
log_error ("error reading data from '%s': %s\n",
read_and_log_stderr (&fderrstate, fds + 2);
}
- err = copy_buffer_flush (&cpbuf[1], output);
+ err = copy_buffer_flush (&cpbuf_out, output);
if (err)
{
log_error ("error reading data from '%s': %s\n",
read_and_log_stderr (&fderrstate, NULL); /* Flush. */
es_fclose (infp); infp = NULL;
+ es_fclose (extrafp); extrafp = NULL;
es_fclose (outfp); outfp = NULL;
es_fclose (errfp); errfp = NULL;
gnupg_kill_process (pid);
es_fclose (infp);
+ es_fclose (extrafp);
es_fclose (outfp);
es_fclose (errfp);
if (pid != (pid_t)(-1))
gnupg_wait_process (pgmname, pid, 1, NULL);
gnupg_release_process (pid);
- copy_buffer_shred (&cpbuf[0]);
- copy_buffer_shred (&cpbuf[1]);
+ copy_buffer_shred (&cpbuf_in);
+ copy_buffer_shred (&cpbuf_out);
+ if (inextra)
+ copy_buffer_shred (&cpbuf_extra);
+ xfree (fderrstate.buffer);
return err;
}
goto leave;
}
- err = gnupg_exec_tool_stream (pgmname, argv, input, output);
+ err = gnupg_exec_tool_stream (pgmname, argv, input, NULL, output, NULL, NULL);
if (err)
goto leave;
#include <gpg-error.h>
+/* This callback can be used to process --status-fd outputs of GnuPG
+ * tools. OPAQUE can be used to communicate between the caller of the
+ * function and the callback. KEYWORD is the status keyword (see
+ * doc/DETAILS); it is never NULL. ARGS are the arguments of the
+ * status line and will also never be NULL; the caller may modify this
+ * string. */
+typedef void (*exec_tool_status_cb_t) (void *opaque,
+ const char *keyword,
+ char *args);
+
+
/* Run the program PGMNAME with the command line arguments given in
the NULL terminates array ARGV. If INPUT_STRING is not NULL it
will be fed to stdin of the process. stderr is logged using
the NULL terminates array ARGV. If INPUT is not NULL it will be
fed to stdin of the process. stderr is logged using log_info and
the process' stdout is written to OUTPUT. On error a diagnostic is
- printed, and an error code returned. */
+ printed, and an error code returned. INEXTRA is reserved. */
gpg_error_t gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
- estream_t input,
- estream_t output);
+ estream_t input, estream_t inextra,
+ estream_t output,
+ exec_tool_status_cb_t status_cb,
+ void *status_cb_value);
#endif /* GNUPG_COMMON_EXECTOOL_H */
{
gpg_err_source_t errsource;
int verbosity;
- const char *homedir;
const char *agent_program;
const char *lc_ctype;
const char *lc_messages;
void
gnupg_prepare_get_passphrase (gpg_err_source_t errsource,
int verbosity,
- const char *homedir,
const char *agent_program,
const char *opt_lc_ctype,
const char *opt_lc_messages,
{
agentargs.errsource = errsource;
agentargs.verbosity = verbosity;
- agentargs.homedir = homedir;
agentargs.agent_program = agent_program;
agentargs.lc_ctype = opt_lc_ctype;
agentargs.lc_messages = opt_lc_messages;
err = start_new_gpg_agent (&agent_ctx,
agentargs.errsource,
- agentargs.homedir,
agentargs.agent_program,
agentargs.lc_ctype,
agentargs.lc_messages,
void gnupg_prepare_get_passphrase (gpg_err_source_t errsource,
int verbosity,
- const char *homedir,
const char *agent_program,
const char *opt_lc_ctype,
const char *opt_lc_messages,
/* homedir.c - Setup the home directory.
* Copyright (C) 2004, 2006, 2007, 2010 Free Software Foundation, Inc.
- * Copyright (C) 2013 Werner Koch
+ * Copyright (C) 2013, 2016 Werner Koch
*
* This file is part of GnuPG.
*
#endif
#endif /*HAVE_W32_SYSTEM*/
+#ifdef HAVE_STAT
+#include <sys/stat.h> /* for stat() */
+#endif
+
#include "util.h"
#include "sysutils.h"
+#include "zb32.h"
+
+/* The GnuPG homedir. This is only accessed by the functions
+ * gnupg_homedir and gnupg_set_homedir. Malloced. */
+static char *the_gnupg_homedir;
+
+/* Flag indicating that home directory is not the default one. */
+static byte non_default_homedir;
+
#ifdef HAVE_W32_SYSTEM
/* A flag used to indicate that a control file for gpgconf has been
This flag is not used on Unix systems.
*/
-static int w32_portable_app;
+static byte w32_portable_app;
#endif /*HAVE_W32_SYSTEM*/
#ifdef HAVE_W32_SYSTEM
/* This flag is true if this process' binary has been installed under
bin and not in the root directory as often used before GnuPG 2.1. */
-static int w32_bin_is_bin;
+static byte w32_bin_is_bin;
#endif /*HAVE_W32_SYSTEM*/
#endif /*HAVE_W32_SYSTEM*/
+/* Check whether DIR is the default homedir. */
+static int
+is_gnupg_default_homedir (const char *dir)
+{
+ int result;
+ char *a = make_absfilename (dir, NULL);
+ char *b = make_absfilename (GNUPG_DEFAULT_HOMEDIR, NULL);
+ result = !compare_filenames (a, b);
+ xfree (b);
+ xfree (a);
+ return result;
+}
+
+
/* Get the standard home directory. In general this function should
not be used as it does not consider a registry value (under W32) or
the GNUPGHOME environment variable. It is better to use
#endif /*HAVE_W32_SYSTEM*/
if (!dir || !*dir)
dir = GNUPG_DEFAULT_HOMEDIR;
+ else if (!is_gnupg_default_homedir (dir))
+ non_default_homedir = 1;
return dir;
}
#endif /*HAVE_W32_SYSTEM*/
+/* Change the homedir. Some care must be taken to set this early
+ * enough because previous calls to gnupg_homedir may else return a
+ * different string. */
+void
+gnupg_set_homedir (const char *newdir)
+{
+ if (!newdir || !*newdir)
+ newdir = default_homedir ();
+ else if (!is_gnupg_default_homedir (newdir))
+ non_default_homedir = 1;
+ xfree (the_gnupg_homedir);
+ the_gnupg_homedir = make_absfilename (newdir, NULL);;
+}
+
+
+/* Return the homedir. The returned string is valid until another
+ * gnupg-set-homedir call. This is always an absolute directory name.
+ * The function replaces the former global var opt.homedir. */
+const char *
+gnupg_homedir (void)
+{
+ /* If a homedir has not been set, set it to the default. */
+ if (!the_gnupg_homedir)
+ the_gnupg_homedir = make_absfilename (default_homedir (), NULL);
+ return the_gnupg_homedir;
+}
+
+
+/* Return whether the home dir is the default one. */
+int
+gnupg_default_homedir_p (void)
+{
+ return !non_default_homedir;
+}
+
+
+/* Helper for gnupg-socketdir. This is a global function, so that
+ * gpgconf can use it for its --create-socketdir command. If
+ * SKIP_CHECKS is set permission checks etc. are not done. The
+ * function always returns a malloced directory name and stores these
+ * bit flags at R_INFO:
+ *
+ * 1 := Internal error, stat failed, out of core, etc.
+ * 2 := No /run/user directory.
+ * 4 := Directory not owned by the user, not a directory
+ * or wrong permissions.
+ * 8 := Same as 4 but for the subdir.
+ * 16 := mkdir failed
+ * 32 := Non default homedir; checking subdir.
+ * 64 := Subdir does not exist.
+ * 128 := Using homedir as fallback.
+ */
+char *
+_gnupg_socketdir_internal (int skip_checks, unsigned *r_info)
+{
+#if defined(HAVE_W32_SYSTEM) || !defined(HAVE_STAT)
+
+ char *name;
+
+ (void)skip_checks;
+ *r_info = 0;
+ name = xstrdup (gnupg_homedir ());
+
+#else /* Unix and stat(2) available. */
+
+ static const char * const bases[] = { "/run", "/var/run", NULL};
+ int i;
+ struct stat sb;
+ char prefix[13 + 1 + 20 + 6 + 1];
+ const char *s;
+ char *name = NULL;
+
+ *r_info = 0;
+
+ /* First make sure that non_default_homedir can be set. */
+ gnupg_homedir ();
+
+ /* It has been suggested to first check XDG_RUNTIME_DIR envvar.
+ * However, the specs state that the lifetime of the directory MUST
+ * be bound to the user being logged in. Now GnuPG may also be run
+ * as a background process with no (desktop) user logged in. Thus
+ * we better don't do that. */
+
+ /* Check whether we have a /run/user dir. */
+ for (i=0; bases[i]; i++)
+ {
+ snprintf (prefix, sizeof prefix, "%s/user/%u",
+ bases[i], (unsigned int)getuid ());
+ if (!stat (prefix, &sb) && S_ISDIR(sb.st_mode))
+ break;
+ }
+ if (!bases[i])
+ {
+ *r_info |= 2; /* No /run/user directory. */
+ goto leave;
+ }
+
+ if (sb.st_uid != getuid ())
+ {
+ *r_info |= 4; /* Not owned by the user. */
+ if (!skip_checks)
+ goto leave;
+ }
+
+ if (strlen (prefix) + 7 >= sizeof prefix)
+ {
+ *r_info |= 1; /* Ooops: Buffer too short to append "/gnupg". */
+ goto leave;
+ }
+ strcat (prefix, "/gnupg");
+
+ /* Check whether the gnupg sub directory has proper permissions. */
+ if (stat (prefix, &sb))
+ {
+ if (errno != ENOENT)
+ {
+ *r_info |= 1; /* stat failed. */
+ goto leave;
+ }
+
+ /* Try to create the directory and check again. */
+ if (gnupg_mkdir (prefix, "-rwx"))
+ {
+ *r_info |= 16; /* mkdir failed. */
+ goto leave;
+ }
+ if (stat (prefix, &sb))
+ {
+ *r_info |= 1; /* stat failed. */
+ goto leave;
+ }
+ }
+ /* Check that it is a directory, owned by the user, and only the
+ * user has permissions to use it. */
+ if (!S_ISDIR(sb.st_mode)
+ || sb.st_uid != getuid ()
+ || (sb.st_mode & (S_IRWXG|S_IRWXO)))
+ {
+ *r_info |= 4; /* Bad permissions or not a directory. */
+ if (!skip_checks)
+ goto leave;
+ }
+
+ /* If a non default homedir is used, we check whether an
+ * corresponding sub directory below the socket dir is available
+ * and use that. We has the non default homedir to keep the new
+ * subdir short enough. */
+ if (non_default_homedir)
+ {
+ char sha1buf[20];
+ char *suffix;
+
+ *r_info |= 32; /* Testing subdir. */
+ s = gnupg_homedir ();
+ gcry_md_hash_buffer (GCRY_MD_SHA1, sha1buf, s, strlen (s));
+ suffix = zb32_encode (sha1buf, 8*15);
+ if (!suffix)
+ {
+ *r_info |= 1; /* Out of core etc. */
+ goto leave;
+ }
+ name = strconcat (prefix, "/d.", suffix, NULL);
+ xfree (suffix);
+ if (!name)
+ {
+ *r_info |= 1; /* Out of core etc. */
+ goto leave;
+ }
+
+ /* Stat that directory and check constraints. Note that we
+ * do not auto create such a directory because we would not
+ * have a way to remove it. Thus the directory needs to be
+ * pre-created. The command
+ * gpgconf --create-socketdir
+ * can be used tocreate that directory. */
+ if (stat (name, &sb))
+ {
+ if (errno != ENOENT)
+ *r_info |= 1; /* stat failed. */
+ else
+ *r_info |= 64; /* Subdir does not exist. */
+ if (!skip_checks)
+ {
+ xfree (name);
+ name = NULL;
+ goto leave;
+ }
+ }
+ else if (!S_ISDIR(sb.st_mode)
+ || sb.st_uid != getuid ()
+ || (sb.st_mode & (S_IRWXG|S_IRWXO)))
+ {
+ *r_info |= 8; /* Bad permissions or subdir is not a directory. */
+ if (!skip_checks)
+ {
+ xfree (name);
+ name = NULL;
+ goto leave;
+ }
+ }
+ }
+ else
+ name = xstrdup (prefix);
+
+ leave:
+ /* If nothing works fall back to the homedir. */
+ if (!name)
+ {
+ *r_info |= 128; /* Fallback. */
+ name = xstrdup (gnupg_homedir ());
+ }
+
+#endif /* Unix */
+
+ return name;
+}
+
+
+/*
+ * Return the name of the socket dir. That is the directory used for
+ * the IPC local sockets. This is an absolute directory name.
+ */
+const char *
+gnupg_socketdir (void)
+{
+ static char *name;
+
+ if (!name)
+ {
+ unsigned int dummy;
+ name = _gnupg_socketdir_internal (0, &dummy);
+ }
+
+ return name;
+}
/* Return the name of the sysconfdir. This is a static string. This
static char *name;
if (!name)
- name = make_absfilename (default_homedir (), DIRMNGR_SOCK_NAME, NULL);
+ name = make_filename (gnupg_socketdir (), DIRMNGR_SOCK_NAME, NULL);
return name;
}
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
-
+/* #include <execinfo.h> */
#define GNUPG_COMMON_NEED_AFLOCAL 1
#include "util.h"
if (missing_lf)
es_putc_unlocked ('\n', logstream );
es_funlockfile (logstream);
+ /* Using backtrace requires a configure test and to pass
+ * -rdynamic to gcc. Thus we do not enable it now. */
+ /* { */
+ /* void *btbuf[20]; */
+ /* int btidx, btlen; */
+ /* char **btstr; */
+
+ /* btlen = backtrace (btbuf, DIM (btbuf)); */
+ /* btstr = backtrace_symbols (btbuf, btlen); */
+ /* if (btstr) */
+ /* for (btidx=0; btidx < btlen; btidx++) */
+ /* log_debug ("[%d] %s\n", btidx, btstr[btidx]); */
+ /* } */
abort ();
}
else
#include <assert.h>
#include "util.h"
-
+#include "openpgpdefs.h"
/* A table with all our supported OpenPGP curves. */
static struct {
const char *oidstr; /* IETF formatted OID. */
unsigned int nbits; /* Nominal bit length of the curve. */
const char *alias; /* NULL or alternative name of the curve. */
+ int pubkey_algo; /* Required OpenPGP algo or 0 for ECDSA/ECDH. */
} oidtable[] = {
- { "Curve25519", "1.3.6.1.4.1.3029.1.5.1", 255, "cv25519" },
- { "Ed25519", "1.3.6.1.4.1.11591.15.1", 255, "ed25519" },
+ { "Curve25519", "1.3.6.1.4.1.3029.1.5.1", 255, "cv25519", PUBKEY_ALGO_ECDH },
+ { "Ed25519", "1.3.6.1.4.1.11591.15.1", 255, "ed25519", PUBKEY_ALGO_EDDSA },
{ "NIST P-256", "1.2.840.10045.3.1.7", 256, "nistp256" },
{ "NIST P-384", "1.3.132.0.34", 384, "nistp384" },
*iterp = idx;
return NULL;
}
+
+
+/* Return the Libgcrypt name for for the gpg curve NAME if supported.
+ * If R_ALGO is not NULL the required OpenPGP public key algo or 0 is
+ * stored at that address. NULL is returned if the curev is not
+ * supported. */
+const char *
+openpgp_is_curve_supported (const char *name, int *r_algo)
+{
+ int idx;
+
+ if (r_algo)
+ *r_algo = 0;
+ for (idx = 0; idx < DIM (oidtable) && oidtable[idx].name; idx++)
+ {
+ if (!strcmp (name, (oidtable[idx].alias? oidtable[idx].alias
+ /**/ : oidtable[idx].name))
+ && curve_supported_p (oidtable[idx].name))
+ {
+ if (r_algo)
+ *r_algo = oidtable[idx].pubkey_algo;
+ return oidtable[idx].name;
+ }
+ }
+ return NULL;
+}
SIGSUBPKT_PREF_HASH = 21, /* Preferred hash algorithms. */
SIGSUBPKT_PREF_COMPR = 22, /* Preferred compression algorithms. */
SIGSUBPKT_KS_FLAGS = 23, /* Key server preferences. */
- SIGSUBPKT_PREF_KS = 24, /* Preferred key server. */
+ SIGSUBPKT_PREF_KS = 24, /* Preferred keyserver. */
SIGSUBPKT_PRIMARY_UID = 25, /* Primary user id. */
SIGSUBPKT_POLICY = 26, /* Policy URL. */
SIGSUBPKT_KEY_FLAGS = 27, /* Key flags. */
STATUS_SIG_CREATED,
STATUS_SESSION_KEY,
STATUS_NOTATION_NAME,
+ STATUS_NOTATION_FLAGS,
STATUS_NOTATION_DATA,
STATUS_POLICY_URL,
STATUS_KEY_CREATED,
STATUS_INV_SGNR,
STATUS_NO_RECP,
STATUS_NO_SGNR,
+ STATUS_KEY_CONSIDERED,
STATUS_ALREADY_SIGNED,
STATUS_KEYEXPIRED,
}
+/* Split a string into space delimited fields and remove leading and
+ * trailing spaces from each field. A pointer to each field is stored
+ * in ARRAY. Stop splitting at ARRAYSIZE fields. The function
+ * modifies STRING. The number of parsed fields is returned.
+ * Example:
+ *
+ * char *fields[2];
+ * if (split_fields (string, fields, DIM (fields)) < 2)
+ * return // Not enough args.
+ * foo (fields[0]);
+ * foo (fields[1]);
+ */
+int
+split_fields (char *string, char **array, int arraysize)
+{
+ int n = 0;
+ char *p, *pend;
+
+ for (p = string; *p == ' '; p++)
+ ;
+ do
+ {
+ if (n == arraysize)
+ break;
+ array[n++] = p;
+ pend = strchr (p, ' ');
+ if (!pend)
+ break;
+ *pend++ = 0;
+ for (p = pend; *p == ' '; p++)
+ ;
+ }
+ while (*p);
+
+ return n;
+}
+
+
\f
/* Version number parsing. */
/* Tokenize STRING using the set of delimiters in DELIM. */
char **strtokenize (const char *string, const char *delim);
+/* Split STRING into space delimited fields and store them in the
+ * provided ARRAY. */
+int split_fields (char *string, char **array, int arraysize);
+
/* Return True if MYVERSION is greater or equal than REQ_VERSION. */
int compare_version_strings (const char *my_version, const char *req_version);
}
-/* A wrapper around mkdir which takes a string for the mode argument.
+/* A wrapper around chmod which takes a string for the mode argument.
This makes it easier to handle the mode argument which is not
defined on all systems. The format of the modestring is the same
as for gnupg_mkdir. */
gnupg_chmod (const char *name, const char *modestr)
{
#ifdef HAVE_W32_SYSTEM
+ (void)name;
+ (void)modestr;
return 0;
#else
return chmod (name, modestr_to_mode (modestr));
--- /dev/null
+/* t-ccparray.c - Module test for ccparray.c
+ * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+#include "ccparray.h"
+
+#define pass() do { ; } while(0)
+#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\
+ __FILE__,__LINE__, (a)); \
+ exit (1); \
+ } while(0)
+
+
+static void
+run_test_1 (void)
+{
+ ccparray_t ccp;
+ const char **argv;
+ size_t nelem;
+
+ ccparray_init (&ccp, 0);
+ ccparray_put (&ccp, "First arg");
+ ccparray_put (&ccp, "Second arg");
+ ccparray_put (&ccp, NULL);
+ ccparray_put (&ccp, "Fourth arg");
+ argv = ccparray_get (&ccp, &nelem);
+ if (!argv)
+ {
+ fprintf (stderr, "error building array: %s\n", strerror (errno));
+ exit (1);
+ }
+
+ if (nelem != 4)
+ fail (1);
+
+ /* for (i=0; argv[i]; i++) */
+ /* printf ("[%d] = '%s'\n", i, argv[i]); */
+ xfree (argv);
+}
+
+
+static void
+run_test_var (int count)
+{
+ ccparray_t ccp;
+ size_t nelem;
+ int i;
+
+ ccparray_init (&ccp, 0);
+ for (i=0; i < count; i++)
+ ccparray_put (&ccp, "An arg");
+ xfree (ccparray_get (&ccp, &nelem));
+ if (nelem != i)
+ fail (2);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ (void)argc;
+ (void)argv;
+
+ run_test_1 ();
+ run_test_var (0);
+ run_test_var (7);
+ run_test_var (8);
+ run_test_var (9);
+ run_test_var (4096);
+
+ return 0;
+}
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <assert.h>
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
}
}
+
+static void
+test_split_fields (void)
+{
+ struct {
+ const char *s;
+ int nfields;
+ const char *fields_expected[10];
+ } tv[] = {
+ {
+ "a bc cde fghi jklmn foo ", 6,
+ { "a", "bc", "cde", "fghi", "jklmn", "foo", NULL }
+ },
+ {
+ " a bc def ", 2,
+ { "a", "bc", "def", NULL }
+ },
+ {
+ " a bc def ", 3,
+ { "a", "bc", "def", NULL }
+ },
+ {
+ " a bc def ", 4,
+ { "a", "bc", "def", NULL }
+ },
+ {
+ "", 0,
+ { NULL }
+ }
+ };
+
+ int tidx;
+ char *fields[10];
+ int field_count_expected, nfields, field_count, i;
+ char *s2;
+
+ for (tidx = 0; tidx < DIM(tv); tidx++)
+ {
+ nfields = tv[tidx].nfields;
+ assert (nfields <= DIM (fields));
+
+ /* Count the fields. */
+ for (field_count_expected = 0;
+ tv[tidx].fields_expected[field_count_expected];
+ field_count_expected ++)
+ ;
+ if (field_count_expected > nfields)
+ field_count_expected = nfields;
+
+ /* We need to copy s since split_fields modifies in place. */
+ s2 = xstrdup (tv[tidx].s);
+ field_count = split_fields (s2, fields, nfields);
+
+ if (field_count != field_count_expected)
+ {
+ printf ("%s: tidx %d: expected %d, got %d\n",
+ __func__, tidx, field_count_expected, field_count);
+ fail (tidx * 1000);
+ }
+ else
+ {
+ for (i = 0; i < field_count_expected; i ++)
+ if (strcmp (tv[tidx].fields_expected[i], fields[i]))
+ {
+ printf ("%s: tidx %d, field %d: expected '%s', got '%s'\n",
+ __func__,
+ tidx, i, tv[tidx].fields_expected[i], fields[i]);
+ fail (tidx * 1000 + i + 1);
+ }
+ }
+
+ xfree (s2);
+ }
+}
+
+
static char *
stresc (char *s)
{
test_make_absfilename_try ();
test_strsplit ();
test_strtokenize ();
+ test_split_fields ();
test_compare_version_strings ();
test_format_text ();
const char *openpgp_curve_to_oid (const char *name, unsigned int *r_nbits);
const char *openpgp_oid_to_curve (const char *oid, int canon);
const char *openpgp_enum_curves (int *idxp);
-
+const char *openpgp_is_curve_supported (const char *name, int *r_algo);
/*-- homedir.c --*/
const char *standard_homedir (void);
const char *default_homedir (void);
+void gnupg_set_homedir (const char *newdir);
+const char *gnupg_homedir (void);
+int gnupg_default_homedir_p (void);
+const char *gnupg_socketdir (void);
const char *gnupg_sysconfdir (void);
const char *gnupg_bindir (void);
const char *gnupg_libexecdir (void);
const char *dirmngr_sys_socket_name (void);
const char *dirmngr_user_socket_name (void);
+char *_gnupg_socketdir_internal (int skip_checks, unsigned *r_info);
+
/* All module names. We also include gpg and gpgsm for the sake for
gpgconf. */
#define GNUPG_MODULE_NAME_AGENT 1
m4_define([mym4_package],[gnupg])
m4_define([mym4_major], [2])
m4_define([mym4_minor], [1])
-m4_define([mym4_micro], [12])
+m4_define([mym4_micro], [13])
# To start a new development series, i.e a new major or minor number
# you need to mark an arbitrary commit before the first beta release
if test "$use_ccid_driver" = auto || test "$use_ccid_driver" = yes; then
case "${host}" in
*-mingw32*)
+ LIBUSB_NAME=
LIBUSB_LIBS=
LIBUSB_CPPFLAGS=
;;
*-*-darwin*)
- LIBUSB_LIBS="-lusb-1.0 -Wl,-framework,CoreFoundation -Wl,-framework,IOKit"
+ LIBUSB_NAME=usb-1.0
+ LIBUSB_LIBS="-Wl,-framework,CoreFoundation -Wl,-framework,IOKit"
;;
*-*-freebsd*)
# FreeBSD has a native 1.0 compatible library by -lusb.
- LIBUSB_LIBS="-lusb"
+ LIBUSB_NAME=usb
+ LIBUSB_LIBS=
;;
*)
- LIBUSB_LIBS="-lusb-1.0"
+ LIBUSB_NAME=usb-1.0
+ LIBUSB_LIBS=
;;
esac
fi
-if test x"$LIBUSB_LIBS" != x ; then
- AC_CHECK_LIB(usb-1.0, libusb_init,
- [ LIBUSB_LIBS="$LIBUSB_LIBS"
+if test x"$LIBUSB_NAME" != x ; then
+ AC_CHECK_LIB($LIBUSB_NAME, libusb_init,
+ [ LIBUSB_LIBS="-l$LIBUSB_NAME $LIBUSB_LIBS"
have_libusb=yes ])
AC_MSG_CHECKING([libusb include dir])
usb_incdir_found="no"
AC_CHECK_FUNCS([ttyname rand ftello fsync stat lstat])
AC_CHECK_FUNCS([memicmp stpcpy strsep strlwr strtoul memmove stricmp strtol \
memrchr isascii timegm getrusage setrlimit stat setlocale \
- flockfile funlockfile fopencookie funopen getpwnam getpwuid \
+ flockfile funlockfile getpwnam getpwuid \
getenv inet_pton strpbrk])
if test "$have_android_system" = yes; then
BUILD_TIMESTAMP=`date -u +%Y-%m-%dT%H:%M+0000 2>/dev/null || date`
else
BUILD_TIMESTAMP="$enableval"
- fi],
- [BUILD_TIMESTAMP="<none>"])
+ fi
+ BUILD_HOSTNAME="$ac_hostname"],
+ [BUILD_TIMESTAMP="<none>"
+ BUILD_HOSTNAME="<anon>"])
AC_SUBST(BUILD_TIMESTAMP)
AC_DEFINE_UNQUOTED(BUILD_TIMESTAMP, "$BUILD_TIMESTAMP",
[The time this package was configured for a build])
-BUILD_HOSTNAME="$ac_hostname"
AC_SUBST(BUILD_HOSTNAME)
endif
dirmngr_client_SOURCES = dirmngr-client.c
-dirmngr_client_LDADD = $(libcommon) no-libgcrypt.o \
- $(LIBASSUAN_LIBS) \
- $(GPG_ERROR_LIBS) $(NETLIBS) $(LIBINTL) $(LIBICONV)
+dirmngr_client_LDADD = $(libcommon) \
+ $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBGCRYPT_LIBS) $(NETLIBS) $(LIBINTL) $(LIBICONV)
dirmngr_client_LDFLAGS = $(extra_bin_ldflags)
-
no-libgcrypt.c : $(top_srcdir)/tools/no-libgcrypt.c
cat $(top_srcdir)/tools/no-libgcrypt.c > no-libgcrypt.c
t_common_src = t-support.h
-t_common_ldadd = $(libcommon) no-libgcrypt.o $(LIBASSUAN_LIBS) \
+t_common_ldadd = $(libcommon) $(LIBASSUAN_LIBS) $(LIBGCRYPT_LIBS) \
$(GPG_ERROR_LIBS) $(NETLIBS) \
$(NTBTLS_LIBS) $(LIBGNUTLS_LIBS) \
$(DNSLIBS) $(LIBINTL) $(LIBICONV)
err = start_new_dirmngr (&ctx,
GPG_ERR_SOURCE_DEFAULT,
- default_homedir (),
opt.dirmngr_program
? opt.dirmngr_program
: gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR),
if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
csh_style = 1;
- opt.homedir = default_homedir ();
-
- /* Now with NPth running we can set the logging callback. Our
+ /* Now with NPth running we can set the logging callback. Our
windows implementation does not yet feature the NPth TLS
functions. */
#ifndef HAVE_W32_SYSTEM
default_config = 0; /* --no-options */
else if (pargs.r_opt == oHomedir)
{
- opt.homedir = pargs.r.ret_str;
+ gnupg_set_homedir (pargs.r.ret_str);
homedir_seen = 1;
}
else if (pargs.r_opt == aDaemon)
if (opt.system_daemon && !homedir_seen)
{
#ifdef HAVE_W32CE_SYSTEM
- opt.homedir = DIRSEP_S "gnupg";
+ gnupg_set_homedir (DIRSEP_S "gnupg");
#else
- opt.homedir = gnupg_sysconfdir ();
+ gnupg_set_homedir (gnupg_sysconfdir ());
#endif
opt.homedir_cache = gnupg_cachedir ();
socket_name = dirmngr_sys_socket_name ();
socket_name = dirmngr_sys_socket_name ();
if (default_config)
- configname = make_filename (opt.homedir, DIRMNGR_NAME".conf", NULL );
+ configname = make_filename (gnupg_homedir (), DIRMNGR_NAME".conf", NULL );
argc = orig_argc;
argv = orig_argv;
greeting = 0;
if (!opt.homedir_cache)
- opt.homedir_cache = opt.homedir;
+ opt.homedir_cache = xstrdup (gnupg_homedir ());
if (greeting)
{
log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
}
- if (!access ("/etc/"DIRMNGR_NAME, F_OK) && !strncmp (opt.homedir, "/etc/", 5))
+ if (!access ("/etc/"DIRMNGR_NAME, F_OK)
+ && !strncmp (gnupg_homedir (), "/etc/", 5))
log_info
("NOTE: DirMngr is now a proper part of %s. The configuration and"
" other directory names changed. Please check that no other version"
#if USE_LDAP
if (!ldapfile)
{
- ldapfile = make_filename (opt.homedir,
+ ldapfile = make_filename (gnupg_homedir (),
opt.system_daemon?
"ldapservers.conf":"dirmngr_ldapservers.conf",
NULL);
}
cleanup_socket = 1;
+ if (gnupg_chmod (serv_addr.sun_path, "-rwx"))
+ log_error (_("can't set permissions of '%s': %s\n"),
+ serv_addr.sun_path, strerror (errno));
+
if (listen (FD2INT (fd), 5) == -1)
{
log_error (_("listen() failed: %s\n"), strerror (errno));
/* First the configuration file. This is not an option, but it
is vital information for GPG Conf. */
if (!opt.config_filename)
- opt.config_filename = make_filename (opt.homedir,
+ opt.config_filename = make_filename (gnupg_homedir (),
"dirmngr.conf", NULL );
filename = percent_escape (opt.config_filename, NULL);
and having both of them is thus problematic. --no-detach is
also only usable on the command line. --batch is unused. */
- filename = make_filename (opt.homedir,
+ filename = make_filename (gnupg_homedir (),
opt.system_daemon?
"ldapservers.conf":"dirmngr_ldapservers.conf",
NULL);
{
if (string[0] == '.' && string[1] == '/' )
string += 2;
- fname = make_filename (opt.homedir, string, NULL);
+ fname = make_filename (gnupg_homedir (), string, NULL);
}
fp = es_fopen (fname, "r");
int quiet; /* be as quiet as possible */
int dry_run; /* don't change any persistent data */
int batch; /* batch mode */
- const char *homedir; /* Configuration directory name */
- const char *homedir_cache; /* Ditto for cache files (/var/cache/dirmngr). */
+ const char *homedir_cache; /* Dir for cache files (/var/cache/dirmngr). */
char *config_filename; /* Name of a config file, which will be
reread on a HUP if it is not NULL. */
/* Fixme: Can we use MYOPT->user or is it shared with other theeads?. */
ret = my_ldap_simple_bind_s (ld, myopt->user, myopt->pass);
npth_protect ();
+#ifdef LDAP_VERSION3
+ if (ret == LDAP_PROTOCOL_ERROR)
+ {
+ /* Protocol error could mean that the server only supports v3. */
+ int version = LDAP_VERSION3;
+ if (myopt->verbose)
+ log_info ("protocol error; retrying bind with v3 protocol\n");
+ npth_unprotect ();
+ ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &version);
+ ret = my_ldap_simple_bind_s (ld, myopt->user, myopt->pass);
+ npth_protect ();
+ }
+#endif
if (ret)
{
log_error (_("binding to '%s:%d' failed: %s\n"),
- host, port, strerror (errno));
+ host, port, ldap_err2string (ret));
ldap_unbind (ld);
return -1;
}
/* Shutdown one end of the socket is desired. As per HTTP/1.0 this
is not required but some very old servers (e.g. the original pksd
- key server didn't worked without it. */
+ keyserver didn't worked without it. */
if ((hd->flags & HTTP_FLAG_SHUTDOWN))
shutdown (hd->sock->fd, 1);
hd->in_data = 0;
return err;
}
- err = gnupg_create_inbound_pipe (outpipe);
+ err = gnupg_create_inbound_pipe (outpipe, NULL, 0);
if (!err)
{
- err = gnupg_create_inbound_pipe (errpipe);
+ err = gnupg_create_inbound_pipe (errpipe, NULL, 0);
if (err)
{
close (outpipe[0]);
uri = strconcat ("https://",
domain,
"/.well-known/openpgpkey/hu/",
- domain,
- "/",
encodedhash,
NULL);
if (!uri)
if (!hello_line)
{
- size_t n;
- const char *cfgname;
-
- cfgname = opt.config_filename? opt.config_filename : "[none]";
-
- n = (30 + strlen (opt.homedir) + strlen (cfgname)
- + strlen (hello) + 1);
- hello_line = xmalloc (n+1);
- snprintf (hello_line, n,
- "Home: %s\n"
- "Config: %s\n"
- "%s",
- opt.homedir,
- cfgname,
- hello);
- hello_line[n] = 0;
+ hello_line = xtryasprintf
+ ("Home: %s\n"
+ "Config: %s\n"
+ "%s",
+ gnupg_homedir (),
+ opt.config_filename? opt.config_filename : "[none]",
+ hello);
}
ctrl->server_local->assuan_ctx = ctx;
arguments in future versions.
** General status codes
-*** NEWSIG
+*** NEWSIG [<signers_uid>]
Is issued right before a signature verification starts. This is
- useful to define a context for parsing ERROR status messages. No
- arguments are currently defined.
+ useful to define a context for parsing ERROR status messages.
+ arguments are currently defined. If SIGNERS_UID is given and is
+ not "-" this is the percent escape value of the OpenPGP Signer's
+ User ID signature sub-packet.
*** GOODSIG <long_keyid_or_fpr> <username>
The signature with the keyid is good. For each signature only one
letter 'T'.
*** NOTATION_
- There are actually two related status codes to convey notation
+ There are actually three related status codes to convey notation
data:
- NOTATION_NAME <name>
+ - NOTATION_FLAGS <critical> <human_readable>
- NOTATION_DATA <string>
- <name> and <string> are %XX escaped; the data may be split among
- several NOTATION_DATA lines.
+ <name> and <string> are %XX escaped. The data may be split among
+ several NOTATION_DATA lines. NOTATION_FLAGS is emitted after
+ NOTATION_NAME and gives the critical and human readable flags;
+ the flag values are either 0 or 1.
*** POLICY_URL <string>
Note that URL in <string> is %XX escaped.
that case, this status tag does not appear.
*** ATTRIBUTE <arguments>
- The list or argemnts are:
+ The list or arguments are:
- <fpr>
- <octets>
- <type>
- 13 :: Key disabled
- 14 :: Syntax error in specification
+ If no specific reason was given a previously emitted status code
+ KEY_CONSIDERED may be used to analyzed the problem.
+
Note that for historical reasons the INV_RECP status is also used
for gpgsm's SIGNER command where it relates to signer's of course.
Newer GnuPG versions are using INV_SGNR; applications should
ignore the INV_RECP during the sender's command processing once
they have seen an INV_SGNR. Different codes are used so that they
can be distinguish while doing an encrypt+sign operation.
+
*** NO_RECP <reserved>
Issued if no recipients are usable.
*** NO_SGNR <reserved>
Issued if no senders are usable.
+*** KEY_CONSIDERED <fpr> <flags>
+ Issued to explian the lookup of a key. FPR is the hexified
+ fingerprint of the primary key. The bit values for FLAGS are:
+
+ - 1 :: The key has not been selected.
+ - 2 :: All subkeys of the key are expired or have been revoked.
+
*** KEYEXPIRED <expire-timestamp>
The key has expired. expire-timestamp is the expiration time in
seconds since Epoch. This status line is not very useful because
This status identifies the key and the userid for all following
Tofu information. The fingerprint is the fingerprint of the
- primary key and the mbox is in general the mailbox part of the
+ primary key and the mbox is in general the addr-spec part of the
userid encoded in UTF-8 and percent escaped.
*** TOFU_STATS <validity> <sign-count> 0 [<policy> [<tm1> <tm2>]]
*** PKA_TRUST_
This is is one:
- - PKA_TRUST_GOOD <mailbox>
- - PKA_TRUST_BAD <mailbox>
+ - PKA_TRUST_GOOD <addr-spec>
+ - PKA_TRUST_BAD <addr-spec>
Depending on the outcome of the PKA check one of the above status
codes is emitted in addition to a =TRUST_*= status.
/pks/lookup/<gnupg_formatierte_user_id>?op=<operation>
This can be implemented using Hurd's translator mechanism.
- However, I think the whole key server stuff has to be re-thought;
+ However, I think the whole keyserver stuff has to be re-thought;
I have some ideas and probably create a white paper.
** Algorithm names for the "keygen.algo" prompt
@item --http-proxy @var{host}[:@var{port}]
@opindex http-proxy
+@efindex http_proxy
Use @var{host} and @var{port} to access HTTP servers. The use of this
option overrides the environment variable @env{http_proxy} regardless
whether @option{--honor-http-proxy} has been set.
@macro mancont
@end macro
+
+
@c Create a separate index for command line options.
@defcodeindex op
-@c Merge the standard indexes into a single one.
+@c Create an index vor environment variables and files.
+@defcodeindex ef
+
+@c Merge the function index into the concept index.
@syncodeindex fn cp
+@c Merge the variable index into the concept index.
@syncodeindex vr cp
+@c Merge the keystroke index into the concept index.
@syncodeindex ky cp
+@c Merge the program index into the concept index.
@syncodeindex pg cp
+@c Merge the data type index into the concept index.
@syncodeindex tp cp
@c %**end of header
@copying
* Glossary:: Short description of terms used.
* Option Index:: Index to command line options.
+* Environment Index:: Index to environment variables and files.
* Index:: Index of concepts and symbol names.
@end menu
@printindex op
+@node Environment Index
+@unnumbered Environment Variable and File Index
+
+@printindex ef
+
@node Index
@unnumbered Index
@end example
@noindent
+@efindex GPG_TTY
You should always add the following lines to your @code{.bashrc} or
whatever initialization file is used for all shell invocations:
@itemx --csh
@opindex sh
@opindex csh
+@efindex SHELL
Format the info output in daemon mode for use with the standard Bourne
shell or the C-shell respectively. The default is to guess it based on
the environment variable @code{SHELL} which is correct in almost all
@anchor{option --log-file}
@item --log-file @var{file}
@opindex log-file
+@efindex HKCU\Software\GNU\GnuPG:DefaultLogFile
Append all logging output to @var{file}. This is very helpful in seeing
what the agent actually does. If neither a log file nor a log file
descriptor has been set on a Windows platform, the Registry entry
Disallow or allow clients to use the loopback pinentry features; see
the option @option{pinentry-mode} for details. Allow is the default.
+The @option{--force} option of the Assuan command @command{DELETE_KEY}
+is also controlled by this option: The option is ignored if a loopback
+pinentry is disallowed.
+
@item --no-allow-external-cache
@opindex no-allow-external-cache
Tell Pinentry not to enable features which use an external cache for
@table @file
@item gpg-agent.conf
-@cindex gpg-agent.conf
+@efindex gpg-agent.conf
This is the standard configuration file read by @command{gpg-agent} on
startup. It may contain any valid long option; the leading
two dashes may not be entered and the option may not be abbreviated.
You should backup this file.
@item trustlist.txt
+@efindex trustlist.txt
This is the list of trusted keys. You should backup this file.
Comment lines, indicated by a leading hash mark, as well as empty
@item sshcontrol
-@cindex sshcontrol
+@efindex sshcontrol
This file is used when support for the secure shell agent protocol has
been enabled (@pxref{option --enable-ssh-support}). Only keys present in
this file are used in the SSH protocol. You should backup this file.
@end cartouche
@item private-keys-v1.d/
+@efindex private-keys-v1.d
This is the directory where gpg-agent stores the private keys. Each
key is stored in a file with the name made up of the keygrip and the
@node Agent Examples
@section Examples
-It is important to set the GPG_TTY environment variable in
+It is important to set the environment variable @code{GPG_TTY} in
your login shell, for example in the @file{~/.bashrc} init script:
@cartouche
@section Agent's Assuan Protocol
Note: this section does only document the protocol, which is used by
-GnuPG components; it does not deal with the ssh-agent protocol.
+GnuPG components; it does not deal with the ssh-agent protocol. To
+see the full specification of each command, use
+
+@example
+ gpg-connect-agent 'help COMMAND' /bye
+@end example
+@noindent
+or just 'help' to list all available commands.
+
+@noindent
The @command{gpg-agent} daemon is started on demand by the GnuPG
components.
the additional output of a line with the fingerprint. May also be
combined with @option{--list-sigs} or @option{--check-sigs}. If this
command is given twice, the fingerprints of all secondary keys are
-listed too.
+listed too. This command also forces pretty printing of fingerprints
+if the keyid format has been set to "none".
@item --list-packets
@opindex list-packets
@item --delete-secret-keys @code{name}
@opindex delete-secret-keys
-Remove key from the secret keyring. In batch mode the key
-must be specified by fingerprint.
+gRemove key from the secret keyring. In batch mode the key must be
+specified by fingerprint. The option @option{--yes} can be used to
+advice gpg-agent not to request a confirmation. This extra
+pre-caution is done because @command{gpg} can't be sure that the
+secret key (as controlled by gpg-agent) is only used for the given
+OpenPGP public key.
+
@item --delete-secret-and-public-key @code{name}
@opindex delete-secret-and-public-key
Same as @option{--delete-key}, but if a secret key exists, it will be
removed first. In batch mode the key must be specified by fingerprint.
+The option @option{--yes} can be used to advice gpg-agent not to
+request a confirmation.
@item --export
@opindex export
@table @gnupgtabopt
-@item --quick-gen-key @code{user-id}
+@item --quick-gen-key @code{user-id} [@code{algo} [@code{usage} [@code{expire}]]]
@opindex quick-gen-key
This is a simple command to generate a standard key with one user id.
In contrast to @option{--gen-key} the key is generated directly
case the user id already exists in the key ring a second prompt to
force the creation of the key will show up.
+If any of the optional arguments are given, only the primary key is
+created and no prompts are shown. For a description of these optional
+arguments see the command @code{--quick-addkey}. The @code{usage}
+accepts also the value ``cert'' which can be used to create a
+certification only primary key; the default is to a create
+certification and signing key.
+
If this command is used with @option{--batch},
@option{--pinentry-mode} has been set to @code{loopback}, and one of
the passphrase options (@option{--passphrase},
for it. To create a key without any protection @code{--passphrase ''}
may be used.
+@item --quick-addkey @code{fpr} [@code{algo} [@code{usage} [@code{expire}]]]
+@opindex quick-addkey
+Directly add a subkey to the key identified by the fingerprint
+@code{fpr}. Without the optional arguments an encryption subkey is
+added. If any of the arguments are given a more specific subkey is
+added.
+
+@code{algo} may be any of the supported algorithms or curve names given
+in the format as used by key listings. To use the default algorithm
+the string ``default'' or ``-'' can be used. Supported algorithms are
+``rsa'', ``dsa'', ``elg'', ``ed25519'', ``cv25519'', and other ECC
+curves. For example the string ``rsa'' adds an RSA key with the
+default key length; a string ``rsa4096'' requests that the key length
+is 4096 bits.
+
+Depending on the given @code{algo} the subkey may either be an
+encryption subkey or a signing subkey. If an algorithm is capable of
+signing and encryption and such a subkey is desired, a @code{usage}
+string must be given. This string is either ``default'' or ``-'' to
+keep the default or a comma delimited list of keywords: ``sign'' for a
+signing subkey, ``auth'' for an authentication subkey, and ``encr''
+for an encryption subkey (``encrypt'' can be used as alias for
+``encr''). The valid combinations depend on the algorithm.
+
+The @code{expire} argument can be used to specify an expiration date
+for the subkey. Several formats are supported; commonly the ISO
+YYYY-MM-DD format is used. The values ``never'', ``none'', or ``-''
+can be used for no expiration date.
+
@item --gen-key
@opindex gen-key
Generate a new key pair using the current default parameters. This is
mode. See the manual section ``Unattended key generation'' on how
to use this.
+
@item --gen-revoke @code{name}
@opindex gen-revoke
Generate a revocation certificate for the complete key. To only revoke
Enable PKA lookups to verify sender addresses. Note that PKA is based
on DNS, and so enabling this option may disclose information on when
and what signatures are verified or to whom data is encrypted. This
- is similar to the "web bug" described for the auto-key-retrieve
- feature.
+ is similar to the "web bug" described for the @option{--auto-key-retrieve}
+ option.
@item pka-trust-increase
@opindex verify-options:pka-trust-increase
@item --exec-path @code{string}
@opindex exec-path
+@efindex PATH
Sets a list of directories to search for photo viewers and keyserver
helpers. If not provided, keyserver helpers use the compiled-in
-default directory, and photo viewers use the $PATH environment
+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.
@end table
-@item --keyid-format @code{short|0xshort|long|0xlong}
+@item --auto-key-retrieve
+@itemx --no-auto-key-retrieve
+@opindex auto-key-retrieve
+@opindex no-auto-key-retrieve
+This option enables the automatic retrieving of keys from a keyserver
+when verifying signatures made by keys that are not on the local
+keyring.
+
+If the method "wkd" is included in the list of methods given to
+@option{auto-key-locate}, the Signer's User ID is part of the
+signature, and the option @option{--disable-signer-uid} is not used,
+the "wkd" method may also be used to retrieve a key.
+
+Note that this option makes a "web bug" like behavior possible.
+Keyserver or Web Key Directory operators can see which keys you
+request, so by sending you a message signed by a brand new key (which
+you naturally will not have on your local keyring), the operator can
+tell both your IP address and the time when you verified the
+signature.
+
+@item --keyid-format @code{none|short|0xshort|long|0xlong}
@opindex keyid-format
-Select how to display key IDs. "short" is the traditional 8-character
-key ID. "long" is the more accurate (but less convenient)
-16-character key ID. Add an "0x" to either to include an "0x" at the
-beginning of the key ID, as in 0x99242560. Note that this option is
-ignored if the option --with-colons is used.
+Select how to display key IDs. "none" does not show the key ID at all
+but shows the fingerprint in a separate line. "short" is the
+traditional 8-character key ID. "long" is the more accurate (but less
+convenient) 16-character key ID. Add an "0x" to either to include an
+"0x" at the beginning of the key ID, as in 0x99242560. Note that this
+option is ignored if the option @option{--with-colons} is used.
@item --keyserver @code{name}
@opindex keyserver
used with HKP keyservers.
@item auto-key-retrieve
- This option enables the automatic retrieving of keys from a keyserver
- when verifying signatures made by keys that are not on the local
- keyring.
-
- Note that this option makes a "web bug" like behavior possible.
- Keyserver operators can see which keys you request, so by sending you
- a message signed by a brand new key (which you naturally will not have
- on your local keyring), the operator can tell both your IP address and
- the time when you verified the signature.
+ This is the same as the option @option{auto-key-retrieve}.
@item honor-keyserver-url
When using @option{--refresh-keys}, if the key in question has a preferred
refreshed. Thus this option is not enabled by default.
@item honor-pka-record
- If auto-key-retrieve is set, and the signature being verified has a
- PKA record, then use the PKA information to fetch the key. Defaults
- to "yes".
+ If @option{--auto-key-retrieve} is used, and the signature being
+ verified has a PKA record, then use the PKA information to fetch
+ the key. Defaults to "yes".
@item include-subkeys
When receiving a key, include subkeys as potential targets. Note that
@item --dirmngr-program @var{file}
@opindex dirmngr-program
Specify a dirmngr program to be used for keyserver access. The
-default value is @file{@value{BINDIR}/dirmngr}. This is only used as a
-fallback when the environment variable @code{DIRMNGR_INFO} is not set or
-a running dirmngr cannot be connected.
+default value is @file{@value{BINDIR}/dirmngr}.
@item --no-autostart
@opindex no-autostart
Same as the command @option{--fingerprint} but changes only the format
of the output and may be used together with another command.
+@item --with-subkey-fingerprint
+@opindex with-subkey-fingerprint
+If a fingerprint is printed for the primary key, this option forces
+printing of the fingerprint for all subkeys. This could also be
+achieved by using the @option{--with-fingerprint} twice but by using
+this option along with keyid-format "none" a compact fingerprint is
+printed.
+
@item --with-icao-spelling
@opindex with-icao-spelling
Print the ICAO spelling of the fingerprint in addition to the hex digits.
using this option, the encrypted message becomes vulnerable to a
message modification attack.
+@item --disable-signer-uid
+@opindex disable-signer-uid
+By default the user ID of the signing key is embedded in the data
+signature. As of now this is only done if the signing key has been
+specified with @option{local-user} using a mail address. This
+information can be helpful for verifier to locate the key; see
+option @option{--auto-key-retrieve}.
+
@item --personal-cipher-preferences @code{string}
@opindex personal-cipher-preferences
Set the list of personal cipher preferences to @code{string}. Use
@table @file
@item gpg.conf
- @cindex gpg.conf
+ @efindex gpg.conf
This is the standard configuration file read by @command{@gpgname} on
startup. It may contain any valid long option; the leading two dashes
may not be entered and the option may not be abbreviated. This default
@table @file
+ @item ~/.gnupg
+ @efindex ~/.gnupg
+ This is the default home directory which is used if neither the
+ environment variable @code{GNUPGHOME} nor the option
+ @option{--homedir} is given.
+
@item ~/.gnupg/pubring.gpg
+ @efindex pubring.gpg
The public keyring. You should backup this file.
@item ~/.gnupg/pubring.gpg.lock
The lock file for the public keyring.
@item ~/.gnupg/pubring.kbx
+ @efindex pubring.kbx
The public keyring using a different format. This file is sharred
with @command{gpgsm}. You should backup this file.
The lock file for @file{pubring.kbx}.
@item ~/.gnupg/secring.gpg
+ @efindex secring.gpg
A secret keyring as used by GnuPG versions before 2.1. It is not
used by GnuPG 2.1 and later.
+ @item ~/.gnupg/secring.gpg.lock
+ The lock file for the secret keyring.
+
@item ~/.gnupg/.gpg-v21-migrated
+ @efindex .gpg-v21-migrated
File indicating that a migration to GnuPG 2.1 has been done.
@item ~/.gnupg/trustdb.gpg
+ @efindex trustdb.gpg
The trust database. There is no need to backup this file; it is better
to backup the ownertrust values (@pxref{option --export-ownertrust}).
The lock file for the trust database.
@item ~/.gnupg/random_seed
+ @efindex random_seed
A file used to preserve the state of the internal random pool.
- @item ~/.gnupg/secring.gpg.lock
- The lock file for the secret keyring.
-
@item ~/.gnupg/openpgp-revocs.d/
+ @efindex openpgp-revocs.d
This is the directory where gpg stores pre-generated revocation
certificates. The file name corresponds to the OpenPGP fingerprint of
the respective key. It is suggested to backup those certificates and
this backup closed away.
@item @value{DATADIR}/options.skel
+ @efindex options.skel
The skeleton options file.
- @item @value{LIBDIR}/
- Default location for extensions.
-
@end table
@c man:.RE
@table @asis
@item HOME
+ @efindex HOME
Used to locate the default home directory.
@item GNUPGHOME
+ @efindex GNUPGHOME
If set directory used instead of "~/.gnupg".
@item GPG_AGENT_INFO
- This variable was used by GnuPG versions before 2.1
+ This variable is obsolete; it was used by GnuPG versions before 2.1.
@item PINENTRY_USER_DATA
+ @efindex PINENTRY_USER_DATA
This value is passed via gpg-agent to pinentry. It is useful to convey
extra information to a custom pinentry.
@item COLUMNS
@itemx LINES
+ @efindex COLUMNS
+ @efindex LINES
Used to size some displays to the full size of the screen.
-
@item LANGUAGE
+ @efindex LANGUAGE
Apart from its use by GNU, it is used in the W32 version to override the
language selection done through the Registry. If used and set to a
valid and available language name (@var{langid}), the file with the
@item --dirmngr-program @var{file}
@opindex dirmngr-program
Specify a dirmngr program to be used for @acronym{CRL} checks. The
-default value is @file{@value{BINDIR}/dirmngr}. This is only used as a
-fallback when the environment variable @code{DIRMNGR_INFO} is not set or
-a running dirmngr cannot be connected.
+default value is @file{@value{BINDIR}/dirmngr}.
@item --prefer-system-dirmngr
@opindex prefer-system-dirmngr
@table @file
@item gpgsm.conf
-@cindex gpgsm.conf
+@efindex gpgsm.conf
This is the standard configuration file read by @command{gpgsm} on
startup. It may contain any valid long option; the leading two dashes
may not be entered and the option may not be abbreviated. This default
@item policies.txt
-@cindex policies.txt
+@efindex policies.txt
This is a list of allowed CA policies. This file should list the
object identifiers of the policies line by line. Empty lines and
lines starting with a hash mark are ignored. Policies missing in this
@c man:.RE
@item qualified.txt
-@cindex qualified.txt
+@efindex qualified.txt
This is the list of root certificates used for qualified certificates.
They are defined as certificates capable of creating legally binding
signatures in the same way as handwritten signatures are. Comments
certificates, appropriate notices will be shown to indicate this fact.
@item help.txt
-@cindex help.txt
+@efindex help.txt
This is plain text file with a few help entries used with
@command{pinentry} as well as a large list of help items for
@command{gpg} and @command{gpgsm}. The standard file has English help
@item com-certs.pem
-@cindex com-certs.pem
+@efindex com-certs.pem
This file is a collection of common certificates used to populated a
newly created @file{pubring.kbx}. An administrator may replace this
file with a custom one. The format is a concatenation of PEM encoded
@table @file
@item pubring.kbx
-@cindex pubring.kbx
+@efindex pubring.kbx
This a database file storing the certificates as well as meta
information. For debugging purposes the tool @command{kbxutil} may be
used to show the internal structure of this file. You should backup
this file.
@item random_seed
-@cindex random_seed
+@efindex random_seed
This content of this file is used to maintain the internal state of the
random number generator across invocations. The same file is used by
other programs of this software too.
@item S.gpg-agent
-@cindex S.gpg-agent
+@efindex S.gpg-agent
If this file exists
@command{gpgsm} will first try to connect to this socket for
accessing @command{gpg-agent} before starting a new @command{gpg-agent}
that string.
@item display
+@efindex DISPLAY
Set the session environment variable @code{DISPLAY} is set to @var{value}.
@item ttyname
+@efindex GPG_TTY
Set the session environment variable @code{GPG_TTY} is set to @var{value}.
@item ttytype
+@efindex TERM
Set the session environment variable @code{TERM} is set to @var{value}.
@item lc-ctype
+@efindex LC_CTYPE
Set the session environment variable @code{LC_CTYPE} is set to @var{value}.
@item lc-messages
+@efindex LC_MESSAGES
Set the session environment variable @code{LC_MESSAGES} is set to @var{value}.
@item xauthority
+@efindex XAUTHORITY
Set the session environment variable @code{XAUTHORITY} is set to @var{value}.
@item pinentry-user-data
+@efindex PINENTRY_USER_DATA
Set the session environment variable @code{PINENTRY_USER_DATA} is set
to @var{value}.
@c This option is included at several places.
@item --homedir @var{dir}
@opindex homedir
+@efindex GNUPGHOME
+@efindex HKCU\Software\GNU\GnuPG:HomeDir
Set the name of the home directory to @var{dir}. If this option is not
used, the home directory defaults to @file{~/.gnupg}. It is only
recognized when given on the command line. It also overrides any home
application. In this case only this command line option is
considered, all other ways to set a home directory are ignored.
+@efindex gpgconf.ctl
To install GnuPG as a portable application under Windows, create an
empty file name @file{gpgconf.ctl} in the same directory as the tool
@file{gpgconf.exe}. The root of the installation is than that
@item --debug-assuan-log-cats @var{cats}
@opindex debug-assuan-log-cats
+@efindex ASSUAN_DEBUG
Changes the active Libassuan logging categories to @var{cats}. The
value for @var{cats} is an unsigned integer given in usual C-Syntax.
A value of of 0 switches to a default category. If this option is not
used the categories are taken from the environment variable
-@samp{ASSUAN_DEBUG}. Note that this option has only an effect if the
+@code{ASSUAN_DEBUG}. Note that this option has only an effect if the
Assuan debug flag has also been with the option @option{--debug}. For
a list of categories see the Libassuan manual.
to fix first. The major problem areas are:
@itemize
-@item
-For logging to sockets and other internal operations the
-@code{fopencookie} function (@code{funopen} under *BSD) is used. This
-is a very convenient function which makes it possible to create outputs in
-a structures and easy maintainable way. The drawback however is that
-most proprietary OSes don't support this function. At g10@tie{}Code we
-have looked into several ways on how to overcome this limitation but no
-sufficiently easy and maintainable way has been found. Porting
-@emph{glibc} to a general POSIX system is of course an option and would
-make writing portable software much easier; this it has not yet been
-done and the system administrator would need to cope with the GNU
-specific admin things in addition to the generic ones of his system.
-
-We have now settled to use explicit stdio wrappers with a functionality
-similar to funopen. Although the code for this has already been written
-(@emph{libestream}), we have not yet changed GnuPG to use it.
-
-This means that on systems not supporting either @code{funopen} or
-@code{fopencookie}, logging to a socket won't work, prompts are not
-formatted as pretty as they should be and @command{gpgsm}'s
-@code{LISTKEYS} Assuan command does not work.
-
@item
We are planning to use file descriptor passing for interprocess
communication. This will allow us save a lot of resources and improve
not yet supported.
@end itemize
-
-
-
-
-
-
ignored. Note that as of now reload and kill have the same effect for
scdaemon.
+@item --create-socketdir
+@opindex create-socketdir
+Create a directory for sockets below /run/user or /var/run/user. This
+is command is only required if a non default home directory is used
+and the /run based sockets shall be used. For the default home
+directory GnUPG creates a directory on the fly.
+
+@item --remove-socketdir
+@opindex remove-socketdir
+Remove a directory created with command @option{--create-socketdir}.
+
@end table
{ "emph", 0, "\\fI", "\\fR" },
{ "w", 1 },
{ "c", 5 },
+ { "efindex", 1 },
{ "opindex", 1 },
{ "cpindex", 1 },
{ "cindex", 1 },
endif
if USE_TOFU
-tofu_source = tofu.h tofu.c sqlite.c sqlite.h
+tofu_source = tofu.h tofu.c gpgsql.c gpgsql.h
else
tofu_source =
endif
if (!a)
return 0;
+ if (!gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
+ return 0; /* e.g. due to generating a key with wrong usage. */
p = gcry_mpi_get_opaque ( a, &n);
if (!p)
return 0; /* For example due to a read error in
}
else
{
- write_header2( out, ctb, uid->len, 2 );
+ write_header2( out, ctb, uid->len, 0 );
rc = iobuf_write( out, uid->name, uid->len );
}
return rc;
{
const byte *p;
size_t len;
- int seq=0,crit;
- struct notation *list=NULL;
+ int seq = 0;
+ int crit;
+ notation_t list = NULL;
/* See RFC 4880, 5.2.3.16 for the format of notation data. In
short, a notation has:
n->value=xmalloc(n2+1);
memcpy(n->value,&p[8+n1],n2);
n->value[n2]='\0';
+ n->flags.human = 1;
}
else
/* Binary data. */
{
rc = start_new_gpg_agent (&agent_ctx,
GPG_ERR_SOURCE_DEFAULT,
- opt.homedir,
opt.agent_program,
opt.lc_ctype, opt.lc_messages,
opt.session_env,
\f
+struct keyinfo_data_parm_s
+{
+ char *serialno;
+ int cleartext;
+};
+
+
static gpg_error_t
keyinfo_status_cb (void *opaque, const char *line)
{
- char **serialno = opaque;
- const char *s, *s2;
+ struct keyinfo_data_parm_s *data = opaque;
+ int is_smartcard;
+ char *s;
- if ((s = has_leading_keyword (line, "KEYINFO")) && !*serialno)
+ if ((s = has_leading_keyword (line, "KEYINFO")) && data)
{
- s = strchr (s, ' ');
- if (s && s[1] == 'T' && s[2] == ' ' && s[3])
+ /* Parse the arguments:
+ * 0 1 2 3 4 5
+ * <keygrip> <type> <serialno> <idstr> <cached> <protection>
+ */
+ char *fields[6];
+
+ if (split_fields (s, fields, DIM (fields)) == 6)
{
- s += 3;
- s2 = strchr (s, ' ');
- if ( s2 > s )
- {
- *serialno = xtrymalloc ((s2 - s)+1);
- if (*serialno)
- {
- memcpy (*serialno, s, s2 - s);
- (*serialno)[s2 - s] = 0;
- }
- }
+ is_smartcard = (fields[1][0] == 'T');
+ if (is_smartcard && !data->serialno && strcmp (fields[2], "-"))
+ data->serialno = xtrystrdup (fields[2]);
+ /* 'P' for protected, 'C' for clear */
+ data->cleartext = (fields[5][0] == 'C');
}
}
return 0;
/* Return the serial number for a secret key. If the returned serial
number is NULL, the key is not stored on a smartcard. Caller needs
- to free R_SERIALNO. */
+ to free R_SERIALNO.
+
+ if r_cleartext is not NULL, the referenced int will be set to 1 if
+ the agent's copy of the key is stored in the clear, or 0 otherwise
+*/
gpg_error_t
-agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
+agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
+ char **r_serialno, int *r_cleartext)
{
gpg_error_t err;
char line[ASSUAN_LINELENGTH];
- char *serialno = NULL;
+ struct keyinfo_data_parm_s keyinfo;
+
+ memset (&keyinfo, 0,sizeof keyinfo);
*r_serialno = NULL;
line[DIM(line)-1] = 0;
err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
- keyinfo_status_cb, &serialno);
- if (!err && serialno)
+ keyinfo_status_cb, &keyinfo);
+ if (!err && keyinfo.serialno)
{
/* Sanity check for bad characters. */
- if (strpbrk (serialno, ":\n\r"))
+ if (strpbrk (keyinfo.serialno, ":\n\r"))
err = GPG_ERR_INV_VALUE;
}
if (err)
- xfree (serialno);
+ xfree (keyinfo.serialno);
else
- *r_serialno = serialno;
+ {
+ *r_serialno = keyinfo.serialno;
+ if (r_cleartext)
+ *r_cleartext = keyinfo.cleartext;
+ }
return err;
}
PASSPHRASE is not NULL the agent is requested to protect the key
with that passphrase instead of asking for one. */
gpg_error_t
-agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
+agent_genkey (ctrl_t ctrl, char **cache_nonce_addr, char **passwd_nonce_addr,
const char *keyparms, int no_protection,
const char *passphrase, gcry_sexp_t *r_pubkey)
{
return err;
dfltparm.ctx = agent_ctx;
- err = assuan_transact (agent_ctx, "RESET",
- NULL, NULL, NULL, NULL, NULL, NULL);
- if (err)
- return err;
+ if (passwd_nonce_addr && *passwd_nonce_addr)
+ ; /* A RESET would flush the passwd nonce cache. */
+ else
+ {
+ err = assuan_transact (agent_ctx, "RESET",
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ if (err)
+ return err;
+ }
init_membuf (&data, 1024);
gk_parm.dflt = &dfltparm;
gk_parm.keyparms = keyparms;
gk_parm.passphrase = passphrase;
- snprintf (line, sizeof line, "GENKEY%s%s%s",
+ snprintf (line, sizeof line, "GENKEY%s%s%s%s%s",
no_protection? " --no-protection" :
passphrase ? " --inq-passwd" :
/* */ "",
+ passwd_nonce_addr && *passwd_nonce_addr? " --passwd-nonce=":"",
+ passwd_nonce_addr && *passwd_nonce_addr? *passwd_nonce_addr:"",
cache_nonce_addr && *cache_nonce_addr? " ":"",
cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"");
cn_parm.cache_nonce_addr = cache_nonce_addr;
\f
/* Receive a secret key from the agent. HEXKEYGRIP is the hexified
keygrip, DESC a prompt to be displayed with the agent's passphrase
- question (needs to be plus+percent escaped). If CACHE_NONCE_ADDR
- is not NULL the agent is advised to first try a passphrase
- associated with that nonce. On success the key is stored as a
- canonical S-expression at R_RESULT and R_RESULTLEN. */
+ question (needs to be plus+percent escaped). if OPENPGP_PROTECTED
+ is not zero, ensure that the key material is returned in RFC
+ 4880-compatible passphrased-protected form. If CACHE_NONCE_ADDR is
+ not NULL the agent is advised to first try a passphrase associated
+ with that nonce. On success the key is stored as a canonical
+ S-expression at R_RESULT and R_RESULTLEN. */
gpg_error_t
agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
- char **cache_nonce_addr,
+ int openpgp_protected, char **cache_nonce_addr,
unsigned char **r_result, size_t *r_resultlen)
{
gpg_error_t err;
return err;
}
- snprintf (line, DIM(line)-1, "EXPORT_KEY --openpgp %s%s %s",
+ snprintf (line, DIM(line)-1, "EXPORT_KEY %s%s%s %s",
+ openpgp_protected ? "--openpgp ":"",
cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"",
cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"",
hexkeygrip);
\f
/* Ask the agent to delete the key identified by HEXKEYGRIP. If DESC
is not NULL, display DESC instead of the default description
- message. */
+ message. If FORCE is true the agent is advised not to ask for
+ confirmation. */
gpg_error_t
-agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc)
+agent_delete_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
+ int force)
{
gpg_error_t err;
char line[ASSUAN_LINELENGTH];
return err;
}
- snprintf (line, DIM(line)-1, "DELETE_KEY %s", hexkeygrip);
+ snprintf (line, DIM(line)-1, "DELETE_KEY%s %s",
+ force? " --force":"", hexkeygrip);
err = assuan_transact (agent_ctx, line, NULL, NULL,
default_inq_cb, &dfltparm,
NULL, NULL);
\f
/* Ask the agent to change the passphrase of the key identified by
- HEXKEYGRIP. If DESC is not NULL, display DESC instead of the
- default description message. If CACHE_NONCE_ADDR is not NULL the
- agent is advised to first try a passphrase associated with that
- nonce. If PASSWD_NONCE_ADDR is not NULL the agent will try to use
- the passphrase associated with that nonce. */
+ * HEXKEYGRIP. If DESC is not NULL, display DESC instead of the
+ * default description message. If CACHE_NONCE_ADDR is not NULL the
+ * agent is advised to first try a passphrase associated with that
+ * nonce. If PASSWD_NONCE_ADDR is not NULL the agent will try to use
+ * the passphrase associated with that nonce for the new passphrase.
+ * If VERIFY is true the passphrase is only verified. */
gpg_error_t
-agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
+agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc, int verify,
char **cache_nonce_addr, char **passwd_nonce_addr)
{
gpg_error_t err;
if (!hexkeygrip || strlen (hexkeygrip) != 40)
return gpg_error (GPG_ERR_INV_VALUE);
-
if (desc)
{
snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
return err;
}
- snprintf (line, DIM(line)-1, "PASSWD %s%s %s%s %s",
- cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"",
- cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"",
- passwd_nonce_addr && *passwd_nonce_addr? "--passwd-nonce=":"",
- passwd_nonce_addr && *passwd_nonce_addr? *passwd_nonce_addr:"",
- hexkeygrip);
+ if (verify)
+ snprintf (line, DIM(line)-1, "PASSWD %s%s --verify %s",
+ cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"",
+ cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"",
+ hexkeygrip);
+ else
+ snprintf (line, DIM(line)-1, "PASSWD %s%s %s%s %s",
+ cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"",
+ cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"",
+ passwd_nonce_addr && *passwd_nonce_addr? "--passwd-nonce=":"",
+ passwd_nonce_addr && *passwd_nonce_addr? *passwd_nonce_addr:"",
+ hexkeygrip);
cn_parm.cache_nonce_addr = cache_nonce_addr;
cn_parm.passwd_nonce_addr = passwd_nonce_addr;
err = assuan_transact (agent_ctx, line, NULL, NULL,
return err;
}
+
/* Return the version reported by gpg-agent. */
gpg_error_t
agent_get_version (ctrl_t ctrl, char **r_version)
/* Return infos about the secret key with HEXKEYGRIP. */
gpg_error_t agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
- char **r_serialno);
+ char **r_serialno, int *r_cleartext);
/* Generate a new key. */
-gpg_error_t agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
+gpg_error_t agent_genkey (ctrl_t ctrl,
+ char **cache_nonce_addr, char **passwd_nonce_addr,
const char *keyparms, int no_protection,
const char *passphrase,
gcry_sexp_t *r_pubkey);
/* Receive a key from the agent. */
gpg_error_t agent_export_key (ctrl_t ctrl, const char *keygrip,
- const char *desc, char **cache_nonce_addr,
+ const char *desc, int openpgp_protected,
+ char **cache_nonce_addr,
unsigned char **r_result, size_t *r_resultlen);
/* Delete a key from the agent. */
gpg_error_t agent_delete_key (ctrl_t ctrl, const char *hexkeygrip,
- const char *desc);
+ const char *desc, int force);
/* Change the passphrase of a key. */
gpg_error_t agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
+ int verify,
char **cache_nonce_addr, char **passwd_nonce_addr);
/* Get the version reported by gpg-agent. */
gpg_error_t agent_get_version (ctrl_t ctrl, char **r_version);
*r_ctx = NULL;
err = start_new_dirmngr (&ctx,
GPG_ERR_SOURCE_DEFAULT,
- opt.homedir,
opt.dirmngr_program,
opt.autostart, opt.verbose, DBG_IPC,
NULL /*gpg_status2*/, ctrl);
prompt = gpg_format_keydesc (node->pkt->pkt.public_key,
FORMAT_KEYDESC_DELKEY, 1);
err = hexkeygrip_from_pk (node->pkt->pkt.public_key, &hexgrip);
+ /* NB: We require --yes to advise the agent not to
+ * request a confirmation. The rationale for this extra
+ * pre-caution is that since 2.1 the secret key may also
+ * be used for other protocols and thus deleting it from
+ * the gpg would also delete the key for other tools. */
if (!err)
- err = agent_delete_key (NULL, hexgrip, prompt);
+ err = agent_delete_key (NULL, hexgrip, prompt,
+ opt.answer_yes);
xfree (prompt);
xfree (hexgrip);
if (err)
}
+/* Return an error if the key represented by the S-expression S_KEY
+ * and the OpenPGP key represented by PK do not use the same curve. */
+static gpg_error_t
+match_curve_skey_pk (gcry_sexp_t s_key, PKT_public_key *pk)
+{
+ gcry_sexp_t curve = NULL;
+ gcry_sexp_t flags = NULL;
+ char *curve_str = NULL;
+ char *flag;
+ const char *oidstr = NULL;
+ gcry_mpi_t curve_as_mpi = NULL;
+ gpg_error_t err;
+ int is_eddsa = 0;
+ int idx = 0;
+
+ if (!(pk->pubkey_algo==PUBKEY_ALGO_ECDH
+ || pk->pubkey_algo==PUBKEY_ALGO_ECDSA
+ || pk->pubkey_algo==PUBKEY_ALGO_EDDSA))
+ return gpg_error (GPG_ERR_PUBKEY_ALGO);
+
+ curve = gcry_sexp_find_token (s_key, "curve", 0);
+ if (!curve)
+ {
+ log_error ("no reported curve\n");
+ return gpg_error (GPG_ERR_UNKNOWN_CURVE);
+ }
+ curve_str = gcry_sexp_nth_string (curve, 1);
+ gcry_sexp_release (curve); curve = NULL;
+ if (!curve_str)
+ {
+ log_error ("no curve name\n");
+ return gpg_error (GPG_ERR_UNKNOWN_CURVE);
+ }
+ oidstr = openpgp_curve_to_oid (curve_str, NULL);
+ if (!oidstr)
+ {
+ log_error ("no OID known for curve '%s'\n", curve_str);
+ xfree (curve_str);
+ return gpg_error (GPG_ERR_UNKNOWN_CURVE);
+ }
+ xfree (curve_str);
+ err = openpgp_oid_from_str (oidstr, &curve_as_mpi);
+ if (err)
+ return err;
+ if (gcry_mpi_cmp (pk->pkey[0], curve_as_mpi))
+ {
+ log_error ("curves do not match\n");
+ gcry_mpi_release (curve_as_mpi);
+ return gpg_error (GPG_ERR_INV_CURVE);
+ }
+ gcry_mpi_release (curve_as_mpi);
+ flags = gcry_sexp_find_token (s_key, "flags", 0);
+ if (flags)
+ {
+ for (idx = 1; idx < gcry_sexp_length (flags); idx++)
+ {
+ flag = gcry_sexp_nth_string (flags, idx);
+ if (flag && (strcmp ("eddsa", flag) == 0))
+ is_eddsa = 1;
+ gcry_free (flag);
+ }
+ }
+ if (is_eddsa != (pk->pubkey_algo == PUBKEY_ALGO_EDDSA))
+ {
+ log_error ("disagreement about EdDSA\n");
+ err = gpg_error (GPG_ERR_INV_CURVE);
+ }
+
+ return err;
+}
+
+
/* Return a canonicalized public key algoithms. This is used to
compare different flavors of algorithms (e.g. ELG and ELG_E are
considered the same). */
}
+/* Take a cleartext dump of a secret key in PK and change the
+ * parameter array in PK to include the secret parameters. */
+static gpg_error_t
+cleartext_secret_key_to_openpgp (gcry_sexp_t s_key, PKT_public_key *pk)
+{
+ gpg_error_t err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ gcry_sexp_t top_list;
+ gcry_sexp_t key = NULL;
+ char *key_type = NULL;
+ enum gcry_pk_algos pk_algo;
+ struct seckey_info *ski;
+ int idx, sec_start;
+ gcry_mpi_t pub_params[10] = { NULL };
+
+ /* we look for a private-key, then the first element in it tells us
+ the type */
+ top_list = gcry_sexp_find_token (s_key, "private-key", 0);
+ if (!top_list)
+ goto bad_seckey;
+ if (gcry_sexp_length(top_list) != 2)
+ goto bad_seckey;
+ key = gcry_sexp_nth (top_list, 1);
+ if (!key)
+ goto bad_seckey;
+ key_type = gcry_sexp_nth_string(key, 0);
+ pk_algo = gcry_pk_map_name (key_type);
+
+ log_assert (!pk->seckey_info);
+
+ pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
+ if (!ski)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+
+ switch (canon_pk_algo (pk_algo))
+ {
+ case GCRY_PK_RSA:
+ if (!is_RSA (pk->pubkey_algo))
+ goto bad_pubkey_algo;
+ err = gcry_sexp_extract_param (key, NULL, "ne",
+ &pub_params[0],
+ &pub_params[1],
+ NULL);
+ for (idx=0; idx < 2 && !err; idx++)
+ if (gcry_mpi_cmp(pk->pkey[idx], pub_params[idx]))
+ err = gpg_error (GPG_ERR_BAD_PUBKEY);
+ if (!err)
+ {
+ for (idx = 2; idx < 6 && !err; idx++)
+ {
+ gcry_mpi_release (pk->pkey[idx]);
+ pk->pkey[idx] = NULL;
+ }
+ err = gcry_sexp_extract_param (key, NULL, "dpqu",
+ &pk->pkey[2],
+ &pk->pkey[3],
+ &pk->pkey[4],
+ &pk->pkey[5],
+ NULL);
+ }
+ if (!err)
+ {
+ for (idx = 2; idx < 6; idx++)
+ ski->csum += checksum_mpi (pk->pkey[idx]);
+ }
+ break;
+
+ case GCRY_PK_DSA:
+ if (!is_DSA (pk->pubkey_algo))
+ goto bad_pubkey_algo;
+ err = gcry_sexp_extract_param (key, NULL, "pqgy",
+ &pub_params[0],
+ &pub_params[1],
+ &pub_params[2],
+ &pub_params[3],
+ NULL);
+ for (idx=0; idx < 4 && !err; idx++)
+ if (gcry_mpi_cmp(pk->pkey[idx], pub_params[idx]))
+ err = gpg_error (GPG_ERR_BAD_PUBKEY);
+ if (!err)
+ {
+ gcry_mpi_release (pk->pkey[4]);
+ pk->pkey[4] = NULL;
+ err = gcry_sexp_extract_param (key, NULL, "x",
+ &pk->pkey[4],
+ NULL);
+ }
+ if (!err)
+ ski->csum += checksum_mpi (pk->pkey[4]);
+ break;
+
+ case GCRY_PK_ELG:
+ if (!is_ELGAMAL (pk->pubkey_algo))
+ goto bad_pubkey_algo;
+ err = gcry_sexp_extract_param (key, NULL, "pgy",
+ &pub_params[0],
+ &pub_params[1],
+ &pub_params[2],
+ NULL);
+ for (idx=0; idx < 3 && !err; idx++)
+ if (gcry_mpi_cmp(pk->pkey[idx], pub_params[idx]))
+ err = gpg_error (GPG_ERR_BAD_PUBKEY);
+ if (!err)
+ {
+ gcry_mpi_release (pk->pkey[3]);
+ pk->pkey[3] = NULL;
+ err = gcry_sexp_extract_param (key, NULL, "x",
+ &pk->pkey[3],
+ NULL);
+ }
+ if (!err)
+ ski->csum += checksum_mpi (pk->pkey[3]);
+ break;
+
+ case GCRY_PK_ECC:
+ err = match_curve_skey_pk (key, pk);
+ if (err)
+ goto leave;
+ if (!err)
+ err = gcry_sexp_extract_param (key, NULL, "q",
+ &pub_params[0],
+ NULL);
+ if (!err && (gcry_mpi_cmp(pk->pkey[1], pub_params[0])))
+ err = gpg_error (GPG_ERR_BAD_PUBKEY);
+
+ sec_start = 2;
+ if (pk->pubkey_algo == PUBKEY_ALGO_ECDH)
+ sec_start += 1;
+ if (!err)
+ {
+ gcry_mpi_release (pk->pkey[sec_start]);
+ pk->pkey[sec_start] = NULL;
+ err = gcry_sexp_extract_param (key, NULL, "d",
+ &pk->pkey[sec_start],
+ NULL);
+ }
+
+ if (!err)
+ ski->csum += checksum_mpi (pk->pkey[sec_start]);
+ break;
+
+ default:
+ pk->seckey_info = NULL;
+ xfree (ski);
+ err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ break;
+ }
+
+ leave:
+ gcry_sexp_release (top_list);
+ gcry_sexp_release (key);
+ gcry_free (key_type);
+
+ for (idx=0; idx < DIM(pub_params); idx++)
+ gcry_mpi_release (pub_params[idx]);
+ return err;
+
+ bad_pubkey_algo:
+ err = gpg_error (GPG_ERR_PUBKEY_ALGO);
+ goto leave;
+
+ bad_seckey:
+ err = gpg_error (GPG_ERR_BAD_SECKEY);
+ goto leave;
+}
+
+
/* Use the key transfer format given in S_PGP to create the secinfo
structure in PK and change the parameter array in PK to include the
secret parameters. */
*
* Since the key data from agant is encrypted, decrypt it by CIPHERHD.
* Then, parse the decrypted key data in transfer format, and put
- * secret papameters into PK.
+ * secret parameters into PK.
+ *
+ * If CLEARTEXT is 0, store the secret key material
+ * passphrase-protected. Otherwise, store secret key material in the
+ * clear.
*
* CACHE_NONCE_ADDR is used to share nonce for multple key retrievals.
*/
gpg_error_t
receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
+ int cleartext,
char **cache_nonce_addr, const char *hexgrip,
PKT_public_key *pk)
{
log_info ("key %s: asking agent for the secret parts\n", hexgrip);
prompt = gpg_format_keydesc (pk, FORMAT_KEYDESC_EXPORT,1);
- err = agent_export_key (ctrl, hexgrip, prompt, cache_nonce_addr,
+ err = agent_export_key (ctrl, hexgrip, prompt, !cleartext, cache_nonce_addr,
&wrappedkey, &wrappedkeylen);
xfree (prompt);
err = gcry_sexp_sscan (&s_skey, NULL, key, realkeylen);
if (!err)
{
- err = transfer_format_to_openpgp (s_skey, pk);
+ if (cleartext)
+ err = cleartext_secret_key_to_openpgp (s_skey, pk);
+ else
+ err = transfer_format_to_openpgp (s_skey, pk);
gcry_sexp_release (s_skey);
}
gcry_cipher_hd_t cipherhd = NULL;
char *cache_nonce = NULL;
struct export_stats_s dummystats;
+ int cleartext = 0;
if (!stats)
stats = &dummystats;
serialno = NULL;
}
else
- err = agent_get_keyinfo (ctrl, hexgrip, &serialno);
+ err = agent_get_keyinfo (ctrl, hexgrip, &serialno, &cleartext);
if ((!err && serialno)
&& secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
}
else if (!err)
{
- err = receive_seckey_from_agent (ctrl, cipherhd, &cache_nonce,
+ err = receive_seckey_from_agent (ctrl, cipherhd,
+ cleartext, &cache_nonce,
hexgrip, pk);
if (err)
{
xfree (sig->pka_info->uri);
xfree (sig->pka_info);
}
+ xfree (sig->signers_uid);
xfree(sig);
}
d->pka_info = s->pka_info? cp_pka_info (s->pka_info) : NULL;
d->hashed = cp_subpktarea (s->hashed);
d->unhashed = cp_subpktarea (s->unhashed);
+ if (s->signers_uid)
+ d->signers_uid = xstrdup (s->signers_uid);
if(s->numrevkeys)
{
d->revkey=NULL;
#include "call-agent.h"
#include "host2net.h"
#include "mbox-util.h"
+#include "status.h"
#define MAX_PK_CACHE_ENTRIES PK_UID_CACHE_SIZE
#define MAX_UID_CACHE_ENTRIES PK_UID_CACHE_SIZE
#error We need the cache for key creation
#endif
+/* Flags values returned by the lookup code. Note that the values are
+ * directly used by the KEY_CONSIDERED status line. */
+#define LOOKUP_NOT_SELECTED (1<<0)
+#define LOOKUP_ALL_SUBKEYS_EXPIRED (1<<1) /* or revoked */
+
+
+/* A context object used by the lookup functions. */
struct getkey_ctx_s
{
/* Part of the search criteria: whether the search is an exact
\f
/* See whether the key satisfies any additional requirements specified
- in CTX. If so, return 1 and set CTX->FOUND_KEY to an appropriate
- key or subkey. Otherwise, return 0 if there was no appropriate
- key.
-
- In case the primary key is not required, select a suitable subkey.
- We need the primary key if PUBKEY_USAGE_CERT is set in
- CTX->REQ_USAGE or we are in PGP6 or PGP7 mode and PUBKEY_USAGE_SIG
- is set in CTX->REQ_USAGE.
-
- If any of PUBKEY_USAGE_SIG, PUBKEY_USAGE_ENC and PUBKEY_USAGE_CERT
- are set in CTX->REQ_USAGE, we filter by the key's function.
- Concretely, if PUBKEY_USAGE_SIG and PUBKEY_USAGE_CERT are set, then
- we only return a key if it is (at least) either a signing or a
- certification key.
-
- If CTX->REQ_USAGE is set, then we reject any keys that are not good
- (i.e., valid, not revoked, not expired, etc.). This allows the
- getkey functions to be used for plain key listings.
-
- Sets the matched key's user id field (pk->user_id) to the user id
- that matched the low-level search criteria or NULL.
-
-
- This function needs to handle several different cases:
-
- 1. No requested usage and no primary key requested
- Examples for this case are that we have a keyID to be used
- for decrytion or verification.
- 2. No usage but primary key requested
- This is the case for all functions which work on an
- entire keyblock, e.g. for editing or listing
- 3. Usage and primary key requested
- FXME
- 4. Usage but no primary key requested
- FIXME
-
+ * in CTX. If so, return 1 and set CTX->FOUND_KEY to an appropriate
+ * key or subkey. Otherwise, return 0 if there was no appropriate
+ * key.
+ *
+ * In case the primary key is not required, select a suitable subkey.
+ * We need the primary key if PUBKEY_USAGE_CERT is set in
+ * CTX->REQ_USAGE or we are in PGP6 or PGP7 mode and PUBKEY_USAGE_SIG
+ * is set in CTX->REQ_USAGE.
+ *
+ * If any of PUBKEY_USAGE_SIG, PUBKEY_USAGE_ENC and PUBKEY_USAGE_CERT
+ * are set in CTX->REQ_USAGE, we filter by the key's function.
+ * Concretely, if PUBKEY_USAGE_SIG and PUBKEY_USAGE_CERT are set, then
+ * we only return a key if it is (at least) either a signing or a
+ * certification key.
+ *
+ * If CTX->REQ_USAGE is set, then we reject any keys that are not good
+ * (i.e., valid, not revoked, not expired, etc.). This allows the
+ * getkey functions to be used for plain key listings.
+ *
+ * Sets the matched key's user id field (pk->user_id) to the user id
+ * that matched the low-level search criteria or NULL. If R_FLAGS is
+ * not NULL set certain flags for more detailed error reporting. Used
+ * flags are:
+ * - LOOKUP_ALL_SUBKEYS_EXPIRED :: All Subkeys are expired or have
+ * been revoked.
+ *
+ * This function needs to handle several different cases:
+ *
+ * 1. No requested usage and no primary key requested
+ * Examples for this case are that we have a keyID to be used
+ * for decrytion or verification.
+ * 2. No usage but primary key requested
+ * This is the case for all functions which work on an
+ * entire keyblock, e.g. for editing or listing
+ * 3. Usage and primary key requested
+ * FIXME
+ * 4. Usage but no primary key requested
+ * FIXME
+ *
*/
-static KBNODE
-finish_lookup (GETKEY_CTX ctx, KBNODE keyblock)
+static kbnode_t
+finish_lookup (getkey_ctx_t ctx, kbnode_t keyblock, unsigned int *r_flags)
{
- KBNODE k;
+ kbnode_t k;
/* If CTX->EXACT is set, the key or subkey that actually matched the
low-level search criteria. */
- KBNODE foundk = NULL;
+ kbnode_t foundk = NULL;
/* The user id (if any) that matched the low-level search criteria. */
PKT_user_id *foundu = NULL;
if signing data while --pgp6 or --pgp7 is on since pgp 6 and 7
do not understand signatures made by a signing subkey. PGP 8
does. */
- int req_prim = (ctx->req_usage & PUBKEY_USAGE_CERT) ||
- ((PGP6 || PGP7) && (ctx->req_usage & PUBKEY_USAGE_SIG));
+ int req_prim = ((ctx->req_usage & PUBKEY_USAGE_CERT)
+ || ((PGP6 || PGP7) && (ctx->req_usage & PUBKEY_USAGE_SIG)));
u32 curtime = make_timestamp ();
u32 latest_date;
- KBNODE latest_key;
+ kbnode_t latest_key;
PKT_public_key *pk;
-
log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
+ if (r_flags)
+ *r_flags = 0;
+
+ /* For an exact match mark the primary or subkey that matched the
+ low-level search criteria. */
if (ctx->exact)
- /* Get the key or subkey that matched the low-level search
- criteria. */
{
for (k = keyblock; k; k = k->next)
{
latest_date = 0;
latest_key = NULL;
- /* Set latest_key to the latest (the one with the most recent
- timestamp) good (valid, not revoked, not expired, etc.) subkey.
-
- Don't bother if we are only looking for a primary key or we need
- an exact match and the exact match is not a subkey. */
+ /* Set LATEST_KEY to the latest (the one with the most recent
+ * timestamp) good (valid, not revoked, not expired, etc.) subkey.
+ *
+ * Don't bother if we are only looking for a primary key or we need
+ * an exact match and the exact match is not a subkey. */
if (req_prim || (foundk && foundk->pkt->pkttype != PKT_PUBLIC_SUBKEY))
;
else
{
- KBNODE nextk;
+ kbnode_t nextk;
+ int n_subkeys = 0;
+ int n_revoked_or_expired = 0;
/* Either start a loop or check just this one subkey. */
for (k = foundk ? foundk : keyblock; k; k = nextk)
{
if (foundk)
- /* If FOUNDK is not NULL, then only consider that exact
- key, i.e., don't iterate. */
- nextk = NULL;
+ {
+ /* If FOUNDK is not NULL, then only consider that exact
+ key, i.e., don't iterate. */
+ nextk = NULL;
+ }
else
nextk = k->next;
if (DBG_LOOKUP)
log_debug ("\tchecking subkey %08lX\n",
(ulong) keyid_from_pk (pk, NULL));
+
if (!pk->flags.valid)
{
if (DBG_LOOKUP)
log_debug ("\tsubkey not valid\n");
continue;
}
+ if (!((pk->pubkey_usage & USAGE_MASK) & req_usage))
+ {
+ if (DBG_LOOKUP)
+ log_debug ("\tusage does not match: want=%x have=%x\n",
+ req_usage, pk->pubkey_usage);
+ continue;
+ }
+
+ n_subkeys++;
if (pk->flags.revoked)
{
if (DBG_LOOKUP)
log_debug ("\tsubkey has been revoked\n");
+ n_revoked_or_expired++;
continue;
}
if (pk->has_expired)
{
if (DBG_LOOKUP)
log_debug ("\tsubkey has expired\n");
+ n_revoked_or_expired++;
continue;
-
}
if (pk->timestamp > curtime && !opt.ignore_valid_from)
{
continue;
}
- if (!((pk->pubkey_usage & USAGE_MASK) & req_usage))
- {
- if (DBG_LOOKUP)
- log_debug ("\tusage does not match: want=%x have=%x\n",
- req_usage, pk->pubkey_usage);
- continue;
- }
-
if (DBG_LOOKUP)
log_debug ("\tsubkey might be fine\n");
/* In case a key has a timestamp of 0 set, we make sure
latest_key = k;
}
}
+ if (n_subkeys == n_revoked_or_expired && r_flags)
+ *r_flags |= LOOKUP_ALL_SUBKEYS_EXPIRED;
}
/* Check if the primary key is ok (valid, not revoke, not expire,
- matches requested usage) if:
-
- - we didn't find an appropriate subkey and we're not doing an
- exact search,
-
- - we're doing an exact match and the exact match was the
- primary key, or,
-
- - we're just considering the primary key. */
+ * matches requested usage) if:
+ *
+ * - we didn't find an appropriate subkey and we're not doing an
+ * exact search,
+ *
+ * - we're doing an exact match and the exact match was the
+ * primary key, or,
+ *
+ * - we're just considering the primary key. */
if ((!latest_key && !ctx->exact) || foundk == keyblock || req_prim)
{
if (DBG_LOOKUP && !foundk && !req_prim)
if (DBG_LOOKUP)
log_debug ("\tprimary key not valid\n");
}
+ else if (!((pk->pubkey_usage & USAGE_MASK) & req_usage))
+ {
+ if (DBG_LOOKUP)
+ log_debug ("\tprimary key usage does not match: "
+ "want=%x have=%x\n", req_usage, pk->pubkey_usage);
+ }
else if (pk->flags.revoked)
{
if (DBG_LOOKUP)
if (DBG_LOOKUP)
log_debug ("\tprimary key has expired\n");
}
- else if (!((pk->pubkey_usage & USAGE_MASK) & req_usage))
- {
- if (DBG_LOOKUP)
- log_debug ("\tprimary key usage does not match: "
- "want=%x have=%x\n", req_usage, pk->pubkey_usage);
- }
else /* Okay. */
{
if (DBG_LOOKUP)
}
+/* Print a KEY_CONSIDERED status line. */
+static void
+print_status_key_considered (kbnode_t keyblock, unsigned int flags)
+{
+ char hexfpr[2*MAX_FINGERPRINT_LEN + 1];
+ kbnode_t node;
+ char flagbuf[20];
+
+ if (!is_status_enabled ())
+ return;
+
+ for (node=keyblock; node; node = node->next)
+ if (node->pkt->pkttype == PKT_PUBLIC_KEY
+ || node->pkt->pkttype == PKT_SECRET_KEY)
+ break;
+ if (!node)
+ {
+ log_error ("%s: keyblock w/o primary key\n", __func__);
+ return;
+ }
+
+ hexfingerprint (node->pkt->pkt.public_key, hexfpr, sizeof hexfpr);
+ snprintf (flagbuf, sizeof flagbuf, " %u", flags);
+ write_status_strings (STATUS_KEY_CONSIDERED, hexfpr, flagbuf, NULL);
+}
+
+
+
/* A high-level function to lookup keys.
This function builds on top of the low-level keydb API. It first
int no_suitable_key = 0;
KBNODE keyblock = NULL;
KBNODE found_key = NULL;
+ unsigned int infoflags;
if (ret_keyblock)
*ret_keyblock = NULL;
* merge_selfsigs. For secret keys, premerge transferred the
* keys to the keyblock. */
merge_selfsigs (keyblock);
- found_key = finish_lookup (ctx, keyblock);
+ found_key = finish_lookup (ctx, keyblock, &infoflags);
+ if (!found_key)
+ infoflags |= LOOKUP_NOT_SELECTED;
+ print_status_key_considered (keyblock, infoflags);
if (found_key)
{
no_suitable_key = 0;
goto found;
}
else
- no_suitable_key = 1;
+ {
+ no_suitable_key = 1;
+ }
skip:
/* Release resources and continue search. */
keydb_disable_caching (ctx->kr_handle);
}
-found:
+ found:
if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
aQuickSignKey,
aQuickLSignKey,
aQuickAddUid,
+ aQuickAddKey,
aListConfig,
aListGcryptConfig,
aGPGConfList,
oNoAskCertLevel,
oFingerprint,
oWithFingerprint,
+ oWithSubkeyFingerprint,
oWithICAOSpelling,
oWithKeygrip,
oWithSecret,
oWeakDigest,
oUnwrap,
oOnlySignTextIDs,
+ oDisableSignerUID,
oNoop
};
N_("quickly generate a new key pair")),
ARGPARSE_c (aQuickAddUid, "quick-adduid",
N_("quickly add a new user-id")),
+ ARGPARSE_c (aQuickAddKey, "quick-addkey", "@"),
ARGPARSE_c (aFullKeygen, "full-gen-key" ,
N_("full featured key pair generation")),
ARGPARSE_c (aGenRevoke, "gen-revoke",N_("generate a revocation certificate")),
ARGPARSE_c (aPasswd, "passwd", N_("change a passphrase")),
ARGPARSE_c (aDesigRevoke, "desig-revoke","@" ),
ARGPARSE_c (aExport, "export" , N_("export keys") ),
- ARGPARSE_c (aSendKeys, "send-keys" , N_("export keys to a key server") ),
- ARGPARSE_c (aRecvKeys, "recv-keys" , N_("import keys from a key server") ),
+ ARGPARSE_c (aSendKeys, "send-keys" , N_("export keys to a keyserver") ),
+ ARGPARSE_c (aRecvKeys, "recv-keys" , N_("import keys from a keyserver") ),
ARGPARSE_c (aSearchKeys, "search-keys" ,
- N_("search for keys on a key server") ),
+ N_("search for keys on a keyserver") ),
ARGPARSE_c (aRefreshKeys, "refresh-keys",
N_("update all keys from a keyserver")),
ARGPARSE_c (aLocateKeys, "locate-keys", "@"),
ARGPARSE_s_n (oDisableMDC, "disable-mdc", "@"),
ARGPARSE_s_n (oNoDisableMDC, "no-disable-mdc", "@"),
+ ARGPARSE_s_n (oDisableSignerUID, "disable-signer-uid", "@"),
+
ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
ARGPARSE_s_n (oInteractive, "interactive", N_("prompt before overwriting")),
ARGPARSE_s_n (oUtf8Strings, "utf8-strings", "@"),
ARGPARSE_s_n (oNoUtf8Strings, "no-utf8-strings", "@"),
ARGPARSE_s_n (oWithFingerprint, "with-fingerprint", "@"),
+ ARGPARSE_s_n (oWithSubkeyFingerprint, "with-subkey-fingerprint", "@"),
+ ARGPARSE_s_n (oWithSubkeyFingerprint, "with-subkey-fingerprints", "@"),
ARGPARSE_s_n (oWithICAOSpelling, "with-icao-spelling", "@"),
ARGPARSE_s_n (oWithKeygrip, "with-keygrip", "@"),
ARGPARSE_s_n (oWithSecret, "with-secret", "@"),
case 31: p = "\nHome: "; break;
#ifndef __riscos__
- case 32: p = opt.homedir; break;
+ case 32: p = gnupg_homedir (); break;
#else /* __riscos__ */
- case 32: p = make_filename(opt.homedir, NULL); break;
+ case 32: p = make_filename(gnupg_homedir (), NULL); break;
#endif /* __riscos__ */
case 33: p = _("\nSupported algorithms:\n"); break;
case 34:
}
-
-/* We need the home directory also in some other directories, so make
- sure that both variables are always in sync. */
-static void
-set_homedir (const char *dir)
-{
- if (!dir)
- dir = "";
- opt.homedir = dir;
-}
-
-
/* We set the screen dimensions for UI purposes. Do not allow screens
smaller than 80x24 for the sake of simplicity. */
static void
could be rectified if the homedir itself had proper
permissions. */
if(item!=0 && homedir_cache>-1
- && ascii_strncasecmp(opt.homedir,tmppath,strlen(opt.homedir))==0)
+ && !ascii_strncasecmp (gnupg_homedir (), tmppath,
+ strlen (gnupg_homedir ())))
{
ret=homedir_cache;
goto end;
static void
gpg_deinit_default_ctrl (ctrl_t ctrl)
{
+#ifdef USE_TOFU
+ tofu_closedbs (ctrl);
+#endif
gpg_dirmngr_deinit_session_data (ctrl);
}
break;
}
- configname = make_filename (opt.homedir, name, NULL);
+ configname = make_filename (gnupg_homedir (), name, NULL);
}
while (access (configname, R_OK));
xfree(name);
if (! configname)
- configname = make_filename (opt.homedir, GPG_NAME EXTSEP_S "conf", NULL);
+ configname = make_filename (gnupg_homedir (),
+ GPG_NAME EXTSEP_S "conf", NULL);
if (! access (configname, R_OK))
{
/* Print a warning when both config files are present. */
- char *p = make_filename (opt.homedir, "options", NULL);
+ char *p = make_filename (gnupg_homedir (), "options", NULL);
if (! access (p, R_OK))
log_info (_("Note: old default options file '%s' ignored\n"), p);
xfree (p);
else
{
/* Use the old default only if it exists. */
- char *p = make_filename (opt.homedir, "options", NULL);
+ char *p = make_filename (gnupg_homedir (), "options", NULL);
if (!access (p, R_OK))
{
xfree (configname);
opt.mangle_dos_filenames = 0;
opt.min_cert_level = 2;
set_screen_dimensions ();
- opt.keyid_format = KF_SHORT;
+ opt.keyid_format = KF_NONE;
opt.def_sig_expire = "0";
opt.def_cert_expire = "0";
- set_homedir (default_homedir ());
+ gnupg_set_homedir (NULL);
opt.passphrase_repeat = 1;
opt.emit_version = 1; /* Limit to the major number. */
opt.weak_digests = NULL;
opt.no_homedir_creation = 1;
}
else if( pargs.r_opt == oHomedir )
- set_homedir ( pargs.r.ret_str );
+ gnupg_set_homedir (pargs.r.ret_str);
else if( pargs.r_opt == oNoPermissionWarn )
opt.no_perm_warn=1;
else if (pargs.r_opt == oStrict )
}
#ifdef HAVE_DOSISH_SYSTEM
- if ( strchr (opt.homedir,'\\') ) {
- char *d, *buf = xmalloc (strlen (opt.homedir)+1);
- const char *s = opt.homedir;
- for (d=buf,s=opt.homedir; *s; s++)
+ if ( strchr (gnupg_homedir (), '\\') ) {
+ char *d, *buf = xmalloc (strlen (gnupg_homedir ())+1);
+ const char *s;
+ for (d=buf, s = gnupg_homedir (); *s; s++)
{
*d++ = *s == '\\'? '/': *s;
#ifdef HAVE_W32_SYSTEM
#endif
}
*d = 0;
- set_homedir (buf);
+ gnupg_set_homedir (buf);
}
#endif
pargs.flags= ARGPARSE_FLAG_KEEP;
/* By this point we have a homedir, and cannot change it. */
- check_permissions(opt.homedir,0);
+ check_permissions (gnupg_homedir (), 0);
next_pass:
if( configname ) {
case aStore:
case aQuickKeygen:
case aQuickAddUid:
+ case aQuickAddKey:
case aExportOwnerTrust:
case aImportOwnerTrust:
case aRebuildKeydbCaches:
opt.with_fingerprint = 1;
opt.fingerprint++;
break;
+ case oWithSubkeyFingerprint:
+ opt.with_subkey_fingerprint = 1;
+ break;
case oWithICAOSpelling:
opt.with_icao_spelling = 1;
break;
case oNoForceMDC: opt.force_mdc = 0; break;
case oDisableMDC: opt.disable_mdc = 1; break;
case oNoDisableMDC: opt.disable_mdc = 0; break;
+
+ case oDisableSignerUID: opt.flags.disable_signer_uid = 1; break;
+
case oS2KMode: opt.s2k_mode = pargs.r.ret_int; break;
case oS2KDigest: s2k_digest_string = xstrdup(pargs.r.ret_str); break;
case oS2KCipher: s2k_cipher_string = xstrdup(pargs.r.ret_str); break;
opt.keyserver_options.options|=KEYSERVER_AUTO_KEY_RETRIEVE;
else
opt.keyserver_options.options&=~KEYSERVER_AUTO_KEY_RETRIEVE;
-
- deprecated_warning(configname,configlineno,
- pargs.r_opt==oAutoKeyRetrieve?"--auto-key-retrieve":
- "--no-auto-key-retrieve","--keyserver-options ",
- pargs.r_opt==oAutoKeyRetrieve?"auto-key-retrieve":
- "no-auto-key-retrieve");
break;
case oShowSessionKey: opt.show_session_key = 1; break;
case oOverrideSessionKey:
opt.keyid_format=KF_0xSHORT;
else if(ascii_strcasecmp(pargs.r.ret_str,"0xlong")==0)
opt.keyid_format=KF_0xLONG;
+ else if(ascii_strcasecmp(pargs.r.ret_str,"none")==0)
+ opt.keyid_format = KF_NONE;
else
log_error("unknown keyid-format '%s'\n",pargs.r.ret_str);
break;
/* Set the random seed file. */
if( use_random_seed ) {
- char *p = make_filename(opt.homedir, "random_seed", NULL );
+ char *p = make_filename (gnupg_homedir (), "random_seed", NULL );
gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
if (!access (p, F_OK))
register_secured_file (p);
case aDeleteSecretAndPublicKeys:
case aQuickKeygen:
case aQuickAddUid:
+ case aQuickAddKey:
case aFullKeygen:
case aKeygen:
case aImport:
break;
case aQuickKeygen:
- if (argc != 1 )
- wrong_args("--gen-key user-id");
- username = make_username (fname);
- quick_generate_keypair (ctrl, username);
- xfree (username);
+ {
+ const char *x_algo, *x_usage, *x_expire;
+
+ if (argc < 1 || argc > 4)
+ wrong_args("--quick-gen-key USER-ID [ALGO [USAGE [EXPIRE]]]");
+ username = make_username (fname);
+ argv++, argc--;
+ x_algo = "";
+ x_usage = "";
+ x_expire = "";
+ if (argc)
+ {
+ x_algo = *argv++; argc--;
+ if (argc)
+ {
+ x_usage = *argv++; argc--;
+ if (argc)
+ {
+ x_expire = *argv++; argc--;
+ }
+ }
+ }
+ quick_generate_keypair (ctrl, username, x_algo, x_usage, x_expire);
+ xfree (username);
+ }
break;
case aKeygen: /* generate a key */
}
break;
+ case aQuickAddKey:
+ {
+ const char *x_fpr, *x_algo, *x_usage, *x_expire;
+
+ if (argc < 1 || argc > 4)
+ wrong_args ("--quick-addkey FINGERPRINT [ALGO [USAGE [EXPIRE]]]");
+ x_fpr = *argv++; argc--;
+ x_algo = "";
+ x_usage = "";
+ x_expire = "";
+ if (argc)
+ {
+ x_algo = *argv++; argc--;
+ if (argc)
+ {
+ x_usage = *argv++; argc--;
+ if (argc)
+ {
+ x_expire = *argv++; argc--;
+ }
+ }
+ }
+ keyedit_quick_addkey (ctrl, x_fpr, x_algo, x_usage, x_expire);
+ }
+ break;
+
case aFastImport:
opt.import_options |= IMPORT_FAST;
case aImport:
case aUpdateTrustDB:
if( argc )
wrong_args("--update-trustdb");
- update_trustdb();
+ update_trustdb (ctrl);
break;
case aCheckTrustDB:
/* Old versions allowed for arguments - ignore them */
- check_trustdb();
+ check_trustdb (ctrl);
break;
case aFixTrustDB:
}
merge_keys_and_selfsig (kb);
- if (tofu_set_policy (kb, policy))
+ if (tofu_set_policy (ctrl, kb, policy))
g10_exit (1);
}
typedef struct kbnode_struct *KBNODE;
typedef struct kbnode_struct *kbnode_t;
+/* TOFU database meta object. */
+struct tofu_dbs_s;
+typedef struct tofu_dbs_s *tofu_dbs_t;
+
/* Session control object. This object is passed to most functions to
convey the status of a session. Note that the defaults are set by
/* Local data for call-dirmngr.c */
dirmngr_local_t dirmngr_local;
+
+ /* Local data for tofu.c */
+ struct {
+ tofu_dbs_t dbs;
+ } tofu;
+
};
"that VALUE is a file to read the data from. "
"(RFC 4880, Section 5.2.3.16)" },
{ "--key-server-preferences", sig_big_endian_arg,
- "Big-endian number encoding the key server preferences. "
+ "Big-endian number encoding the keyserver preferences. "
"(RFC 4880, Section 5.2.3.17)" },
{ "--key-server", sig_string_arg,
- "The preferred key server. (RFC 4880, Section 5.2.3.18)" },
+ "The preferred keyserver. (RFC 4880, Section 5.2.3.18)" },
{ "--primary-user-id", sig_flag,
"Sets the primary user id flag. (RFC 4880, Section 5.2.3.19)" },
{ "--policy-uri", sig_string_arg,
int processed;
ctrl_t ctrl;
- opt.homedir = default_homedir ();
- if (! opt.homedir)
- opt.homedir = "";
-
opt.ignore_time_conflict = 1;
/* Allow notations in the IETF space, for instance. */
opt.expert = 1;
-/* sqlite.c - SQLite helper functions.
+/* gpgsql.c - SQLite helper functions.
* Copyright (C) 2015 g10 Code GmbH
*
* This file is part of GnuPG.
#include "util.h"
#include "logging.h"
-#include "sqlite.h"
+#include "gpgsql.h"
/* This is a convenience function that combines sqlite3_mprintf and
sqlite3_exec. */
int
-sqlite3_exec_printf (sqlite3 *db,
- int (*callback)(void*,int,char**,char**), void *cookie,
- char **errmsg,
- const char *sql, ...)
+gpgsql_exec_printf (sqlite3 *db,
+ int (*callback)(void*,int,char**,char**), void *cookie,
+ char **errmsg,
+ const char *sql, ...)
{
va_list ap;
int rc;
}
int
-sqlite3_stepx (sqlite3 *db,
- sqlite3_stmt **stmtp,
- sqlite3_stepx_callback callback,
- void *cookie,
- char **errmsg,
- const char *sql, ...)
+gpgsql_stepx (sqlite3 *db,
+ sqlite3_stmt **stmtp,
+ gpgsql_stepx_callback callback,
+ void *cookie,
+ char **errmsg,
+ const char *sql, ...)
{
int rc;
int err = 0;
va_list va;
int args;
- enum sqlite_arg_type t;
+ enum gpgsql_arg_type t;
int i;
int cols;
{
for (i = 1; i <= args; i ++)
{
- t = va_arg (va, enum sqlite_arg_type);
+ t = va_arg (va, enum gpgsql_arg_type);
switch (t)
{
case SQLITE_ARG_INT:
}
}
- t = va_arg (va, enum sqlite_arg_type);
+ t = va_arg (va, enum gpgsql_arg_type);
log_assert (t == SQLITE_ARG_END);
va_end (va);
--- /dev/null
+/* gpgsql.h - SQLite helper functions.
+ * Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GNUPG_GPGSQL_H
+#define GNUPG_GPGSQL_H
+
+#include <sqlite3.h>
+
+enum gpgsql_arg_type
+ {
+ SQLITE_ARG_END = 0xdead001,
+ SQLITE_ARG_INT,
+ SQLITE_ARG_LONG_LONG,
+ SQLITE_ARG_STRING,
+ /* This takes two arguments: the blob as a void * and the length
+ of the blob as a long long. */
+ SQLITE_ARG_BLOB
+ };
+
+int gpgsql_exec_printf (sqlite3 *db,
+ int (*callback)(void*,int,char**,char**), void *cookie,
+ char **errmsg,
+ const char *sql, ...);
+
+typedef int (*gpgsql_stepx_callback) (void *cookie,
+ /* number of columns. */
+ int cols,
+ /* columns as text. */
+ char **values,
+ /* column names. */
+ char **names,
+ /* The prepared statement so
+ * that it is possible to use
+ * something like
+ * sqlite3_column_blob(). */
+ sqlite3_stmt *statement);
+
+int gpgsql_stepx (sqlite3 *db,
+ sqlite3_stmt **stmtp,
+ gpgsql_stepx_callback callback,
+ void *cookie,
+ char **errmsg,
+ const char *sql, ...);
+
+#endif /*GNUPG_GPGSQL_H*/
N_("|FD|write status info to this FD")),
ARGPARSE_s_i (oLoggerFD, "logger-fd", "@"),
ARGPARSE_s_s (oHomedir, "homedir", "@"),
- ARGPARSE_s_s (oWeakDigest, "weak-digest", "@"),
+ ARGPARSE_s_s (oWeakDigest, "weak-digest",
+ N_("|ALGO|reject signatures made with ALGO")),
ARGPARSE_end ()
};
opt.trust_model = TM_ALWAYS;
opt.batch = 1;
- opt.homedir = default_homedir ();
opt.weak_digests = NULL;
tty_no_terminal(1);
case oLoggerFD:
log_set_fd (translate_sys2libc_fd_int (pargs.r.ret_int, 1));
break;
- case oHomedir: opt.homedir = pargs.r.ret_str; break;
+ case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
case oWeakDigest:
additional_weak_digest(pargs.r.ret_str);
break;
* this utility assumes that all keys in the keyring are trustworthy
*/
int
-check_signatures_trust( PKT_signature *sig )
+check_signatures_trust (ctrl_t ctrl, PKT_signature *sig)
{
+ (void)ctrl;
(void)sig;
return 0;
}
}
void
-check_trustdb_stale(void)
+check_trustdb_stale (ctrl_t ctrl)
{
+ (void)ctrl;
}
int
-get_validity_info (PKT_public_key *pk, PKT_user_id *uid)
+get_validity_info (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid)
{
+ (void)ctrl;
(void)pk;
(void)uid;
return '?';
}
unsigned int
-get_validity (PKT_public_key *pk, PKT_user_id *uid, PKT_signature *sig,
- int may_ask)
+get_validity (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid,
+ PKT_signature *sig, int may_ask)
{
+ (void)ctrl;
(void)pk;
(void)uid;
(void)sig;
}
const char *
-uid_trust_string_fixed (PKT_public_key *key, PKT_user_id *uid)
+uid_trust_string_fixed (ctrl_t ctrl, PKT_public_key *key, PKT_user_id *uid)
{
+ (void)ctrl;
(void)key;
(void)uid;
return "err";
}
gpg_error_t
-agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
+agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
+ char **r_serialno, int *r_cleartext)
{
(void)ctrl;
(void)hexkeygrip;
+ (void)r_cleartext;
*r_serialno = NULL;
return gpg_error (GPG_ERR_NO_SECKEY);
}
}
gpg_error_t
-tofu_get_policy (PKT_public_key *pk, PKT_user_id *user_id,
+tofu_get_policy (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *user_id,
enum tofu_policy *policy)
{
+ (void)ctrl;
(void)pk;
(void)user_id;
(void)policy;
interactive or by not setting no-auto-check-trustdb */
if (!(options & IMPORT_FAST))
- check_or_update_trustdb ();
+ check_or_update_trustdb (ctrl);
return rc;
}
)
filename = make_filename (resname, NULL);
else
- filename = make_filename (opt.homedir, resname, NULL);
+ filename = make_filename (gnupg_homedir (), resname, NULL);
}
else
filename = xstrdup (resname);
/*-- pkclist.c --*/
void show_revocation_reason( PKT_public_key *pk, int mode );
-int check_signatures_trust( PKT_signature *sig );
+int check_signatures_trust (ctrl_t ctrl, PKT_signature *sig);
void release_pk_list (PK_LIST pk_list);
int build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list);
/* keyedit.c - Edit properties of a key
* Copyright (C) 1998-2010 Free Software Foundation, Inc.
- * Copyright (C) 1998-2015 Werner Koch
+ * Copyright (C) 1998-2016 Werner Koch
* Copyright (C) 2015, 2016 g10 Code GmbH
*
* This file is part of GnuPG.
static void show_prefs (PKT_user_id * uid, PKT_signature * selfsig,
int verbose);
-static void show_names (estream_t fp, KBNODE keyblock, PKT_public_key * pk,
+static void show_names (ctrl_t ctrl, estream_t fp,
+ kbnode_t keyblock, PKT_public_key * pk,
unsigned int flag, int with_prefs);
static void show_key_with_all_names (ctrl_t ctrl, estream_t fp,
KBNODE keyblock, int only_marked,
static void show_key_and_fingerprint (kbnode_t keyblock, int with_subkeys);
static void show_key_and_grip (kbnode_t keyblock);
static void subkey_expire_warning (kbnode_t keyblock);
-static int menu_adduid (KBNODE keyblock, int photo, const char *photo_name,
- const char *uidstr);
+static int menu_adduid (ctrl_t ctrl, kbnode_t keyblock,
+ int photo, const char *photo_name, const char *uidstr);
static void menu_deluid (KBNODE pub_keyblock);
static int menu_delsig (KBNODE pub_keyblock);
static int menu_clean (KBNODE keyblock, int self_only);
static int real_uids_left (KBNODE keyblock);
static int count_selected_keys (KBNODE keyblock);
static int menu_revsig (KBNODE keyblock);
-static int menu_revuid (KBNODE keyblock);
+static int menu_revuid (ctrl_t ctrl, kbnode_t keyblock);
static int menu_revkey (KBNODE pub_keyblock);
static int menu_revsubkey (KBNODE pub_keyblock);
#ifndef NO_TRUST_MODELS
static int enable_disable_key (KBNODE keyblock, int disable);
#endif /*!NO_TRUST_MODELS*/
-static void menu_showphoto (KBNODE keyblock);
+static void menu_showphoto (ctrl_t ctrl, kbnode_t keyblock);
static int update_trust = 0;
return 1;
ndataa = pubkey_get_nsig (a->pubkey_algo);
- ndatab = pubkey_get_nsig (a->pubkey_algo);
- log_assert (ndataa == ndatab);
+ ndatab = pubkey_get_nsig (b->pubkey_algo);
+ if (ndataa != ndatab)
+ return (ndataa < ndatab)? -1 : 1;
for (i = 0; i < ndataa; i ++)
{
sig = n->pkt->pkt.signature;
- pending_desc = xasprintf (" sig: class: 0x%x, issuer: %s, timestamp: %s (%lld), digest: %02x %02x",
+ pending_desc = xasprintf (" sig: class: 0x%x, issuer: %s,"
+ " timestamp: %s (%lld), digest: %02x %02x",
sig->sig_class,
keystr (sig->keyid),
isotimestamp (sig->timestamp),
{
if (pending_desc)
log_debug ("%s", pending_desc);
- log_debug (" Can't check signature allegedly issued by %s: %s\n",
- keystr (sig->keyid), gpg_strerror (err));
+ log_debug (" Can't check signature allegedly"
+ " issued by %s: %s\n",
+ keystr (sig->keyid), gpg_strerror (err));
}
missing_issuer ++;
break;
err = hexkeygrip_from_pk (pk, &hexgrip);
if (err)
goto leave;
- err = agent_get_keyinfo (ctrl, hexgrip, &serialno);
+ err = agent_get_keyinfo (ctrl, hexgrip, &serialno, NULL);
if (!err && serialno)
; /* Key on card. */
else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
goto leave;
desc = gpg_format_keydesc (pk, FORMAT_KEYDESC_NORMAL, 1);
- err = agent_passwd (ctrl, hexgrip, desc, &cache_nonce, &passwd_nonce);
+ err = agent_passwd (ctrl, hexgrip, desc, 0,
+ &cache_nonce, &passwd_nonce);
xfree (desc);
if (err)
and run the stale check as early as possible. Note, that for
non- W32 platforms it is run indirectly trough a call to
get_validity (). */
- check_trustdb_stale ();
+ check_trustdb_stale (ctrl);
#endif
/* Get the public key */
break;
case cmdCHECK:
- check_all_keysigs (keyblock, count_selected_uids (keyblock),
- !strcmp (arg_string, "selfsig"));
+ if (check_all_keysigs (keyblock, count_selected_uids (keyblock),
+ !strcmp (arg_string, "selfsig")))
+ modified = 1;
break;
case cmdSIGN:
photo = 1;
/* fall through */
case cmdADDUID:
- if (menu_adduid (keyblock, photo, arg_string, NULL))
+ if (menu_adduid (ctrl, keyblock, photo, arg_string, NULL))
{
update_trust = 1;
redisplay = 1;
break;
case cmdADDKEY:
- if (!generate_subkeypair (ctrl, keyblock))
+ if (!generate_subkeypair (ctrl, keyblock, NULL, NULL, NULL))
{
redisplay = 1;
modified = 1;
else if (*arg_string == '~')
fname = make_filename (arg_string, NULL);
else
- fname = make_filename (opt.homedir, arg_string, NULL);
+ fname = make_filename (gnupg_homedir (), arg_string, NULL);
/* Open that file. */
a = iobuf_open (fname);
n1 > 1 ? _("Really revoke all selected user IDs? (y/N) ")
: _("Really revoke this user ID? (y/N) ")))
{
- if (menu_revuid (keyblock))
+ if (menu_revuid (ctrl, keyblock))
{
modified = 1;
redisplay = 1;
show_key_with_all_names (ctrl, NULL, keyblock, 0, 0, 0, 1, 0, 0);
tty_printf ("\n");
- if (edit_ownertrust (find_kbnode (keyblock,
+ if (edit_ownertrust (ctrl, find_kbnode (keyblock,
PKT_PUBLIC_KEY)->pkt->pkt.
public_key, 1))
{
{
int count = count_selected_uids (keyblock);
log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
- show_names (NULL, keyblock, keyblock->pkt->pkt.public_key,
+ show_names (ctrl, NULL, keyblock, keyblock->pkt->pkt.public_key,
count ? NODFLG_SELUID : 0, 1);
}
break;
{
int count = count_selected_uids (keyblock);
log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
- show_names (NULL, keyblock, keyblock->pkt->pkt.public_key,
+ show_names (ctrl, NULL, keyblock, keyblock->pkt->pkt.public_key,
count ? NODFLG_SELUID : 0, 2);
}
break;
#endif /*!NO_TRUST_MODELS*/
case cmdSHOWPHOTO:
- menu_showphoto (keyblock);
+ menu_showphoto (ctrl, keyblock);
break;
case cmdCLEAN:
#ifdef HAVE_W32_SYSTEM
/* See keyedit_menu for why we need this. */
- check_trustdb_stale ();
+ check_trustdb_stale (ctrl);
#endif
/* Search the key; we don't want the whole getkey stuff here. */
fix_keyblock (&keyblock);
- if (menu_adduid (keyblock, 0, NULL, uidstring))
+ if (menu_adduid (ctrl, keyblock, 0, NULL, uidstring))
{
err = keydb_update_keyblock (kdbhd, keyblock);
if (err)
}
+/* Find a keyblock by fingerprint because only this uniquely
+ * identifies a key and may thus be used to select a key for
+ * unattended subkey creation os key signing. */
+static gpg_error_t
+find_by_primary_fpr (ctrl_t ctrl, const char *fpr,
+ kbnode_t *r_keyblock, KEYDB_HANDLE *r_kdbhd)
+{
+ gpg_error_t err;
+ kbnode_t keyblock = NULL;
+ KEYDB_HANDLE kdbhd = NULL;
+ KEYDB_SEARCH_DESC desc;
+ byte fprbin[MAX_FINGERPRINT_LEN];
+ size_t fprlen;
+
+ *r_keyblock = NULL;
+ *r_kdbhd = NULL;
+
+ if (classify_user_id (fpr, &desc, 1)
+ || !(desc.mode == KEYDB_SEARCH_MODE_FPR
+ || desc.mode == KEYDB_SEARCH_MODE_FPR16
+ || desc.mode == KEYDB_SEARCH_MODE_FPR20))
+ {
+ log_error (_("\"%s\" is not a fingerprint\n"), fpr);
+ err = gpg_error (GPG_ERR_INV_NAME);
+ goto leave;
+ }
+ err = get_pubkey_byname (ctrl, NULL, NULL, fpr, &keyblock, &kdbhd, 1, 1);
+ if (err)
+ {
+ log_error (_("key \"%s\" not found: %s\n"), fpr, gpg_strerror (err));
+ goto leave;
+ }
+
+ /* Check that the primary fingerprint has been given. */
+ fingerprint_from_pk (keyblock->pkt->pkt.public_key, fprbin, &fprlen);
+ if (fprlen == 16 && desc.mode == KEYDB_SEARCH_MODE_FPR16
+ && !memcmp (fprbin, desc.u.fpr, 16))
+ ;
+ else if (fprlen == 16 && desc.mode == KEYDB_SEARCH_MODE_FPR
+ && !memcmp (fprbin, desc.u.fpr, 16)
+ && !desc.u.fpr[16]
+ && !desc.u.fpr[17]
+ && !desc.u.fpr[18]
+ && !desc.u.fpr[19])
+ ;
+ else if (fprlen == 20 && (desc.mode == KEYDB_SEARCH_MODE_FPR20
+ || desc.mode == KEYDB_SEARCH_MODE_FPR)
+ && !memcmp (fprbin, desc.u.fpr, 20))
+ ;
+ else
+ {
+ log_error (_("\"%s\" is not the primary fingerprint\n"), fpr);
+ err = gpg_error (GPG_ERR_INV_NAME);
+ goto leave;
+ }
+
+ *r_keyblock = keyblock;
+ keyblock = NULL;
+ *r_kdbhd = kdbhd;
+ kdbhd = NULL;
+ err = 0;
+
+ leave:
+ release_kbnode (keyblock);
+ keydb_release (kdbhd);
+ return err;
+}
+
+
/* Unattended key signing function. If the key specifified by FPR is
available and FPR is the primary fingerprint all user ids of the
key are signed using the default signing key. If UIDS is an empty
kbnode_t keyblock = NULL;
KEYDB_HANDLE kdbhd = NULL;
int modified = 0;
- KEYDB_SEARCH_DESC desc;
PKT_public_key *pk;
kbnode_t node;
strlist_t sl;
#ifdef HAVE_W32_SYSTEM
/* See keyedit_menu for why we need this. */
- check_trustdb_stale ();
+ check_trustdb_stale (ctrl);
#endif
/* We require a fingerprint because only this uniquely identifies a
key and may thus be used to select a key for unattended key
signing. */
- if (classify_user_id (fpr, &desc, 1)
- || !(desc.mode == KEYDB_SEARCH_MODE_FPR
- || desc.mode == KEYDB_SEARCH_MODE_FPR16
- || desc.mode == KEYDB_SEARCH_MODE_FPR20))
- {
- log_error (_("\"%s\" is not a fingerprint\n"), fpr);
- goto leave;
- }
- err = get_pubkey_byname (ctrl, NULL, NULL, fpr, &keyblock, &kdbhd, 1, 1);
- if (err)
- {
- log_error (_("key \"%s\" not found: %s\n"), fpr, gpg_strerror (err));
- goto leave;
- }
-
- /* Check that the primary fingerprint has been given. */
- {
- byte fprbin[MAX_FINGERPRINT_LEN];
- size_t fprlen;
-
- fingerprint_from_pk (keyblock->pkt->pkt.public_key, fprbin, &fprlen);
- if (fprlen == 16 && desc.mode == KEYDB_SEARCH_MODE_FPR16
- && !memcmp (fprbin, desc.u.fpr, 16))
- ;
- else if (fprlen == 16 && desc.mode == KEYDB_SEARCH_MODE_FPR
- && !memcmp (fprbin, desc.u.fpr, 16)
- && !desc.u.fpr[16]
- && !desc.u.fpr[17]
- && !desc.u.fpr[18]
- && !desc.u.fpr[19])
- ;
- else if (fprlen == 20 && (desc.mode == KEYDB_SEARCH_MODE_FPR20
- || desc.mode == KEYDB_SEARCH_MODE_FPR)
- && !memcmp (fprbin, desc.u.fpr, 20))
- ;
- else
- {
- log_error (_("\"%s\" is not the primary fingerprint\n"), fpr);
- goto leave;
- }
- }
+ if (find_by_primary_fpr (ctrl, fpr, &keyblock, &kdbhd))
+ goto leave;
if (fix_keyblock (&keyblock))
modified++;
}
+/* Unattended subkey creation function.
+ *
+ */
+void
+keyedit_quick_addkey (ctrl_t ctrl, const char *fpr, const char *algostr,
+ const char *usagestr, const char *expirestr)
+{
+ gpg_error_t err;
+ kbnode_t keyblock;
+ KEYDB_HANDLE kdbhd;
+ int modified = 0;
+ PKT_public_key *pk;
+
+#ifdef HAVE_W32_SYSTEM
+ /* See keyedit_menu for why we need this. */
+ check_trustdb_stale (ctrl);
+#endif
+
+ /* We require a fingerprint because only this uniquely identifies a
+ * key and may thus be used to select a key for unattended subkey
+ * creation. */
+ if (find_by_primary_fpr (ctrl, fpr, &keyblock, &kdbhd))
+ goto leave;
+
+ if (fix_keyblock (&keyblock))
+ modified++;
+
+ pk = keyblock->pkt->pkt.public_key;
+ if (pk->flags.revoked)
+ {
+ if (!opt.verbose)
+ show_key_with_all_names (ctrl, es_stdout, keyblock, 0, 0, 0, 0, 0, 1);
+ log_error ("%s%s", _("Key is revoked."), "\n");
+ goto leave;
+ }
+
+ /* Create the subkey. Noet that the called function already prints
+ * an error message. */
+ if (!generate_subkeypair (ctrl, keyblock, algostr, usagestr, expirestr))
+ modified = 1;
+ es_fflush (es_stdout);
+
+ /* Store. */
+ if (modified)
+ {
+ err = keydb_update_keyblock (kdbhd, keyblock);
+ if (err)
+ {
+ log_error (_("update failed: %s\n"), gpg_strerror (err));
+ goto leave;
+ }
+ }
+ else
+ log_info (_("Key not changed so no update needed.\n"));
+
+ leave:
+ release_kbnode (keyblock);
+ keydb_release (kdbhd);
+}
+
+
\f
static void
tty_print_notations (int indent, PKT_signature * sig)
es_putc ('e', fp);
else if (!(opt.fast_list_mode || opt.no_expensive_trust_checks))
{
- int trust = get_validity_info (pk, NULL);
+ int trust = get_validity_info (ctrl, pk, NULL);
if (trust == 'u')
ulti_hack = 1;
es_putc (trust, fp);
int uid_validity;
if (primary && !ulti_hack)
- uid_validity = get_validity_info (primary, uid);
+ uid_validity = get_validity_info (ctrl, primary, uid);
else
uid_validity = 'u';
es_fprintf (fp, "%c::::::::", uid_validity);
{
#ifdef USE_TOFU
enum tofu_policy policy;
- if (! tofu_get_policy (primary, uid, &policy)
+ if (! tofu_get_policy (ctrl, primary, uid, &policy)
&& policy != TOFU_POLICY_NONE)
es_fprintf (fp, "%s", tofu_policy_str (policy));
#endif /*USE_TOFU*/
static void
-show_names (estream_t fp,
- KBNODE keyblock, PKT_public_key * pk, unsigned int flag,
+show_names (ctrl_t ctrl, estream_t fp,
+ kbnode_t keyblock, PKT_public_key * pk, unsigned int flag,
int with_prefs)
{
KBNODE node;
if (!flag || (flag && (node->flag & flag)))
{
if (!(flag & NODFLG_MARK_A) && pk)
- tty_fprintf (fp, "%s ", uid_trust_string_fixed (pk, uid));
+ tty_fprintf (fp, "%s ", uid_trust_string_fixed (ctrl, pk, uid));
if (flag & NODFLG_MARK_A)
tty_fprintf (fp, " ");
* output */
static int did_warn = 0;
- trust = get_validity_string (pk, NULL);
+ trust = get_validity_string (ctrl, pk, NULL);
otrust = get_ownertrust_string (pk);
/* Show a warning once */
if (!did_warn
- && (get_validity (pk, NULL, NULL, 0)
+ && (get_validity (ctrl, pk, NULL, NULL, 0)
& TRUST_FLAG_PENDING_CHECK))
{
did_warn = 1;
have_seckey = 0;
}
else
- have_seckey = !agent_get_keyinfo (ctrl, hexgrip, &serialno);
+ have_seckey = !agent_get_keyinfo (ctrl, hexgrip, &serialno, NULL);
xfree (hexgrip);
}
}
}
- show_names (fp,
+ show_names (ctrl, fp,
keyblock, primary, only_marked ? NODFLG_MARK_A : 0, with_prefs);
if (do_warn && !nowarn)
* user id.
*/
static int
-menu_adduid (kbnode_t pub_keyblock, int photo, const char *photo_name,
- const char *uidstring)
+menu_adduid (ctrl_t ctrl, kbnode_t pub_keyblock,
+ int photo, const char *photo_name, const char *uidstring)
{
PKT_user_id *uid;
PKT_public_key *pk = NULL;
}
}
- uid = generate_photo_id (pk, photo_name);
+ uid = generate_photo_id (ctrl, pk, photo_name);
}
else
uid = generate_user_id (pub_keyblock, uidstring);
/* Revoke a user ID (i.e. revoke a user ID selfsig). Return true if
keyblock changed. */
static int
-menu_revuid (KBNODE pub_keyblock)
+menu_revuid (ctrl_t ctrl, kbnode_t pub_keyblock)
{
PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key;
KBNODE node;
/* If the trustdb has an entry for this key+uid then the
trustdb needs an update. */
if (!update_trust
- && (get_validity (pk, uid, NULL, 0) & TRUST_MASK) >=
+ && (get_validity (ctrl, pk, uid, NULL, 0) & TRUST_MASK) >=
TRUST_UNDEFINED)
update_trust = 1;
#endif /*!NO_TRUST_MODELS*/
static void
-menu_showphoto (KBNODE keyblock)
+menu_showphoto (ctrl_t ctrl, kbnode_t keyblock)
{
KBNODE node;
int select_all = !count_selected_uids (keyblock);
"key %s (uid %d)\n"),
image_type_to_string (type, 1),
(ulong) size, keystr_from_pk (pk), count);
- show_photos (&uid->attribs[i], 1, pk, uid);
+ show_photos (ctrl, &uid->attribs[i], 1, pk, uid);
}
}
}
/* keygen.c - Generate a key pair
* Copyright (C) 1998-2007, 2009-2011 Free Software Foundation, Inc.
- * Copyright (C) 2014, 2015 Werner Koch
+ * Copyright (C) 2014, 2015, 2016 Werner Koch
*
* This file is part of GnuPG.
*
is inside the bounds enforced by ask_keysize and gen_xxx. */
#define DEFAULT_STD_ALGO PUBKEY_ALGO_RSA
#define DEFAULT_STD_KEYSIZE 2048
+#define DEFAULT_STD_KEYUSE (PUBKEY_USAGE_CERT|PUBKEY_USAGE_SIG)
#define DEFAULT_STD_CURVE NULL
#define DEFAULT_STD_SUBALGO PUBKEY_ALGO_RSA
#define DEFAULT_STD_SUBKEYSIZE 2048
+#define DEFAULT_STD_SUBKEYUSE PUBKEY_USAGE_ENC
#define DEFAULT_STD_SUBCURVE NULL
/* Flag bits used during key generation. */
static int nzip_prefs;
static int mdc_available,ks_modify;
+static gpg_error_t parse_algo_usage_expire (ctrl_t ctrl, int for_subkey,
+ const char *algostr, const char *usagestr,
+ const char *expirestr,
+ int *r_algo, unsigned int *r_usage,
+ u32 *r_expire,
+ unsigned int *r_nbits, char **r_curve);
static void do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
struct output_control_s *outctrl, int card );
static int write_keyblock (iobuf_t out, kbnode_t node);
if (letter || pk)
{
*p++ = letter;
- *p++ = ' ';
- fingerprint_from_pk (pk, array, &n);
- s = array;
- for (i=0; i < n ; i++, s++, p += 2)
- sprintf (p, "%02X", *s);
+ if (pk)
+ {
+ *p++ = ' ';
+ fingerprint_from_pk (pk, array, &n);
+ s = array;
+ for (i=0; i < n ; i++, s++, p += 2)
+ sprintf (p, "%02X", *s);
+ }
}
if (*handle)
{
static int
common_gen (const char *keyparms, int algo, const char *algoelem,
kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey,
- int keygen_flags, const char *passphrase, char **cache_nonce_addr)
+ int keygen_flags, const char *passphrase,
+ char **cache_nonce_addr, char **passwd_nonce_addr)
{
int err;
PACKET *pkt;
PKT_public_key *pk;
gcry_sexp_t s_key;
- err = agent_genkey (NULL, cache_nonce_addr, keyparms,
+ err = agent_genkey (NULL, cache_nonce_addr, passwd_nonce_addr, keyparms,
!!(keygen_flags & KEYGEN_FLAG_NO_PROTECTION),
passphrase,
&s_key);
static int
gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
u32 timestamp, u32 expireval, int is_subkey,
- int keygen_flags, const char *passphrase, char **cache_nonce_addr)
+ int keygen_flags, const char *passphrase,
+ char **cache_nonce_addr, char **passwd_nonce_addr)
{
int err;
char *keyparms;
{
err = common_gen (keyparms, algo, "pgy",
pub_root, timestamp, expireval, is_subkey,
- keygen_flags, passphrase, cache_nonce_addr);
+ keygen_flags, passphrase,
+ cache_nonce_addr, passwd_nonce_addr);
xfree (keyparms);
}
static gpg_error_t
gen_dsa (unsigned int nbits, KBNODE pub_root,
u32 timestamp, u32 expireval, int is_subkey,
- int keygen_flags, const char *passphrase, char **cache_nonce_addr)
+ int keygen_flags, const char *passphrase,
+ char **cache_nonce_addr, char **passwd_nonce_addr)
{
int err;
unsigned int qbits;
{
err = common_gen (keyparms, PUBKEY_ALGO_DSA, "pqgy",
pub_root, timestamp, expireval, is_subkey,
- keygen_flags, passphrase, cache_nonce_addr);
+ keygen_flags, passphrase,
+ cache_nonce_addr, passwd_nonce_addr);
xfree (keyparms);
}
static gpg_error_t
gen_ecc (int algo, const char *curve, kbnode_t pub_root,
u32 timestamp, u32 expireval, int is_subkey,
- int keygen_flags, const char *passphrase, char **cache_nonce_addr)
+ int keygen_flags, const char *passphrase,
+ char **cache_nonce_addr, char **passwd_nonce_addr)
{
gpg_error_t err;
char *keyparms;
{
err = common_gen (keyparms, algo, "",
pub_root, timestamp, expireval, is_subkey,
- keygen_flags, passphrase, cache_nonce_addr);
+ keygen_flags, passphrase,
+ cache_nonce_addr, passwd_nonce_addr);
xfree (keyparms);
}
static int
gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
u32 timestamp, u32 expireval, int is_subkey,
- int keygen_flags, const char *passphrase, char **cache_nonce_addr)
+ int keygen_flags, const char *passphrase,
+ char **cache_nonce_addr, char **passwd_nonce_addr)
{
int err;
char *keyparms;
{
err = common_gen (keyparms, algo, "ne",
pub_root, timestamp, expireval, is_subkey,
- keygen_flags, passphrase, cache_nonce_addr);
+ keygen_flags, passphrase,
+ cache_nonce_addr, passwd_nonce_addr);
xfree (keyparms);
}
}
-/* Ask for the key size. ALGO is the algorithm. If PRIMARY_KEYSIZE
- is not 0, the function asks for the size of the encryption
- subkey. */
-static unsigned
-ask_keysize (int algo, unsigned int primary_keysize)
+static void
+get_keysize_range (int algo,
+ unsigned int *min, unsigned int *def, unsigned int *max)
{
- unsigned int nbits;
- unsigned int min = 1024;
- unsigned int def = DEFAULT_STD_KEYSIZE;
- unsigned int max = 4096;
- int for_subkey = !!primary_keysize;
- int autocomp = 0;
-
- if (primary_keysize && !opt.expert)
- {
- /* Deduce the subkey size from the primary key size. */
- if (algo == PUBKEY_ALGO_DSA && primary_keysize > 3072)
- nbits = 3072; /* For performance reasons we don't support more
- than 3072 bit DSA. However we won't see this
- case anyway because DSA can't be used as an
- encryption subkey ;-). */
- else
- nbits = primary_keysize;
- autocomp = 1;
- goto leave;
- }
+ *min = 1024;
+ *def = DEFAULT_STD_KEYSIZE;
+ *max = 4096;
/* Deviations from the standard values. */
switch(algo)
{
case PUBKEY_ALGO_DSA:
- min = opt.expert? 768 : 1024;
- def=2048;
- max=3072;
+ *min = opt.expert? 768 : 1024;
+ *def=2048;
+ *max=3072;
break;
case PUBKEY_ALGO_ECDSA:
case PUBKEY_ALGO_ECDH:
- min=256;
- def=256;
- max=521;
+ *min=256;
+ *def=256;
+ *max=521;
break;
case PUBKEY_ALGO_EDDSA:
- min=255;
- def=255;
- max=441;
+ *min=255;
+ *def=255;
+ *max=441;
break;
}
+}
- tty_printf(_("%s keys may be between %u and %u bits long.\n"),
- openpgp_pk_algo_name (algo), min, max);
-
- for (;;)
- {
- char *prompt, *answer;
-
- if (for_subkey)
- prompt = xasprintf (_("What keysize do you want "
- "for the subkey? (%u) "), def);
- else
- prompt = xasprintf (_("What keysize do you want? (%u) "), def);
- answer = cpr_get ("keygen.size", prompt);
- cpr_kill_prompt ();
- nbits = *answer? atoi (answer): def;
- xfree(prompt);
- xfree(answer);
-
- if(nbits<min || nbits>max)
- tty_printf(_("%s keysizes must be in the range %u-%u\n"),
- openpgp_pk_algo_name (algo), min, max);
- else
- break;
- }
-
- tty_printf (_("Requested keysize is %u bits\n"), nbits);
- leave:
+/* Return a fixed up keysize depending on ALGO. */
+static unsigned int
+fixup_keysize (unsigned int nbits, int algo, int silent)
+{
if (algo == PUBKEY_ALGO_DSA && (nbits % 64))
{
nbits = ((nbits + 63) / 64) * 64;
- if (!autocomp)
+ if (!silent)
tty_printf (_("rounded up to %u bits\n"), nbits);
}
else if (algo == PUBKEY_ALGO_EDDSA)
nbits = 255;
else
nbits = 441;
- if (!autocomp)
+ if (!silent)
tty_printf (_("rounded to %u bits\n"), nbits);
}
}
nbits = 384;
else
nbits = 521;
- if (!autocomp)
+ if (!silent)
tty_printf (_("rounded to %u bits\n"), nbits);
}
}
else if ((nbits % 32))
{
nbits = ((nbits + 31) / 32) * 32;
- if (!autocomp)
+ if (!silent)
tty_printf (_("rounded up to %u bits\n"), nbits );
}
}
+/* Ask for the key size. ALGO is the algorithm. If PRIMARY_KEYSIZE
+ is not 0, the function asks for the size of the encryption
+ subkey. */
+static unsigned
+ask_keysize (int algo, unsigned int primary_keysize)
+{
+ unsigned int nbits;
+ unsigned int min, def, max;
+ int for_subkey = !!primary_keysize;
+ int autocomp = 0;
+
+ get_keysize_range (algo, &min, &def, &max);
+
+ if (primary_keysize && !opt.expert)
+ {
+ /* Deduce the subkey size from the primary key size. */
+ if (algo == PUBKEY_ALGO_DSA && primary_keysize > 3072)
+ nbits = 3072; /* For performance reasons we don't support more
+ than 3072 bit DSA. However we won't see this
+ case anyway because DSA can't be used as an
+ encryption subkey ;-). */
+ else
+ nbits = primary_keysize;
+ autocomp = 1;
+ goto leave;
+ }
+
+ tty_printf(_("%s keys may be between %u and %u bits long.\n"),
+ openpgp_pk_algo_name (algo), min, max);
+
+ for (;;)
+ {
+ char *prompt, *answer;
+
+ if (for_subkey)
+ prompt = xasprintf (_("What keysize do you want "
+ "for the subkey? (%u) "), def);
+ else
+ prompt = xasprintf (_("What keysize do you want? (%u) "), def);
+ answer = cpr_get ("keygen.size", prompt);
+ cpr_kill_prompt ();
+ nbits = *answer? atoi (answer): def;
+ xfree(prompt);
+ xfree(answer);
+
+ if(nbits<min || nbits>max)
+ tty_printf(_("%s keysizes must be in the range %u-%u\n"),
+ openpgp_pk_algo_name (algo), min, max);
+ else
+ break;
+ }
+
+ tty_printf (_("Requested keysize is %u bits\n"), nbits);
+
+ leave:
+ nbits = fixup_keysize (nbits, algo, autocomp);
+ return nbits;
+}
+
+
/* Ask for the curve. ALGO is the selected algorithm which this
function may adjust. Returns a malloced string with the name of
the curve. BOTH tells that gpg creates a primary and subkey. */
static int
do_create (int algo, unsigned int nbits, const char *curve, KBNODE pub_root,
u32 timestamp, u32 expiredate, int is_subkey,
- int keygen_flags, const char *passphrase, char **cache_nonce_addr)
+ int keygen_flags, const char *passphrase,
+ char **cache_nonce_addr, char **passwd_nonce_addr)
{
gpg_error_t err;
if (algo == PUBKEY_ALGO_ELGAMAL_E)
err = gen_elg (algo, nbits, pub_root, timestamp, expiredate, is_subkey,
- keygen_flags, passphrase, cache_nonce_addr);
+ keygen_flags, passphrase,
+ cache_nonce_addr, passwd_nonce_addr);
else if (algo == PUBKEY_ALGO_DSA)
err = gen_dsa (nbits, pub_root, timestamp, expiredate, is_subkey,
- keygen_flags, passphrase, cache_nonce_addr);
+ keygen_flags, passphrase,
+ cache_nonce_addr, passwd_nonce_addr);
else if (algo == PUBKEY_ALGO_ECDSA
|| algo == PUBKEY_ALGO_EDDSA
|| algo == PUBKEY_ALGO_ECDH)
err = gen_ecc (algo, curve, pub_root, timestamp, expiredate, is_subkey,
- keygen_flags, passphrase, cache_nonce_addr);
+ keygen_flags, passphrase,
+ cache_nonce_addr, passwd_nonce_addr);
else if (algo == PUBKEY_ALGO_RSA)
err = gen_rsa (algo, nbits, pub_root, timestamp, expiredate, is_subkey,
- keygen_flags, passphrase, cache_nonce_addr);
+ keygen_flags, passphrase,
+ cache_nonce_addr, passwd_nonce_addr);
else
BUG();
return i;
}
+
+/* Parse a usage string. The usage keywords "auth", "sign", "encr"
+ * may be elimited by space, tab, or comma. On error -1 is returned
+ * instead of the usage flags/ */
+static int
+parse_usagestr (const char *usagestr)
+{
+ gpg_error_t err;
+ char **tokens = NULL;
+ const char *s;
+ int i;
+ unsigned int use = 0;
+
+ tokens = strtokenize (usagestr, " \t,");
+ if (!tokens)
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("strtokenize failed: %s\n", gpg_strerror (err));
+ return -1;
+ }
+
+ for (i=0; (s = tokens[i]); i++)
+ {
+ if (!*s)
+ ;
+ else if (!ascii_strcasecmp (s, "sign"))
+ use |= PUBKEY_USAGE_SIG;
+ else if (!ascii_strcasecmp (s, "encrypt")
+ || !ascii_strcasecmp (s, "encr"))
+ use |= PUBKEY_USAGE_ENC;
+ else if (!ascii_strcasecmp (s, "auth"))
+ use |= PUBKEY_USAGE_AUTH;
+ else if (!ascii_strcasecmp (s, "cert"))
+ use |= PUBKEY_USAGE_CERT;
+ else
+ {
+ xfree (tokens);
+ return -1; /* error */
+ }
+ }
+
+ xfree (tokens);
+ return use;
+}
+
+
/*
* Parse the usage parameter and set the keyflags. Returns -1 on
* error, 0 for no usage given or 1 for usage available.
parse_parameter_usage (const char *fname,
struct para_data_s *para, enum para_name key)
{
- struct para_data_s *r = get_parameter( para, key );
- char *p, *pn;
- unsigned int use;
-
- if( !r )
- return 0; /* none (this is an optional parameter)*/
-
- use = 0;
- pn = r->u.value;
- while ( (p = strsep (&pn, " \t,")) ) {
- if ( !*p)
- ;
- else if ( !ascii_strcasecmp (p, "sign") )
- use |= PUBKEY_USAGE_SIG;
- else if ( !ascii_strcasecmp (p, "encrypt") )
- use |= PUBKEY_USAGE_ENC;
- else if ( !ascii_strcasecmp (p, "auth") )
- use |= PUBKEY_USAGE_AUTH;
- else {
- log_error("%s:%d: invalid usage list\n", fname, r->lnr );
- return -1; /* error */
- }
+ struct para_data_s *r = get_parameter( para, key );
+ int i;
+
+ if (!r)
+ return 0; /* none (this is an optional parameter)*/
+
+ i = parse_usagestr (r->u.value);
+ if (i == -1)
+ {
+ log_error ("%s:%d: invalid usage list\n", fname, r->lnr );
+ return -1; /* error */
}
- r->u.usage = use;
- return 1;
+
+ r->u.usage = i;
+ return 1;
}
+
static int
parse_revocation_key (const char *fname,
struct para_data_s *para, enum para_name key)
/* Helper for quick_generate_keypair. */
static struct para_data_s *
quickgen_set_para (struct para_data_s *para, int for_subkey,
- int algo, int nbits, const char *curve)
+ int algo, int nbits, const char *curve, unsigned int use)
{
struct para_data_s *r;
- r = xmalloc_clear (sizeof *r + 20);
+ r = xmalloc_clear (sizeof *r + 30);
r->key = for_subkey? pSUBKEYUSAGE : pKEYUSAGE;
- strcpy (r->u.value, for_subkey ? "encrypt" : "sign");
+ if (use)
+ snprintf (r->u.value, 30, "%s%s%s%s",
+ (use & PUBKEY_USAGE_ENC)? "encr " : "",
+ (use & PUBKEY_USAGE_SIG)? "sign " : "",
+ (use & PUBKEY_USAGE_AUTH)? "auth " : "",
+ (use & PUBKEY_USAGE_CERT)? "cert " : "");
+ else
+ strcpy (r->u.value, for_subkey ? "encr" : "sign");
r->next = para;
para = r;
r = xmalloc_clear (sizeof *r + 20);
* Unattended generation of a standard key.
*/
void
-quick_generate_keypair (ctrl_t ctrl, const char *uid)
+quick_generate_keypair (ctrl_t ctrl, const char *uid, const char *algostr,
+ const char *usagestr, const char *expirestr)
{
gpg_error_t err;
struct para_data_s *para = NULL;
memset (&outctrl, 0, sizeof outctrl);
use_tty = (!opt.batch && !opt.answer_yes
+ && !*algostr && !*usagestr && !*expirestr
&& !cpr_enabled ()
&& gnupg_isatty (fileno (stdin))
&& gnupg_isatty (fileno (stdout))
}
}
- para = quickgen_set_para (para, 0,
- DEFAULT_STD_ALGO, DEFAULT_STD_KEYSIZE,
- DEFAULT_STD_CURVE);
- para = quickgen_set_para (para, 1,
- DEFAULT_STD_SUBALGO, DEFAULT_STD_SUBKEYSIZE,
- DEFAULT_STD_SUBCURVE);
+ if (*algostr || *usagestr || *expirestr)
+ {
+ /* Extended unattended mode. Creates only the primary key. */
+ int algo;
+ unsigned int use;
+ u32 expire;
+ unsigned int nbits;
+ char *curve;
+
+ err = parse_algo_usage_expire (ctrl, 0, algostr, usagestr, expirestr,
+ &algo, &use, &expire, &nbits, &curve);
+ if (err)
+ {
+ log_error (_("Key generation failed: %s\n"), gpg_strerror (err) );
+ goto leave;
+ }
+
+ para = quickgen_set_para (para, 0, algo, nbits, curve, use);
+ r = xmalloc_clear (sizeof *r + 20);
+ r->key = pKEYEXPIRE;
+ r->u.expire = expire;
+ r->next = para;
+ para = r;
+ }
+ else
+ {
+ para = quickgen_set_para (para, 0,
+ DEFAULT_STD_ALGO, DEFAULT_STD_KEYSIZE,
+ DEFAULT_STD_CURVE, 0);
+ para = quickgen_set_para (para, 1,
+ DEFAULT_STD_SUBALGO, DEFAULT_STD_SUBKEYSIZE,
+ DEFAULT_STD_SUBCURVE, 0);
+ }
/* If the pinentry loopback mode is not and we have a static
passphrase (i.e. set with --passphrase{,-fd,-file} while in batch
}
proc_parameter_file (ctrl, para, "[internal]", &outctrl, 0);
+
leave:
release_parameter_list (para);
}
, "--full-gen-key" );
para = quickgen_set_para (para, 0,
DEFAULT_STD_ALGO, DEFAULT_STD_KEYSIZE,
- DEFAULT_STD_CURVE);
+ DEFAULT_STD_CURVE, 0);
para = quickgen_set_para (para, 1,
DEFAULT_STD_SUBALGO, DEFAULT_STD_SUBKEYSIZE,
- DEFAULT_STD_SUBCURVE);
+ DEFAULT_STD_SUBCURVE, 0);
}
goto leave;
}
- err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_AESWRAP, 0);
+ err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
+ GCRY_CIPHER_MODE_AESWRAP, 0);
if (!err)
err = gcry_cipher_setkey (cipherhd, kek, keklen);
if (err)
{
- log_error ("error setting up an encryption context: %s\n", gpg_strerror (err));
+ log_error ("error setting up an encryption context: %s\n",
+ gpg_strerror (err));
goto leave;
}
- err = receive_seckey_from_agent (ctrl, cipherhd, &cache_nonce, hexgrip, sk);
+ err = receive_seckey_from_agent (ctrl, cipherhd, 0,
+ &cache_nonce, hexgrip, sk);
if (err)
{
- log_error ("error getting secret key from agent: %s\n", gpg_strerror (err));
+ log_error ("error getting secret key from agent: %s\n",
+ gpg_strerror (err));
goto leave;
}
get_parameter_u32( para, pKEYEXPIRE ), 0,
outctrl->keygen_flags,
get_parameter_passphrase (para),
- &cache_nonce);
+ &cache_nonce, NULL);
else
err = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root,
×tamp,
get_parameter_u32 (para, pSUBKEYEXPIRE), 1,
s ? KEYGEN_FLAG_NO_PROTECTION : outctrl->keygen_flags,
get_parameter_passphrase (para),
- &cache_nonce);
+ &cache_nonce, NULL);
/* Get the pointer to the generated public subkey packet. */
if (!err)
{
log_assert (sub_psk);
if (s)
- err = card_store_key_with_backup (ctrl, sub_psk, opt.homedir);
+ err = card_store_key_with_backup (ctrl,
+ sub_psk, gnupg_homedir ());
}
}
else
}
+static gpg_error_t
+parse_algo_usage_expire (ctrl_t ctrl, int for_subkey,
+ const char *algostr, const char *usagestr,
+ const char *expirestr,
+ int *r_algo, unsigned int *r_usage, u32 *r_expire,
+ unsigned int *r_nbits, char **r_curve)
+{
+ int algo;
+ unsigned int use, nbits;
+ u32 expire;
+ int wantuse;
+ unsigned int min, def, max;
+ const char *curve = NULL;
+ int eccalgo = 0;
+
+ *r_curve = NULL;
+
+ nbits = 0;
+ /* Parse the algo string. */
+ if (!algostr || !*algostr
+ || !strcmp (algostr, "default") || !strcmp (algostr, "-"))
+ {
+ algo = for_subkey? DEFAULT_STD_SUBALGO : DEFAULT_STD_ALGO;
+ use = for_subkey? DEFAULT_STD_SUBKEYUSE : DEFAULT_STD_KEYUSE;
+ nbits = for_subkey?DEFAULT_STD_SUBKEYSIZE : DEFAULT_STD_KEYSIZE;
+ }
+ else if (*algostr == '&' && strlen (algostr) == 41)
+ {
+ /* Take algo from existing key. */
+ algo = check_keygrip (ctrl, algostr+1);
+ /* FIXME: We need the curve name as well. */
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ }
+ else if (!strncmp (algostr, "rsa", 3))
+ {
+ algo = PUBKEY_ALGO_RSA;
+ use = for_subkey? DEFAULT_STD_SUBKEYUSE : DEFAULT_STD_KEYUSE;
+ if (algostr[3])
+ nbits = atoi (algostr + 3);
+ }
+ else if (!strncmp (algostr, "elg", 3))
+ {
+ algo = PUBKEY_ALGO_ELGAMAL_E;
+ use = PUBKEY_USAGE_ENC;
+ if (algostr[3])
+ nbits = atoi (algostr + 3);
+ }
+ else if (!strncmp (algostr, "dsa", 3))
+ {
+ algo = PUBKEY_ALGO_DSA;
+ use = PUBKEY_USAGE_SIG;
+ if (algostr[3])
+ nbits = atoi (algostr + 3);
+ }
+ else if ((curve = openpgp_is_curve_supported (algostr, &algo)))
+ {
+ if (!algo)
+ {
+ algo = PUBKEY_ALGO_ECDH; /* Default ECC algorithm. */
+ eccalgo = 1; /* Remember - we may need to fix it up. */
+ }
+
+ if (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_EDDSA)
+ use = PUBKEY_USAGE_SIG;
+ else
+ use = PUBKEY_USAGE_ENC;
+ }
+ else
+ return gpg_error (GPG_ERR_INV_CURVE);
+
+ /* Parse the usage string. */
+ if (!usagestr || !*usagestr
+ || !strcmp (usagestr, "default") || !strcmp (usagestr, "-"))
+ ; /* Keep default usage */
+ else if ((wantuse = parse_usagestr (usagestr)) != -1)
+ {
+ use = wantuse;
+ if (eccalgo && !(use & PUBKEY_USAGE_ENC))
+ algo = PUBKEY_ALGO_ECDSA; /* Switch from ECDH to ECDSA. */
+ }
+ else
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ /* Make sure a primary key has the CERT usage. */
+ if (!for_subkey)
+ use |= PUBKEY_USAGE_CERT;
+
+ /* Check that usage is possible. */
+ if (/**/((use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH|PUBKEY_USAGE_CERT))
+ && !pubkey_get_nsig (algo))
+ || ((use & PUBKEY_USAGE_ENC)
+ && !pubkey_get_nenc (algo))
+ || (for_subkey && (use & PUBKEY_USAGE_CERT)))
+ return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
+
+ /* Parse the expire string. */
+ if (!expirestr || !*expirestr || !strcmp (expirestr, "none")
+ || !strcmp (expirestr, "never") || !strcmp (expirestr, "-"))
+ expire = 0;
+ else
+ expire = parse_expire_string (expirestr);
+ if (expire == (u32)-1 )
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ /* Make sure the keysize is in the allowed range. */
+ get_keysize_range (algo, &min, &def, &max);
+ if (!nbits)
+ nbits = def;
+ else if (nbits < min)
+ nbits = min;
+ else if (nbits > max)
+ nbits = max;
+
+ nbits = fixup_keysize (nbits, algo, 1);
+
+ if (curve)
+ {
+ *r_curve = xtrystrdup (curve);
+ if (!*r_curve)
+ return gpg_error_from_syserror ();
+ }
+ *r_algo = algo;
+ *r_usage = use;
+ *r_expire = expire;
+ *r_nbits = nbits;
+ return 0;
+}
+
+
/* Add a new subkey to an existing key. Returns 0 if a new key has
- been generated and put into the keyblocks. */
+ been generated and put into the keyblocks. If any of ALGOSTR,
+ USAGESTR, or EXPIRESTR is NULL interactive mode is used. */
gpg_error_t
-generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock)
+generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr,
+ const char *usagestr, const char *expirestr)
{
gpg_error_t err = 0;
+ int interactive;
kbnode_t node;
PKT_public_key *pri_psk = NULL;
PKT_public_key *sub_psk = NULL;
unsigned int nbits = 0;
char *curve = NULL;
u32 cur_time;
+ char *key_from_hexgrip = NULL;
char *hexgrip = NULL;
char *serialno = NULL;
+ char *cache_nonce = NULL;
+ char *passwd_nonce = NULL;
+
+ interactive = (!algostr || !usagestr || !expirestr);
/* Break out the primary key. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
err = hexkeygrip_from_pk (pri_psk, &hexgrip);
if (err)
goto leave;
- if (agent_get_keyinfo (NULL, hexgrip, &serialno))
+ if (agent_get_keyinfo (NULL, hexgrip, &serialno, NULL))
{
- tty_printf (_("Secret parts of primary key are not available.\n"));
+ if (interactive)
+ tty_printf (_("Secret parts of primary key are not available.\n"));
+ else
+ log_info ( _("Secret parts of primary key are not available.\n"));
+ err = gpg_error (GPG_ERR_NO_SECKEY);
goto leave;
}
if (serialno)
- tty_printf (_("Secret parts of primary key are stored on-card.\n"));
-
- xfree (hexgrip);
- hexgrip = NULL;
- algo = ask_algo (ctrl, 1, NULL, &use, &hexgrip);
- log_assert (algo);
+ {
+ if (interactive)
+ tty_printf (_("Secret parts of primary key are stored on-card.\n"));
+ else
+ log_info ( _("Secret parts of primary key are stored on-card.\n"));
+ }
- if (hexgrip)
- nbits = 0;
- else if (algo == PUBKEY_ALGO_ECDSA
- || algo == PUBKEY_ALGO_EDDSA
- || algo == PUBKEY_ALGO_ECDH)
- curve = ask_curve (&algo, NULL);
- else
- nbits = ask_keysize (algo, 0);
+ if (interactive)
+ {
+ algo = ask_algo (ctrl, 1, NULL, &use, &key_from_hexgrip);
+ log_assert (algo);
+
+ if (key_from_hexgrip)
+ nbits = 0;
+ else if (algo == PUBKEY_ALGO_ECDSA
+ || algo == PUBKEY_ALGO_EDDSA
+ || algo == PUBKEY_ALGO_ECDH)
+ curve = ask_curve (&algo, NULL);
+ else
+ nbits = ask_keysize (algo, 0);
- expire = ask_expire_interval (0, NULL);
- if (!cpr_enabled() && !cpr_get_answer_is_yes("keygen.sub.okay",
- _("Really create? (y/N) ")))
+ expire = ask_expire_interval (0, NULL);
+ if (!cpr_enabled() && !cpr_get_answer_is_yes("keygen.sub.okay",
+ _("Really create? (y/N) ")))
+ {
+ err = gpg_error (GPG_ERR_CANCELED);
+ goto leave;
+ }
+ }
+ else /* Unattended mode. */
{
- err = gpg_error (GPG_ERR_CANCELED);
- goto leave;
+ err = parse_algo_usage_expire (ctrl, 1, algostr, usagestr, expirestr,
+ &algo, &use, &expire, &nbits, &curve);
+ if (err)
+ goto leave;
}
- if (hexgrip)
- err = do_create_from_keygrip (ctrl, algo, hexgrip,
- keyblock, cur_time, expire, 1);
+ /* Verify the passphrase now so that we get a cache item for the
+ * primary key passphrase. The agent also returns a passphrase
+ * nonce, which we can use to set the passphrase for the subkey to
+ * that of the primary key. */
+ {
+ char *desc = gpg_format_keydesc (pri_psk, FORMAT_KEYDESC_NORMAL, 1);
+ err = agent_passwd (ctrl, hexgrip, desc, 1 /*=verify*/,
+ &cache_nonce, &passwd_nonce);
+ xfree (desc);
+ }
+
+ /* Start creation. */
+ if (key_from_hexgrip)
+ {
+ err = do_create_from_keygrip (ctrl, algo, key_from_hexgrip,
+ keyblock, cur_time, expire, 1);
+ }
else
- err = do_create (algo, nbits, curve,
- keyblock, cur_time, expire, 1, 0, NULL, NULL);
+ {
+ const char *passwd;
+
+ /* If the pinentry loopback mode is not and we have a static
+ passphrase (i.e. set with --passphrase{,-fd,-file} while in batch
+ mode), we use that passphrase for the new subkey. */
+ if (opt.pinentry_mode != PINENTRY_MODE_LOOPBACK
+ && have_static_passphrase ())
+ passwd = get_static_passphrase ();
+ else
+ passwd = NULL;
+
+ err = do_create (algo, nbits, curve,
+ keyblock, cur_time, expire, 1, 0,
+ passwd, &cache_nonce, &passwd_nonce);
+ }
if (err)
goto leave;
sub_psk = node->pkt->pkt.public_key;
/* Write the binding signature. */
- err = write_keybinding (keyblock, pri_psk, sub_psk, use, cur_time, NULL);
+ err = write_keybinding (keyblock, pri_psk, sub_psk, use, cur_time,
+ cache_nonce);
if (err)
goto leave;
- write_status_text (STATUS_KEY_CREATED, "S");
+ print_status_key_created ('S', sub_psk, NULL);
+
leave:
+ xfree (key_from_hexgrip);
xfree (curve);
xfree (hexgrip);
xfree (serialno);
+ xfree (cache_nonce);
+ xfree (passwd_nonce);
if (err)
log_error (_("Key generation failed: %s\n"), gpg_strerror (err) );
return err;
u32 expire;
u32 cur_time;
struct para_data_s *para = NULL;
+ PKT_public_key *sub_pk = NULL;
log_assert (keyno >= 1 && keyno <= 3);
/* Get the pointer to the generated public subkey packet. */
if (!err)
{
- PKT_public_key *sub_pk = NULL;
-
for (node = pub_keyblock; node; node = node->next)
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
sub_pk = node->pkt->pkt.public_key;
if (err)
log_error (_("Key generation failed: %s\n"), gpg_strerror (err) );
else
- write_status_text (STATUS_KEY_CREATED, "S");
+ print_status_key_created ('S', sub_pk, NULL);
release_parameter_list (para);
return err;
}
if (format == KF_DEFAULT)
format = opt.keyid_format;
if (format == KF_DEFAULT)
- format = KF_SHORT;
+ format = KF_NONE;
switch (format)
{
+ case KF_NONE:
+ if (len)
+ *buffer = 0;
+ break;
+
case KF_SHORT:
snprintf (buffer, len, "%08lX", (ulong)keyid[1]);
break;
{
int format = opt.keyid_format;
if (format == KF_DEFAULT)
- format = KF_SHORT;
+ format = KF_NONE;
switch(format)
{
+ case KF_NONE:
+ return 0;
+
case KF_SHORT:
return 8;
keystr (u32 *keyid)
{
static char keyid_str[KEYID_STR_SIZE];
- return format_keyid (keyid, opt.keyid_format, keyid_str, sizeof (keyid_str));
-}
+ int format = opt.keyid_format;
+ if (format == KF_NONE)
+ format = KF_LONG;
+ return format_keyid (keyid, format, keyid_str, sizeof (keyid_str));
+}
+
+/* This function returns the key id of the main and possible the
+ * subkey as one string. It is used by error messages. */
const char *
keystr_with_sub (u32 *main_kid, u32 *sub_kid)
{
static char buffer[KEYID_STR_SIZE+1+KEYID_STR_SIZE];
char *p;
+ int format = opt.keyid_format;
+
+ if (format == KF_NONE)
+ format = KF_LONG;
- mem2str (buffer, keystr (main_kid), KEYID_STR_SIZE);
+ format_keyid (main_kid, format, buffer, KEYID_STR_SIZE);
if (sub_kid)
{
p = buffer + strlen (buffer);
*p++ = '/';
- mem2str (p, keystr (sub_kid), KEYID_STR_SIZE);
+ format_keyid (sub_kid, format, p, KEYID_STR_SIZE);
}
return buffer;
}
is very bad for W32 because of a sharing violation. For real OSes
it might lead to false results if we are later listing a keyring
which is associated with the inode of a deleted file. */
- check_trustdb_stale ();
+ check_trustdb_stale (ctrl);
#ifdef USE_TOFU
tofu_begin_batch_update ();
{
(void)ctrl;
- check_trustdb_stale ();
+ check_trustdb_stale (ctrl);
if (!list)
list_all (ctrl, 1, 0);
log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
s2k_char = '?';
}
- else if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
+ else if (!agent_get_keyinfo (NULL, hexgrip, &serialno, NULL))
s2k_char = serialno? '>':' ';
else
s2k_char = '#'; /* Key not found. */
show_notation (PKT_signature * sig, int indent, int mode, int which)
{
estream_t fp = mode ? log_get_stream () : es_stdout;
- struct notation *nd, *notations;
+ notation_t nd, notations;
if (which == 0)
which = 3;
{
write_status_buffer (STATUS_NOTATION_NAME,
nd->name, strlen (nd->name), 0);
+ if (nd->flags.critical || nd->flags.human)
+ write_status_text (STATUS_NOTATION_FLAGS,
+ nd->flags.critical && nd->flags.human? "1 1" :
+ nd->flags.critical? "1 0" : "0 1");
write_status_buffer (STATUS_NOTATION_DATA,
nd->value, strlen (nd->value), 50);
}
static void
-list_keyblock_print (KBNODE keyblock, int secret, int fpr,
+list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
struct keylist_context *listctx)
{
int rc;
KBNODE node;
PKT_public_key *pk;
int skip_sigs = 0;
- int s2k_char;
char *hexgrip = NULL;
char *serialno = NULL;
- char pkstrbuf[PUBKEY_STRING_SIZE];
/* Get the keyid from the keyblock. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
if (secret)
{
- if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
- s2k_char = serialno? '>':' ';
+ /* Encode some info about the secret key in SECRET. */
+ if (!agent_get_keyinfo (NULL, hexgrip, &serialno, NULL))
+ secret = serialno? 3 : 1;
else
- s2k_char = '#'; /* Key not found. */
+ secret = 2; /* Key not found. */
}
- else
- s2k_char = ' ';
- check_trustdb_stale ();
-
-
- es_fprintf (es_stdout, "%s%c %s/%s %s",
- secret? "sec":"pub",
- s2k_char,
- pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
- keystr_from_pk (pk), datestr_from_pk (pk));
+ check_trustdb_stale (ctrl);
- if ((opt.list_options & LIST_SHOW_USAGE))
- {
- es_fprintf (es_stdout, " [%s]", usagestr_from_pk (pk, 0));
- }
- if (pk->flags.revoked)
- {
- es_fprintf (es_stdout, " [");
- es_fprintf (es_stdout, _("revoked: %s"), revokestr_from_pk (pk));
- es_fprintf (es_stdout, "]");
- }
- else if (pk->has_expired)
- {
- es_fprintf (es_stdout, " [");
- es_fprintf (es_stdout, _("expired: %s"), expirestr_from_pk (pk));
- es_fprintf (es_stdout, "]");
- }
- else if (pk->expiredate)
- {
- es_fprintf (es_stdout, " [");
- es_fprintf (es_stdout, _("expires: %s"), expirestr_from_pk (pk));
- es_fprintf (es_stdout, "]");
- }
+ /* Print the "pub" line and in KF_NONE mode the fingerprint. */
+ print_key_line (es_stdout, pk, secret);
-#if 0
- /* I need to think about this some more. It's easy enough to
- include, but it looks sort of confusing in the listing... */
- if (opt.list_options & LIST_SHOW_VALIDITY)
- {
- int validity = get_validity (pk, NULL, NULL, 0);
- es_fprintf (es_stdout, " [%s]", trust_value_to_string (validity));
- }
-#endif
-
- if (pk->pubkey_algo >= 100)
- es_fprintf (es_stdout, " [experimental algorithm %d]", pk->pubkey_algo);
-
- es_fprintf (es_stdout, "\n");
-
- if (fpr)
+ if (fpr && opt.keyid_format != KF_NONE)
print_fingerprint (NULL, pk, 0);
if (opt.with_keygrip && hexgrip)
{
PKT_user_id *uid = node->pkt->pkt.user_id;
int indent;
+ int kl = opt.keyid_format == KF_NONE? 10 : keystrlen ();
if ((uid->is_expired || uid->is_revoked)
&& !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
{
const char *validity;
- validity = uid_trust_string_fixed (pk, uid);
- indent = ((keystrlen () + (opt.legacy_list_mode? 9:11))
- - atoi (uid_trust_string_fixed (NULL, NULL)));
+ validity = uid_trust_string_fixed (ctrl, pk, uid);
+ indent = ((kl + (opt.legacy_list_mode? 9:11))
+ - atoi (uid_trust_string_fixed (ctrl, NULL, NULL)));
if (indent < 0 || indent > 40)
indent = 0;
}
else
{
- indent = keystrlen () + (opt.legacy_list_mode? 10:12);
+ indent = kl + (opt.legacy_list_mode? 10:12);
es_fprintf (es_stdout, "uid%*s", indent, "");
}
}
if ((opt.list_options & LIST_SHOW_PHOTOS) && uid->attribs != NULL)
- show_photos (uid->attribs, uid->numattribs, pk, uid);
+ show_photos (ctrl, uid->attribs, uid->numattribs, pk, uid);
}
else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
}
if (secret)
{
- if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
- s2k_char = serialno? '>':' ';
+ if (!agent_get_keyinfo (NULL, hexgrip, &serialno, NULL))
+ secret = serialno? 3 : 1;
else
- s2k_char = '#'; /* Key not found. */
+ secret = '2'; /* Key not found. */
}
- else
- s2k_char = ' ';
- es_fprintf (es_stdout, "%s%c %s/%s %s",
- secret? "ssb":"sub",
- s2k_char,
- pubkey_string (pk2, pkstrbuf, sizeof pkstrbuf),
- keystr_from_pk (pk2), datestr_from_pk (pk2));
-
- if ((opt.list_options & LIST_SHOW_USAGE))
- {
- es_fprintf (es_stdout, " [%s]", usagestr_from_pk (pk2, 0));
- }
- if (pk2->flags.revoked)
- {
- es_fprintf (es_stdout, " [");
- es_fprintf (es_stdout, _("revoked: %s"), revokestr_from_pk (pk2));
- es_fprintf (es_stdout, "]");
- }
- else if (pk2->has_expired)
- {
- es_fprintf (es_stdout, " [");
- es_fprintf (es_stdout, _("expired: %s"), expirestr_from_pk (pk2));
- es_fprintf (es_stdout, "]");
- }
- else if (pk2->expiredate)
- {
- es_fprintf (es_stdout, " [");
- es_fprintf (es_stdout, _("expires: %s"), expirestr_from_pk (pk2));
- es_fprintf (es_stdout, "]");
- }
- es_putc ('\n', es_stdout);
- if (fpr > 1)
+ /* Print the "sub" line. */
+ print_key_line (es_stdout, pk2, secret);
+ if (fpr > 1 || opt.with_subkey_fingerprint)
{
print_fingerprint (NULL, pk2, 0);
if (serialno)
record (i.e. requested via --list-secret-key). If HAS_SECRET a
secret key is available even if SECRET is not set. */
static void
-list_keyblock_colon (KBNODE keyblock, int secret, int has_secret, int fpr)
+list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
+ int secret, int has_secret, int fpr)
{
int rc;
KBNODE kbctx;
log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
}
stubkey = 0;
- if ((secret||has_secret) && agent_get_keyinfo (NULL, hexgrip, &serialno))
+ if ((secret || has_secret)
+ && agent_get_keyinfo (NULL, hexgrip, &serialno, NULL))
stubkey = 1; /* Key not found. */
keyid_from_pk (pk, keyid);
;
else
{
- trustletter = get_validity_info (pk, NULL);
+ trustletter = get_validity_info (ctrl, pk, NULL);
if (trustletter == 'u')
ulti_hack = 1;
es_putc (trustletter, es_stdout);
int uid_validity;
if (!ulti_hack)
- uid_validity = get_validity_info (pk, uid);
+ uid_validity = get_validity_info (ctrl, pk, uid);
else
uid_validity = 'u';
es_fprintf (es_stdout, "%s:%c::::", str, uid_validity);
{
#ifdef USE_TOFU
enum tofu_policy policy;
- if (! tofu_get_policy (pk, uid, &policy)
+ if (! tofu_get_policy (ctrl, pk, uid, &policy)
&& policy != TOFU_POLICY_NONE)
es_fprintf (es_stdout, "%s", tofu_policy_str (policy));
#endif /*USE_TOFU*/
}
stubkey = 0;
if ((secret||has_secret)
- && agent_get_keyinfo (NULL, hexgrip, &serialno))
+ && agent_get_keyinfo (NULL, hexgrip, &serialno, NULL))
stubkey = 1; /* Key not found. */
keyid_from_pk (pk2, keyid2);
}
es_putc (':', es_stdout); /* End of field 15. */
es_putc (':', es_stdout); /* End of field 16. */
- if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
- || pk->pubkey_algo == PUBKEY_ALGO_EDDSA
- || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
+ if (pk2->pubkey_algo == PUBKEY_ALGO_ECDSA
+ || pk2->pubkey_algo == PUBKEY_ALGO_EDDSA
+ || pk2->pubkey_algo == PUBKEY_ALGO_ECDH)
{
- char *curve = openpgp_oid_to_str (pk->pkey[0]);
+ char *curve = openpgp_oid_to_str (pk2->pkey[0]);
const char *name = openpgp_oid_to_curve (curve, 0);
if (!name)
name = curve;
if (opt.print_pka_records || opt.print_dane_records)
list_keyblock_pka (ctrl, keyblock);
else if (opt.with_colons)
- list_keyblock_colon (keyblock, secret, has_secret, fpr);
+ list_keyblock_colon (ctrl, keyblock, secret, has_secret, fpr);
else
- list_keyblock_print (keyblock, secret, fpr, listctx);
+ list_keyblock_print (ctrl, keyblock, secret, fpr, listctx);
if (secret)
es_fflush (es_stdout);
}
* 3: direct use of tty but only primary key.
* 4: direct use of tty but only subkey.
* 10: Same as 0 but with_colons etc is ignored.
+ * 20: Same as 0 but using a compact format.
*
* Modes 1 and 2 will try and print both subkey and primary key
* fingerprints. A MODE with bit 7 set is used internally. If
int primary = 0;
int with_colons = opt.with_colons;
int with_icao = opt.with_icao_spelling;
+ int compact = 0;
if (mode == 10)
{
with_colons = 0;
with_icao = 0;
}
+ else if (mode == 20)
+ {
+ mode = 0;
+ with_colons = 0;
+ compact = 1;
+ }
+
+ if (!opt.fingerprint && !opt.with_fingerprint
+ && opt.with_subkey_fingerprint && opt.keyid_format == KF_NONE)
+ compact = 1;
if (pk->main_keyid[0] == pk->keyid[0]
&& pk->main_keyid[1] == pk->keyid[1])
else
{
fp = override_fp? override_fp : es_stdout;
- text = _(" Key fingerprint =");
+ if (opt.keyid_format == KF_NONE)
+ {
+ text = " "; /* To indent ICAO spelling. */
+ compact = 1;
+ }
+ else
+ text = _(" Key fingerprint =");
}
hexfingerprint (pk, hexfpr, sizeof hexfpr);
{
es_fprintf (fp, "fpr:::::::::%s:", hexfpr);
}
+ else if (compact && !opt.fingerprint && !opt.with_fingerprint)
+ {
+ tty_fprintf (fp, "%*s%s", 6, "", hexfpr);
+ }
else
{
char fmtfpr[MAX_FORMATTED_FINGERPRINT_LEN + 1];
format_hexfingerprint (hexfpr, fmtfpr, sizeof fmtfpr);
- tty_fprintf (fp, "%s %s", text, fmtfpr);
+ if (compact)
+ tty_fprintf (fp, "%*s%s", 6, "", fmtfpr);
+ else
+ tty_fprintf (fp, "%s %s", text, fmtfpr);
}
tty_fprintf (fp, "\n");
if (!with_colons && with_icao)
}
+/* Print a public or secret (sub)key line. Example:
+ *
+ * pub dsa2048 2007-12-31 [SC] [expires: 2018-12-31]
+ * 80615870F5BAD690333686D0F2AD85AC1E42B367
+ *
+ * Some global options may result in a different output format. If
+ * SECRET is set, "sec" or "ssb" is used instead of "pub" or "sub" and
+ * depending on the value a flag character is shown:
+ *
+ * 1 := ' ' Regular secret key
+ * 2 := '#' Stub secret key
+ * 3 := '>' Secret key is on a token.
+ */
+void
+print_key_line (estream_t fp, PKT_public_key *pk, int secret)
+{
+ char pkstrbuf[PUBKEY_STRING_SIZE];
+
+ tty_fprintf (fp, "%s%c %s",
+ pk->flags.primary? (secret? "sec":"pub")
+ /**/ : (secret? "ssb":"sub"),
+ secret == 2? '#' : secret == 3? '>' : ' ',
+ pubkey_string (pk, pkstrbuf, sizeof pkstrbuf));
+ if (opt.keyid_format != KF_NONE)
+ tty_fprintf (fp, "/%s", keystr_from_pk (pk));
+ tty_fprintf (fp, " %s", datestr_from_pk (pk));
+
+ if ((opt.list_options & LIST_SHOW_USAGE))
+ {
+ tty_fprintf (fp, " [%s]", usagestr_from_pk (pk, 0));
+ }
+ if (pk->flags.revoked)
+ {
+ tty_fprintf (fp, " [");
+ tty_fprintf (fp, _("revoked: %s"), revokestr_from_pk (pk));
+ tty_fprintf (fp, "]");
+ }
+ else if (pk->has_expired)
+ {
+ tty_fprintf (fp, " [");
+ tty_fprintf (fp, _("expired: %s"), expirestr_from_pk (pk));
+ tty_fprintf (fp, "]");
+ }
+ else if (pk->expiredate)
+ {
+ tty_fprintf (fp, " [");
+ tty_fprintf (fp, _("expires: %s"), expirestr_from_pk (pk));
+ tty_fprintf (fp, "]");
+ }
+
+#if 0
+ /* I need to think about this some more. It's easy enough to
+ include, but it looks sort of confusing in the listing... */
+ if (opt.list_options & LIST_SHOW_VALIDITY)
+ {
+ int validity = get_validity (ctrl, pk, NULL, NULL, 0);
+ tty_fprintf (fp, " [%s]", trust_value_to_string (validity));
+ }
+#endif
+
+ if (pk->pubkey_algo >= 100)
+ tty_fprintf (fp, " [experimental algorithm %d]", pk->pubkey_algo);
+
+ tty_fprintf (fp, "\n");
+
+ if (pk->flags.primary && opt.keyid_format == KF_NONE)
+ print_fingerprint (fp, pk, 20);
+}
+
void
set_attrib_fd (int fd)
/* If the original options didn't have fast import, and the trustdb
is dirty, rebuild. */
if(!(opt.keyserver_options.import_options&IMPORT_FAST))
- check_or_update_trustdb ();
+ check_or_update_trustdb (ctrl);
return err;
}
/* Loop over all URLs in STRLIST and fetch the key at that URL. Note
- that the fetch operation ignores the configured key servers and
+ that the fetch operation ignores the configured keyservers and
instead directly retrieves the keys. */
int
keyserver_fetch (ctrl_t ctrl, strlist_t urilist)
/* If the original options didn't have fast import, and the trustdb
is dirty, rebuild. */
if (!(opt.keyserver_options.import_options&IMPORT_FAST))
- check_or_update_trustdb ();
+ check_or_update_trustdb (ctrl);
return 0;
}
void keyedit_passwd (ctrl_t ctrl, const char *username);
void keyedit_quick_adduid (ctrl_t ctrl, const char *username,
const char *newuid);
+void keyedit_quick_addkey (ctrl_t ctrl, const char *fpr, const char *algostr,
+ const char *usagestr, const char *expirestr);
void keyedit_quick_sign (ctrl_t ctrl, const char *fpr,
strlist_t uids, strlist_t locusr, int local);
void show_basic_key_info (KBNODE keyblock);
u32 ask_expire_interval(int object,const char *def_expire);
u32 ask_expiredate(void);
unsigned int ask_key_flags (int algo, int subkey, unsigned int current);
-void quick_generate_keypair (ctrl_t ctrl, const char *uid);
+void quick_generate_keypair (ctrl_t ctrl, const char *uid, const char *algostr,
+ const char *usagestr, const char *expirestr);
void generate_keypair (ctrl_t ctrl, int full, const char *fname,
const char *card_serialno, int card_backup_key);
int keygen_set_std_prefs (const char *string,int personal);
gpg_error_t make_backsig (PKT_signature *sig, PKT_public_key *pk,
PKT_public_key *sub_pk, PKT_public_key *sub_psk,
u32 timestamp, const char *cache_nonce);
-gpg_error_t generate_subkeypair (ctrl_t ctrl, kbnode_t pub_keyblock);
+gpg_error_t generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock,
+ const char *algostr,
+ const char *usagestr,
+ const char *expirestr);
#ifdef ENABLE_CARD_SUPPORT
gpg_error_t generate_card_subkeypair (kbnode_t pub_keyblock,
int keyno, const char *serialno);
void **r_data, size_t *r_datalen);
gpg_error_t receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
+ int cleartext,
char **cache_nonce_addr, const char *hexgrip,
PKT_public_key *pk);
void print_seckey_info (PKT_public_key *pk);
void print_pubkey_info (estream_t fp, PKT_public_key *pk);
void print_card_key_info (estream_t fp, KBNODE keyblock);
+void print_key_line (estream_t fp, PKT_public_key *pk, int secret);
/*-- verify.c --*/
void print_file_status( int status, const char *name, int what );
static void
list_node (CTX c, kbnode_t node)
{
- int mainkey;
- char pkstrbuf[PUBKEY_STRING_SIZE];
-
if (!node)
;
- else if ((mainkey = (node->pkt->pkttype == PKT_PUBLIC_KEY))
- || node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
+ else if (node->pkt->pkttype == PKT_PUBLIC_KEY
+ || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
PKT_public_key *pk = node->pkt->pkt.public_key;
u32 keyid[2];
keyid_from_pk( pk, keyid );
- if (mainkey)
+ if (pk->flags.primary)
c->trustletter = (opt.fast_list_mode?
- 0 : get_validity_info( pk, NULL));
- es_printf ("%s:", mainkey? "pub":"sub" );
+ 0 : get_validity_info (c->ctrl, pk, NULL));
+ es_printf ("%s:", pk->flags.primary? "pub":"sub" );
if (c->trustletter)
es_putc (c->trustletter, es_stdout);
es_printf (":%u:%d:%08lX%08lX:%s:%s::",
(ulong)keyid[0],(ulong)keyid[1],
colon_datestr_from_pk( pk ),
colon_strtime (pk->expiredate) );
- if (mainkey && !opt.fast_list_mode)
+ if (pk->flags.primary && !opt.fast_list_mode)
es_putc (get_ownertrust_info (pk), es_stdout);
es_putc (':', es_stdout);
+ es_putc ('\n', es_stdout);
}
else
- es_printf ("%s %s/%s %s",
- mainkey? "pub":"sub",
- pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
- keystr_from_pk (pk),
- datestr_from_pk (pk));
-
- if (pk->flags.revoked)
- {
- es_printf (" [");
- es_printf (_("revoked: %s"), revokestr_from_pk (pk));
- es_printf ("]\n");
- }
- else if( pk->expiredate && !opt.with_colons)
{
- es_printf (" [");
- es_printf (_("expires: %s"), expirestr_from_pk (pk));
- es_printf ("]\n");
+ print_key_line (es_stdout, pk, 0);
}
- else
- es_putc ('\n', es_stdout);
- if ((mainkey && opt.fingerprint) || opt.fingerprint > 1)
+ if (opt.keyid_format == KF_NONE && !opt.with_colons)
+ ; /* Already printed. */
+ else if ((pk->flags.primary && opt.fingerprint) || opt.fingerprint > 1)
print_fingerprint (NULL, pk, 0);
if (opt.with_colons)
node->next->pkt->pkt.ring_trust->trustval);
}
- if (mainkey)
+ if (pk->flags.primary)
{
+ int kl = opt.keyid_format == KF_NONE? 0 : keystrlen ();
+
/* Now list all userids with their signatures. */
for (node = node->next; node; node = node->next)
{
node->pkt->pkt.user_id->attrib_data?"uat":"uid");
else
es_printf ("uid%*s",
- (int)keystrlen ()+(opt.legacy_list_mode? 9:11),
+ kl + (opt.legacy_list_mode? 9:11),
"" );
print_userid (node->pkt);
if (opt.with_colons)
}
}
}
- else if ((mainkey = (node->pkt->pkttype == PKT_SECRET_KEY) )
+ else if (node->pkt->pkttype == PKT_SECRET_KEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY)
{
}
+/* Return true if the AKL has the WKD method specified. */
+static int
+akl_has_wkd_method (void)
+{
+ struct akl *akl;
+
+ for (akl = opt.auto_key_locate; akl; akl = akl->next)
+ if (akl->type == AKL_WKD)
+ return 1;
+ return 0;
+}
+
+
static void
print_good_bad_signature (int statno, const char *keyid_str, kbnode_t un,
PKT_signature *sig, int rc)
}
/* Check that the message composition is valid.
-
- Per RFC-2440bis (-15) allowed:
-
- S{1,n} -- detached signature.
- S{1,n} P -- old style PGP2 signature
- O{1,n} P S{1,n} -- standard OpenPGP signature.
- C P S{1,n} -- cleartext signature.
-
-
- O = One-Pass Signature packet.
- S = Signature packet.
- P = OpenPGP Message packet (Encrypted | Compressed | Literal)
- (Note that the current rfc2440bis draft also allows
- for a signed message but that does not work as it
- introduces ambiguities.)
- We keep track of these packages using the marker packet
- CTRLPKT_PLAINTEXT_MARK.
- C = Marker packet for cleartext signatures.
-
- We reject all other messages.
-
- Actually we are calling this too often, i.e. for verification of
- each message but better have some duplicate work than to silently
- introduce a bug here.
- */
+ *
+ * Per RFC-2440bis (-15) allowed:
+ *
+ * S{1,n} -- detached signature.
+ * S{1,n} P -- old style PGP2 signature
+ * O{1,n} P S{1,n} -- standard OpenPGP signature.
+ * C P S{1,n} -- cleartext signature.
+ *
+ *
+ * O = One-Pass Signature packet.
+ * S = Signature packet.
+ * P = OpenPGP Message packet (Encrypted | Compressed | Literal)
+ * (Note that the current rfc2440bis draft also allows
+ * for a signed message but that does not work as it
+ * introduces ambiguities.)
+ * We keep track of these packages using the marker packet
+ * CTRLPKT_PLAINTEXT_MARK.
+ * C = Marker packet for cleartext signatures.
+ *
+ * We reject all other messages.
+ *
+ * Actually we are calling this too often, i.e. for verification of
+ * each message but better have some duplicate work than to silently
+ * introduce a bug here.
+ */
{
kbnode_t n;
int n_onepass, n_sig;
}
}
- write_status_text (STATUS_NEWSIG, NULL);
+ if (sig->signers_uid)
+ write_status_buffer (STATUS_NEWSIG,
+ sig->signers_uid, strlen (sig->signers_uid), 0);
+ else
+ write_status_text (STATUS_NEWSIG, NULL);
astr = openpgp_pk_algo_name ( sig->pubkey_algo );
if (keystrlen () > 8)
{
log_info (_("Signature made %s\n"), asctimestamp(sig->timestamp));
log_info (_(" using %s key %s\n"),
- astr? astr: "?",keystr(sig->keyid));
+ astr? astr: "?", keystr(sig->keyid));
}
else
log_info (_("Signature made %s using %s key ID %s\n"),
rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey );
- /* If the key isn't found, check for a preferred keyserver */
-
+ /* If the key isn't found, check for a preferred keyserver. */
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && sig->flags.pref_ks)
{
const byte *p;
}
}
- /* If the preferred keyserver thing above didn't work, our second
- try is to use the URI from a DNS PKA record. */
+ /* If the avove methods didn't work, our next try is to use the URI
+ * from a DNS PKA record. */
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
&& (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE)
&& (opt.keyserver_options.options & KEYSERVER_HONOR_PKA_RECORD))
{
glo_ctrl.in_auto_key_retrieve++;
res = keyserver_import_keyid (c->ctrl, sig->keyid, spec);
- glo_ctrl.in_auto_key_retrieve--;
- free_keyserver_spec (spec);
- if (!res)
- rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey );
+ glo_ctrl.in_auto_key_retrieve--;
+ free_keyserver_spec (spec);
+ if (!res)
+ rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey );
}
}
}
- /* If the preferred keyserver thing above didn't work and we got
- no information from the DNS PKA, this is a third try. */
+ /* If the above methods didn't work, our next try is to use locate
+ * the key via its fingerprint from a keyserver. This requires
+ * that the signers fingerprint is encoded in the signature. We
+ * favor this over the WKD method (to be tried next), because an
+ * arbitrary keyserver is less subject to web bug like
+ * monitoring. */
+ /* if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY */
+ /* && signature_hash_full_fingerprint (sig) */
+ /* && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE) */
+ /* && keyserver_any_configured (c->ctrl)) */
+ /* { */
+ /* int res; */
+
+ /* glo_ctrl.in_auto_key_retrieve++; */
+ /* res = keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver ); */
+ /* glo_ctrl.in_auto_key_retrieve--; */
+ /* if (!res) */
+ /* rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey ); */
+ /* } */
+
+ /* 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;
+
+ glo_ctrl.in_auto_key_retrieve++;
+ res = keyserver_import_wkd (c->ctrl, sig->signers_uid, 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, NULL, &is_expkey, &is_revkey );
+ }
+ /* 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)
&& keyserver_any_configured (c->ctrl))
int res;
glo_ctrl.in_auto_key_retrieve++;
- res=keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver );
+ res = keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver );
glo_ctrl.in_auto_key_retrieve--;
if (!res)
rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey );
does not print a LF we need to compute the validity
before calling that function. */
if ((opt.verify_options & VERIFY_SHOW_UID_VALIDITY))
- valid = get_validity (pk, un->pkt->pkt.user_id, NULL, 0);
+ valid = get_validity (c->ctrl, pk, un->pkt->pkt.user_id, NULL, 0);
else
valid = 0; /* Not used. */
dump_attribs (un->pkt->pkt.user_id, pk);
if (opt.verify_options&VERIFY_SHOW_PHOTOS)
- show_photos (un->pkt->pkt.user_id->attribs,
+ show_photos (c->ctrl,
+ un->pkt->pkt.user_id->attribs,
un->pkt->pkt.user_id->numattribs,
pk ,un->pkt->pkt.user_id);
}
actually ask the user to update any trust
information. */
valid = (trust_value_to_string
- (get_validity (pk, un->pkt->pkt.user_id, sig, 0)));
+ (get_validity (c->ctrl, pk,
+ un->pkt->pkt.user_id, sig, 0)));
log_printf (" [%s]\n",valid);
}
else
{
if ((opt.verify_options & VERIFY_PKA_LOOKUPS))
pka_uri_from_sig (c, sig); /* Make sure PKA info is available. */
- rc = check_signatures_trust (sig);
+ rc = check_signatures_trust (c->ctrl, sig);
}
/* Print extra information about the signature. */
char *flagfile = NULL;
char *agent_version = NULL;
- secring = make_filename (opt.homedir, "secring" EXTSEP_S "gpg", NULL);
+ secring = make_filename (gnupg_homedir (), "secring" EXTSEP_S "gpg", NULL);
if (access (secring, F_OK))
goto leave; /* Does not exist or is not readable. */
- flagfile = make_filename (opt.homedir, V21_MIGRATION_FNAME, NULL);
+ flagfile = make_filename (gnupg_homedir (), V21_MIGRATION_FNAME, NULL);
if (!access (flagfile, F_OK))
goto leave; /* Does exist - fine. */
int with_key_data;
int with_icao_spelling; /* Print ICAO spelling with fingerprints. */
int with_fingerprint; /* Option --with-fingerprint active. */
+ int with_subkey_fingerprint; /* Option --with-subkey-fingerprint active. */
int with_keygrip; /* Option --with-keygrip active. */
int with_secret; /* Option --with-secret active. */
int with_wkd_hash; /* Option --with-wkd-hash. */
int marginals_needed;
int completes_needed;
int max_cert_depth;
- const char *homedir;
const char *agent_program;
const char *dirmngr_program;
} compliance;
enum
{
- KF_DEFAULT, KF_SHORT, KF_LONG, KF_0xSHORT, KF_0xLONG
+ KF_DEFAULT, KF_NONE, KF_SHORT, KF_LONG, KF_0xSHORT, KF_0xLONG
} keyid_format;
int shm_coprocess;
const char *set_filename;
unsigned int allow_multiple_messages:1;
unsigned int allow_weak_digest_algos:1;
unsigned int large_rsa:1;
+ unsigned int disable_signer_uid:1;
} flags;
/* Linked list of ways to find a key if the key isn't on the local
#define DBG_IPC_VALUE 1024 /* debug assuan communication */
#define DBG_CARD_IO_VALUE 2048 /* debug smart card I/O. */
#define DBG_CLOCK_VALUE 4096
-#define DBG_LOOKUP_VALUE 8192 /* debug the kety lookup */
+#define DBG_LOOKUP_VALUE 8192 /* debug the key lookup */
#define DBG_EXTPROG_VALUE 16384 /* debug external program calls */
/* Tests for the debugging flags. */
int numrevkeys;
pka_info_t *pka_info; /* Malloced PKA data or NULL if not
available. See also flags.pka_tried. */
+ char *signers_uid; /* Malloced value of the SIGNERS_UID
+ * subpacket. */
subpktarea_t *hashed; /* All subpackets with hashed data (v4 only). */
subpktarea_t *unhashed; /* Ditto for unhashed data. */
/* First 2 bytes of the digest. (Serialized. Note: this is not
/* The notation's name. */
char *name;
/* If the notation is human readable, then the value is stored here
- as a NUL-terminated string. */
+ as a NUL-terminated string. If it is not human readable a human
+ readable approximation of the binary value _may_ be stored
+ here. */
char *value;
/* Sometimes we want to %-expand the value. In these cases, we save
that transformed value here. */
char *altvalue;
- /* If the notation is not human readable, then the value is strored
+ /* If the notation is not human readable, then the value is stored
here. */
unsigned char *bdat;
/* The amount of data stored in BDAT.
{
/* The notation is critical. */
unsigned int critical:1;
+ /* The notation is human readable. */
+ unsigned int human:1;
/* The notation should be deleted. */
unsigned int ignore:1;
} flags;
/* A field to facilitate creating a list of notations. */
struct notation *next;
};
+typedef struct notation *notation_t;
/*-- mainproc.c --*/
void reset_literals_seen(void);
es_fprintf (listfp, " %d", buffer[i]);
break;
case SIGSUBPKT_KS_FLAGS:
- es_fputs ("key server preferences:", listfp);
+ es_fputs ("keyserver preferences:", listfp);
for (i = 0; i < length; i++)
es_fprintf (listfp, " %02X", buffer[i]);
break;
case SIGSUBPKT_PREF_KS:
- es_fputs ("preferred key server: ", listfp);
+ es_fputs ("preferred keyserver: ", listfp);
es_write_sanitized (listfp, buffer, length, ")", NULL);
break;
case SIGSUBPKT_PRIMARY_UID:
if (p)
sig->flags.pref_ks = 1;
+ p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIGNERS_UID, &len);
+ if (p && len)
+ {
+ sig->signers_uid = xtrymalloc (len+1);
+ if (!sig->signers_uid)
+ {
+ rc = gpg_error_from_syserror ();
+ goto leave;
+ }
+ /* Note that we don't care about binary zeroes in the value. */
+ memcpy (sig->signers_uid, p, len);
+ sig->signers_uid[len] = 0;
+ }
+
p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_NOTATION, NULL);
if (p)
sig->flags.notation = 1;
/* Generate a new photo id packet, or return NULL if canceled.
FIXME: Should we add a duplicates check similar to generate_user_id? */
PKT_user_id *
-generate_photo_id(PKT_public_key *pk,const char *photo_name)
+generate_photo_id (ctrl_t ctrl, PKT_public_key *pk,const char *photo_name)
{
PKT_user_id *uid;
int error=1,i;
"user" may not be able to dismiss a viewer window! */
if(opt.command_fd==-1)
{
- show_photos (uid->attribs, uid->numattribs, pk, uid);
+ show_photos (ctrl, uid->attribs, uid->numattribs, pk, uid);
switch(cpr_get_answer_yes_no_quit("photoid.jpeg.okay",
_("Is this photo correct (y/N/q)? ")))
{
}
#endif
+
void
-show_photos(const struct user_attribute *attrs, int count,
- PKT_public_key *pk, PKT_user_id *uid)
+show_photos (ctrl_t ctrl, const struct user_attribute *attrs, int count,
+ PKT_public_key *pk, PKT_user_id *uid)
{
#ifdef DISABLE_PHOTO_VIEWER
(void)attrs;
memset (&args, 0, sizeof(args));
args.pk = pk;
- args.validity_info = get_validity_info (pk, uid);
- args.validity_string = get_validity_string (pk, uid);
+ args.validity_info = get_validity_info (ctrl, pk, uid);
+ args.validity_string = get_validity_string (ctrl, pk, uid);
namehash_from_uid (uid);
args.namehash = uid->namehash;
#include "packet.h"
-PKT_user_id *generate_photo_id(PKT_public_key *pk,const char *filename);
+PKT_user_id *generate_photo_id (ctrl_t ctrl,
+ PKT_public_key *pk,const char *filename);
int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len);
char *image_type_to_string(byte type,int style);
-void show_photos (const struct user_attribute *attrs, int count,
+void show_photos (ctrl_t ctrl, const struct user_attribute *attrs, int count,
PKT_public_key *pk, PKT_user_id *uid);
#endif /* !_PHOTOID_H_ */
*/
#ifndef NO_TRUST_MODELS
static int
-do_edit_ownertrust (PKT_public_key *pk, int mode,
+do_edit_ownertrust (ctrl_t ctrl, PKT_public_key *pk, int mode,
unsigned *new_trust, int defer_help )
{
char *p;
int min_num;
int did_help=defer_help;
unsigned int minimum = tdb_get_min_ownertrust (pk);
- char pkstrbuf[PUBKEY_STRING_SIZE];
switch(minimum)
{
{
KBNODE keyblock, un;
- tty_printf(_("No trust value assigned to:\n"));
- tty_printf("%s/%s %s\n",
- pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
- keystr(keyid), datestr_from_pk( pk ) );
- p=get_user_id_native(keyid);
- tty_printf(_(" \"%s\"\n"),p);
- xfree(p);
+ tty_printf (_("No trust value assigned to:\n"));
+ print_key_line (NULL, pk, 0);
+
+ p = get_user_id_native(keyid);
+ tty_printf (_(" \"%s\"\n"),p);
+ xfree (p);
keyblock = get_pubkeyblock (keyid);
if (!keyblock)
if((opt.verify_options&VERIFY_SHOW_PHOTOS)
&& un->pkt->pkt.user_id->attrib_data)
- show_photos (un->pkt->pkt.user_id->attribs,
+ show_photos (ctrl,
+ un->pkt->pkt.user_id->attribs,
un->pkt->pkt.user_id->numattribs, pk,
un->pkt->pkt.user_id);
*/
#ifndef NO_TRUST_MODELS
int
-edit_ownertrust (PKT_public_key *pk, int mode )
+edit_ownertrust (ctrl_t ctrl, PKT_public_key *pk, int mode )
{
unsigned int trust = 0;
int no_help = 0;
for(;;)
{
- switch ( do_edit_ownertrust (pk, mode, &trust, no_help ) )
+ switch ( do_edit_ownertrust (ctrl, pk, mode, &trust, no_help ) )
{
case -1: /* quit */
return -1;
* Returns an error code if we should not trust this signature.
*/
int
-check_signatures_trust( PKT_signature *sig )
+check_signatures_trust (ctrl_t ctrl, PKT_signature *sig)
{
PKT_public_key *pk = xmalloc_clear( sizeof *pk );
unsigned int trustlevel = TRUST_UNKNOWN;
log_info(_("WARNING: this key might be revoked (revocation key"
" not present)\n"));
- trustlevel = get_validity (pk, NULL, sig, 1);
+ trustlevel = get_validity (ctrl, pk, NULL, sig, 1);
if ( (trustlevel & TRUST_FLAG_REVOKED) )
{
}
/* Key found and usable. Check validity. */
- trustlevel = get_validity (pk, pk->user_id, NULL, 1);
+ trustlevel = get_validity (ctrl, pk, pk->user_id, NULL, 1);
if ( (trustlevel & TRUST_FLAG_DISABLED) )
{
/* Key has been disabled. */
{ /* Check validity of this key. */
int trustlevel;
- trustlevel = get_validity (pk, pk->user_id, NULL, 1);
+ trustlevel = get_validity (ctrl, pk, pk->user_id, NULL, 1);
if ( (trustlevel & TRUST_FLAG_DISABLED) )
{
tty_printf (_("Public key is disabled.\n") );
}
+static void
+write_status_progress (const char *what,
+ unsigned long current, unsigned long total)
+{
+ char buffer[50];
+
+ /* Although we use an unsigned long for the values, 32 bit
+ * applications using GPGME will use an "int" and thus are limited
+ * in the total size which can be represented. On Windows, where
+ * sizeof(int)==sizeof(long), this is even worse and will lead to an
+ * integer overflow for all files larger than 2 GiB. Although, the
+ * allowed value range of TOTAL and CURRENT is nowhere specified, we
+ * better protect applications from the need to handle negative
+ * values. The common usage pattern of the progress information is
+ * to display how many percent of the operation has been done and
+ * thus scaling CURRENT and TOTAL down before they get to large,
+ * should not have a noticeable effect except for rounding
+ * imprecision. */
+ if (total)
+ {
+ if (current > total)
+ current = total;
+
+ while (total > 1024*1024)
+ {
+ total /= 1024;
+ current /= 1024;
+ }
+ }
+ else
+ {
+ while (current > 1024*1024)
+ {
+ current /= 1024;
+ }
+ }
+
+ snprintf (buffer, sizeof buffer, "%.20s ? %lu %lu",
+ what? what : "?", current, total);
+ write_status_text (STATUS_PROGRESS, buffer);
+}
+
+
/****************
* The filter is used to report progress to the user.
*/
if (control == IOBUFCTRL_INIT)
{
- char buffer[50];
-
pfx->last = 0;
pfx->offset = 0;
pfx->last_time = make_timestamp ();
- sprintf (buffer, "%.20s ? %lu %lu",
- pfx->what? pfx->what : "?",
- pfx->offset,
- pfx->total);
- write_status_text (STATUS_PROGRESS, buffer);
+ write_status_progress (pfx->what, pfx->offset, pfx->total);
}
else if (control == IOBUFCTRL_UNDERFLOW)
{
if ((len == -1 && pfx->offset != pfx->last)
|| timestamp - pfx->last_time > 0)
{
- char buffer[50];
-
- sprintf (buffer, "%.20s ? %lu %lu",
- pfx->what? pfx->what : "?",
- pfx->offset,
- pfx->total);
- write_status_text (STATUS_PROGRESS, buffer);
-
+ write_status_progress (pfx->what, pfx->offset, pfx->total);
pfx->last = pfx->offset;
pfx->last_time = timestamp;
}
void *leadin;
size_t len;
u32 keyid[2];
- char pkstrbuf[PUBKEY_STRING_SIZE];
+ int kl;
char *orig_codeset;
- dir = get_openpgp_revocdir (opt.homedir);
+ dir = get_openpgp_revocdir (gnupg_homedir ());
tmpstr = hexfingerprint (psk, NULL, 0);
fname = xstrconcat (dir, DIRSEP_S, tmpstr, NULL);
xfree (tmpstr);
es_fprintf (memfp, "%s\n\n",
_("This is a revocation certificate for the OpenPGP key:"));
- es_fprintf (memfp, "pub %s/%s %s\n",
- pubkey_string (psk, pkstrbuf, sizeof pkstrbuf),
- keystr (keyid),
- datestr_from_pk (psk));
+ print_key_line (memfp, psk, 0);
- print_fingerprint (memfp, psk, 3);
+ if (opt.keyid_format != KF_NONE)
+ print_fingerprint (memfp, psk, 3);
+
+ kl = opt.keyid_format == KF_NONE? 0 : keystrlen ();
tmpstr = get_user_id (keyid, &len);
es_fprintf (memfp, "uid%*s%.*s\n\n",
- (int)keystrlen () + 10, "",
+ kl + 10, "",
(int)len, tmpstr);
xfree (tmpstr);
assuan_set_pointer (ctx, ctrl);
if (opt.verbose || opt.debug)
{
- char *tmp = NULL;
+ char *tmp;
tmp = xtryasprintf ("Home: %s\n"
"Config: %s\n"
"%s",
- opt.homedir,
+ gnupg_homedir (),
"fixme: need config filename",
hello);
if (tmp)
int i,n;
gcry_mpi_t a;
- if( len + asnlen + 4 > nframe )
- log_bug ("can't encode a %d bit MD into a %d bits frame, algo=%d\n",
- (int)(len*8), (int)nbits, algo);
+ if (len + asnlen + 4 > nframe)
+ {
+ log_error ("can't encode a %d bit MD into a %d bits frame, algo=%d\n",
+ (int)(len*8), (int)nbits, algo);
+ return NULL;
+ }
/* We encode the MD in this way:
*
*is_selfsig = 1;
}
else
- /* See if one of the subkeys was the signer (although this is
- extremely unlikely). */
{
kbnode_t ctx = NULL;
kbnode_t n;
- while ((n = walk_kbnode (kb, &ctx, PKT_PUBLIC_SUBKEY)))
+ /* See if one of the subkeys was the signer (although this
+ is extremely unlikely). */
+ while ((n = walk_kbnode (kb, &ctx, 0)))
{
- PKT_public_key *subk = n->pkt->pkt.public_key;
+ PKT_public_key *subk;
+
+ if (n->pkt->pkttype != PKT_PUBLIC_SUBKEY)
+ continue;
+
+ subk = n->pkt->pkt.public_key;
if (sig->keyid[0] == subk->keyid[0]
&& sig->keyid[1] == subk->keyid[1])
/* Issued by a subkey. */
#include "pkglue.h"
#include "sysutils.h"
#include "call-agent.h"
-
+#include "mbox-util.h"
#ifdef HAVE_DOSISH_SYSTEM
#define LF "\r\n"
mk_notation_policy_etc (PKT_signature *sig,
PKT_public_key *pk, PKT_public_key *pksk)
{
- const char *string;
- char *s=NULL;
- strlist_t pu=NULL;
- struct notation *nd=NULL;
- struct expando_args args;
+ const char *string;
+ char *p = NULL;
+ strlist_t pu = NULL;
+ struct notation *nd = NULL;
+ struct expando_args args;
- log_assert(sig->version>=4);
+ log_assert (sig->version >= 4);
- memset(&args,0,sizeof(args));
- args.pk=pk;
- args.pksk=pksk;
+ memset (&args, 0, sizeof(args));
+ args.pk = pk;
+ args.pksk = pksk;
- /* notation data */
- if(IS_SIG(sig) && opt.sig_notations)
- nd=opt.sig_notations;
- else if( IS_CERT(sig) && opt.cert_notations )
- nd=opt.cert_notations;
+ /* Notation data. */
+ if (IS_SIG(sig) && opt.sig_notations)
+ nd = opt.sig_notations;
+ else if (IS_CERT(sig) && opt.cert_notations)
+ nd = opt.cert_notations;
- if(nd)
- {
- struct notation *i;
+ if (nd)
+ {
+ struct notation *item;
- for(i=nd;i;i=i->next)
- {
- i->altvalue=pct_expando(i->value,&args);
- if(!i->altvalue)
- log_error(_("WARNING: unable to %%-expand notation "
- "(too large). Using unexpanded.\n"));
- }
+ for (item = nd; item; item = item->next)
+ {
+ item->altvalue = pct_expando (item->value,&args);
+ if (!item->altvalue)
+ log_error (_("WARNING: unable to %%-expand notation "
+ "(too large). Using unexpanded.\n"));
+ }
- keygen_add_notations(sig,nd);
+ keygen_add_notations (sig, nd);
- for(i=nd;i;i=i->next)
- {
- xfree(i->altvalue);
- i->altvalue=NULL;
- }
- }
+ for (item = nd; item; item = item->next)
+ {
+ xfree (item->altvalue);
+ item->altvalue = NULL;
+ }
+ }
- /* set policy URL */
- if( IS_SIG(sig) && opt.sig_policy_url )
- pu=opt.sig_policy_url;
- else if( IS_CERT(sig) && opt.cert_policy_url )
- pu=opt.cert_policy_url;
+ /* Set policy URL. */
+ if (IS_SIG(sig) && opt.sig_policy_url)
+ pu = opt.sig_policy_url;
+ else if (IS_CERT(sig) && opt.cert_policy_url)
+ pu = opt.cert_policy_url;
- for(;pu;pu=pu->next)
- {
- string = pu->d;
+ for (; pu; pu = pu->next)
+ {
+ string = pu->d;
- s=pct_expando(string,&args);
- if(!s)
- {
- log_error(_("WARNING: unable to %%-expand policy URL "
- "(too large). Using unexpanded.\n"));
- s=xstrdup(string);
- }
+ p = pct_expando (string, &args);
+ if (!p)
+ {
+ log_error(_("WARNING: unable to %%-expand policy URL "
+ "(too large). Using unexpanded.\n"));
+ p = xstrdup(string);
+ }
- build_sig_subpkt(sig,SIGSUBPKT_POLICY|
- ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0),
- s,strlen(s));
+ build_sig_subpkt (sig, (SIGSUBPKT_POLICY
+ | ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0)),
+ p, strlen (p));
- xfree(s);
- }
+ xfree (p);
+ }
- /* preferred keyserver URL */
- if( IS_SIG(sig) && opt.sig_keyserver_url )
- pu=opt.sig_keyserver_url;
+ /* Preferred keyserver URL. */
+ if (IS_SIG(sig) && opt.sig_keyserver_url)
+ pu = opt.sig_keyserver_url;
- for(;pu;pu=pu->next)
- {
- string = pu->d;
+ for (; pu; pu = pu->next)
+ {
+ string = pu->d;
- s=pct_expando(string,&args);
- if(!s)
- {
- log_error(_("WARNING: unable to %%-expand preferred keyserver URL"
- " (too large). Using unexpanded.\n"));
- s=xstrdup(string);
- }
+ p = pct_expando (string, &args);
+ if (!p)
+ {
+ log_error (_("WARNING: unable to %%-expand preferred keyserver URL"
+ " (too large). Using unexpanded.\n"));
+ p = xstrdup (string);
+ }
- build_sig_subpkt(sig,SIGSUBPKT_PREF_KS|
- ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0),
- s,strlen(s));
+ build_sig_subpkt (sig, (SIGSUBPKT_PREF_KS
+ | ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0)),
+ p, strlen (p));
+ xfree (p);
+ }
- xfree(s);
- }
+ /* Set signer's user id. */
+ if (IS_SIG (sig) && !opt.flags.disable_signer_uid)
+ {
+ char *mbox;
+
+ /* For now we use the uid which was used to locate the key. */
+ if (pksk->user_id && (mbox = mailbox_from_userid (pksk->user_id->name)))
+ {
+ if (DBG_LOOKUP)
+ log_debug ("setting Signer's UID to '%s'\n", mbox);
+ build_sig_subpkt (sig, SIGSUBPKT_SIGNERS_UID, mbox, strlen (mbox));
+ }
+ }
}
}
xfree (pk->serialno);
- agent_get_keyinfo (NULL, hexgrip, &pk->serialno);
+ agent_get_keyinfo (NULL, hexgrip, &pk->serialno, NULL);
xfree (hexgrip);
pk->flags.serialno_valid = 1;
}
+++ /dev/null
-/* sqlite.h - SQLite helper functions.
- * Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GNUPG_SQLITE_H
-#define GNUPG_SQLITE_H
-
-#include <sqlite3.h>
-
-enum sqlite_arg_type
- {
- SQLITE_ARG_END = 0xdead001,
- SQLITE_ARG_INT,
- SQLITE_ARG_LONG_LONG,
- SQLITE_ARG_STRING,
- /* This takes two arguments: the blob as a void * and the length
- of the blob as a long long. */
- SQLITE_ARG_BLOB
- };
-
-
-int sqlite3_exec_printf (sqlite3 *db,
- int (*callback)(void*,int,char**,char**), void *cookie,
- char **errmsg,
- const char *sql, ...);
-
-typedef int (*sqlite3_stepx_callback) (void *cookie,
- /* number of columns. */
- int cols,
- /* columns as text. */
- char **values,
- /* column names. */
- char **names,
- /* The prepared statement so
- that it is possible to use
- something like
- sqlite3_column_blob(). */
- sqlite3_stmt *statement);
-
-int sqlite3_stepx (sqlite3 *db,
- sqlite3_stmt **stmtp,
- sqlite3_stepx_callback callback,
- void *cookie,
- char **errmsg,
- const char *sql, ...);
-
-#endif
if (!new_dbname)
{
- fname = make_filename (opt.homedir, "trustdb" EXTSEP_S GPGEXT_GPG, NULL);
+ fname = make_filename (gnupg_homedir (),
+ "trustdb" EXTSEP_S GPGEXT_GPG, NULL);
}
else if (*new_dbname != DIRSEP_C )
{
if (strchr (new_dbname, DIRSEP_C))
fname = make_filename (new_dbname, NULL);
else
- fname = make_filename (opt.homedir, new_dbname, NULL);
+ fname = make_filename (gnupg_homedir (), new_dbname, NULL);
}
else
{
* this utility assumes that all keys in the keyring are trustworthy
*/
int
-check_signatures_trust( PKT_signature *sig )
+check_signatures_trust (ctrl_t ctrl, PKT_signature *sig)
{
+ (void)ctrl;
(void)sig;
return 0;
}
}
void
-check_trustdb_stale(void)
+check_trustdb_stale (ctrl_t ctrl)
{
+ (void)ctrl;
}
int
-get_validity_info (PKT_public_key *pk, PKT_user_id *uid)
+get_validity_info (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid)
{
+ (void)ctrl;
(void)pk;
(void)uid;
return '?';
}
unsigned int
-get_validity (PKT_public_key *pk, PKT_user_id *uid, PKT_signature *sig,
- int may_ask)
+get_validity (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid,
+ PKT_signature *sig, int may_ask)
{
+ (void)ctrl;
(void)pk;
(void)uid;
(void)sig;
}
const char *
-uid_trust_string_fixed (PKT_public_key *key, PKT_user_id *uid)
+uid_trust_string_fixed (ctrl_t ctrl, PKT_public_key *key, PKT_user_id *uid)
{
+ (void)ctrl;
(void)key;
(void)uid;
return "err";
}
gpg_error_t
-agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
+agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
+ char **r_serialno, int *r_cleartext)
{
(void)ctrl;
(void)hexkeygrip;
+ (void)r_cleartext;
*r_serialno = NULL;
return gpg_error (GPG_ERR_NO_SECKEY);
}
}
gpg_error_t
-tofu_get_policy (PKT_public_key *pk, PKT_user_id *user_id,
+tofu_get_policy (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *user_id,
enum tofu_policy *policy)
{
+ (void)ctrl;
(void)pk;
(void)user_id;
(void)policy;
#include "ttyio.h"
#include "trustdb.h"
#include "mkdir_p.h"
-#include "sqlite.h"
+#include "gpgsql.h"
#include "status.h"
#include "tofu.h"
theis case, NAME is either the normalized email address or the
fingerprint.
- To initialize this data structure, call opendbs(). When you are
- done, clean it up using closedbs(). To get a handle to a database,
+ To initialize this data structure, call opendbs(). Cleanup is done
+ when the CTRL object is released. To get a handle to a database,
use the getdb() function. This will either return an existing
handle or open a new DB connection, as appropriate. */
struct db
if (batch_update && ! db->batch_update)
{
- rc = sqlite3_stepx (db->db, &db->s.savepoint_batch,
+ rc = gpgsql_stepx (db->db, &db->s.savepoint_batch,
NULL, NULL, &err,
"savepoint batch;", SQLITE_ARG_END);
if (rc)
if (only_batch)
return 0;
- rc = sqlite3_stepx (db->db, &db->s.savepoint_inner,
+ rc = gpgsql_stepx (db->db, &db->s.savepoint_inner,
NULL, NULL, &err,
"savepoint inner;", SQLITE_ARG_END);
if (rc)
{
db->batch_update = 0;
- rc = sqlite3_stepx (db->db, &db->s.savepoint_batch_commit,
+ rc = gpgsql_stepx (db->db, &db->s.savepoint_batch_commit,
NULL, NULL, &err,
"release batch;", SQLITE_ARG_END);
if (rc)
if (only_batch)
return 0;
- rc = sqlite3_stepx (db->db, &db->s.savepoint_inner_commit,
+ rc = gpgsql_stepx (db->db, &db->s.savepoint_inner_commit,
NULL, NULL, &err,
"release inner;", SQLITE_ARG_END);
if (rc)
* know why this occurred, we also set conflict to 0xbaddecaf.
*/
if (type == DB_EMAIL || type == DB_COMBINED)
- rc = sqlite3_exec_printf
+ rc = gpgsql_exec_printf
(db, NULL, NULL, &err,
"create table bindings\n"
" (oid INTEGER PRIMARY KEY AUTOINCREMENT,\n"
Note: since the data is split on the email address, there is no
need to index the email column. */
- rc = sqlite3_exec_printf
+ rc = gpgsql_exec_printf
(db, NULL, NULL, &err,
"create table bindings\n"
" (oid INTEGER PRIMARY KEY AUTOINCREMENT,\n"
log_assert (! filename);
log_assert (type == DB_COMBINED);
- filename = make_filename (opt.homedir, "tofu.db", NULL);
+ filename = make_filename (gnupg_homedir (), "tofu.db", NULL);
filename_free = 1;
}
else
return db;
}
-struct dbs
+/* Definition of the Tofu dabase meta handle. */
+struct tofu_dbs_s
{
struct db *db;
};
TYPE must be either DB_MAIL or DB_KEY. In the combined format, the
combined DB is always returned. */
static struct db *
-getdb (struct dbs *dbs, const char *name, enum db_type type)
+getdb (tofu_dbs_t dbs, const char *name, enum db_type type)
{
struct db *t = NULL;
char *name_sanitized = NULL;
char *name_db;
/* Make the directory. */
- rc = gnupg_mkdir_p (opt.homedir, "tofu.d", type_str, prefix, NULL);
+ rc = gnupg_mkdir_p (gnupg_homedir (), "tofu.d", type_str, prefix, NULL);
if (rc)
{
- name_db = xstrconcat (opt.homedir, "tofu.d",
+ name_db = xstrconcat (gnupg_homedir (), "tofu.d",
type_str, prefix, NULL);
log_error (_("can't create directory '%s': %s\n"),
name_db, gpg_strerror (rc));
name_db = xstrconcat (name_sanitized, ".db", NULL);
filename = make_filename
- (opt.homedir, "tofu.d", type_str, prefix, name_db, NULL);
+ (gnupg_homedir (), "tofu.d", type_str, prefix, name_db, NULL);
xfree (name_db);
}
}
/* Create a new DB meta-handle. Returns NULL on error. */
/* FIXME: Change to return an error code for better reporting by the
caller. */
-static struct dbs *
-opendbs (void)
+static tofu_dbs_t
+opendbs (ctrl_t ctrl)
{
+ if (ctrl->tofu.dbs)
+ return ctrl->tofu.dbs;
+
if (opt.tofu_db_format == TOFU_DB_AUTO)
{
- char *filename = make_filename (opt.homedir, "tofu.db", NULL);
+ char *filename = make_filename (gnupg_homedir (), "tofu.db", NULL);
struct stat s;
int have_tofu_db = 0;
int have_tofu_d = 0;
}
}
- return xmalloc_clear (sizeof (struct dbs));
+ ctrl->tofu.dbs = xmalloc_clear (sizeof (struct tofu_dbs_s));
+ return ctrl->tofu.dbs;
}
+
/* Release all of the resources associated with a DB meta-handle. */
-static void
-closedbs (struct dbs *dbs)
+void
+tofu_closedbs (ctrl_t ctrl)
{
- if (dbs->db)
+ tofu_dbs_t dbs = ctrl->tofu.dbs;
+
+ if (!dbs)
+ return; /* Not initialized. */
+
+ if (dbs->db && dbs->db->type == DB_COMBINED)
+ {
+ log_assert (!dbs->db->next);
+ closedb (dbs->db);
+ }
+ else if (dbs->db)
{
struct db *old_head = db_cache;
struct db *db;
}
}
- xfree (dbs);
+ xfree (ctrl->tofu.dbs);
+ ctrl->tofu.dbs = NULL;
#if DEBUG_TOFU_CACHE
log_debug ("Queries: %d (prepares saved: %d)\n",
If SHOW_OLD is set, the binding's old policy is displayed. */
static gpg_error_t
-record_binding (struct dbs *dbs, const char *fingerprint, const char *email,
+record_binding (tofu_dbs_t dbs, const char *fingerprint, const char *email,
const char *user_id, enum tofu_policy policy, int show_old)
{
char *fingerprint_pp = format_hexfingerprint (fingerprint, NULL, 0);
purposes, there is no need to start a transaction or to die if
there is a failure. */
{
- rc = sqlite3_stepx
+ rc = gpgsql_stepx
(db_email->db, &db_email->s.record_binding_get_old_policy,
get_single_long_cb2, &policy_old, &err,
"select policy from bindings where fingerprint = ? and email = ?",
goto out;
}
- rc = sqlite3_stepx
+ rc = gpgsql_stepx
(db_email->db, &db_email->s.record_binding_update, NULL, NULL, &err,
"insert or replace into bindings\n"
" (oid, fingerprint, email, user_id, time, policy)\n"
{
log_assert (opt.tofu_db_format == TOFU_DB_SPLIT);
- rc = sqlite3_stepx
+ rc = gpgsql_stepx
(db_key->db, &db_key->s.record_binding_update2, NULL, NULL, &err,
"insert or replace into bindings\n"
" (oid, fingerprint, email, user_id)\n"
if CONFLICT is not NULL. Returns _tofu_GET_POLICY_ERROR if an error
occurs. */
static enum tofu_policy
-get_policy (struct dbs *dbs, const char *fingerprint, const char *email,
+get_policy (tofu_dbs_t dbs, const char *fingerprint, const char *email,
char **conflict)
{
struct db *db;
(TOFU_POLICY_NONE cannot appear in the DB. Thus, if POLICY is
still TOFU_POLICY_NONE after executing the query, then the
result set was empty.) */
- rc = sqlite3_stepx (db->db, &db->s.get_policy_select_policy_and_conflict,
+ rc = gpgsql_stepx (db->db, &db->s.get_policy_select_policy_and_conflict,
strings_collect_cb2, &strlist, &err,
"select policy, conflict from bindings\n"
" where fingerprint = ? and email = ?",
return policy;
}
-/* Return the trust level (TRUST_NEVER, etc.) for the binding
- <FINGERPRINT, EMAIL> (email is already normalized). If no policy
- is registered, returns TOFU_POLICY_NONE. If an error occurs,
- returns _tofu_GET_TRUST_ERROR.
- USER_ID is the unadultered user id.
+/* Format the first part of a conflict message and return that as a
+ * malloced string. */
+static char *
+format_conflict_msg_part1 (int policy, const char *conflict,
+ const char *fingerprint, const char *email)
+{
+ estream_t fp;
+ char *binding;
+ int binding_shown = 0;
+ char *tmpstr, *text;
+
+ binding = xasprintf ("<%s, %s>", fingerprint, email);
+
+ fp = es_fopenmem (0, "rw,samethread");
+ if (!fp)
+ log_fatal ("error creating memory stream: %s\n",
+ gpg_strerror (gpg_error_from_syserror()));
+
+ if (policy == TOFU_POLICY_NONE)
+ {
+ es_fprintf (fp, _("The binding %s is NOT known."), binding);
+ es_fputs (" ", fp);
+ binding_shown = 1;
+ }
+ else if (policy == TOFU_POLICY_ASK
+ /* If there the conflict is with itself, then don't
+ * display this message. */
+ && conflict && strcmp (conflict, fingerprint))
+ {
+ es_fprintf (fp,
+ _("The key with fingerprint %s raised a conflict "
+ "with the binding %s."
+ " Since this binding's policy was 'auto', it was "
+ "changed to 'ask'."),
+ conflict, binding);
+ es_fputs (" ", fp);
+ binding_shown = 1;
+ }
+
+ /* TRANSLATORS: The %s%s is replaced by either a fingerprint and a
+ blank or by two empty strings. */
+ es_fprintf (fp,
+ _("Please indicate whether you believe the binding %s%s"
+ "is legitimate (the key belongs to the stated owner) "
+ "or a forgery (bad)."),
+ binding_shown ? "" : binding,
+ binding_shown ? "" : " ");
+ es_fputc ('\n', fp);
+
+ xfree (binding);
+
+ es_fputc (0, fp);
+ if (es_fclose_snatch (fp, (void **)&tmpstr, NULL))
+ log_fatal ("error snatching memory stream\n");
+ text = format_text (tmpstr, 0, 72, 80);
+ es_free (tmpstr);
+
+ return text;
+}
+
+
+/* Ask the user about the binding. There are three ways we could end
+ * up here:
+ *
+ * - This is a new binding and there is a conflict
+ * (policy == TOFU_POLICY_NONE && bindings_with_this_email_count > 0),
+ *
+ * - This is a new binding and opt.tofu_default_policy is set to
+ * ask. (policy == TOFU_POLICY_NONE && opt.tofu_default_policy ==
+ * TOFU_POLICY_ASK), or,
+ *
+ * - The policy is ask (the user deferred last time) (policy ==
+ * TOFU_POLICY_ASK).
+ */
+static void
+ask_about_binding (tofu_dbs_t dbs,
+ struct db *db,
+ enum tofu_policy *policy,
+ int *trust_level,
+ int bindings_with_this_email_count,
+ strlist_t bindings_with_this_email,
+ char *conflict,
+ const char *fingerprint,
+ const char *email,
+ const char *user_id)
+{
+ char *sqerr = NULL;
+ int rc;
+ estream_t fp;
+ strlist_t other_user_ids = NULL;
+ struct signature_stats *stats = NULL;
+ struct signature_stats *stats_iter = NULL;
+ char *prompt;
+ char *choices;
+ struct db *db_key;
+
+ fp = es_fopenmem (0, "rw,samethread");
+ if (!fp)
+ log_fatal ("error creating memory stream: %s\n",
+ gpg_strerror (gpg_error_from_syserror()));
+
+ {
+ char *text = format_conflict_msg_part1 (*policy, conflict,
+ fingerprint, email);
+ es_fputs (text, fp);
+ es_fputc ('\n', fp);
+ xfree (text);
+ }
+
+ /* Find other user ids associated with this key and whether the
+ * bindings are marked as good or bad. */
+ if (opt.tofu_db_format == TOFU_DB_SPLIT)
+ {
+ /* In the split format, we need to search in the fingerprint DB
+ * for all the emails associated with this key, not the email DB. */
+ db_key = getdb (dbs, fingerprint, DB_KEY);
+ }
+ else
+ db_key = db;
+
+ if (db_key)
+ {
+ rc = gpgsql_stepx
+ (db_key->db, &db_key->s.get_trust_gather_other_user_ids,
+ strings_collect_cb2, &other_user_ids, &sqerr,
+ opt.tofu_db_format == TOFU_DB_SPLIT
+ ? "select user_id, email from bindings where fingerprint = ?;"
+ : "select user_id, policy from bindings where fingerprint = ?;",
+ SQLITE_ARG_STRING, fingerprint, SQLITE_ARG_END);
+ if (rc)
+ {
+ log_error (_("error gathering other user IDs: %s\n"), sqerr);
+ sqlite3_free (sqerr);
+ sqerr = NULL;
+ }
+ }
+
+ if (other_user_ids)
+ {
+ strlist_t strlist_iter;
+
+ es_fprintf (fp, _("Known user IDs associated with this key:\n"));
+ for (strlist_iter = other_user_ids;
+ strlist_iter;
+ strlist_iter = strlist_iter->next)
+ {
+ char *other_user_id = strlist_iter->d;
+ char *other_thing;
+ enum tofu_policy other_policy;
+
+ log_assert (strlist_iter->next);
+ strlist_iter = strlist_iter->next;
+ other_thing = strlist_iter->d;
+
+ if (opt.tofu_db_format == TOFU_DB_SPLIT)
+ other_policy = get_policy (dbs, fingerprint, other_thing, NULL);
+ else
+ other_policy = atoi (other_thing);
+
+ es_fprintf (fp, " %s (", other_user_id);
+ es_fprintf (fp, _("policy: %s"), tofu_policy_str (other_policy));
+ es_fprintf (fp, ")\n");
+ }
+ es_fprintf (fp, "\n");
+
+ free_strlist (other_user_ids);
+ }
+
+ /* Find other keys associated with this email address. */
+ /* FIXME: When generating the statistics, do we want the time
+ embedded in the signature (column 'sig_time') or the time that
+ we first verified the signature (column 'time'). */
+ rc = gpgsql_stepx
+ (db->db, &db->s.get_trust_gather_other_keys,
+ signature_stats_collect_cb, &stats, &sqerr,
+ "select fingerprint, policy, time_ago, count(*)\n"
+ " from (select bindings.*,\n"
+ " case\n"
+ /* From the future (but if its just a couple of hours in the
+ * future don't turn it into a warning)? Or should we use
+ * small, medium or large units? (Note: whatever we do, we
+ * keep the value in seconds. Then when we group, everything
+ * that rounds to the same number of seconds is grouped.) */
+ " when delta < -("STRINGIFY (TIME_AGO_FUTURE_IGNORE)") then -1\n"
+ " when delta < ("STRINGIFY (TIME_AGO_MEDIUM_THRESHOLD)")\n"
+ " then max(0,\n"
+ " round(delta / ("STRINGIFY (TIME_AGO_UNIT_SMALL)"))\n"
+ " * ("STRINGIFY (TIME_AGO_UNIT_SMALL)"))\n"
+ " when delta < ("STRINGIFY (TIME_AGO_LARGE_THRESHOLD)")\n"
+ " then round(delta / ("STRINGIFY (TIME_AGO_UNIT_MEDIUM)"))\n"
+ " * ("STRINGIFY (TIME_AGO_UNIT_MEDIUM)")\n"
+ " else round(delta / ("STRINGIFY (TIME_AGO_UNIT_LARGE)"))\n"
+ " * ("STRINGIFY (TIME_AGO_UNIT_LARGE)")\n"
+ " end time_ago,\n"
+ " delta time_ago_raw\n"
+ " from bindings\n"
+ " left join\n"
+ " (select *,\n"
+ " cast(strftime('%s','now') - sig_time as real) delta\n"
+ " from signatures) ss\n"
+ " on ss.binding = bindings.oid)\n"
+ " where email = ?\n"
+ " group by fingerprint, time_ago\n"
+ /* Make sure the current key is first. */
+ " order by fingerprint = ? asc, fingerprint desc, time_ago desc;\n",
+ SQLITE_ARG_STRING, email, SQLITE_ARG_STRING, fingerprint,
+ SQLITE_ARG_END);
+ if (rc)
+ {
+ strlist_t strlist_iter;
+
+ log_error (_("error gathering signature stats: %s\n"), sqerr);
+ sqlite3_free (sqerr);
+ sqerr = NULL;
- If MAY_ASK is set, then we may interact with the user. This is
- necessary if there is a conflict or the binding's policy is
- TOFU_POLICY_ASK. In the case of a conflict, we set the new
- conflicting binding's policy to TOFU_POLICY_ASK. In either case,
- we return TRUST_UNDEFINED. */
+ es_fprintf (fp, ngettext("The email address \"%s\" is"
+ " associated with %d key:\n",
+ "The email address \"%s\" is"
+ " associated with %d keys:\n",
+ bindings_with_this_email_count),
+ email, bindings_with_this_email_count);
+ for (strlist_iter = bindings_with_this_email;
+ strlist_iter;
+ strlist_iter = strlist_iter->next)
+ es_fprintf (fp, " %s\n", strlist_iter->d);
+ }
+ else
+ {
+ char *key = NULL;
+
+ if (! stats || strcmp (stats->fingerprint, fingerprint))
+ {
+ /* If we have already added this key to the DB, then it will
+ * be first (see the above select). Since the first key on
+ * the list is not this key, we must not yet have verified any
+ * messages signed by this key. Add a dummy entry. */
+ signature_stats_prepend (&stats, fingerprint, TOFU_POLICY_AUTO, 0, 0);
+ }
+
+ es_fprintf (fp, _("Statistics for keys with the email address \"%s\":\n"),
+ email);
+ for (stats_iter = stats; stats_iter; stats_iter = stats_iter->next)
+ {
+ if (! key || strcmp (key, stats_iter->fingerprint))
+ {
+ int this_key;
+ char *key_pp;
+
+ key = stats_iter->fingerprint;
+ this_key = strcmp (key, fingerprint) == 0;
+ key_pp = format_hexfingerprint (key, NULL, 0);
+ es_fprintf (fp, " %s (", key_pp);
+ if (this_key)
+ es_fprintf (fp, _("this key"));
+ else
+ es_fprintf (fp, _("policy: %s"),
+ tofu_policy_str (stats_iter->policy));
+ es_fputs ("):\n", fp);
+ xfree (key_pp);
+ }
+
+ es_fputs (" ", fp);
+ if (stats_iter->time_ago == -1)
+ es_fprintf (fp, ngettext("%ld message signed in the future.",
+ "%ld messages signed in the future.",
+ stats_iter->count), stats_iter->count);
+ else
+ {
+ long t_scaled = time_ago_scale (stats_iter->time_ago);
+
+ /* TANSLATORS: This string is concatenated with one of
+ * the day/week/month strings to form one sentence. */
+ es_fprintf (fp, ngettext("%ld message signed",
+ "%ld messages signed",
+ stats_iter->count), stats_iter->count);
+ if (!stats_iter->count)
+ es_fputs (".", fp);
+ else if (stats_iter->time_ago < TIME_AGO_UNIT_MEDIUM)
+ es_fprintf (fp, ngettext(" over the past %ld day.",
+ " over the past %ld days.",
+ t_scaled), t_scaled);
+ else if (stats_iter->time_ago < TIME_AGO_UNIT_LARGE)
+ es_fprintf (fp, ngettext(" over the past %ld week.",
+ " over the past %ld weeks.",
+ t_scaled), t_scaled);
+ else
+ es_fprintf (fp, ngettext(" over the past %ld month.",
+ " over the past %ld months.",
+ t_scaled), t_scaled);
+ }
+ es_fputs ("\n", fp);
+ }
+ }
+
+
+ if ((*policy == TOFU_POLICY_NONE && bindings_with_this_email_count > 0)
+ || (*policy == TOFU_POLICY_ASK && conflict))
+ {
+ /* This is a conflict. */
+
+ /* TRANSLATORS: Please translate the text found in the source
+ * file below. We don't directly internationalize that text so
+ * that we can tweak it without breaking translations. */
+ char *text = _("TOFU detected a binding conflict");
+ char *textbuf;
+ if (!strcmp (text, "TOFU detected a binding conflict"))
+ {
+ /* No translation. Use the English text. */
+ text =
+ "Normally, there is only a single key associated with an email "
+ "address. However, people sometimes generate a new key if "
+ "their key is too old or they think it might be compromised. "
+ "Alternatively, a new key may indicate a man-in-the-middle "
+ "attack! Before accepting this key, you should talk to or "
+ "call the person to make sure this new key is legitimate.";
+ }
+ textbuf = format_text (text, 0, 72, 80);
+ es_fprintf (fp, "\n%s\n", text);
+ xfree (textbuf);
+ }
+
+ es_fputc ('\n', fp);
+
+ /* Add a NUL terminator. */
+ es_fputc (0, fp);
+ if (es_fclose_snatch (fp, (void **) &prompt, NULL))
+ log_fatal ("error snatching memory stream\n");
+
+ /* I think showing the large message once is sufficient. If we
+ * would move it right before the cpr_get many lines will scroll
+ * away and the user might not realize that he merely entered a
+ * wrong choise (because he does not see that either). As a small
+ * benefit we allow C-L to redisplay everything. */
+ tty_printf ("%s", prompt);
+ while (1)
+ {
+ char *response;
+
+ /* TRANSLATORS: Two letters (normally the lower and upper case
+ * version of the hotkey) for each of the five choices. If
+ * there is only one choice in your language, repeat it. */
+ choices = _("gG" "aA" "uU" "rR" "bB");
+ if (strlen (choices) != 10)
+ log_bug ("Bad TOFU conflict translation! Please report.");
+
+ response = cpr_get
+ ("tofu.conflict",
+ _("(G)ood, (A)ccept once, (U)nknown, (R)eject once, (B)ad? "));
+ trim_spaces (response);
+ cpr_kill_prompt ();
+ if (*response == CONTROL_L)
+ tty_printf ("%s", prompt);
+ else if (strlen (response) == 1)
+ {
+ char *choice = strchr (choices, *response);
+ if (choice)
+ {
+ int c = ((size_t) choice - (size_t) choices) / 2;
+
+ switch (c)
+ {
+ case 0: /* Good. */
+ *policy = TOFU_POLICY_GOOD;
+ *trust_level = tofu_policy_to_trust_level (*policy);
+ break;
+ case 1: /* Accept once. */
+ *policy = TOFU_POLICY_ASK;
+ *trust_level = tofu_policy_to_trust_level (TOFU_POLICY_GOOD);
+ break;
+ case 2: /* Unknown. */
+ *policy = TOFU_POLICY_UNKNOWN;
+ *trust_level = tofu_policy_to_trust_level (*policy);
+ break;
+ case 3: /* Reject once. */
+ *policy = TOFU_POLICY_ASK;
+ *trust_level = tofu_policy_to_trust_level (TOFU_POLICY_BAD);
+ break;
+ case 4: /* Bad. */
+ *policy = TOFU_POLICY_BAD;
+ *trust_level = tofu_policy_to_trust_level (*policy);
+ break;
+ default:
+ log_bug ("c should be between 0 and 4 but it is %d!", c);
+ }
+
+ if (record_binding (dbs, fingerprint, email, user_id,
+ *policy, 0))
+ {
+ /* If there's an error registering the
+ * binding, don't save the signature. */
+ *trust_level = _tofu_GET_TRUST_ERROR;
+ }
+ break;
+ }
+ }
+ xfree (response);
+ }
+
+ xfree (prompt);
+
+ signature_stats_free (stats);
+}
+
+
+/* Return the trust level (TRUST_NEVER, etc.) for the binding
+ * <FINGERPRINT, EMAIL> (email is already normalized). If no policy
+ * is registered, returns TOFU_POLICY_NONE. If an error occurs,
+ * returns _tofu_GET_TRUST_ERROR.
+ *
+ * PK is the public key object for FINGERPRINT.
+ *
+ * USER_ID is the unadulterated user id.
+ *
+ * If MAY_ASK is set, then we may interact with the user. This is
+ * necessary if there is a conflict or the binding's policy is
+ * TOFU_POLICY_ASK. In the case of a conflict, we set the new
+ * conflicting binding's policy to TOFU_POLICY_ASK. In either case,
+ * we return TRUST_UNDEFINED. */
static enum tofu_policy
-get_trust (struct dbs *dbs, const char *fingerprint, const char *email,
+get_trust (tofu_dbs_t dbs, PKT_public_key *pk,
+ const char *fingerprint, const char *email,
const char *user_id, int may_ask)
{
- char *fingerprint_pp;
struct db *db;
enum tofu_policy policy;
char *conflict = NULL;
int rc;
- char *err = NULL;
+ char *sqerr = NULL;
strlist_t bindings_with_this_email = NULL;
int bindings_with_this_email_count;
int change_conflicting_to_ask = 0;
if (! db)
return _tofu_GET_TRUST_ERROR;
- fingerprint_pp = format_hexfingerprint (fingerprint, NULL, 0);
-
policy = get_policy (dbs, fingerprint, email, &conflict);
if (policy == TOFU_POLICY_AUTO || policy == TOFU_POLICY_NONE)
- /* See if the key is ultimately trusted. If so, we're done. */
- {
- PKT_public_key *pk;
+ { /* See if the key is ultimately trusted. If so, we're done. */
u32 kid[2];
- char fpr_bin[MAX_FINGERPRINT_LEN+1];
- size_t fpr_bin_len;
- if (!hex2str (fingerprint, fpr_bin, sizeof fpr_bin, &fpr_bin_len))
- {
- log_error ("error converting fingerprint: %s\n",
- gpg_strerror (gpg_error_from_syserror ()));
- return _tofu_GET_TRUST_ERROR;
- }
-
- /* We need to lookup the key by fingerprint again so that we can
- properly extract the keyid. Extracting direct from the
- fingerprint works only for v4 keys and would assume that
- there is no collision in the low 64 bit. We can't guarantee
- the latter in case the Tofu DB is used with a different
- keyring. In any case the UTK stuff needs to be changed to
- use only fingerprints. */
- pk = xtrycalloc (1, sizeof *pk);
- if (!pk)
- {
- log_error (_("out of core\n"));
- return _tofu_GET_TRUST_ERROR;
- }
- rc = get_pubkey_byfprint_fast (pk, fpr_bin, fpr_bin_len);
- if (rc)
- {
- log_error (_("public key %s not found: %s\n"),
- fingerprint, gpg_strerror (rc));
- return _tofu_GET_TRUST_ERROR;
- }
keyid_from_pk (pk, kid);
- free_public_key (pk);
if (tdb_keyid_is_utk (kid))
{
case TOFU_POLICY_UNKNOWN:
case TOFU_POLICY_BAD:
/* The saved judgement is auto -> auto, good, unknown or bad.
- We don't need to ask the user anything. */
+ * We don't need to ask the user anything. */
if (DBG_TRUST)
log_debug ("TOFU: Known binding <%s, %s>'s policy: %s\n",
fingerprint, email, tofu_policy_str (policy));
case TOFU_POLICY_NONE:
/* The binding is new, we need to check for conflicts. Case #3
- below. */
+ * below. */
break;
case _tofu_GET_POLICY_ERROR:
/* We get here if:
-
- 1. The saved policy is auto and the default policy is ask
- (get_policy() == TOFU_POLICY_AUTO
- && opt.tofu_default_policy == TOFU_POLICY_ASK)
-
- 2. The saved policy is ask (either last time the user selected
- accept once or reject once or there was a conflict and this
- binding's policy was changed from auto to ask)
- (policy == TOFU_POLICY_ASK), or,
-
- 3. We don't have a saved policy (policy == TOFU_POLICY_NONE)
- (need to check for a conflict).
+ *
+ * 1. The saved policy is auto and the default policy is ask
+ * (get_policy() == TOFU_POLICY_AUTO
+ * && opt.tofu_default_policy == TOFU_POLICY_ASK)
+ *
+ * 2. The saved policy is ask (either last time the user selected
+ * accept once or reject once or there was a conflict and this
+ * binding's policy was changed from auto to ask)
+ * (policy == TOFU_POLICY_ASK), or,
+ *
+ * 3. We don't have a saved policy (policy == TOFU_POLICY_NONE)
+ * (need to check for a conflict).
*/
/* Look for conflicts. This is needed in all 3 cases.
-
- Get the fingerprints of any bindings that share the email
- address. Note: if the binding in question is in the DB, it will
- also be returned. Thus, if the result set is empty, then this is
- a new binding. */
- rc = sqlite3_stepx
+ *
+ * Get the fingerprints of any bindings that share the email
+ * address. Note: if the binding in question is in the DB, it will
+ * also be returned. Thus, if the result set is empty, then this is
+ * a new binding. */
+ rc = gpgsql_stepx
(db->db, &db->s.get_trust_bindings_with_this_email,
- strings_collect_cb2, &bindings_with_this_email, &err,
+ strings_collect_cb2, &bindings_with_this_email, &sqerr,
"select distinct fingerprint from bindings where email = ?;",
SQLITE_ARG_STRING, email, SQLITE_ARG_END);
if (rc)
{
- log_error (_("error reading TOFU database: %s\n"), err);
+ log_error (_("error reading TOFU database: %s\n"), sqerr);
print_further_info ("listing fingerprints");
- sqlite3_free (err);
+ sqlite3_free (sqerr);
goto out;
}
bindings_with_this_email_count = strlist_length (bindings_with_this_email);
if (bindings_with_this_email_count == 0
&& opt.tofu_default_policy != TOFU_POLICY_ASK)
- /* New binding with no conflict and a concrete default policy.
-
- We've never observed a binding with this email address
- (BINDINGS_WITH_THIS_EMAIL_COUNT is 0 and the above query would return
- the current binding if it were in the DB) and we have a default
- policy, which is not to ask the user. */
{
+ /* New binding with no conflict and a concrete default policy.
+ *
+ * We've never observed a binding with this email address
+ * BINDINGS_WITH_THIS_EMAIL_COUNT is 0 and the above query would
+ * return the current binding if it were in the DB) and we have
+ * a default policy, which is not to ask the user.
+ */
+
/* If we've seen this binding, then we've seen this email and
policy couldn't possibly be TOFU_POLICY_NONE. */
log_assert (policy == TOFU_POLICY_NONE);
}
if (policy == TOFU_POLICY_NONE)
- /* This is a new binding and we have a conflict. Mark any
- conflicting bindings that have an automatic policy as now
- requiring confirmation. Note: we delay this until after we ask
- for confirmation so that when the current policy is printed, it
- is correct. */
- change_conflicting_to_ask = 1;
+ {
+ /* This is a new binding and we have a conflict. Mark any
+ * conflicting bindings that have an automatic policy as now
+ * requiring confirmation. Note: we delay this until after we
+ * ask for confirmation so that when the current policy is
+ * printed, it is correct. */
+ change_conflicting_to_ask = 1;
+ }
if (! may_ask)
- /* We can only get here in the third case (no saved policy) and if
- there is a conflict. (If the policy was ask (cases #1 and #2)
- and we weren't allowed to ask, we'd have already exited). */
{
+ /* We can only get here in the third case (no saved policy) and
+ * if there is a conflict. (If the policy was ask (cases #1 and
+ * #2) and we weren't allowed to ask, we'd have already exited). */
log_assert (policy == TOFU_POLICY_NONE);
if (record_binding (dbs, fingerprint, email, user_id,
goto out;
}
- /* If we get here, we need to ask the user about the binding. There
- are three ways we could end up here:
-
- - This is a new binding and there is a conflict
- (policy == TOFU_POLICY_NONE && bindings_with_this_email_count > 0),
-
- - This is a new binding and opt.tofu_default_policy is set to
- ask. (policy == TOFU_POLICY_NONE && opt.tofu_default_policy ==
- TOFU_POLICY_ASK), or,
-
- - The policy is ask (the user deferred last time) (policy ==
- TOFU_POLICY_ASK).
- */
- {
- int is_conflict =
- ((policy == TOFU_POLICY_NONE && bindings_with_this_email_count > 0)
- || (policy == TOFU_POLICY_ASK && conflict));
- estream_t fp;
- strlist_t other_user_ids = NULL;
- struct signature_stats *stats = NULL;
- struct signature_stats *stats_iter = NULL;
- char *prompt;
- char *choices;
-
- fp = es_fopenmem (0, "rw,samethread");
- if (! fp)
- log_fatal ("error creating memory stream: %s\n",
- gpg_strerror (gpg_error_from_syserror()));
-
- /* Format the first part of the message. */
- {
- estream_t fp1;
- char *binding = xasprintf ("<%s, %s>", fingerprint, email);
- int binding_shown = 0;
- char *tmpstr, *text;
-
- fp1 = es_fopenmem (0, "rw,samethread");
- if (!fp1)
- log_fatal ("error creating memory stream: %s\n",
- gpg_strerror (gpg_error_from_syserror()));
-
- if (policy == TOFU_POLICY_NONE)
- {
- es_fprintf (fp1, _("The binding %s is NOT known."), binding);
- es_fputs (" ", fp1);
- binding_shown = 1;
- }
- else if (policy == TOFU_POLICY_ASK
- /* If there the conflict is with itself, then don't
- display this message. */
- && conflict && strcmp (conflict, fingerprint) != 0)
- {
- es_fprintf (fp1,
- _("The key with fingerprint %s raised a conflict "
- "with the binding %s."
- " Since this binding's policy was 'auto', it was "
- "changed to 'ask'."),
- conflict, binding);
- es_fputs (" ", fp1);
- binding_shown = 1;
- }
-
- /* TRANSLATORS: The %s%s is replaced by either a fingerprint and a
- blank or by two empty strings. */
- es_fprintf (fp1,
- _("Please indicate whether you believe the binding %s%s"
- "is legitimate (the key belongs to the stated owner) "
- "or a forgery (bad)."),
- binding_shown ? "" : binding,
- binding_shown ? "" : " ");
- es_fputc ('\n', fp1);
-
- xfree (binding);
-
- es_fputc (0, fp1);
- if (es_fclose_snatch (fp1, (void **)&tmpstr, NULL))
- log_fatal ("error snatching memory stream\n");
- text = format_text (tmpstr, 0, 72, 80);
- es_free (tmpstr);
-
- es_fputs (text, fp);
- xfree (text);
- }
-
- es_fputc ('\n', fp);
-
- /* Find other user ids associated with this key and whether the
- bindings are marked as good or bad. */
- {
- struct db *db_key;
-
- if (opt.tofu_db_format == TOFU_DB_SPLIT)
- /* In the split format, we need to search in the fingerprint
- DB for all the emails associated with this key, not the
- email DB. */
- db_key = getdb (dbs, fingerprint, DB_KEY);
- else
- db_key = db;
-
- if (db_key)
- {
- rc = sqlite3_stepx
- (db_key->db, &db_key->s.get_trust_gather_other_user_ids,
- strings_collect_cb2, &other_user_ids, &err,
- opt.tofu_db_format == TOFU_DB_SPLIT
- ? "select user_id, email from bindings where fingerprint = ?;"
- : "select user_id, policy from bindings where fingerprint = ?;",
- SQLITE_ARG_STRING, fingerprint, SQLITE_ARG_END);
- if (rc)
- {
- log_error (_("error gathering other user IDs: %s\n"), err);
- sqlite3_free (err);
- err = NULL;
- }
- }
- }
-
- if (other_user_ids)
- {
- strlist_t strlist_iter;
-
- es_fprintf (fp, _("Known user IDs associated with this key:\n"));
- for (strlist_iter = other_user_ids;
- strlist_iter;
- strlist_iter = strlist_iter->next)
- {
- char *other_user_id = strlist_iter->d;
- char *other_thing;
- enum tofu_policy other_policy;
-
- log_assert (strlist_iter->next);
- strlist_iter = strlist_iter->next;
- other_thing = strlist_iter->d;
-
- if (opt.tofu_db_format == TOFU_DB_SPLIT)
- other_policy = get_policy (dbs, fingerprint, other_thing, NULL);
- else
- other_policy = atoi (other_thing);
-
- es_fprintf (fp, " %s (", other_user_id);
- es_fprintf (fp, _("policy: %s"), tofu_policy_str (other_policy));
- es_fprintf (fp, ")\n");
- }
- es_fprintf (fp, "\n");
-
- free_strlist (other_user_ids);
- }
-
- /* Find other keys associated with this email address. */
- /* XXX: When generating the statistics, do we want the time
- embedded in the signature (column 'sig_time') or the time that
- we first verified the signature (column 'time'). */
- rc = sqlite3_stepx
- (db->db, &db->s.get_trust_gather_other_keys,
- signature_stats_collect_cb, &stats, &err,
- "select fingerprint, policy, time_ago, count(*)\n"
- " from (select bindings.*,\n"
- " case\n"
- /* From the future (but if its just a couple of hours in the
- future don't turn it into a warning)? Or should we use
- small, medium or large units? (Note: whatever we do, we
- keep the value in seconds. Then when we group, everything
- that rounds to the same number of seconds is grouped.) */
- " when delta < -("STRINGIFY (TIME_AGO_FUTURE_IGNORE)") then -1\n"
- " when delta < ("STRINGIFY (TIME_AGO_MEDIUM_THRESHOLD)")\n"
- " then max(0,\n"
- " round(delta / ("STRINGIFY (TIME_AGO_UNIT_SMALL)"))\n"
- " * ("STRINGIFY (TIME_AGO_UNIT_SMALL)"))\n"
- " when delta < ("STRINGIFY (TIME_AGO_LARGE_THRESHOLD)")\n"
- " then round(delta / ("STRINGIFY (TIME_AGO_UNIT_MEDIUM)"))\n"
- " * ("STRINGIFY (TIME_AGO_UNIT_MEDIUM)")\n"
- " else round(delta / ("STRINGIFY (TIME_AGO_UNIT_LARGE)"))\n"
- " * ("STRINGIFY (TIME_AGO_UNIT_LARGE)")\n"
- " end time_ago,\n"
- " delta time_ago_raw\n"
- " from bindings\n"
- " left join\n"
- " (select *,\n"
- " cast(strftime('%s','now') - sig_time as real) delta\n"
- " from signatures) ss\n"
- " on ss.binding = bindings.oid)\n"
- " where email = ?\n"
- " group by fingerprint, time_ago\n"
- /* Make sure the current key is first. */
- " order by fingerprint = ? asc, fingerprint desc, time_ago desc;\n",
- SQLITE_ARG_STRING, email, SQLITE_ARG_STRING, fingerprint,
- SQLITE_ARG_END);
- if (rc)
- {
- strlist_t strlist_iter;
-
- log_error (_("error gathering signature stats: %s\n"), err);
- sqlite3_free (err);
- err = NULL;
-
- es_fprintf (fp, ngettext("The email address \"%s\" is"
- " associated with %d key:\n",
- "The email address \"%s\" is"
- " associated with %d keys:\n",
- bindings_with_this_email_count),
- email, bindings_with_this_email_count);
- for (strlist_iter = bindings_with_this_email;
- strlist_iter;
- strlist_iter = strlist_iter->next)
- es_fprintf (fp, " %s\n", strlist_iter->d);
- }
- else
- {
- char *key = NULL;
-
- if (! stats || strcmp (stats->fingerprint, fingerprint) != 0)
- /* If we have already added this key to the DB, then it will
- be first (see the above select). Since the first key on
- the list is not this key, we must not yet have verified
- any messages signed by this key. Add a dummy entry. */
- signature_stats_prepend (&stats, fingerprint, TOFU_POLICY_AUTO, 0, 0);
-
- es_fprintf
- (fp, _("Statistics for keys with the email address \"%s\":\n"),
- email);
- for (stats_iter = stats; stats_iter; stats_iter = stats_iter->next)
- {
- if (! key || strcmp (key, stats_iter->fingerprint) != 0)
- {
- int this_key;
- char *key_pp;
- key = stats_iter->fingerprint;
- this_key = strcmp (key, fingerprint) == 0;
- key_pp = format_hexfingerprint (key, NULL, 0);
- es_fprintf (fp, " %s (", key_pp);
- if (this_key)
- es_fprintf (fp, _("this key"));
- else
- es_fprintf (fp, _("policy: %s"),
- tofu_policy_str (stats_iter->policy));
- es_fputs ("):\n", fp);
- xfree (key_pp);
- }
-
- es_fputs (" ", fp);
- if (stats_iter->time_ago == -1)
- es_fprintf (fp, ngettext("%ld message signed in the future.",
- "%ld messages signed in the future.",
- stats_iter->count), stats_iter->count);
- else
- {
- long t_scaled = time_ago_scale (stats_iter->time_ago);
-
- /* TANSLATORS: This string is concatenated with one of
- * the day/week/month strings to form one sentence. */
- es_fprintf (fp, ngettext("%ld message signed",
- "%ld messages signed",
- stats_iter->count), stats_iter->count);
- if (!stats_iter->count)
- es_fputs (".", fp);
- else if (stats_iter->time_ago < TIME_AGO_UNIT_MEDIUM)
- es_fprintf (fp, ngettext(" over the past %ld day.",
- " over the past %ld days.",
- t_scaled), t_scaled);
- else if (stats_iter->time_ago < TIME_AGO_UNIT_LARGE)
- es_fprintf (fp, ngettext(" over the past %ld week.",
- " over the past %ld weeks.",
- t_scaled), t_scaled);
- else
- es_fprintf (fp, ngettext(" over the past %ld month.",
- " over the past %ld months.",
- t_scaled), t_scaled);
- }
- es_fputs ("\n", fp);
- }
- }
-
- if (is_conflict)
- {
- /* TRANSLATORS: Please translate the text found in the source
- file below. We don't directly internationalize that text
- so that we can tweak it without breaking translations. */
- const char *text = _("TOFU detected a binding conflict");
- char *textbuf;
- if (strcmp (text, "TOFU detected a binding conflict") == 0)
- /* No translation. Use the English text. */
- text =
- "Normally, there is only a single key associated with an email "
- "address. However, people sometimes generate a new key if "
- "their key is too old or they think it might be compromised. "
- "Alternatively, a new key may indicate a man-in-the-middle "
- "attack! Before accepting this key, you should talk to or "
- "call the person to make sure this new key is legitimate.";
- textbuf = format_text (text, 0, 72, 80);
- es_fprintf (fp, "\n%s\n", text);
- xfree (textbuf);
- }
-
- es_fputc ('\n', fp);
-
- /* Add a NUL terminator. */
- es_fputc (0, fp);
- if (es_fclose_snatch (fp, (void **) &prompt, NULL))
- log_fatal ("error snatching memory stream\n");
-
- /* I think showing the large message once is sufficient. If we
- would move it right before the cpr_get many lines will scroll
- away and the user might not realize that he merely entered a
- wrong choise (because he does not see that either). As a small
- benefit we allow C-L to redisplay everything. */
- tty_printf ("%s", prompt);
- while (1)
- {
- char *response;
-
- /* TRANSLATORS: Two letters (normally the lower and upper case
- version of the hotkey) for each of the five choices. If
- there is only one choice in your language, repeat it. */
- choices = _("gG" "aA" "uU" "rR" "bB");
- if (strlen (choices) != 10)
- log_bug ("Bad TOFU conflict translation! Please report.");
-
- response = cpr_get
- ("tofu.conflict",
- _("(G)ood, (A)ccept once, (U)nknown, (R)eject once, (B)ad? "));
- trim_spaces (response);
- cpr_kill_prompt ();
- if (*response == CONTROL_L)
- tty_printf ("%s", prompt);
- else if (strlen (response) == 1)
- {
- char *choice = strchr (choices, *response);
- if (choice)
- {
- int c = ((size_t) choice - (size_t) choices) / 2;
-
- switch (c)
- {
- case 0: /* Good. */
- policy = TOFU_POLICY_GOOD;
- trust_level = tofu_policy_to_trust_level (policy);
- break;
- case 1: /* Accept once. */
- policy = TOFU_POLICY_ASK;
- trust_level =
- tofu_policy_to_trust_level (TOFU_POLICY_GOOD);
- break;
- case 2: /* Unknown. */
- policy = TOFU_POLICY_UNKNOWN;
- trust_level = tofu_policy_to_trust_level (policy);
- break;
- case 3: /* Reject once. */
- policy = TOFU_POLICY_ASK;
- trust_level =
- tofu_policy_to_trust_level (TOFU_POLICY_BAD);
- break;
- case 4: /* Bad. */
- policy = TOFU_POLICY_BAD;
- trust_level = tofu_policy_to_trust_level (policy);
- break;
- default:
- log_bug ("c should be between 0 and 4 but it is %d!", c);
- }
-
- if (record_binding (dbs, fingerprint, email, user_id,
- policy, 0) != 0)
- /* If there's an error registering the
- binding, don't save the signature. */
- trust_level = _tofu_GET_TRUST_ERROR;
-
- break;
- }
- }
- xfree (response);
- }
-
- xfree (prompt);
-
- signature_stats_free (stats);
- }
+ /* If we get here, we need to ask the user about the binding. */
+ ask_about_binding (dbs, db,
+ &policy,
+ &trust_level,
+ bindings_with_this_email_count,
+ bindings_with_this_email,
+ conflict,
+ fingerprint,
+ email,
+ user_id);
out:
if (change_conflicting_to_ask)
{
if (! may_ask)
- /* If we weren't allowed to ask, also update this key as
- conflicting with itself. */
- rc = sqlite3_exec_printf
- (db->db, NULL, NULL, &err,
- "update bindings set policy = %d, conflict = %Q"
- " where email = %Q"
- " and (policy = %d or (policy = %d and fingerprint = %Q));",
- TOFU_POLICY_ASK, fingerprint, email, TOFU_POLICY_AUTO,
- TOFU_POLICY_ASK, fingerprint);
+ {
+ /* If we weren't allowed to ask, also update this key as
+ conflicting with itself. */
+ rc = gpgsql_exec_printf
+ (db->db, NULL, NULL, &sqerr,
+ "update bindings set policy = %d, conflict = %Q"
+ " where email = %Q"
+ " and (policy = %d or (policy = %d and fingerprint = %Q));",
+ TOFU_POLICY_ASK, fingerprint, email, TOFU_POLICY_AUTO,
+ TOFU_POLICY_ASK, fingerprint);
+ }
else
- rc = sqlite3_exec_printf
- (db->db, NULL, NULL, &err,
- "update bindings set policy = %d, conflict = %Q"
- " where email = %Q and fingerprint != %Q and policy = %d;",
- TOFU_POLICY_ASK, fingerprint, email, fingerprint, TOFU_POLICY_AUTO);
+ {
+ rc = gpgsql_exec_printf
+ (db->db, NULL, NULL, &sqerr,
+ "update bindings set policy = %d, conflict = %Q"
+ " where email = %Q and fingerprint != %Q and policy = %d;",
+ TOFU_POLICY_ASK, fingerprint, email, fingerprint,
+ TOFU_POLICY_AUTO);
+ }
+
if (rc)
{
- log_error (_("error changing TOFU policy: %s\n"), err);
- sqlite3_free (err);
- goto out;
+ log_error (_("error changing TOFU policy: %s\n"), sqerr);
+ sqlite3_free (sqerr);
+ sqerr = NULL;
}
}
xfree (conflict);
free_strlist (bindings_with_this_email);
- xfree (fingerprint_pp);
return trust_level;
}
}
static void
-show_statistics (struct dbs *dbs, const char *fingerprint,
+show_statistics (tofu_dbs_t dbs, const char *fingerprint,
const char *email, const char *user_id,
const char *sig_exclude)
{
fingerprint_pp = format_hexfingerprint (fingerprint, NULL, 0);
- rc = sqlite3_exec_printf
+ rc = gpgsql_exec_printf
(db->db, strings_collect_cb, &strlist, &err,
"select count (*), strftime('%%s','now') - min (signatures.time),\n"
" strftime('%%s','now') - max (signatures.time)\n"
log_fatal ("error snatching memory stream\n");
msg = format_text (tmpmsg, 0, 72, 80);
es_free (tmpmsg);
- for (p=msg; *p; p++)
- if (*p == '~')
- *p = ' ';
/* Print a status line but suppress the trailing LF.
* Spaces are not percent escaped. */
if (*msg)
write_status_buffer (STATUS_TOFU_STATS_LONG,
msg, strlen (msg)-1, -1);
+
+ /* Remove the non-breaking space markers. */
+ for (p=msg; *p; p++)
+ if (*p == '~')
+ *p = ' ';
+
}
log_string (GPGRT_LOG_INFO, msg);
This function returns the binding's trust level on return. If an
error occurs, this function returns TRUST_UNKNOWN. */
int
-tofu_register (PKT_public_key *pk, const char *user_id,
+tofu_register (ctrl_t ctrl, PKT_public_key *pk, const char *user_id,
const byte *sig_digest_bin, int sig_digest_bin_len,
time_t sig_time, const char *origin, int may_ask)
{
- struct dbs *dbs;
+ tofu_dbs_t dbs;
struct db *db;
char *fingerprint = NULL;
- char *fingerprint_pp = NULL;
char *email = NULL;
char *err = NULL;
int rc;
sig_digest = make_radix64_string (sig_digest_bin, sig_digest_bin_len);
- dbs = opendbs ();
+ dbs = opendbs (ctrl);
if (! dbs)
{
log_error (_("error opening TOFU database: %s\n"),
}
fingerprint = hexfingerprint (pk, NULL, 0);
- fingerprint_pp = format_hexfingerprint (fingerprint, NULL, 0);
if (! *user_id)
{
/* It's necessary to get the trust so that we are certain that the
binding has been registered. */
- trust_level = get_trust (dbs, fingerprint, email, user_id, may_ask);
+ trust_level = get_trust (dbs, pk, fingerprint, email, user_id, may_ask);
if (trust_level == _tofu_GET_TRUST_ERROR)
/* An error. */
{
/* If we've already seen this signature before, then don't add
it again. */
- rc = sqlite3_stepx
+ rc = gpgsql_stepx
(db->db, &db->s.register_already_seen,
get_single_unsigned_long_cb2, &c, &err,
"select count (*)\n"
log_assert (c == 0);
- rc = sqlite3_stepx
+ rc = gpgsql_stepx
(db->db, &db->s.register_insert, NULL, NULL, &err,
"insert into signatures\n"
" (binding, sig_digest, origin, sig_time, time)\n"
already_verified ? NULL : sig_digest);
xfree (email);
- xfree (fingerprint_pp);
xfree (fingerprint);
- if (dbs)
- closedbs (dbs);
xfree (sig_digest);
return trust_level;
Returns TRUST_UNDEFINED if an error occurs. */
int
-tofu_get_validity (PKT_public_key *pk, const char *user_id,
+tofu_get_validity (ctrl_t ctrl, PKT_public_key *pk, const char *user_id,
int may_ask)
{
- struct dbs *dbs;
+ tofu_dbs_t dbs;
char *fingerprint = NULL;
char *email = NULL;
int trust_level = TRUST_UNDEFINED;
- dbs = opendbs ();
+ dbs = opendbs (ctrl);
if (! dbs)
{
log_error (_("error opening TOFU database: %s\n"),
email = email_from_user_id (user_id);
- trust_level = get_trust (dbs, fingerprint, email, user_id, may_ask);
+ trust_level = get_trust (dbs, pk, fingerprint, email, user_id, may_ask);
if (trust_level == _tofu_GET_TRUST_ERROR)
/* An error. */
trust_level = TRUST_UNDEFINED;
die:
xfree (email);
xfree (fingerprint);
- if (dbs)
- closedbs (dbs);
-
return trust_level;
}
Returns 0 on success and an error code otherwise. */
gpg_error_t
-tofu_set_policy (kbnode_t kb, enum tofu_policy policy)
+tofu_set_policy (ctrl_t ctrl, kbnode_t kb, enum tofu_policy policy)
{
- struct dbs *dbs;
+ tofu_dbs_t dbs;
PKT_public_key *pk;
char *fingerprint = NULL;
log_assert (kb->pkt->pkttype == PKT_PUBLIC_KEY);
pk = kb->pkt->pkt.public_key;
- dbs = opendbs ();
+ dbs = opendbs (ctrl);
if (! dbs)
{
log_error (_("error opening TOFU database: %s\n"),
}
xfree (fingerprint);
- closedbs (dbs);
-
return 0;
}
Returns 0 on success and an error code otherwise. */
gpg_error_t
-tofu_set_policy_by_keyid (u32 *keyid, enum tofu_policy policy)
+tofu_set_policy_by_keyid (ctrl_t ctrl, u32 *keyid, enum tofu_policy policy)
{
kbnode_t keyblock = get_pubkeyblock (keyid);
if (! keyblock)
return gpg_error (GPG_ERR_NO_PUBKEY);
- return tofu_set_policy (keyblock, policy);
+ return tofu_set_policy (ctrl, keyblock, policy);
}
/* Return the TOFU policy for the specified binding in *POLICY. If no
Returns 0 on success and an error code otherwise. */
gpg_error_t
-tofu_get_policy (PKT_public_key *pk, PKT_user_id *user_id,
+tofu_get_policy (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *user_id,
enum tofu_policy *policy)
{
- struct dbs *dbs;
+ tofu_dbs_t dbs;
char *fingerprint;
char *email;
log_assert (pk->main_keyid[0] == pk->keyid[0]
&& pk->main_keyid[1] == pk->keyid[1]);
- dbs = opendbs ();
+ dbs = opendbs (ctrl);
if (! dbs)
{
log_error (_("error opening TOFU database: %s\n"),
xfree (email);
xfree (fingerprint);
- closedbs (dbs);
-
if (*policy == _tofu_GET_POLICY_ERROR)
return gpg_error (GPG_ERR_GENERAL);
return 0;
_tofu_GET_POLICY_ERROR = 100
};
+
/* Return a string representation of a trust policy. Returns "???" if
POLICY is not valid. */
const char *tofu_policy_str (enum tofu_policy policy);
interact with the user in the case of a conflict or if the
binding's policy is ask. This function returns the binding's trust
level. If an error occurs, it returns TRUST_UNKNOWN. */
-int tofu_register (PKT_public_key *pk, const char *user_id,
+int tofu_register (ctrl_t ctrl, PKT_public_key *pk, const char *user_id,
const byte *sigs_digest, int sigs_digest_len,
time_t sig_time, const char *origin, int may_ask);
<PK, USER_ID>. If MAY_ASK is 1, then this function may
interact with the user. If not, TRUST_UNKNOWN is returned. If an
error occurs, TRUST_UNDEFINED is returned. */
-int tofu_get_validity (PKT_public_key *pk, const char *user_id, int may_ask);
+int tofu_get_validity (ctrl_t ctrl,
+ PKT_public_key *pk, const char *user_id, int may_ask);
/* Set the policy for all non-revoked user ids in the keyblock KB to
POLICY. */
-gpg_error_t tofu_set_policy (kbnode_t kb, enum tofu_policy policy);
+gpg_error_t tofu_set_policy (ctrl_t ctrl, kbnode_t kb, enum tofu_policy policy);
/* Set the TOFU policy for all non-revoked users in the key with the
key id KEYID to POLICY. */
-gpg_error_t tofu_set_policy_by_keyid (u32 *keyid, enum tofu_policy policy);
+gpg_error_t tofu_set_policy_by_keyid (ctrl_t ctrl,
+ u32 *keyid, enum tofu_policy policy);
/* Return the TOFU policy for the specified binding in *POLICY. */
-gpg_error_t tofu_get_policy (PKT_public_key *pk, PKT_user_id *user_id,
+gpg_error_t tofu_get_policy (ctrl_t ctrl,
+ PKT_public_key *pk, PKT_user_id *user_id,
enum tofu_policy *policy);
/* When doing a lot of DB activities (in particular, when listing
void tofu_begin_batch_update (void);
void tofu_end_batch_update (void);
+/* Release all of the resources associated with a DB meta-handle. */
+void tofu_closedbs (ctrl_t ctrl);
+
#endif /*G10_TOFU_H*/
const char *
-uid_trust_string_fixed (PKT_public_key *key, PKT_user_id *uid)
+uid_trust_string_fixed (ctrl_t ctrl, PKT_public_key *key, PKT_user_id *uid)
{
if (!key && !uid)
{
return _("[ expired]");
else if(key)
{
- switch (get_validity (key, uid, NULL, 0) & TRUST_MASK)
+ switch (get_validity (ctrl, key, uid, NULL, 0) & TRUST_MASK)
{
case TRUST_UNKNOWN: return _("[ unknown]");
case TRUST_EXPIRED: return _("[ expired]");
case TRUST_UNDEFINED: return _("[ undef ]");
+ case TRUST_NEVER: return _("[ never ]");
case TRUST_MARGINAL: return _("[marginal]");
case TRUST_FULLY: return _("[ full ]");
case TRUST_ULTIMATE: return _("[ultimate]");
void
-check_trustdb_stale (void)
+check_trustdb_stale (ctrl_t ctrl)
{
#ifndef NO_TRUST_MODELS
- tdb_check_trustdb_stale ();
+ tdb_check_trustdb_stale (ctrl);
+#else
+ (void)ctrl;
#endif
}
void
-check_or_update_trustdb (void)
+check_or_update_trustdb (ctrl_t ctrl)
{
#ifndef NO_TRUST_MODELS
- tdb_check_or_update ();
+ tdb_check_or_update (ctrl);
+#else
+ (void)ctrl;
#endif
}
* otherwise, a reasonable value for the entire key is returned.
*/
unsigned int
-get_validity (PKT_public_key *pk, PKT_user_id *uid, PKT_signature *sig,
- int may_ask)
+get_validity (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid,
+ PKT_signature *sig, int may_ask)
{
int rc;
unsigned int validity;
#ifdef NO_TRUST_MODELS
validity = TRUST_UNKNOWN;
#else
- validity = tdb_get_validity_core (pk, uid, main_pk, sig, may_ask);
+ validity = tdb_get_validity_core (ctrl, pk, uid, main_pk, sig, may_ask);
#endif
leave:
int
-get_validity_info (PKT_public_key *pk, PKT_user_id *uid)
+get_validity_info (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid)
{
int trustlevel;
if (!pk)
return '?'; /* Just in case a NULL PK is passed. */
- trustlevel = get_validity (pk, uid, NULL, 0);
+ trustlevel = get_validity (ctrl, pk, uid, NULL, 0);
if ((trustlevel & TRUST_FLAG_REVOKED))
return 'r';
return trust_letter (trustlevel);
const char *
-get_validity_string (PKT_public_key *pk, PKT_user_id *uid)
+get_validity_string (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid)
{
int trustlevel;
if (!pk)
return "err"; /* Just in case a NULL PK is passed. */
- trustlevel = get_validity (pk, uid, NULL, 0);
+ trustlevel = get_validity (ctrl, pk, uid, NULL, 0);
if ((trustlevel & TRUST_FLAG_REVOKED))
return _("revoked");
return trust_value_to_string (trustlevel);
static int pending_check_trustdb;
-static int validate_keys (int interactive);
+static int validate_keys (ctrl_t ctrl, int interactive);
\f
/**********************************************
* when a check is due. This can be used to run the check from a crontab
*/
void
-check_trustdb ()
+check_trustdb (ctrl_t ctrl)
{
init_trustdb();
if (opt.trust_model == TM_PGP || opt.trust_model == TM_CLASSIC
}
}
- validate_keys (0);
+ validate_keys (ctrl, 0);
}
else
log_info (_("no need for a trustdb check with '%s' trust model\n"),
* Recreate the WoT.
*/
void
-update_trustdb()
+update_trustdb (ctrl_t ctrl)
{
- init_trustdb();
+ init_trustdb ();
if (opt.trust_model == TM_PGP || opt.trust_model == TM_CLASSIC
|| opt.trust_model == TM_TOFU_PGP || opt.trust_model == TM_TOFU)
- validate_keys (1);
+ validate_keys (ctrl, 1);
else
log_info (_("no need for a trustdb update with '%s' trust model\n"),
trust_model_string(opt.trust_model));
/* If the trustdb is dirty, and we're interactive, update it.
Otherwise, check it unless no-auto-check-trustdb is set. */
void
-tdb_check_or_update (void)
+tdb_check_or_update (ctrl_t ctrl)
{
- if(trustdb_pending_check())
+ if (trustdb_pending_check ())
{
- if(opt.interactive)
- update_trustdb();
- else if(!opt.no_auto_check_trustdb)
- check_trustdb();
+ if (opt.interactive)
+ update_trustdb (ctrl);
+ else if (!opt.no_auto_check_trustdb)
+ check_trustdb (ctrl);
}
}
void
-tdb_check_trustdb_stale (void)
+tdb_check_trustdb_stale (ctrl_t ctrl)
{
static int did_nextcheck=0;
{
if (!opt.quiet)
log_info (_("checking the trustdb\n"));
- validate_keys (0);
+ validate_keys (ctrl, 0);
}
}
}
* by the TOFU code to record statistics.
*/
unsigned int
-tdb_get_validity_core (PKT_public_key *pk, PKT_user_id *uid,
+tdb_get_validity_core (ctrl_t ctrl,
+ PKT_public_key *pk, PKT_user_id *uid,
PKT_public_key *main_pk,
PKT_signature *sig,
int may_ask)
if (trustdb_args.no_trustdb && opt.trust_model == TM_ALWAYS)
return TRUST_UNKNOWN;
- check_trustdb_stale();
+ check_trustdb_stale (ctrl);
if(opt.trust_model==TM_DIRECT)
{
user_ids ++;
if (sig)
- tl = tofu_register (main_pk, user_id->name,
+ tl = tofu_register (ctrl, main_pk, user_id->name,
sig->digest, sig->digest_len,
sig->timestamp, "unknown",
may_ask);
else
- tl = tofu_get_validity (main_pk, user_id->name, may_ask);
+ tl = tofu_get_validity (ctrl, main_pk, user_id->name, may_ask);
if (tl == TRUST_EXPIRED)
user_ids_expired ++;
****************************************/
static int
-ask_ownertrust (u32 *kid,int minimum)
+ask_ownertrust (ctrl_t ctrl, u32 *kid, int minimum)
{
PKT_public_key *pk;
int rc;
}
else
{
- ot=edit_ownertrust(pk,0);
+ ot=edit_ownertrust (ctrl, pk, 0);
if(ot>0)
ot = tdb_get_ownertrust (pk);
else if(ot==0)
*
*/
static int
-validate_keys (int interactive)
+validate_keys (ctrl_t ctrl, int interactive)
{
int rc = 0;
int quit=0;
if (interactive && k->ownertrust == TRUST_UNKNOWN)
{
- k->ownertrust = ask_ownertrust (k->kid,min);
+ k->ownertrust = ask_ownertrust (ctrl, k->kid,min);
if (k->ownertrust == (unsigned int)(-1))
{
const char *trust_value_to_string (unsigned int value);
int string_to_trust_value (const char *str);
-const char *uid_trust_string_fixed (PKT_public_key *key, PKT_user_id *uid);
+const char *uid_trust_string_fixed (ctrl_t ctrl,
+ PKT_public_key *key, PKT_user_id *uid);
unsigned int get_ownertrust (PKT_public_key *pk);
void update_ownertrust (PKT_public_key *pk, unsigned int new_trust);
int clear_ownertrusts (PKT_public_key *pk);
void revalidation_mark (void);
-void check_trustdb_stale (void);
-void check_or_update_trustdb (void);
+void check_trustdb_stale (ctrl_t ctrl);
+void check_or_update_trustdb (ctrl_t ctrl);
-unsigned int get_validity (PKT_public_key *pk, PKT_user_id *uid,
+unsigned int get_validity (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid,
PKT_signature *sig, int may_ask);
-int get_validity_info (PKT_public_key *pk, PKT_user_id *uid);
-const char *get_validity_string (PKT_public_key *pk, PKT_user_id *uid);
+int get_validity_info (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid);
+const char *get_validity_string (ctrl_t ctrl,
+ PKT_public_key *pk, PKT_user_id *uid);
void mark_usable_uid_certs (kbnode_t keyblock, kbnode_t uidnode,
u32 *main_kid, struct key_item *klist,
void tdb_register_trusted_key (const char *string);
/* Returns whether KID is on the list of ultimately trusted keys. */
int tdb_keyid_is_utk (u32 *kid);
-void check_trustdb (void);
-void update_trustdb (void);
+void check_trustdb (ctrl_t ctrl);
+void update_trustdb (ctrl_t ctrl);
int setup_trustdb( int level, const char *dbname );
void how_to_fix_the_trustdb (void);
const char *trust_model_string (int model);
void init_trustdb( void );
-void tdb_check_trustdb_stale (void);
+void tdb_check_trustdb_stale (ctrl_t ctrl);
void sync_trustdb( void );
void tdb_revalidation_mark (void);
int trustdb_pending_check(void);
-void tdb_check_or_update (void);
+void tdb_check_or_update (ctrl_t ctrl);
int tdb_cache_disabled_value (PKT_public_key *pk);
-unsigned int tdb_get_validity_core (PKT_public_key *pk, PKT_user_id *uid,
+unsigned int tdb_get_validity_core (ctrl_t ctrl,
+ PKT_public_key *pk, PKT_user_id *uid,
PKT_public_key *main_pk,
PKT_signature *sig, int may_ask);
void import_ownertrust(const char *fname);
/*-- pkclist.c --*/
-int edit_ownertrust (PKT_public_key *pk, int mode );
+int edit_ownertrust (ctrl_t ctrl, PKT_public_key *pk, int mode);
#endif /*G10_TRUSTDB_H*/
if (err)
goto leave;
- err = gnupg_create_inbound_pipe (inbound);
+ err = gnupg_create_inbound_pipe (inbound, NULL, 0);
if (!err)
- err = gnupg_create_outbound_pipe (outbound);
+ err = gnupg_create_outbound_pipe (outbound, NULL, 0);
if (err)
{
log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
int quiet; /* Be as quiet as possible. */
int dry_run; /* Don't change any persistent data. */
- const char *homedir; /* Configuration directory name. */
const char *config_filename; /* Name of the used config file. */
/* Filename of the AGENT program. */
break;
case 31: p = "\nHome: "; break;
- case 32: p = opt.homedir; break;
+ case 32: p = gnupg_homedir (); break;
default: p = NULL; break;
}
log_fatal ("error allocating session environment block: %s\n",
strerror (errno));
- opt.homedir = default_homedir ();
/* Fixme: We enable verbose mode here because there is currently no
way to do this when starting g13-syshelp. To fix that we should
add a g13-syshelp.conf file in /etc/gnupg. */
case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;
- case oHomedir: opt.homedir = pargs.r.ret_str; break;
+ case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
case oFakedSystemTime:
{
configname = NULL;
if (!opt.config_filename)
- opt.config_filename = make_filename (opt.homedir, G13_NAME".conf", NULL);
+ opt.config_filename = make_filename (gnupg_homedir (),
+ G13_NAME".conf", NULL);
if (log_get_errorcount(0))
g13_exit(2);
/* Set the standard GnuPG random seed file. */
if (use_random_seed)
{
- char *p = make_filename (opt.homedir, "random_seed", NULL);
+ char *p = make_filename (gnupg_homedir (), "random_seed", NULL);
gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
xfree(p);
}
break;
case 31: p = "\nHome: "; break;
- case 32: p = opt.homedir; break;
+ case 32: p = gnupg_homedir (); break;
default: p = NULL; break;
}
log_fatal ("error allocating session environment block: %s\n",
strerror (errno));
- opt.homedir = default_homedir ();
-
/* First check whether we have a config file on the commandline. */
orig_argc = argc;
orig_argv = argv;
else if (pargs.r_opt == oNoOptions)
default_config = 0; /* --no-options */
else if (pargs.r_opt == oHomedir)
- opt.homedir = pargs.r.ret_str;
+ gnupg_set_homedir (pargs.r.ret_str);
}
/* Initialize the secure memory. */
/* Set the default option file */
if (default_config )
- configname = make_filename (opt.homedir, G13_NAME".conf", NULL);
+ configname = make_filename (gnupg_homedir (), G13_NAME".conf", NULL);
argc = orig_argc;
argv = orig_argv;
}
break;
- case oHomedir: opt.homedir = pargs.r.ret_str; break;
+ case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
case oGpgProgram: opt.gpg_program = pargs.r.ret_str; break;
configname = NULL;
if (!opt.config_filename)
- opt.config_filename = make_filename (opt.homedir, G13_NAME".conf", NULL);
+ opt.config_filename = make_filename (gnupg_homedir (),
+ G13_NAME".conf", NULL);
if (log_get_errorcount(0))
g13_exit(2);
/* Set the standard GnuPG random seed file. */
if (use_random_seed)
{
- char *p = make_filename (opt.homedir, "random_seed", NULL);
+ char *p = make_filename (gnupg_homedir (), "random_seed", NULL);
gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
xfree(p);
}
if (opt.verbose || opt.debug)
{
- char *tmp = NULL;
+ char *tmp;
tmp = xtryasprintf ("Home: %s\n"
"Config: %s\n"
"%s",
- opt.homedir,
+ gnupg_homedir (),
opt.config_filename,
hello);
if (tmp)
/* Don't know whether this is needed: */
/* static struct { */
-/* const char *homedir; */
/* int dry_run; */
/* int quiet; */
/* int verbose; */
msgstr "error mentre s'enviava a «%s»: %s\n"
#, fuzzy, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "AVÍS: els permissos són insegurs en %s «%s»\n"
+
+#, fuzzy, c-format
msgid "listen() failed: %s\n"
msgstr "ha fallat l'actualització: %s\n"
msgstr "%s: s'ha creat el directori\n"
#, fuzzy, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "AVÍS: els permissos són insegurs en %s «%s»\n"
-
-#, fuzzy, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "base de dades de confiança: ha fallat la lectura (n=%d): %s\n"
msgid "export keys"
msgstr "exporta claus"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "exporta claus a un servidor de claus"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "importa claus d'un servidor de claus"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "cerca claus en un servidor de claus"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|escriu informació d'estat en aquest FD"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Forma d'ús: gpgv [opcions] [fitxers] (-h per a veure l'ajuda)"
msgid "No key with this keygrip\n"
msgstr "No hi ha cap ID amb l'índex %d\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "arrodonida fins a %u bits\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr ""
msgid "Requested keysize is %u bits\n"
msgstr "La grandària sol·licitada és %u bits\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "arrodonida fins a %u bits\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgid "error updating TOFU database: %s\n"
msgstr "error mentre s'enviava a «%s»: %s\n"
-#, fuzzy, c-format
-msgid "public key %s not found: %s\n"
-msgstr "no s'ha trobat la clau pública %08lX: %s\n"
-
-#, fuzzy, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "error en la lectura de «%s»: %s\n"
-
#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "error en la lectura de «%s»: %s\n"
+
+#, fuzzy, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "error en la creació de la contrasenya: %s\n"
"no és necessària una comprovació de la base de dades de confiança\n"
"\n"
+#, fuzzy, c-format
+msgid "public key %s not found: %s\n"
+msgstr "no s'ha trobat la clau pública %08lX: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "si us plau, feu un --check-trustdb\n"
msgid "[ undef ]"
msgstr ""
+#, fuzzy
+msgid "[ never ]"
+msgstr "mai "
+
msgid "[marginal]"
msgstr ""
msgid "error binding socket to '%s': %s\n"
msgstr "chyba při přilepování socketu na „%s“: %s\n"
+# TODO: i18n of first %s
+#, fuzzy, c-format
+#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
+msgid "can't set permissions of '%s': %s\n"
+msgstr "Varování: přístupová práva %s „%s“ nejsou bezpečná\n"
+
#, c-format
msgid "listen() failed: %s\n"
msgstr "volání listen() selhalo: %s\n"
msgid "directory '%s' created\n"
msgstr "adresář „%s“ vytvořen\n"
-# TODO: i18n of first %s
-#, fuzzy, c-format
-#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
-msgid "can't set permissions of '%s': %s\n"
-msgstr "Varování: přístupová práva %s „%s“ nejsou bezpečná\n"
-
#, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "volání stat() na „%s“ selhalo: %s\n"
msgid "export keys"
msgstr "exportovat klíče"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "exportovat klíče na server klíčů"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "importovat klíče ze serveru klíčů"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "vyhledat klíče na serveru klíčů"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|zapsat informace o stavu do tohoto FD"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Použití: gpg [volby] [soubory] (-h pro pomoc)"
msgstr "Klíč s takovým keygripem neexistuje\n"
#, c-format
+msgid "rounded to %u bits\n"
+msgstr "zaokrouhleno na %u bitů\n"
+
+#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr "klíč %s může mít délku v intervalu %u až %u bitů.\n"
msgid "Requested keysize is %u bits\n"
msgstr "Požadovaná délka klíče je %u bitů.\n"
-#, c-format
-msgid "rounded to %u bits\n"
-msgstr "zaokrouhleno na %u bitů\n"
-
msgid "Please select which elliptic curve you want:\n"
msgstr "Prosím, vyberte, kterou eliptickou křivku chcete:\n"
msgstr "chyba při odesílání dat: %s\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "veřejný klíč %s nebyl nalezen: %s\n"
-
-#, fuzzy, c-format
-#| msgid "error setting OCSP target: %s\n"
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "chyba při nastavování cíle OCSP: %s\n"
-
-#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[2] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+#| msgid "error setting OCSP target: %s\n"
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "chyba při nastavování cíle OCSP: %s\n"
+
+#, fuzzy, c-format
#| msgid "error creating a pipe: %s\n"
msgid "error changing TOFU policy: %s\n"
msgstr "chyba při vytváření roury: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "není nutné aktualizovat databázi důvěry s modelem „%s“\n"
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "veřejný klíč %s nebyl nalezen: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "prosím proveďte --check-trustdb\n"
msgid "[ undef ]"
msgstr "[nedefinovaná]"
+#, fuzzy
+#| msgid "never"
+msgid "[ never ]"
+msgstr "žádná"
+
msgid "[marginal]"
msgstr "[ částečná ]"
msgid "error binding socket to '%s': %s\n"
msgstr "fejl ved binding af sokkel til »%s«: %s\n"
+#, fuzzy, c-format
+#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
+msgid "can't set permissions of '%s': %s\n"
+msgstr "Advarsel: usikre rettigheder på %s »%s«\n"
+
#, c-format
msgid "listen() failed: %s\n"
msgstr "listen() mislykkedes: %s\n"
msgstr "mappe »%s« oprettet\n"
#, fuzzy, c-format
-#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
-msgid "can't set permissions of '%s': %s\n"
-msgstr "Advarsel: usikre rettigheder på %s »%s«\n"
-
-#, fuzzy, c-format
#| msgid "stat() failed for `%s': %s\n"
msgid "stat() failed for '%s': %s\n"
msgstr "stat() mislykkedes for »%s«: %s\n"
msgid "export keys"
msgstr "eksporter nøgler"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "eksporter nøgler til en nøgletjener"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "importer nøgler fra en nøgleserver"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "søg efter nøgler på en nøgleserver"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|skriv statusinformation til denne FD"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Brug: gpgv [tilvalg] [filer] (-h for hjælp)"
msgid "No key with this keygrip\n"
msgstr "Ingen nøgle med dette nøglegreb\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "afrundet op til %u bit\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr "%s nøgler kan være mellem %u og %u bit lange.\n"
msgid "Requested keysize is %u bits\n"
msgstr "Ønsket nøglestørrelse er %u bit\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "afrundet op til %u bit\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgstr "fejl under afsendelse af %s-kommando: %s\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "offentlig nøgle %s blev ikke fundet: %s\n"
-
-#, fuzzy, c-format
-#| msgid "error storing flags: %s\n"
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "fejl ved lagring af flag: %s\n"
-
-#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+#| msgid "error storing flags: %s\n"
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "fejl ved lagring af flag: %s\n"
+
+#, fuzzy, c-format
#| msgid "error creating a pipe: %s\n"
msgid "error changing TOFU policy: %s\n"
msgstr "fejl ved oprettelse af datakanal: %s\n"
msgstr ""
"intet behov for en opdatering af trustdb med troværdighedsmodellen »%s«\n"
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "offentlig nøgle %s blev ikke fundet: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "udfør venligst en --check-trustdb\n"
msgid "[ undef ]"
msgstr "[ ej def]"
+#, fuzzy
+#| msgid "never"
+msgid "[ never ]"
+msgstr "aldrig"
+
msgid "[marginal]"
msgstr "[marginal]"
msgstr ""
"Project-Id-Version: gnupg-2.1.0\n"
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
-"PO-Revision-Date: 2016-05-04 11:03+0200\n"
+"PO-Revision-Date: 2016-06-16 17:04+0200\n"
"Last-Translator: Werner Koch <wk@gnupg.org>\n"
"Language-Team: German <de@li.org>\n"
"Language: de\n"
msgstr "Der Socket kann nicht an `%s' gebunden werden: %s\n"
#, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "Zugriffsrechte für '%s' können nicht gesetzt werden: %s\n"
+
+#, c-format
msgid "listen() failed: %s\n"
msgstr "Der listen()-Aufruf ist fehlgeschlagen: %s\n"
msgstr "Verzeichnis `%s' erzeugt\n"
#, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "Zugriffsrechte für '%s' können nicht gesetzt werden: %s\n"
-
-#, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "stat()-Aufruf für `%s' fehlgeschlagen: %s\n"
msgid "export keys"
msgstr "Schlüssel exportieren"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "Schlüssel zu einem Schlü.server exportieren"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "Schlüssel von einem Schlü.server importieren"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "Schlüssel auf einem Schlü.server suchen"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|Statusinfo auf FD (Dateihandle) ausgeben"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr "|ALGO|Weise mit ALGO erstellte Signaturen zurück"
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Aufruf: gpgv [Optionen] [Dateien] (-h für Hilfe)"
msgstr "Kein Schlüssel mit diesem \"Keygrip\"\n"
#, c-format
+msgid "rounded to %u bits\n"
+msgstr "gerundet auf %u Bit\n"
+
+#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr "%s-Schlüssel können zwischen %u und %u Bit lang sein.\n"
msgid "Requested keysize is %u bits\n"
msgstr "Die verlangte Schlüssellänge beträgt %u Bit\n"
-#, c-format
-msgid "rounded to %u bits\n"
-msgstr "gerundet auf %u Bit\n"
-
msgid "Please select which elliptic curve you want:\n"
msgstr "Bitte wählen Sie, welche elliptische Kurve Sie möchten:\n"
msgstr "Fehler beim Schreiben der TOFU Datenbank: %s\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "Öffentlicher Schlüssel %s nicht gefunden: %s\n"
-
-#, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "Fehler beim Setzen der TOFU Binding Vertrauensstufe auf %s\n"
-
-#, c-format
msgid "The binding %s is NOT known."
msgstr "Die Bindung %s ist NICHT bekannt."
msgstr[1] " innerhalb der letzten %ld Monate."
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
"Normalerweise ist lediglich ein Schlüssel mit einer Email-Adresse "
"ob der neue Schlüssel legitim ist."
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr "gGaAuUlLfF"
msgstr "(G)ut, einmal (A)kzeptieren, (U)nbekannt, einmal ab(L)ehnen, (F)alsch?"
#, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "Fehler beim Setzen der TOFU Binding Vertrauensstufe auf %s\n"
+
+#, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "Fehler beim Ändern der TOFU Richtlinie: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "\"Trust-DB\"-Änderung ist beim `%s'-Vertrauensmodell nicht nötig\n"
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "Öffentlicher Schlüssel %s nicht gefunden: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "Bitte ein --check-trustdb durchführen\n"
msgstr "[ widerrufen]"
msgid "[ expired]"
-msgstr "[ verfallen]"
+msgstr "[ verfallen ]"
msgid "[ unknown]"
-msgstr "[ unbekannt]"
+msgstr "[ unbekannt ]"
msgid "[ undef ]"
msgstr "[undefiniert]"
+msgid "[ never ]"
+msgstr "[ niemals ]"
+
msgid "[marginal]"
-msgstr "[ marginal]"
+msgstr "[ marginal ]"
msgid "[ full ]"
msgstr "[vollständig]"
msgid "[ultimate]"
-msgstr "[ ultimativ]"
+msgstr "[ ultimativ ]"
msgid ""
"the signature could not be verified.\n"
msgstr "óöÜëìá óôç áðïóôïëÞ ðñïò ôï `%s': %s\n"
#, fuzzy, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "ÐÑÏÅÉÄÏÐÏÉÇÓÇ: ìç áóöáëåßò Üäåéåò óôï %s \"%s\"\n"
+
+#, fuzzy, c-format
msgid "listen() failed: %s\n"
msgstr "ç åíçìÝñùóç áðÝôõ÷å: %s\n"
msgstr "%s: êáôÜëïãïò äçìéïõñãÞèçêå\n"
#, fuzzy, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "ÐÑÏÅÉÄÏÐÏÉÇÓÇ: ìç áóöáëåßò Üäåéåò óôï %s \"%s\"\n"
-
-#, fuzzy, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "trustdb: read áðÝôõ÷å (n=%d): %s\n"
msgid "export keys"
msgstr "åîáãùãÞ êëåéäéþí"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "åîáãùãÞ êëåéäéþí óå Ýíá äéáêïìéóôÞ êëåéäéþí"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "åéóáãùãÞ êëåéäéþí áðü Ýíá äéáêïìéóôÞ êëåéäéþí"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "áíáæÞôçóç êëåéäéþí óå Ýíá äéáêïìéóôÞ êëåéäéþí"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|åããñáöÞ ôùí ðëçñïöïñéþí êáôÜóôáóçò óôï FD"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "×ñÞóç: gpgv [åðéëïãÝò] [áñ÷åßá] (-h ãéá âïÞèåéá)"
msgid "No key with this keygrip\n"
msgstr "Äåí õðÜñ÷åé user ID ìå äåßêôç %d\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "óôñïããõëïðïéÞèçêå Ýùò ôá %u bits\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr ""
msgid "Requested keysize is %u bits\n"
msgstr "Ôï ìÝãåèïò êëåéäéïý ðïõ æçôÞèçêå åßíáé %u bits\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "óôñïããõëïðïéÞèçêå Ýùò ôá %u bits\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgid "error updating TOFU database: %s\n"
msgstr "óöÜëìá óôç áðïóôïëÞ ðñïò ôï `%s': %s\n"
-#, fuzzy, c-format
-msgid "public key %s not found: %s\n"
-msgstr "ôï äçìüóéï êëåéäß %08lX äåí âñÝèçêå: %s\n"
-
-#, fuzzy, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "óöÜëìá êáôÜ ôçí áíÜãíùóç ôïõ `%s': %s\n"
-
#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "óöÜëìá êáôÜ ôçí áíÜãíùóç ôïõ `%s': %s\n"
+
+#, fuzzy, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "óöÜëìá óôç äçìéïõñãßá ôçò öñÜóçò êëåéäß: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "äåí õðÜñ÷åé áíÜãêç ãéá Ýëåã÷ï ôçò trustdb\n"
+#, fuzzy, c-format
+msgid "public key %s not found: %s\n"
+msgstr "ôï äçìüóéï êëåéäß %08lX äåí âñÝèçêå: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "ðáñáêáëþ êÜíôå Ýíá --check-trustdb\n"
msgid "[ undef ]"
msgstr ""
+#, fuzzy
+msgid "[ never ]"
+msgstr "ðïôÝ "
+
msgid "[marginal]"
msgstr ""
msgstr "eraro dum sendo al '%s': %s\n"
#, fuzzy, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "Averto: malsekuraj permesoj sur %s \"%s\"\n"
+
+#, fuzzy, c-format
msgid "listen() failed: %s\n"
msgstr "aktualigo malsukcesis: %s\n"
msgstr "%s: dosierujo kreita\n"
#, fuzzy, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "Averto: malsekuraj permesoj sur %s \"%s\"\n"
-
-#, fuzzy, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "fido-datenaro: lego malsukcesis (n=%d): %s\n"
msgid "export keys"
msgstr "eksporti þlosilojn"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "eksporti þlosilojn al þlosilservilo"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "importi þlosilojn de þlosilservilo"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "seræi þlosilojn æe þlosilservilo"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|skribi statusinformojn al FD (dosierpriskribilo)"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
#, fuzzy
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Uzado: gpg [opcioj] [dosieroj] (-h por helpo)"
msgid "No key with this keygrip\n"
msgstr "Mankas uzantidentigilo kun indekso %d\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "rondigita øis %u bitoj\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr ""
msgid "Requested keysize is %u bits\n"
msgstr "Petita þlosilgrando estas %u bitoj\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "rondigita øis %u bitoj\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgid "error updating TOFU database: %s\n"
msgstr "eraro dum sendo al '%s': %s\n"
-#, fuzzy, c-format
-msgid "public key %s not found: %s\n"
-msgstr "publika þlosilo %08lX ne trovita: %s\n"
-
-#, fuzzy, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "eraro dum legado de '%s': %s\n"
-
#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "eraro dum legado de '%s': %s\n"
+
+#, fuzzy, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "eraro dum kreado de pasfrazo: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "kontrolo de fido-datenaro ne estas bezonata\n"
+#, fuzzy, c-format
+msgid "public key %s not found: %s\n"
+msgstr "publika þlosilo %08lX ne trovita: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr ""
msgid "[ undef ]"
msgstr ""
+msgid "[ never ]"
+msgstr ""
+
msgid "[marginal]"
msgstr ""
msgid "error binding socket to '%s': %s\n"
msgstr "error enlazando el socket con `%s': %s\n"
+#, fuzzy, c-format
+#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
+msgid "can't set permissions of '%s': %s\n"
+msgstr "Aviso: permisos inseguros en %s \"%s\"\n"
+
#, c-format
msgid "listen() failed: %s\n"
msgstr "listen() falló: %s\n"
msgstr "directorio `%s' creado\n"
#, fuzzy, c-format
-#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
-msgid "can't set permissions of '%s': %s\n"
-msgstr "Aviso: permisos inseguros en %s \"%s\"\n"
-
-#, fuzzy, c-format
#| msgid "stat() failed for `%s': %s\n"
msgid "stat() failed for '%s': %s\n"
msgstr "stat() falló para `%s': %s\n"
msgid "export keys"
msgstr "exporta claves"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "exporta claves a un servidor de claves"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "importa claves desde un servidor de claves"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "busca claves en un servidor de claves"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|DF|escribe información de estado en este descriptor de fichero"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Uso: gpgv [opciones] [ficheros] (-h para ayuda)"
msgid "No key with this keygrip\n"
msgstr "No hay claves con ese keygrip\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "redondeados a %u bits\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr "las claves %s pueden tener entre %u y %u bits de longitud.\n"
msgid "Requested keysize is %u bits\n"
msgstr "El tamaño requerido es de %u bits\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "redondeados a %u bits\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgstr "error enviando orden %s: %s\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "clave pública %s no encontrada: %s\n"
-
-#, fuzzy, c-format
-#| msgid "error storing flags: %s\n"
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "error almacenando parámetros: %s\n"
-
-#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+#| msgid "error storing flags: %s\n"
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "error almacenando parámetros: %s\n"
+
+#, fuzzy, c-format
#| msgid "error creating a pipe: %s\n"
msgid "error changing TOFU policy: %s\n"
msgstr "error creando tubería: %s\n"
"no es necesario comprobar la base de datos de confianza\n"
"con el modelo `%s'\n"
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "clave pública %s no encontrada: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "por favor haga un --check-trustdb\n"
msgid "[ undef ]"
msgstr "[no definida]"
+#, fuzzy
+#| msgid "never"
+msgid "[ never ]"
+msgstr "nunca"
+
msgid "[marginal]"
msgstr "[ dudosa ]"
msgstr "viga teate saatmisel serverile `%s': %s\n"
#, fuzzy, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "HOIATUS: ebaturvalised õigused %s \"%s\"\n"
+
+#, fuzzy, c-format
msgid "listen() failed: %s\n"
msgstr "uuendamine ebaõnnestus: %s\n"
msgstr "%s: kataloog on loodud\n"
#, fuzzy, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "HOIATUS: ebaturvalised õigused %s \"%s\"\n"
-
-#, fuzzy, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "trustdb: lugemine ebaõnnestus (n=%d): %s\n"
msgid "export keys"
msgstr "ekspordi võtmed"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "ekspordi võtmed võtmeserverisse"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "impordi võtmed võtmeserverist"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "otsi võtmeid võtmeserverist"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FP|kirjuta olekuinfo sellesse failipidemesse"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Kasuta: gpgv [võtmed] [failid] (-h näitab abiinfot)"
msgid "No key with this keygrip\n"
msgstr "Kasutaja ID numbriga %d puudub\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "ümardatud üles %u bitini\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr ""
msgid "Requested keysize is %u bits\n"
msgstr "Soovitud võtmepikkus on %u bitti\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "ümardatud üles %u bitini\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgid "error updating TOFU database: %s\n"
msgstr "viga teate saatmisel serverile `%s': %s\n"
-#, fuzzy, c-format
-msgid "public key %s not found: %s\n"
-msgstr "ei leia avalikku võtit %08lX: %s\n"
-
-#, fuzzy, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "viga `%s' lugemisel: %s\n"
-
#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "viga `%s' lugemisel: %s\n"
+
+#, fuzzy, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "viga parooli loomisel: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "trustdb kontrolliks puudub vajadus\n"
+#, fuzzy, c-format
+msgid "public key %s not found: %s\n"
+msgstr "ei leia avalikku võtit %08lX: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "palun tehke --check-trustdb\n"
msgid "[ undef ]"
msgstr ""
+#, fuzzy
+msgid "[ never ]"
+msgstr "mitte kunagi"
+
msgid "[marginal]"
msgstr ""
msgstr "virhe lähettäessä kohteeseen \"%s\": %s\n"
#, fuzzy, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "VAROITUS: oikeudet kohteessa %s \"%s\" eivät ole turvallisia\"\n"
+
+#, fuzzy, c-format
msgid "listen() failed: %s\n"
msgstr "päivitys epäonnistui: %s\n"
msgstr "%s: hakemisto luotu\n"
#, fuzzy, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "VAROITUS: oikeudet kohteessa %s \"%s\" eivät ole turvallisia\"\n"
-
-#, fuzzy, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "trustdb: luku epäonnistui (n=%d): %s\n"
msgid "export keys"
msgstr "vie avaimia"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "vie avaimia palvelimelle"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "nouda avaimia avainpalvelimelta"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "etsi avaimia avainpalvelimelta"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|tilatiedot kirjoitetaan FD:iin"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Käyttö: gpgv [valitsimet] [tiedostot] (-h näyttää ohjeen)"
msgid "No key with this keygrip\n"
msgstr "Indeksillä %d ei löydy käyttäjätunnusta\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "pyöristetty %u bittiin\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr ""
msgid "Requested keysize is %u bits\n"
msgstr "Halutun avaimen koko on %u bittiä\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "pyöristetty %u bittiin\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgid "error updating TOFU database: %s\n"
msgstr "virhe lähettäessä kohteeseen \"%s\": %s\n"
-#, fuzzy, c-format
-msgid "public key %s not found: %s\n"
-msgstr "julkista avainta %08lX ei löydy: %s\n"
-
-#, fuzzy, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "virhe luettaessa tiedostoa \"%s\": %s\n"
-
#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "virhe luettaessa tiedostoa \"%s\": %s\n"
+
+#, fuzzy, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "virhe luotaessa salasanaa: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "trustdb:n tarkistusta ei tarvita\n"
+#, fuzzy, c-format
+msgid "public key %s not found: %s\n"
+msgstr "julkista avainta %08lX ei löydy: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "tee --check-trustdb, kiitos\n"
msgid "[ undef ]"
msgstr ""
+#, fuzzy
+msgid "[ never ]"
+msgstr "ei koskaan"
+
msgid "[marginal]"
msgstr ""
msgid "error binding socket to '%s': %s\n"
msgstr "erreur de lien de la socket à « %s » : %s\n"
+#, fuzzy, c-format
+#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
+msgid "can't set permissions of '%s': %s\n"
+msgstr "Avertissement : les droits de %s ne sont pas sûrs « %s »\n"
+
#, c-format
msgid "listen() failed: %s\n"
msgstr "échec de listen() : %s\n"
msgid "directory '%s' created\n"
msgstr "répertoire « %s » créé\n"
-#, fuzzy, c-format
-#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
-msgid "can't set permissions of '%s': %s\n"
-msgstr "Avertissement : les droits de %s ne sont pas sûrs « %s »\n"
-
#, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "échec de stat() pour « %s » : %s\n"
msgid "export keys"
msgstr "exporter les clefs"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "exporter les clefs vers un serveur de clefs"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "importer les clefs d'un serveur de clefs"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "chercher les clefs avec un serveur de clefs"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|écrire l'état sur ce descripteur"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Utilisation : gpgv [options] [fichiers] (-h pour l'aide)"
msgstr "Pas de clef avec ce keygrip\n"
#, c-format
+msgid "rounded to %u bits\n"
+msgstr "arrondie à %u bits\n"
+
+#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr "les clefs %s peuvent faire une taille comprise entre %u et %u bits.\n"
msgid "Requested keysize is %u bits\n"
msgstr "La taille demandée est %u bits\n"
-#, c-format
-msgid "rounded to %u bits\n"
-msgstr "arrondie à %u bits\n"
-
msgid "Please select which elliptic curve you want:\n"
msgstr "Sélectionnez le type de courbe elliptique désiré :\n"
msgstr "erreur d'envoi de données : %s\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "clef publique %s introuvable : %s\n"
-
-#, fuzzy, c-format
-#| msgid "error setting OCSP target: %s\n"
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "erreur de configuration de la cible OCSP : %s\n"
-
-#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+#| msgid "error setting OCSP target: %s\n"
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "erreur de configuration de la cible OCSP : %s\n"
+
+#, fuzzy, c-format
#| msgid "error creating a pipe: %s\n"
msgid "error changing TOFU policy: %s\n"
msgstr "erreur de création d'un tube : %s\n"
"inutile de mettre à jour la base de confiance avec le modèle de\n"
" confiance « %s »\n"
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "clef publique %s introuvable : %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "veuillez faire un --check-trustdb\n"
msgid "[ undef ]"
msgstr "[indéfinie]"
+#, fuzzy
+#| msgid "never"
+msgid "[ never ]"
+msgstr "jamais"
+
msgid "[marginal]"
msgstr "[marginale]"
msgstr "erro ao enviar a `%s': %s\n"
#, fuzzy, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "AVISO: permisos inseguros en %s \"%s\"\n"
+
+#, fuzzy, c-format
msgid "listen() failed: %s\n"
msgstr "a actualización fallou: %s\n"
msgstr "%s: directorio creado\n"
#, fuzzy, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "AVISO: permisos inseguros en %s \"%s\"\n"
-
-#, fuzzy, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "base de datos de confianza: fallou a lectura (n=%d): %s\n"
msgid "export keys"
msgstr "exportar chaves"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "exportar chaves a un servidor de chaves"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "importar chaves dun servidor de chaves"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "buscar chaves nun servidor de chaves"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|DF|escribi-la información de estado a este DF"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Uso: gpgv [opcións] [ficheiros] (-h para ve-la axuda)"
msgid "No key with this keygrip\n"
msgstr "Non hai ID de usuario con índice %d\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "redondeado a %u bits\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr ""
msgid "Requested keysize is %u bits\n"
msgstr "O tamaño de chave requerido son %u bits\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "redondeado a %u bits\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgid "error updating TOFU database: %s\n"
msgstr "erro ao enviar a `%s': %s\n"
-#, fuzzy, c-format
-msgid "public key %s not found: %s\n"
-msgstr "non se atopou a chave pública %08lX: %s\n"
-
-#, fuzzy, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "erro lendo `%s': %s\n"
-
#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "erro lendo `%s': %s\n"
+
+#, fuzzy, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "erro ao crea-lo contrasinal: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "non se precisa comproba-la base de datos de confianza\n"
+#, fuzzy, c-format
+msgid "public key %s not found: %s\n"
+msgstr "non se atopou a chave pública %08lX: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "por favor, execute con --check-trustdb\n"
msgid "[ undef ]"
msgstr ""
+#, fuzzy
+msgid "[ never ]"
+msgstr "nunca "
+
msgid "[marginal]"
msgstr ""
msgstr "Hiba %s-ra/-re küldéskor: %s\n"
#, fuzzy, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "FIGYELEM: nem biztonságos engedélyek: %s \"%s\"\n"
+
+#, fuzzy, c-format
msgid "listen() failed: %s\n"
msgstr "Frissítés sikertelen: %s.\n"
msgstr "%s: Könyvtárat létrehoztam.\n"
#, fuzzy, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "FIGYELEM: nem biztonságos engedélyek: %s \"%s\"\n"
-
-#, fuzzy, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "Bizalmi adatbázis: olvasás sikertelen (n=%d): %s.\n"
msgid "export keys"
msgstr "kulcsok exportálása"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "kulcsok exportálása kulcsszerverre"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "kulcsok importálása kulcsszerverrõl"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "kulcsok keresése kulcsszerveren"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|ÁL|állapotinformációk írása ÁL állományleíróra"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Használat: gpgv [opciók] [fájlok] (-h a súgóhoz)"
msgid "No key with this keygrip\n"
msgstr "Nincs %d indexû felhasználóazonosító!\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "Felkerekítve %u bitre.\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr ""
msgid "Requested keysize is %u bits\n"
msgstr "A kívánt kulcsméret %u bit.\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "Felkerekítve %u bitre.\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgid "error updating TOFU database: %s\n"
msgstr "Hiba %s-ra/-re küldéskor: %s\n"
-#, fuzzy, c-format
-msgid "public key %s not found: %s\n"
-msgstr "A(z) %08lX nyilvános kulcsot nem találom: %s.\n"
-
-#, fuzzy, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "Hiba \"%s\" olvasásakor: %s\n"
-
#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "Hiba \"%s\" olvasásakor: %s\n"
+
+#, fuzzy, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "Hiba a jelszó létrehozásakor: %s.\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "Nincs szükség a bizalmi adatbázis ellenõrzésére.\n"
+#, fuzzy, c-format
+msgid "public key %s not found: %s\n"
+msgstr "A(z) %08lX nyilvános kulcsot nem találom: %s.\n"
+
msgid "please do a --check-trustdb\n"
msgstr "Kérem, hajtson végre egy --check-trustdb parancsot!\n"
msgid "[ undef ]"
msgstr ""
+#, fuzzy
+msgid "[ never ]"
+msgstr "soha "
+
msgid "[marginal]"
msgstr ""
#, fuzzy
msgid "use a log file for the server"
-msgstr "cari kunci di key server"
+msgstr "cari kunci di keyserver"
msgid "|PGM|use PGM as the PIN-Entry program"
msgstr ""
msgstr "kesalahan mengirim ke `%s': %s\n"
#, fuzzy, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "Peringatan: permisi tidak aman pada %s \"%s\"\n"
+
+#, fuzzy, c-format
msgid "listen() failed: %s\n"
msgstr "gagal memperbarui: %s\n"
msgstr "%s: direktori tercipta\n"
#, fuzzy, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "Peringatan: permisi tidak aman pada %s \"%s\"\n"
-
-#, fuzzy, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "trustdb: read failed (n=%d): %s\n"
msgid "export keys"
msgstr "ekspor kunci"
-msgid "export keys to a key server"
-msgstr "ekspor kunci ke key server"
+msgid "export keys to a keyserver"
+msgstr "ekspor kunci ke keyserver"
-msgid "import keys from a key server"
-msgstr "impor kunci dari key server"
+msgid "import keys from a keyserver"
+msgstr "impor kunci dari keyserver"
-msgid "search for keys on a key server"
-msgstr "cari kunci di key server"
+msgid "search for keys on a keyserver"
+msgstr "cari kunci di keyserver"
msgid "update all keys from a keyserver"
msgstr "update semua kunci dari keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|tulis info status ke FD ini"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Pemakaian: gpgv [opsi] [file] (-h untuk bantuan)"
msgid "No key with this keygrip\n"
msgstr "Tidak ada ID user dengan index %d\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "dibulatkan hingga %u bit\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr ""
msgid "Requested keysize is %u bits\n"
msgstr "Keysize yang diminta adalah %u bit\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "dibulatkan hingga %u bit\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgid "error updating TOFU database: %s\n"
msgstr "kesalahan mengirim ke `%s': %s\n"
-#, fuzzy, c-format
-msgid "public key %s not found: %s\n"
-msgstr "kunci publik %08lX tidak ditemukan: %s\n"
-
-#, fuzzy, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "kesalahan membaca `%s': %s\n"
-
#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "kesalahan membaca `%s': %s\n"
+
+#, fuzzy, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "kesalahan penciptaan passphrase: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "tidak perlu memeriksa trustdb\n"
+#, fuzzy, c-format
+msgid "public key %s not found: %s\n"
+msgstr "kunci publik %08lX tidak ditemukan: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "lakukanlah --check-trustdb\n"
msgid "[ undef ]"
msgstr ""
+#, fuzzy
+msgid "[ never ]"
+msgstr "tidak pernah..."
+
msgid "[marginal]"
msgstr ""
#, fuzzy
msgid "use a log file for the server"
-msgstr "cerca delle chiavi su un key server"
+msgstr "cerca delle chiavi su un keyserver"
msgid "|PGM|use PGM as the PIN-Entry program"
msgstr ""
msgstr "errore leggendo `%s': %s\n"
#, fuzzy, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "ATTENZIONE: i permessi \"%s\" di %s sono insicuri\n"
+
+#, fuzzy, c-format
msgid "listen() failed: %s\n"
msgstr "aggiornamento fallito: %s\n"
msgstr "%s: directory creata\n"
#, fuzzy, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "ATTENZIONE: i permessi \"%s\" di %s sono insicuri\n"
-
-#, fuzzy, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "trustdb: read fallita (n=%d): %s\n"
msgid "export keys"
msgstr "esporta delle chiavi"
-msgid "export keys to a key server"
-msgstr "esporta le chiavi a un key server"
+msgid "export keys to a keyserver"
+msgstr "esporta le chiavi a un keyserver"
-msgid "import keys from a key server"
-msgstr "importa le chiavi da un key server"
+msgid "import keys from a keyserver"
+msgstr "importa le chiavi da un keyserver"
-msgid "search for keys on a key server"
-msgstr "cerca delle chiavi su un key server"
+msgid "search for keys on a keyserver"
+msgstr "cerca delle chiavi su un keyserver"
msgid "update all keys from a keyserver"
-msgstr "aggiorna tutte le chiavi da un key server"
+msgstr "aggiorna tutte le chiavi da un keyserver"
msgid "import/merge keys"
msgstr "importa/aggiungi delle chiavi"
msgid "|FD|write status info to this FD"
msgstr "|FD|scrivi le informazioni di stato sul FD"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Uso: gpgv [opzioni] [file] (-h per l'aiuto)"
msgid "No key with this keygrip\n"
msgstr "Nessun user ID con l'indice %d\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "arrotondate a %u bit\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr ""
msgid "Requested keysize is %u bits\n"
msgstr "La dimensione richiesta della chiave è %u bit\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "arrotondate a %u bit\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgid "error updating TOFU database: %s\n"
msgstr "errore leggendo `%s': %s\n"
-#, fuzzy, c-format
-msgid "public key %s not found: %s\n"
-msgstr "chiave pubblica %08lX non trovata: %s\n"
-
-#, fuzzy, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "errore leggendo `%s': %s\n"
-
#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "errore leggendo `%s': %s\n"
+
+#, fuzzy, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "errore nella creazione della passhprase: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "non è necessario un controllo del trustdb\n"
+#, fuzzy, c-format
+msgid "public key %s not found: %s\n"
+msgstr "chiave pubblica %08lX non trovata: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "per favore usa --check-trustdb\n"
msgid "[ undef ]"
msgstr ""
+#, fuzzy
+msgid "[ never ]"
+msgstr "mai "
+
msgid "[marginal]"
msgstr ""
# IIDA Yosiaki <iida@gnu.org>, 1999, 2000, 2002, 2003, 2004.
# Yoshihiro Kajiki <kajiki@ylug.org>, 1999.
# Takashi P.KATOH, 2002.
-# NIIBE Yutaka <gniibe@fsij.org>, 2013, 2014, 2015.
+# NIIBE Yutaka <gniibe@fsij.org>, 2013, 2014, 2015, 2016.
#
msgid ""
msgstr ""
-"Project-Id-Version: gnupg 2.1.10\n"
+"Project-Id-Version: gnupg 2.1.12\n"
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
-"PO-Revision-Date: 2015-12-21 21:21+0900\n"
+"PO-Revision-Date: 2016-06-07 14:12+0900\n"
"Last-Translator: NIIBE Yutaka <gniibe@fsij.org>\n"
"Language-Team: none\n"
"Language: ja\n"
msgid "allow presetting passphrase"
msgstr "パスフレーズの事前設定を認める"
-#, fuzzy
-#| msgid "allow caller to override the pinentry"
msgid "disallow caller to override the pinentry"
-msgstr "pinentryã\82\88ã\82\8aå\84ªå\85\88ã\81\97ã\81¦ã\83\91ã\82¹ã\83\95ã\83¬ã\83¼ã\82ºå\85¥å\8a\9bã\82\92èª\8dã\82\81ã\82\8b"
+msgstr "pinentryã\82\88ã\82\8aå\84ªå\85\88ã\81\97ã\81¦ã\83\91ã\82¹ã\83\95ã\83¬ã\83¼ã\82ºå\85¥å\8a\9bã\82\92èª\8dã\82\81ã\81ªã\81\84"
msgid "allow passphrase to be prompted through Emacs"
msgstr "Emacsを通じてパスフレーズを催促することを認める"
msgstr "'%s'でソケットのバインドのエラー: %s\n"
#, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "'%s'の許可が設定できません: %s\n"
+
+#, c-format
msgid "listen() failed: %s\n"
msgstr "listen() に失敗しました: %s\n"
msgid "directory '%s' created\n"
msgstr "ディレクトリ'%s'が作成されました\n"
-#, fuzzy, c-format
-#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
-msgid "can't set permissions of '%s': %s\n"
-msgstr "警告: '%s'の安全でない許可 \"%s\"\n"
-
#, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "'%s'でstat()が失敗しました: %s\n"
msgid "error forking process: %s\n"
msgstr "プロセスforkエラー: %s\n"
-#, fuzzy, c-format
-#| msgid "waiting for process %d to terminate failed: %s\n"
+#, c-format
msgid "waiting for processes to terminate failed: %s\n"
-msgstr "プロセス%dの終了待ちが失敗: %s\n"
+msgstr "プロセスの終了待ちが失敗: %s\n"
#, c-format
msgid "error running '%s': probably not installed\n"
msgid "problem with the agent\n"
msgstr "エージェントに障害\n"
-#, fuzzy, c-format
-#| msgid "problem with the agent: %s\n"
+#, c-format
msgid "problem with the agent (unexpected response \"%s\")\n"
-msgstr "エージェントに問題: %s\n"
+msgstr "エージェントに問題 (予期しない応答 \"%s\")\n"
#, c-format
msgid "can't disable core dumps: %s\n"
"外装の中にquoted printable文字があります。おそらくバグのあるMTAが使われたので"
"しょう\n"
-#, fuzzy, c-format
-#| msgid "not human readable"
+#, c-format
msgid "[ not human readable (%zu bytes: %s%s) ]"
-msgstr "人には読めません"
+msgstr "[ 人には読めません (%zuバイト: %s%s) ]"
msgid ""
"a notation name must have only printable characters or spaces, and end with "
msgid "a notation value must not use any control characters\n"
msgstr "注釈名の値に制御文字を使ってはいけません\n"
-#, fuzzy
-#| msgid "a notation name must not contain more than one '@' character\n"
msgid "a notation name may not contain an '=' character\n"
-msgstr "ユーザ注釈名は、一つより大きい'@'文字を含んではなりません\n"
+msgstr "ユーザ注釈名は、'='の文字を含んではなりません\n"
-#, fuzzy
-#| msgid ""
-#| "a notation name must have only printable characters or spaces, and end "
-#| "with an '='\n"
msgid "a notation name must have only printable characters or spaces\n"
-msgstr ""
-"注釈名には印字可能な文字か空白のみを使い、'='で終わらなければなりません\n"
+msgstr "注釈名には印字可能な文字か空白のみを使わなければなりません\n"
msgid "WARNING: invalid notation data found\n"
msgstr "*警告*: 無効な注釈データを発見\n"
msgid "Enter passphrase: "
msgstr "パスフレーズを入力: "
-#, fuzzy, c-format
-#| msgid "error creating keyring '%s': %s\n"
+#, c-format
msgid "error getting version from '%s': %s\n"
-msgstr "鍵リング'%s'の作成エラー: %s\n"
+msgstr "%s'からバージョン取得エラー: %s\n"
#, c-format
msgid "server '%s' is older than us (%s < %s)"
-msgstr ""
+msgstr "サーバ'%s'はこちらより古いです(%s < %s)"
-#, fuzzy, c-format
-#| msgid "WARNING: %s overrides %s\n"
+#, c-format
msgid "WARNING: %s\n"
-msgstr "*警告*: %sは%sより優先\n"
+msgstr "*警告*: %s\n"
#, c-format
msgid "OpenPGP card not available: %s\n"
msgid "(check argument of option '%s')\n"
msgstr "(オプション'%s'の引数を確認ください)\n"
-#, fuzzy, c-format
-#| msgid ""
-#| "Warning: value '%s' for option '%s' should be a long key ID or a "
-#| "fingerprint\n"
+#, c-format
msgid "Warning: '%s' should be a long key ID or a fingerprint\n"
-msgstr ""
-"警告: 値'%s'(オプション'%s'に対する)は長い鍵IDかフィンガープリントであるべき"
-"です。\n"
+msgstr "警告: '%s'は長い鍵IDかフィンガープリントであるべきです。\n"
-#, fuzzy, c-format
-#| msgid "error closing %s: %s\n"
+#, c-format
msgid "error looking up: %s\n"
-msgstr "'%s'でクローズのエラー: %s\n"
+msgstr "検索のエラー: %s\n"
-#, fuzzy, c-format
-#| msgid "error searching the keyring: %s\n"
+#, c-format
msgid "Warning: %s appears in the keyring %d times\n"
-msgstr "鍵リング探索エラー: %s\n"
+msgstr "警告: %sは鍵リングに%d回出現します\n"
#, c-format
msgid "automatically retrieved '%s' via %s\n"
msgid "secret key \"%s\" not found: %s\n"
msgstr "秘密鍵\"%s\"が見つかりません: %s\n"
-#, fuzzy, c-format
-#| msgid "using \"%s\" as default secret key\n"
+#, c-format
msgid "Warning: not using '%s' as default key: %s\n"
-msgstr "デフォルトの秘密鍵として\"%s\"を用います\n"
+msgstr "警告: デフォルトの秘密鍵として '%s' を用いません: %s\n"
-#, fuzzy, c-format
-#| msgid "using \"%s\" as default secret key\n"
+#, c-format
msgid "using \"%s\" as default secret key for signing\n"
-msgstr "デフォルトの秘密鍵として\"%s\"を用います\n"
+msgstr "ã\83\87ã\83\95ã\82©ã\83«ã\83\88ã\81®ç½²å\90\8dç\94¨ã\81®ç§\98å¯\86é\8dµã\81¨ã\81\97ã\81¦\"%s\"ã\82\92ç\94¨ã\81\84ã\81¾ã\81\99\n"
#, c-format
msgid "all values passed to '%s' ignored\n"
-msgstr ""
+msgstr "'%s'に渡されたすべての値は無視されました\n"
#, c-format
msgid "Invalid key %s made valid by --allow-non-selfsigned-uid\n"
msgid "export keys"
msgstr "鍵をエクスポートする"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "鍵サーバに鍵をエクスポートする"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "鍵サーバから鍵をインポートする"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "鍵サーバの鍵を検索する"
msgid "update all keys from a keyserver"
msgid "run in server mode"
msgstr "サーバ・モードで実行"
-#, fuzzy
-#| msgid "|VALUE|set the TOFU policy for a key (good, unknown, bad, ask, auto)"
msgid "|VALUE|set the TOFU policy for a key"
-msgstr "|VALUE|TOFUポリシーを鍵に設定する(good, unknown, bad, ask, auto)"
+msgstr "|VALUE|TOFUポリシーを鍵に設定する"
msgid "create ascii armored output"
msgstr "ASCII形式の外装を作成"
msgid "key export failed: %s\n"
msgstr "鍵のエクスポートに失敗しました: %s\n"
-#, fuzzy, c-format
-#| msgid "key export failed: %s\n"
+#, c-format
msgid "export as ssh key failed: %s\n"
-msgstr "鍵のエクスポートに失敗しました: %s\n"
+msgstr "ssh鍵としてのエクスポートに失敗しました: %s\n"
#, c-format
msgid "keyserver search failed: %s\n"
msgid "|FD|write status info to this FD"
msgstr "|FD|このFDにステイタス情報を書き出す"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr "|ALGO|ALGOで作成された署名を拒絶する"
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "使い方: gpgv [オプション] [ファイル] (ヘルプは -h)"
msgid "[self-signature]"
msgstr "[自己署名]"
-#, fuzzy, c-format
-#| msgid "key %s: unsupported public key algorithm\n"
+#, c-format
msgid "can't check signature with unsupported public-key algorithm (%d): %s.\n"
-msgstr "鍵%s: サポートしていない公開鍵アルゴリズムです\n"
+msgstr "サポートしていない公開鍵アルゴリズム(%d)の署名は確認できません: %s.\n"
-#, fuzzy, c-format
-#| msgid "card does not support digest algorithm %s\n"
+#, c-format
msgid ""
"can't check signature with unsupported message-digest algorithm %d: %s.\n"
-msgstr "カードはダイジェスト・アルゴリズム %s をサポートしていません\n"
+msgstr ""
+"サポートしていないメッセージ・ダイジェスト(%d)の署名は確認できません: %s.\n"
-#, fuzzy
-#| msgid "Good signature from"
msgid " (reordered signatures follow)"
-msgstr "正しい署名"
+msgstr "(順番を変えた署名が続きます)"
-#, fuzzy, c-format
-#| msgid "key %s: %s\n"
+#, c-format
msgid "key %s:\n"
-msgstr "鍵 %s: %s\n"
+msgstr "鍵 %s:\n"
-#, fuzzy, c-format
-#| msgid "User ID \"%s\": %d signature removed\n"
+#, c-format
msgid "%d duplicate signature removed\n"
msgid_plural "%d duplicate signatures removed\n"
-msgstr[0] "ユーザID \"%s\": %d の署名が除去されました\n"
+msgstr[0] "%d個の重複した署名が除去されました\n"
-#, fuzzy, c-format
-#| msgid "1 signature not checked due to a missing key\n"
+#, c-format
msgid "%d signature not checked due to a missing key\n"
msgid_plural "%d signatures not checked due to missing keys\n"
-msgstr[0] "鍵がないため1個の署名を検査しません\n"
+msgstr[0] "鍵がないため%d個の署名は検査しません\n"
-#, fuzzy, c-format
-#| msgid "%d bad signatures\n"
+#, c-format
msgid "%d bad signature\n"
msgid_plural "%d bad signatures\n"
-msgstr[0] "不正な署名%d個\n"
+msgstr[0] "%d個の不正な署名\n"
-#, fuzzy, c-format
-#| msgid "Good signature from"
+#, c-format
msgid "%d signature reordered\n"
msgid_plural "%d signatures reordered\n"
-msgstr[0] "正しい署名"
+msgstr[0] "%d個の正しい署名\n"
#, c-format
msgid ""
"Warning: errors found and only checked self-signatures, run '%s' to check "
"all signatures.\n"
msgstr ""
+"警告: エラーがあり、自己署名だけ確認しました。'%s'を実行してすべての署名を確"
+"認ください。\n"
msgid ""
"Please decide how far you trust this user to correctly verify other users' "
msgid "\"%s\" is not the primary fingerprint\n"
msgstr "\"%s\" はプライマリ・フィンガープリントではありません\n"
-#, fuzzy, c-format
-#| msgid "read error in '%s': %s\n"
+#, c-format
msgid "Invalid user ID '%s': %s\n"
-msgstr "'%s'で読み込みエラー: %s\n"
+msgstr "無効なユーザID '%s': %s\n"
msgid "No matching user IDs."
msgstr "マッチするユーザIDはありません。"
msgid "Really delete this self-signature? (y/N)"
msgstr "この自己署名を本当に削除しますか? (y/N)"
-#, fuzzy, c-format
-#| msgid "Deleted %d signature.\n"
+#, c-format
msgid "Deleted %d signature.\n"
msgid_plural "Deleted %d signatures.\n"
msgstr[0] "%d個の署名を削除しました。\n"
msgid "User ID \"%s\" compacted: %s\n"
msgstr "ユーザID \"%s\" は、コンパクトになりました: %s\n"
-#, fuzzy, c-format
-#| msgid "User ID \"%s\": %d signature removed\n"
+#, c-format
msgid "User ID \"%s\": %d signature removed\n"
msgid_plural "User ID \"%s\": %d signatures removed\n"
msgstr[0] "ユーザID \"%s\": %d の署名が除去されました\n"
msgstr "このkeygripの鍵はありません\n"
#, c-format
+msgid "rounded to %u bits\n"
+msgstr "%uビットに切り上げます\n"
+
+#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr "%s 鍵は %u から %u ビットの長さで可能です。\n"
msgid "Requested keysize is %u bits\n"
msgstr "要求された鍵長は%uビット\n"
-#, c-format
-msgid "rounded to %u bits\n"
-msgstr "%uビットに切り上げます\n"
-
msgid "Please select which elliptic curve you want:\n"
msgstr "ご希望の楕円曲線を選択してください:\n"
msgid "Signature notation: "
msgstr "署名注釈: "
-#, fuzzy, c-format
-#| msgid "%d good signatures\n"
+#, c-format
msgid "%d good signature\n"
msgid_plural "%d good signatures\n"
msgstr[0] "正しい署名%d個\n"
-#, fuzzy, c-format
-#| msgid "1 signature not checked due to an error\n"
+#, c-format
msgid "%d signature not checked due to an error\n"
msgid_plural "%d signatures not checked due to errors\n"
-msgstr[0] "エラーのため1個の署名を検査しません\n"
+msgstr[0] "エラーのため%d個の署名を検査しません\n"
-#, fuzzy, c-format
-#| msgid "Warning: %lu key(s) skipped due to their large size\n"
+#, c-format
msgid "Warning: %lu key skipped due to its large size\n"
msgid_plural "Warning: %lu keys skipped due to their large sizes\n"
-msgstr[0] "*警告*: %lu 鍵がその大きさのためスキップされました\n"
+msgstr[0] "*警告*: %lu個の鍵がその大きさのためスキップされました\n"
msgid "Keyring"
msgstr "鍵リング"
msgid "caching keyring '%s'\n"
msgstr "鍵リング'%s'をキャッシュします\n"
-#, fuzzy, c-format
-#| msgid "%lu keys cached so far (%lu signatures)\n"
+#, c-format
msgid "%lu keys cached so far (%lu signature)\n"
msgid_plural "%lu keys cached so far (%lu signatures)\n"
-msgstr[0] "%lu個の鍵までキャッシュ済 (%lu個の署名)\n"
+msgstr[0] "これまで%lu個の鍵をキャッシュしました (%lu個の署名)\n"
-#, fuzzy, c-format
-#| msgid "flush the cache"
+#, c-format
msgid "%lu key cached"
msgid_plural "%lu keys cached"
-msgstr[0] "キャッシュをフラッシュします"
+msgstr[0] "%lu個の鍵をキャッシュしました"
-#, fuzzy, c-format
-#| msgid "1 bad signature\n"
+#, c-format
msgid " (%lu signature)\n"
msgid_plural " (%lu signatures)\n"
-msgstr[0] "不正な署名1個\n"
+msgstr[0] " (%lu個の不正な署名)\n"
#, c-format
msgid "%s: keyring created\n"
msgid "\"%s\" not a key ID: skipping\n"
msgstr "\"%s\"鍵IDではありません: スキップします\n"
-#, fuzzy, c-format
-#| msgid "refreshing %d keys from %s\n"
+#, c-format
msgid "refreshing %d key from %s\n"
msgid_plural "refreshing %d keys from %s\n"
msgstr[0] "%d本の鍵を%sから更新\n"
msgid "requesting key %s from %s\n"
msgstr "鍵%sを%sに要求\n"
-#, fuzzy
-#| msgid "invalid keyserver options\n"
msgid "no keyserver known\n"
-msgstr "無効な鍵サーバ・オプションです\n"
+msgstr "鍵サーバがわかりません\n"
#, c-format
msgid "sending key %s to %s\n"
msgid "Note: signatures using the %s algorithm are rejected\n"
msgstr "注意: アルゴリズム %s を用いた署名は拒否されました\n"
-#, fuzzy, c-format
-#| msgid "%s:%u: read error: %s\n"
+#, c-format
msgid "(reported error: %s)\n"
-msgstr "%s:%u: 読み込みエラー: %s\n"
+msgstr "(報告されたエラー: %s)\n"
-#, fuzzy, c-format
-#| msgid "read error in '%s': %s\n"
+#, c-format
msgid "(reported error: %s <%s>)\n"
-msgstr "'%s'で読み込みエラー: %s\n"
+msgstr "(報告されたエラー: %s <%s>)\n"
msgid "(further info: "
-msgstr ""
+msgstr "(より詳細な情報: "
#, c-format
msgid "%s:%d: deprecated option \"%s\"\n"
msgid "%s: skipped: public key already present\n"
msgstr "%s: スキップ: 公開鍵はもうあります\n"
-#, fuzzy, c-format
-#| msgid "can't connect to '%s': %s\n"
+#, c-format
msgid "can't encrypt to '%s'\n"
-msgstr "'%s'ã\81¸æ\8e¥ç¶\9aã\81§ã\81\8dã\81¾ã\81\9bã\82\93: %s\n"
+msgstr "'%s'ã\81«æ\9a\97å\8f·å\8c\96ã\81§ã\81\8dã\81¾ã\81\9bã\82\93\n"
#, c-format
msgid "option '%s' given, but no valid default keys given\n"
"declare that a key shall not anymore be used. It is not possible\n"
"to retract such a revocation certificate once it has been published."
msgstr ""
+"失効証明書は \"殺すスイッチ\" のようなもので、鍵がそれ以上使えない\n"
+"ように公に宣言するものです。一度発行されると、そのような失効証明書は\n"
+"撤回することはできません。"
-#, fuzzy
-#| msgid ""
-#| "Use it to revoke this key in case of a compromise or loss of\n"
-#| "the secret key. However, if the secret key is still accessible,\n"
-#| "it is better to generate a new revocation certificate and give\n"
-#| "a reason for the revocation."
msgid ""
"Use it to revoke this key in case of a compromise or loss of\n"
"the secret key. However, if the secret key is still accessible,\n"
msgstr ""
"秘密鍵のコンプロマイズや紛失の場合、これを使ってこの鍵を失効させます。\n"
"しかし、秘密鍵がまだアクセス可能である場合、新しい失効証明書を生成し、\n"
-"失効の理由をつける方がよいでしょう。"
+"失効の理由をつける方がよいでしょう。詳細は、GnuPGマニュアルのgpgコマンド \"--"
+"gen-revoke\"の記述をご覧ください。"
-#, fuzzy
-#| msgid ""
-#| "To avoid an accidental use of this file, a colon has been inserted\n"
-#| "before the 5 dashes below. Remove this colon with a text editor\n"
-#| "before making use of this revocation certificate."
msgid ""
"To avoid an accidental use of this file, a colon has been inserted\n"
"before the 5 dashes below. Remove this colon with a text editor\n"
"before importing and publishing this revocation certificate."
msgstr ""
-"このファイルを誤って使うのを避けるため、以下ではコロンが5つのダッシュの前に挿"
-"入されます。\n"
-"ã\81\93ã\81®å¤±å\8a¹è¨¼æ\98\8eæ\9b¸ã\82\92使ã\81\86å\89\8dã\81«ã\81¯ã\83\86ã\82¯ã\82¹ã\83\88ã\83»ã\82¨ã\83\87ã\82£ã\82¿ã\81§ã\81\93ã\81®ã\82³ã\83ã\83³ã\82\92å\89\8aé\99¤ã\81\97ã\81¦ã\81\8fã\81 ã\81\95ã\81\84ã\80\82"
+"このファイルを誤って使うのを避けるため、以下ではコロンが5つのダッシュ\n"
+"の前に挿入されます。この失効証明書をインポートして公開する前に、テク\n"
+"スト・エディタでこのコロンを削除してください。"
-#, fuzzy, c-format
-#| msgid "Revocation certificate created.\n"
+#, c-format
msgid "revocation certificate stored as '%s.rev'\n"
-msgstr "失効証明書を作成。\n"
+msgstr "失効証明書を '%s.rev' に保管しました。\n"
#, c-format
msgid "secret key \"%s\" not found\n"
msgid "WARNING: signing subkey %s has an invalid cross-certification\n"
msgstr "*警告*: 無効な相互証明が、署名副鍵%sにあります\n"
-#, fuzzy, c-format
-#| msgid "public key %s is %lu second newer than the signature\n"
+#, c-format
msgid "public key %s is %lu second newer than the signature\n"
msgid_plural "public key %s is %lu seconds newer than the signature\n"
-msgstr[0] "公開鍵%sは、署名よりも%lu秒新しいものです\n"
+msgstr[0] "公開鍵%sは、署名よりも%lu秒、新しいものです\n"
-#, fuzzy, c-format
-#| msgid "public key %s is %lu second newer than the signature\n"
+#, c-format
msgid "public key %s is %lu day newer than the signature\n"
msgid_plural "public key %s is %lu days newer than the signature\n"
-msgstr[0] "公開鍵%sは、署名よりも%lu秒新しいものです\n"
+msgstr[0] "公開鍵%sは、署名よりも%lu日、新しいものです\n"
-#, fuzzy, c-format
-#| msgid ""
-#| "key %s was created %lu second in the future (time warp or clock problem)\n"
+#, c-format
msgid ""
"key %s was created %lu second in the future (time warp or clock problem)\n"
msgid_plural ""
"key %s was created %lu seconds in the future (time warp or clock problem)\n"
-msgstr[0] "鍵%sは%lu秒未来にできました (時間歪曲か時計の障害でしょう)\n"
+msgstr[0] "鍵%sは%lu秒、未来にできました (時間歪曲か時計の障害でしょう)\n"
-#, fuzzy, c-format
-#| msgid ""
-#| "key %s was created %lu second in the future (time warp or clock problem)\n"
+#, c-format
msgid "key %s was created %lu day in the future (time warp or clock problem)\n"
msgid_plural ""
"key %s was created %lu days in the future (time warp or clock problem)\n"
-msgstr[0] "鍵%sは%lu秒未来にできました (時間歪曲か時計の障害でしょう)\n"
+msgstr[0] "鍵%sは%lu日、未来にできました (時間歪曲か時計の障害でしょう)\n"
#, c-format
msgid "Note: signature key %s expired %s\n"
msgid "input line longer than %d characters\n"
msgstr "入力行の長さが%d文字を超えています\n"
-#, fuzzy, c-format
-#| msgid "error sending standard options: %s\n"
+#, c-format
msgid "error beginning transaction on TOFU database: %s\n"
-msgstr "標準オプションを送信エラー: %s\n"
+msgstr "TOFUデータベースのトランザクション開始エラー: %s\n"
#, c-format
msgid "error committing transaction on TOFU database: %s\n"
-msgstr ""
+msgstr "TOFUデータベースのトランザクションコミットのエラー: %s\n"
#, c-format
msgid "error rolling back transaction on TOFU database: %s\n"
-msgstr ""
+msgstr "TOFUデータベースのトランザクションのロールバックのエラー: %s\n"
-#, fuzzy, c-format
-#| msgid "unsupported algorithm: %s"
+#, c-format
msgid "unsupported TOFU database version: %s\n"
-msgstr "サポートされていないアルゴリズム: %s"
+msgstr "サポートされていないTOFUデータベースバージョン: %s\n"
-#, fuzzy, c-format
-#| msgid "error sending data: %s\n"
+#, c-format
msgid "error reading TOFU database: %s\n"
-msgstr "データ送信エラー: %s\n"
+msgstr "TOFUデータベースの読み込みエラー: %s\n"
-#, fuzzy, c-format
-#| msgid "error writing base64 encoding: %s\n"
+#, c-format
msgid "error determining TOFU database's version: %s\n"
-msgstr "base64エンコーディングの書き込みエラー: %s\n"
+msgstr "TOFUデータベースのバージョン判定エラー: %s\n"
-#, fuzzy, c-format
-#| msgid "error initializing reader object: %s\n"
+#, c-format
msgid "error initializing TOFU database: %s\n"
-msgstr "リーダ・オブジェクトの初期化エラー: %s\n"
+msgstr "TOFUデータベースの初期化エラー: %s\n"
-#, fuzzy, c-format
-#| msgid "error opening '%s': %s\n"
+#, c-format
msgid "error opening TOFU database '%s': %s\n"
-msgstr "'%s'を開く際、エラー: %s\n"
+msgstr "TOFUデータベースのオープンでエラー '%s': %s\n"
msgid "Warning: Home directory contains both tofu.db and tofu.d.\n"
-msgstr ""
+msgstr "警告: tofu.db と tofu.d の両方がホームディレクトリにあります。\n"
msgid "Using split format for TOFU database\n"
-msgstr ""
-
-#, fuzzy, c-format
-#| msgid "error sending data: %s\n"
-msgid "error updating TOFU database: %s\n"
-msgstr "データ送信エラー: %s\n"
+msgstr "TOFUデータベースに分割フォーマットを使用\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "公開鍵%sが見つかりません: %s\n"
-
-#, fuzzy, c-format
-#| msgid "error setting OCSP target: %s\n"
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "OCSPターゲットの設定エラー: %s\n"
+msgid "error updating TOFU database: %s\n"
+msgstr "TOFUデータベースの更新エラー: %s\n"
#, c-format
msgid "The binding %s is NOT known."
-msgstr ""
+msgstr "%sのバインディングは不明です。"
#, c-format
msgid ""
"The key with fingerprint %s raised a conflict with the binding %s. Since "
"this binding's policy was 'auto', it was changed to 'ask'."
msgstr ""
+"鍵のフィンガープリント%sがバインディング%sと衝突しました。このバインディング"
+"ポリシーは'auto'だったので、'ask'に変更されました。"
#, c-format
msgid ""
"Please indicate whether you believe the binding %s%sis legitimate (the key "
"belongs to the stated owner) or a forgery (bad)."
msgstr ""
+"バインディング%s%sが適切(鍵は述べられた所有者に属する)か、偽られたものか(ダ"
+"メ)かを指示してください。"
-#, fuzzy, c-format
-#| msgid "error getting responder ID: %s\n"
+#, c-format
msgid "error gathering other user IDs: %s\n"
-msgstr "応答IDの取得エラー: %s\n"
+msgstr "ほかのユーザIDの収集エラー: %s\n"
msgid "Known user IDs associated with this key:\n"
-msgstr ""
+msgstr "この鍵に結びつけられた知られているユーザID:\n"
-#, fuzzy, c-format
-#| msgid "validity: %s"
+#, c-format
msgid "policy: %s"
-msgstr "有効性: %s"
+msgstr "ポリシー: %s"
-#, fuzzy, c-format
-#| msgid "error getting stored flags: %s\n"
+#, c-format
msgid "error gathering signature stats: %s\n"
-msgstr "保存されたフラグの取得エラー: %s\n"
+msgstr "署名の統計の収集エラー: %s\n"
#, c-format
msgid "The email address \"%s\" is associated with %d key:\n"
msgid_plural "The email address \"%s\" is associated with %d keys:\n"
-msgstr[0] ""
+msgstr[0] "電子メールアドレス\"%s\"は%d個の鍵に結びつけられます:\n"
#, c-format
msgid "Statistics for keys with the email address \"%s\":\n"
-msgstr ""
+msgstr "この電子メールアドレス\"%s\"の鍵の統計:\n"
-#, fuzzy
-#| msgid "list keys"
msgid "this key"
-msgstr "鍵の一覧"
+msgstr "この鍵"
#, c-format
msgid "%ld message signed in the future."
msgid_plural "%ld messages signed in the future."
-msgstr[0] ""
+msgstr[0] "%ld個のメッセージが未来に署名されました。"
-#, fuzzy, c-format
-#| msgid "print message digests"
+#, c-format
msgid "%ld message signed"
msgid_plural "%ld messages signed"
-msgstr[0] "メッセージ・ダイジェストを表示"
+msgstr[0] "%ld個のメッセージに署名しました"
#, c-format
msgid " over the past %ld day."
msgid_plural " over the past %ld days."
-msgstr[0] ""
+msgstr[0] "過去%ld日に。"
#, c-format
msgid " over the past %ld week."
msgid_plural " over the past %ld weeks."
-msgstr[0] ""
+msgstr[0] "過去%ld週間に。"
#, c-format
msgid " over the past %ld month."
msgid_plural " over the past %ld months."
-msgstr[0] ""
+msgstr[0] "過去%ld月に。"
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
-msgstr ""
+msgstr "TOFUはバインディングの衝突を検出しました"
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
-msgstr ""
+msgstr "gGaAuUrRbB"
msgid "(G)ood, (A)ccept once, (U)nknown, (R)eject once, (B)ad? "
msgstr ""
+"(G)ood-良, (A)ccept once-一度だけ良, (U)nknown-不明, (R)eject once-一度だけ"
+"否, (B)ad-ダメ? "
-#, fuzzy, c-format
-#| msgid "error creating a pipe: %s\n"
+#, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "TOFUデータベースの信用レベルの設定エラー: %s\n"
+
+#, c-format
msgid "error changing TOFU policy: %s\n"
-msgstr "パイプの作成エラー: %s\n"
+msgstr "TOFUポリシーの作成エラー: %s\n"
#. TRANSLATORS: The tilde ('~') is used here to indicate a
#. * non-breakable space
#, c-format
msgid "%d~year"
msgid_plural "%d~years"
-msgstr[0] ""
+msgstr[0] "%d~年"
#, c-format
msgid "%d~month"
msgid_plural "%d~months"
-msgstr[0] ""
+msgstr[0] "%d~月"
#, c-format
msgid "%d~day"
msgid_plural "%d~days"
-msgstr[0] ""
+msgstr[0] "%d~月"
#, c-format
msgid "%d~hour"
msgid_plural "%d~hours"
-msgstr[0] ""
+msgstr[0] "%d~時間"
#, c-format
msgid "%d~minute"
msgid_plural "%d~minutes"
-msgstr[0] ""
+msgstr[0] "%d~分"
#, c-format
msgid "%d~second"
msgid_plural "%d~seconds"
-msgstr[0] ""
+msgstr[0] "%d~秒"
#, c-format
msgid "Have never verified a message signed by key %s!\n"
-msgstr ""
+msgstr "鍵%sで署名されたメッセージを検証したことは一度もありません!\n"
#, c-format
msgid ""
"Failed to collect signature statistics for \"%s\"\n"
"(key %s)\n"
msgstr ""
+"\"%s\"の署名の統計を収集することに失敗しました\n"
+"(鍵 %s)\n"
-#, fuzzy, c-format
-#| msgid "print message digests"
+#, c-format
msgid "Verified %ld messages signed by \"%s\"."
-msgstr "メッセージ・ダイジェストを表示"
+msgstr "%ld個のメッセージを検証しました(\"%s\"で署名されたもの)。"
#, c-format
msgid ""
msgid_plural ""
"Verified %ld messages signed by \"%s\"\n"
"in the past %s."
-msgstr[0] ""
+msgstr[0] "メッセージを%ld回検証しました(\"%s\"で署名されたもの。かつて %s)。"
#, c-format
msgid "The most recent message was verified %s ago."
-msgstr ""
+msgstr "もっとも最近のメッセージは%s前に検証されました。"
msgid "Warning: we've have yet to see a message signed by this key!\n"
-msgstr ""
+msgstr "警告: この鍵で署名されたメッセージを検証したことはありません!\n"
msgid "Warning: we've only seen a single message signed by this key!\n"
msgstr ""
+"警告: この鍵で署名されたメッセージを検証したことは一度しかありません!\n"
#, c-format
msgid ""
" %s\n"
"to mark it as being bad.\n"
msgstr[0] ""
+"警告: この鍵で署名されたメッセージを%ld回以上見たと思う場合、偽者の可能性があ"
+"ります! 少数のバリエーションでこの電子メールアドレスを注意深く検査してくださ"
+"い。この鍵が疑われる場合、\n"
+" %s\n"
+"でダメとマークしてください。\n"
-#, fuzzy, c-format
-#| msgid "error sending data: %s\n"
+#, c-format
msgid "error opening TOFU database: %s\n"
-msgstr "データ送信エラー: %s\n"
+msgstr "TOFUデータベースのオープンでエラー: %s\n"
#, c-format
msgid "'%s' is not a valid long keyID\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "信用モデル'%s'で信用データベースの更新は、不要です\n"
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "公開鍵%sが見つかりません: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "--check-trustdbを実行してください\n"
msgid "checking the trustdb\n"
msgstr "信用データベースの検査\n"
-#, fuzzy, c-format
-#| msgid "%lu keys processed so far\n"
+#, c-format
msgid "%d key processed"
msgid_plural "%d keys processed"
-msgstr[0] "これまで%lu個の鍵を処理\n"
+msgstr[0] "%d個の鍵を処理"
-#, fuzzy, c-format
-#| msgid "%d keys processed (%d validity counts cleared)\n"
+#, c-format
msgid " (%d validity count cleared)\n"
msgid_plural " (%d validity counts cleared)\n"
-msgstr[0] "%d本の鍵を処理 (うち%d本の有効性数をクリア)\n"
+msgstr[0] " (うち%d本の有効性数をクリア)\n"
msgid "no ultimately trusted keys found\n"
msgstr "究極的に信用する鍵が見つかりません\n"
msgstr "未定義"
msgid "never"
-msgstr "断じてなし"
+msgstr "全くなし"
msgid "marginal"
msgstr "まぁまぁ"
msgid "[ undef ]"
msgstr "[ 未定義 ]"
+msgid "[ never ]"
+msgstr "[全くなし]"
+
msgid "[marginal]"
msgstr "[まぁまぁ]"
msgid "card is permanently locked!\n"
msgstr "カードが永久にロックされてます!\n"
-#, fuzzy, c-format
-#| msgid "%d Admin PIN attempts remaining before card is permanently locked\n"
+#, c-format
msgid "%d Admin PIN attempt remaining before card is permanently locked\n"
msgid_plural ""
"%d Admin PIN attempts remaining before card is permanently locked\n"
msgid "generating key failed\n"
msgstr "鍵の生成に失敗しました\n"
-#, fuzzy, c-format
-#| msgid "key generation completed (%d seconds)\n"
+#, c-format
msgid "key generation completed (%d second)\n"
msgid_plural "key generation completed (%d seconds)\n"
msgstr[0] "鍵の生成が完了しました (%d秒)\n"
msgid "do not allow the reuse of old passphrases"
msgstr "古いパスフレーズを再使用することを認めない"
-#, fuzzy
-#| msgid "|N|set LDAP timeout to N seconds"
msgid "|N|set the Pinentry timeout to N seconds"
-msgstr "|N|LDAPのタイムアウトをN秒とする"
+msgstr "|N|PinentryのタイムアウトをN秒とする"
msgid "|NAME|use NAME as default secret key"
msgstr "|NAME|デフォルトの秘密鍵としてNAMEを用いる"
#~ msgid "you found a bug ... (%s:%d)\n"
#~ msgstr "あなたはバグを発見しました ... (%s:%d)\n"
-#, fuzzy
-#~| msgid "%d user IDs without valid self-signatures detected\n"
-#~ msgid "%d user ID without valid self-signature detected\n"
-#~ msgid_plural "%d user IDs without valid self-signatures detected\n"
-#~ msgstr[0] "有効な自己署名のないユーザIDを%d個検出\n"
-
#~ msgid "moving a key signature to the correct place\n"
#~ msgstr "鍵の署名を正しい場所に移動します\n"
msgstr "feil ved søking etter tillitspost i «%s»: %s\n"
#, fuzzy, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "ADVARSEL: utrygge rettigheter på utvidelsen «%s»\n"
+
+#, fuzzy, c-format
msgid "listen() failed: %s\n"
msgstr "oppdatering mislyktes: %s\n"
msgstr "katalogen «%s» ble opprettet\n"
#, fuzzy, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "ADVARSEL: utrygge rettigheter på utvidelsen «%s»\n"
-
-#, fuzzy, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "fstat(%d) mislyktes in %s: %s\n"
msgid "export keys"
msgstr "eksportere nøkler"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "eksportere nøkler til en nøkkelserver"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "importere nøkler fra en nøkkelserver"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "søke etter nøkler på en nøkkelserver"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|skrive statusinfo til denne FD"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Bruksmåte: gpgv [valg] [filer] (-h for hjelp)"
msgid "No key with this keygrip\n"
msgstr ""
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "rundet opp til %u bits\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr ""
msgid "Requested keysize is %u bits\n"
msgstr "Ønsket nøkkelstørrelse er %u bits\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "rundet opp til %u bits\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgstr "feil ved lesing av «%s»: %s\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "fant ikke offentlig nøkkel %s: %s\n"
-
-#, fuzzy, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "feil ved lesing av «%s»: %s\n"
-
-#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "feil ved lesing av «%s»: %s\n"
+
+#, fuzzy, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "feil ved opprettelse av passfrase: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr ""
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "fant ikke offentlig nøkkel %s: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr ""
msgid "[ undef ]"
msgstr "[ udef ]"
+msgid "[ never ]"
+msgstr ""
+
msgid "[marginal]"
msgstr ""
msgid "error binding socket to '%s': %s\n"
msgstr "b³±d podczas przypisywania gniazda do ,,%s'': %s\n"
+#, fuzzy, c-format
+#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
+msgid "can't set permissions of '%s': %s\n"
+msgstr "Ostrze¿enie: niebezpieczne prawa dostêpu do %s ,,%s''\n"
+
#, c-format
msgid "listen() failed: %s\n"
msgstr "listen() nie powiod³o siê: %s\n"
msgstr "katalog ,,%s'' utworzony\n"
#, fuzzy, c-format
-#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
-msgid "can't set permissions of '%s': %s\n"
-msgstr "Ostrze¿enie: niebezpieczne prawa dostêpu do %s ,,%s''\n"
-
-#, fuzzy, c-format
#| msgid "stat() failed for `%s': %s\n"
msgid "stat() failed for '%s': %s\n"
msgstr "stat() nie powiod³o siê dla ,,%s'': %s\n"
msgid "export keys"
msgstr "eksport kluczy do pliku"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "eksport kluczy do serwera kluczy"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "import kluczy z serwera kluczy"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "szukanie kluczy na serwerze"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|pisanie opisu stanu do deskryptora FD"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Wywo³anie: gpgv [opcje] [pliki] (-h podaje pomoc)"
msgid "No key with this keygrip\n"
msgstr "Brak klucza o tym uchwycie\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "zaokr±glono do %u bitów\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr "Klucze %s bêd± mia³y od %u do %u bitów d³ugo¶ci.\n"
msgid "Requested keysize is %u bits\n"
msgstr "¯±dana d³ugo¶æ klucza to %u bitów.\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "zaokr±glono do %u bitów\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgstr "b³±d wysy³ania polecenia %s: %s\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "klucz publiczny %s nie odnaleziony: %s\n"
-
-#, fuzzy, c-format
-#| msgid "error storing flags: %s\n"
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "b³±d zapisywania flag: %s\n"
-
-#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[2] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+#| msgid "error storing flags: %s\n"
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "b³±d zapisywania flag: %s\n"
+
+#, fuzzy, c-format
#| msgid "error creating a pipe: %s\n"
msgid "error changing TOFU policy: %s\n"
msgstr "b³±d tworzenia potoku: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "aktualizacja bazy jest niepotrzebna przy modelu zaufania ,,%s''\n"
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "klucz publiczny %s nie odnaleziony: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "nale¿y uruchomiæ gpg z opcj± ,,--check-trustdb''\n"
msgid "[ undef ]"
msgstr "[ nieokre¶lone ]"
+#, fuzzy
+#| msgid "never"
+msgid "[ never ]"
+msgstr "nigdy"
+
msgid "[marginal]"
msgstr "[ marginalne ]"
msgstr "erro ao enviar para `%s': %s\n"
#, fuzzy, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "AVISO: permissões pouco seguras em %s \"%s\"\n"
+
+#, fuzzy, c-format
msgid "listen() failed: %s\n"
msgstr "actualização falhou: %s\n"
msgstr "%s: directoria criada\n"
#, fuzzy, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "AVISO: permissões pouco seguras em %s \"%s\"\n"
-
-#, fuzzy, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "base de dados de confiança: leitura falhou (n=%d): %s\n"
msgid "export keys"
msgstr "exportar chaves"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "exportar chaves para um servidor de chaves"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "importar chaves de um servidor de chaves"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "procurar chaves num servidor de chaves"
msgid "update all keys from a keyserver"
"|DF|escrever informações de estado para o\n"
"descritor de ficheiro DF"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
#, fuzzy
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Uso: gpg [opções] [ficheiros] (-h para ajuda)"
msgid "No key with this keygrip\n"
msgstr "Nenhum ID de utilizador com índice %d\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "arredondado para %u bits\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr ""
msgid "Requested keysize is %u bits\n"
msgstr "O tamanho de chave pedido é %u bits\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "arredondado para %u bits\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgid "error updating TOFU database: %s\n"
msgstr "erro ao enviar para `%s': %s\n"
-#, fuzzy, c-format
-msgid "public key %s not found: %s\n"
-msgstr "chave pública %08lX não encontrada: %s\n"
-
-#, fuzzy, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "erro na leitura de `%s': %s\n"
-
#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "erro na leitura de `%s': %s\n"
+
+#, fuzzy, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "erro na criação da frase secreta: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "não é necessária uma verificação da base de dados de confiança\n"
+#, fuzzy, c-format
+msgid "public key %s not found: %s\n"
+msgstr "chave pública %08lX não encontrada: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr ""
msgid "[ undef ]"
msgstr ""
+msgid "[ never ]"
+msgstr ""
+
msgid "[marginal]"
msgstr ""
msgstr "eroare trimitere la `%s': %s\n"
#, fuzzy, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "AVERTISMENT: permisiuni nesigure (unsafe) pentru extensia `%s'\n"
+
+#, fuzzy, c-format
msgid "listen() failed: %s\n"
msgstr "actualizarea a eºuat: %s\n"
msgstr "director `%s' creat\n"
#, fuzzy, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "AVERTISMENT: permisiuni nesigure (unsafe) pentru extensia `%s'\n"
-
-#, fuzzy, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "fstat(%d) a eºuat în %s: %s\n"
msgid "export keys"
msgstr "exportã chei"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "exportã chei pentru un server de chei"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "importã chei de la un server de chei"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "cautã pentru chei pe un server de chei"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|scrie informaþii de stare în acest FD"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Folosire: gpgv [opþiuni] [fiºiere] (-h pentru ajutor)"
msgid "No key with this keygrip\n"
msgstr "Nici o subcheie cu indicele %d\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "rotunjitã prin adaos la %u biþi\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr "cheile %s pot avea lungimea între %u ºi %u biþi.\n"
msgid "Requested keysize is %u bits\n"
msgstr "Lungimea cheii necesarã este %u biþi\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "rotunjitã prin adaos la %u biþi\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgstr "eroare trimitere la `%s': %s\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "cheia publicã %s nu a fost gãsitã: %s\n"
-
-#, fuzzy, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "eroare la citire `%s': %s\n"
-
-#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "eroare la citire `%s': %s\n"
+
+#, fuzzy, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "eroare la crearea frazei-parolã: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "nu e nevoie de o actualizare trustdb cu modelul de încredere `%s'\n"
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "cheia publicã %s nu a fost gãsitã: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "vã rugãm faceþi un --check-trustdb\n"
msgid "[ undef ]"
msgstr "[ nedef ]"
+#, fuzzy
+#| msgid "never"
+msgid "[ never ]"
+msgstr "niciodatã"
+
msgid "[marginal]"
msgstr "[marginal]"
#, c-format
msgid "failed to acquire the pinentry lock: %s\n"
-msgstr "сбой при блокировке для ввода PIN: %s\n"
+msgstr "сбой при блокировке для ввода пароля: %s\n"
#. TRANSLATORS: These are labels for buttons etc used in
#. Pinentries. An underscore indicates that the next letter
msgid "allow presetting passphrase"
msgstr "разрешить предустанавливать фразу-пароль"
-#, fuzzy
-#| msgid "allow caller to override the pinentry"
msgid "disallow caller to override the pinentry"
-msgstr "разрешить клиентам замещать собой pinentry"
+msgstr ""
+"не позволять вызывающей программе замещать собой программу ввода пароля"
msgid "allow passphrase to be prompted through Emacs"
msgstr "разрешить ввод фразы-пароля через Emacs"
msgstr "ошибка связывания сокета с '%s': %s\n"
#, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "не удалось задать права доступа для '%s': %s\n"
+
+#, c-format
msgid "listen() failed: %s\n"
msgstr "сбой listen(): %s\n"
msgid "directory '%s' created\n"
msgstr "создан каталог '%s'\n"
-#, fuzzy, c-format
-#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
-msgid "can't set permissions of '%s': %s\n"
-msgstr "Внимание: небезопасные права доступа %s \"%s\"\n"
-
#, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "сбой stat() для '%s': %s\n"
"Удаление его может лишить Вас возможности доступа к удаленным машинам."
msgid "DSA requires the hash length to be a multiple of 8 bits\n"
-msgstr "DSA требует длины хэша, кратной 8 битам\n"
+msgstr "DSA требует длины хеша, кратной 8 битам\n"
#, c-format
msgid "%s key uses an unsafe (%u bit) hash\n"
-msgstr "%s ключ использует небезопасный (%u бит) хэш\n"
+msgstr "%s ключ использует небезопасный (%u бит) хеш\n"
#, c-format
msgid "a %zu bit hash is not valid for a %u bit %s key\n"
-msgstr "%zu-битный хэш недопустим для %u-битного ключа %s\n"
+msgstr "%zu-битный хеш недопустим для %u-битного ключа %s\n"
#, c-format
msgid "checking created signature failed: %s\n"
#, c-format
msgid "protection hash algorithm %d (%s) is not supported\n"
-msgstr "хэш-функция защиты %d (%s) не поддерживается\n"
+msgstr "хеш-функция защиты %d (%s) не поддерживается\n"
#, c-format
msgid "error creating a pipe: %s\n"
msgid "error forking process: %s\n"
msgstr "ошибка при дублировании процесса: %s\n"
-#, fuzzy, c-format
-#| msgid "waiting for process %d to terminate failed: %s\n"
+#, c-format
msgid "waiting for processes to terminate failed: %s\n"
-msgstr "сбой при ожидании завершения процесса %d: %s\n"
+msgstr "сбой при ожидании завершения процесса: %s\n"
#, c-format
msgid "error running '%s': probably not installed\n"
msgid "problem with the agent\n"
msgstr "проблема с агентом\n"
-#, fuzzy, c-format
-#| msgid "problem with the agent: %s\n"
+#, c-format
msgid "problem with the agent (unexpected response \"%s\")\n"
-msgstr "проблема с агентом: %s\n"
+msgstr "проблема с агентом (неожиданный ответ \"%s\")\n"
#, c-format
msgid "can't disable core dumps: %s\n"
#, c-format
msgid "data hash algorithm: %s"
-msgstr "хэш-функция данных: %s"
+msgstr "хеш-функция данных: %s"
#, c-format
msgid "Signer %d"
#, c-format
msgid "attr hash algorithm: %s"
-msgstr "хэш-функция атрибутов: %s"
+msgstr "хеш-функция атрибутов: %s"
msgid "Data decryption succeeded"
msgstr "Данные успешно расшифрованы"
#, c-format
msgid "bad data hash algorithm: %s"
-msgstr "недопустимая хэш-функция данных: %s"
+msgstr "недопустимая хеш-функция данных: %s"
#, c-format
msgid "Signature %d"
"символ quoted printable в текстовом формате - испорчено почтовой "
"программой?\n"
-#, fuzzy, c-format
-#| msgid "not human readable"
+#, c-format
msgid "[ not human readable (%zu bytes: %s%s) ]"
-msgstr "не для чтения человеком"
+msgstr "[ не для чтения человеком (%zu байт: %s%s) ]"
msgid ""
"a notation name must have only printable characters or spaces, and end with "
"an '='\n"
msgstr ""
-"имÑ\8f пÑ\80имечания должно содержать только печатные символы или пробелы и "
+"имÑ\8f замечания должно содержать только печатные символы или пробелы и "
"заканчиваться знаком '='\n"
msgid "a user notation name must contain the '@' character\n"
-msgstr "имÑ\8f пÑ\80имеÑ\87аниÑ\8f полÑ\8cзоваÑ\82еля должно содержать символ '@'\n"
+msgstr "имÑ\8f замеÑ\87ания должно содержать символ '@'\n"
msgid "a notation name must not contain more than one '@' character\n"
-msgstr ""
-"имя примечания пользователя не должно содержать более одного символа '@'\n"
+msgstr "имя замечания не должно содержать более одного символа '@'\n"
msgid "a notation value must not use any control characters\n"
-msgstr "в значении примечания не должно быть управляющих символов\n"
+msgstr "в тексте замечания не должно быть управляющих символов\n"
-#, fuzzy
-#| msgid "a notation name must not contain more than one '@' character\n"
msgid "a notation name may not contain an '=' character\n"
-msgstr ""
-"имя примечания пользователя не должно содержать более одного символа '@'\n"
+msgstr "имя примечания не должно содержать символа '='\n"
-#, fuzzy
-#| msgid ""
-#| "a notation name must have only printable characters or spaces, and end "
-#| "with an '='\n"
msgid "a notation name must have only printable characters or spaces\n"
-msgstr ""
-"имя примечания должно содержать только печатные символы или пробелы и "
-"заканчиваться знаком '='\n"
+msgstr "имя замечания должно содержать только печатные символы или пробелы\n"
msgid "WARNING: invalid notation data found\n"
-msgstr "Ð\92нимание: найдена недопÑ\83Ñ\81Ñ\82имаÑ\8f Ñ\84оÑ\80ма запиÑ\81и пÑ\80имечания\n"
+msgstr "Ð\92нимание: найдена недопÑ\83Ñ\81Ñ\82имаÑ\8f Ñ\84оÑ\80ма запиÑ\81и замечания\n"
#, c-format
msgid "failed to proxy %s inquiry to client\n"
msgid "export keys"
msgstr "экспортировать ключи"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "экспортировать ключи на сервер ключей"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "импортировать ключи с сервера ключей"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "искать ключи на сервере ключей"
msgid "update all keys from a keyserver"
msgstr "обновить таблицу доверия"
msgid "print message digests"
-msgstr "вывести хэши сообщений"
+msgstr "вывести хеши сообщений"
msgid "run in server mode"
msgstr "запуск в режиме сервера"
-#, fuzzy
-#| msgid "|VALUE|set the TOFU policy for a key (good, unknown, bad, ask, auto)"
msgid "|VALUE|set the TOFU policy for a key"
-msgstr ""
-"|VALUE|установить правила TOFU для ключа (good - хороший, unknown - "
-"неизвестно, bad - плохой, ask - спрашивать, auto - автоматически)"
+msgstr "|VALUE|установить правила TOFU для ключа"
msgid "create ascii armored output"
msgstr "вывод в текстовом формате"
msgstr "Симметричные шифры: "
msgid "Hash: "
-msgstr "Хэш-функции: "
+msgstr "Хеш-функции: "
msgid "Compression: "
msgstr "Алгоритмы сжатия: "
msgstr "показать в списке подписей URL правил"
msgid "show all notations during signature listings"
-msgstr "показаÑ\82Ñ\8c в Ñ\81пиÑ\81ке подпиÑ\81ей вÑ\81е пÑ\80имечания"
+msgstr "показаÑ\82Ñ\8c в Ñ\81пиÑ\81ке подпиÑ\81ей вÑ\81е замечания"
msgid "show IETF standard notations during signature listings"
-msgstr "показаÑ\82Ñ\8c в Ñ\81пиÑ\81ке подпиÑ\81ей пÑ\80имечания стандарта IETF"
+msgstr "показаÑ\82Ñ\8c в Ñ\81пиÑ\81ке подпиÑ\81ей замечания стандарта IETF"
msgid "show user-supplied notations during signature listings"
-msgstr "показаÑ\82Ñ\8c в Ñ\81пиÑ\81ке подпиÑ\81ей полÑ\8cзоваÑ\82елÑ\8cÑ\81кие пÑ\80имечания"
+msgstr "показаÑ\82Ñ\8c в Ñ\81пиÑ\81ке подпиÑ\81ей полÑ\8cзоваÑ\82елÑ\8cÑ\81кие замечания"
msgid "show preferred keyserver URLs during signature listings"
msgstr "показать в списке подписей URL предпочтительных серверов ключей"
#, c-format
msgid "invalid pinentry mode '%s'\n"
-msgstr "недопустимый режим ввода PIN '%s'\n"
+msgstr "недопустимый режим ввода пароля '%s'\n"
#, c-format
msgid "'%s' is not a valid character set\n"
msgstr "показать при проверке подписи URL правил"
msgid "show all notations during signature verification"
-msgstr "показаÑ\82Ñ\8c пÑ\80и пÑ\80овеÑ\80ке подпиÑ\81ей вÑ\81е пÑ\80имечания"
+msgstr "показаÑ\82Ñ\8c пÑ\80и пÑ\80овеÑ\80ке подпиÑ\81ей вÑ\81е замечания"
msgid "show IETF standard notations during signature verification"
-msgstr "показаÑ\82Ñ\8c пÑ\80и пÑ\80овеÑ\80ке подпиÑ\81ей пÑ\80имечания стандарта IETF"
+msgstr "показаÑ\82Ñ\8c пÑ\80и пÑ\80овеÑ\80ке подпиÑ\81ей замечания стандарта IETF"
msgid "show user-supplied notations during signature verification"
-msgstr "показаÑ\82Ñ\8c пÑ\80и пÑ\80овеÑ\80ке подпиÑ\81ей полÑ\8cзоваÑ\82елÑ\8cÑ\81кие пÑ\80имечания"
+msgstr "показаÑ\82Ñ\8c пÑ\80и пÑ\80овеÑ\80ке подпиÑ\81ей полÑ\8cзоваÑ\82елÑ\8cÑ\81кие замечания"
msgid "show preferred keyserver URLs during signature verification"
msgstr "показать при проверке подписей URL предпочтительных серверов ключей"
msgstr "выбран недопустимый алгоритм шифрования\n"
msgid "selected digest algorithm is invalid\n"
-msgstr "выбрана недопустимая хэш-функция\n"
+msgstr "выбрана недопустимая хеш-функция\n"
msgid "selected compression algorithm is invalid\n"
msgstr "выбран недопустимый алгоритм сжатия\n"
msgid "selected certification digest algorithm is invalid\n"
-msgstr "выбрана недопустимая хэш-функция для сертификации\n"
+msgstr "выбрана недопустимая хеш-функция для сертификации\n"
msgid "completes-needed must be greater than 0\n"
msgstr "completes-needed должен быть больше 0\n"
msgstr "недопустимые личные предпочтения шифра\n"
msgid "invalid personal digest preferences\n"
-msgstr "недопустимые личные предпочтения хэш-функции\n"
+msgstr "недопустимые личные предпочтения хеш-функции\n"
msgid "invalid personal compress preferences\n"
msgstr "недопустимые личные предпочтения алгоритмов сжатия\n"
#, c-format
msgid "you may not use digest algorithm '%s' while in %s mode\n"
-msgstr "хэш-функцию '%s' в режиме %s использовать нельзя\n"
+msgstr "хеш-функцию '%s' в режиме %s использовать нельзя\n"
#, c-format
msgid "you may not use compression algorithm '%s' while in %s mode\n"
#, c-format
msgid "invalid hash algorithm '%s'\n"
-msgstr "недопустимая хэш-функция '%s'\n"
+msgstr "недопустимая хеш-функция '%s'\n"
#, c-format
msgid "error parsing key specification '%s': %s\n"
msgid "|FD|write status info to this FD"
msgstr "|FD|выводить информацию в файл с дескриптором FD"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Вызов: gpgv [параметры] [файлы] (-h для подсказки)"
#, c-format
msgid " \"%s\": preference for digest algorithm %s\n"
-msgstr " \"%s\": предпочитает хэш-функцию %s\n"
+msgstr " \"%s\": предпочитает хеш-функцию %s\n"
#, c-format
msgid " \"%s\": preference for compression algorithm %s\n"
msgid "[self-signature]"
msgstr "[самоподпись]"
-#, fuzzy, c-format
-#| msgid "key %s: unsupported public key algorithm\n"
+#, c-format
msgid "can't check signature with unsupported public-key algorithm (%d): %s.\n"
-msgstr "ключ %s: алгоритм с открытым ключом не поддерживается\n"
+msgstr ""
+"не удалось проверить подпись: алгоритм с открытым ключом %d не "
+"поддерживается: %s.\n"
-#, fuzzy, c-format
-#| msgid "card does not support digest algorithm %s\n"
+#, c-format
msgid ""
"can't check signature with unsupported message-digest algorithm %d: %s.\n"
-msgstr "каÑ\80Ñ\82а не поддеÑ\80живаеÑ\82 Ñ\85Ñ\8dÑ\88-Ñ\84Ñ\83нкÑ\86иÑ\8e %s\n"
+msgstr "не Ñ\83далоÑ\81Ñ\8c пÑ\80овеÑ\80иÑ\82Ñ\8c подпиÑ\81Ñ\8c: Ñ\85еÑ\88-Ñ\84Ñ\83нкÑ\86иÑ\8f %d не поддеÑ\80живаеÑ\82Ñ\81Ñ\8f: %s.\n"
-#, fuzzy
-#| msgid "Good signature from"
msgid " (reordered signatures follow)"
-msgstr "Хорошая подпись пользователя"
+msgstr "(порядок подписей изменен)"
-#, fuzzy, c-format
-#| msgid "key %s: %s\n"
+#, c-format
msgid "key %s:\n"
-msgstr "ключ %s: %s\n"
+msgstr "ключ %s:\n"
-#, fuzzy, c-format
-#| msgid "User ID \"%s\": %d signature removed\n"
-#| msgid_plural "User ID \"%s\": %d signatures removed\n"
+#, c-format
msgid "%d duplicate signature removed\n"
msgid_plural "%d duplicate signatures removed\n"
-msgstr[0] "ID пользователя \"%s\": %d подпись удалена\n"
-msgstr[1] "ID пользователя \"%s\": %d подписи удалены\n"
-msgstr[2] "ID пользователя \"%s\": %d подписей удалено\n"
+msgstr[0] "%d повторная подпись удалена\n"
+msgstr[1] "%d повторные подписи удалены\n"
+msgstr[2] "%d повторных подписей удалено\n"
#, c-format
msgid "%d signature not checked due to a missing key\n"
msgstr[1] "%d плохих подписи\n"
msgstr[2] "%d плохих подписей\n"
-#, fuzzy, c-format
-#| msgid "Good signature from"
+#, c-format
msgid "%d signature reordered\n"
msgid_plural "%d signatures reordered\n"
-msgstr[0] "ХоÑ\80оÑ\88аÑ\8f подпиÑ\81Ñ\8c полÑ\8cзоваÑ\82елÑ\8f"
-msgstr[1] "ХоÑ\80оÑ\88аÑ\8f подпиÑ\81Ñ\8c полÑ\8cзоваÑ\82елÑ\8f"
-msgstr[2] "ХоÑ\80оÑ\88аÑ\8f подпиÑ\81Ñ\8c полÑ\8cзоваÑ\82елÑ\8f"
+msgstr[0] "Ð\9fоÑ\80Ñ\8fдок %d подпиÑ\81и изменен\n"
+msgstr[1] "Ð\9fоÑ\80Ñ\8fдок %d подпиÑ\81ей изменен\n"
+msgstr[2] "Ð\9fоÑ\80Ñ\8fдок %d подпиÑ\81ей изменен\n"
#, c-format
msgid ""
"Warning: errors found and only checked self-signatures, run '%s' to check "
"all signatures.\n"
msgstr ""
+"Внимание: обнаружены ошибки, проверялись только самоподписи; для проверки "
+"всех подписей выполните '%s'.\n"
msgid ""
"Please decide how far you trust this user to correctly verify other users' "
"установить URL предпочтительного сервера ключей для выбранных ID пользователя"
msgid "set a notation for the selected user IDs"
-msgstr "Ñ\83Ñ\81Ñ\82ановиÑ\82Ñ\8c пÑ\80имечание для выбранных ID пользователя"
+msgstr "Ñ\83Ñ\81Ñ\82ановиÑ\82Ñ\8c замечание для выбранных ID пользователя"
msgid "change the passphrase"
msgstr "сменить фразу-пароль"
msgid "\"%s\" is not the primary fingerprint\n"
msgstr "\"%s\" - не первичный отпечаток\n"
-#, fuzzy, c-format
-#| msgid "invalid value\n"
+#, c-format
msgid "Invalid user ID '%s': %s\n"
-msgstr "недопÑ\83Ñ\81Ñ\82имое знаÑ\87ение\n"
+msgstr "Ð\9dедопÑ\83Ñ\81Ñ\82имÑ\8bй ID полÑ\8cзоваÑ\82елÑ\8f '%s': %s\n"
msgid "No matching user IDs."
msgstr "Нет подходящих ID пользователей."
msgstr "Подписывать нечего.\n"
msgid "Digest: "
-msgstr "Хэш: "
+msgstr "Хеш: "
msgid "Features: "
msgstr "Характеристики: "
msgstr "Предпочтительный сервер ключей: "
msgid "Notations: "
-msgstr "Ð\9fÑ\80имечания: "
+msgstr "Ð\97амечания: "
msgid "There are no preferences on a PGP 2.x-style user ID.\n"
msgstr "В ID пользователя типа PGP 2.x не может быть предпочтений.\n"
msgstr "Вы действительно хотите удалить его? (y/N) "
msgid "Enter the notation: "
-msgstr "Ð\92ведиÑ\82е пÑ\80имечание: "
+msgstr "Ð\92ведиÑ\82е замечание: "
msgid "Proceed? (y/N) "
msgstr "Продолжить? (y/N) "
#, c-format
msgid "No user ID with hash %s\n"
-msgstr "Нет ID пользователя с хэшем %s\n"
+msgstr "Нет ID пользователя с хешем %s\n"
#, c-format
msgid "No subkey with key ID '%s'.\n"
msgstr "слишком много шифровых предпочтений\n"
msgid "too many digest preferences\n"
-msgstr "слишком много предпочтений для хэш-функций\n"
+msgstr "слишком много предпочтений для хеш-функций\n"
msgid "too many compression preferences\n"
msgstr "слишком много предпочтений для методов сжатия\n"
"WARNING: some OpenPGP programs can't handle a DSA key with this digest size\n"
msgstr ""
"Внимание: некоторые реализации OpenPGP не могут обрабатывать ключи DSA с "
-"такой длиной хэша\n"
+"такой длиной хеша\n"
msgid "Sign"
msgstr "Подписать"
msgstr "Нет ключа с таким кодом\n"
#, c-format
+msgid "rounded to %u bits\n"
+msgstr "округлен до %u бит\n"
+
+#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr "длина ключей %s может быть от %u до %u бит.\n"
msgid "Requested keysize is %u bits\n"
msgstr "Запрошенный размер ключа - %u бит\n"
-#, c-format
-msgid "rounded to %u bits\n"
-msgstr "округлен до %u бит\n"
-
msgid "Please select which elliptic curve you want:\n"
msgstr "Выберите эллиптическую кривую:\n"
msgstr "Критический предпочтительный сервер ключей: "
msgid "Critical signature notation: "
-msgstr "Ð\9aÑ\80иÑ\82иÑ\87еÑ\81кое пÑ\80имечание к подписи: "
+msgstr "Ð\9aÑ\80иÑ\82иÑ\87еÑ\81кое замечание к подписи: "
msgid "Signature notation: "
-msgstr "Ð\9fÑ\80имечание к подписи: "
+msgstr "Ð\97амечание к подписи: "
#, c-format
msgid "%d good signature\n"
msgstr "пропущено \"%s\": %s\n"
msgid "Primary key fingerprint:"
-msgstr "Ð\9eÑ\82пеÑ\87аÑ\82ок главного ключа:"
+msgstr "Ð\9eÑ\82пеÑ\87аÑ\82ок пеÑ\80виÑ\87ного ключа:"
msgid " Subkey fingerprint:"
msgstr " Отпечаток подключа:"
#. TRANSLATORS: this should fit into 24 bytes so that the
#. * fingerprint data is properly aligned with the user ID
msgid " Primary key fingerprint:"
-msgstr " Ð\9eÑ\82пеÑ\87аÑ\82ок главного ключа:"
+msgstr " Ð\9eÑ\82пеÑ\87аÑ\82ок пеÑ\80виÑ\87ного ключа:"
msgid " Subkey fingerprint:"
msgstr " Отпечаток подключа:"
#, c-format
msgid "passphrase generated with unknown digest algorithm %d\n"
-msgstr "фраза-пароль создана с незнакомой хэш-функцией %d\n"
+msgstr "фраза-пароль создана с незнакомой хеш-функцией %d\n"
#, c-format
msgid "public key is %s\n"
#, c-format
msgid "%s signature, digest algorithm %s%s%s\n"
-msgstr "формат подписи: %s, хэш-функция %s%s%s\n"
+msgstr "формат подписи: %s, хеш-функция %s%s%s\n"
msgid "binary"
msgstr "двоичный"
#, c-format
msgid "WARNING: using experimental digest algorithm %s\n"
-msgstr "Внимание: используется экспериментальная хэш-функция %s\n"
+msgstr "Внимание: используется экспериментальная хеш-функция %s\n"
#, c-format
msgid "WARNING: digest algorithm %s is deprecated\n"
-msgstr "Внимание: хэш-функция %s не рекомендуется\n"
+msgstr "Внимание: хеш-функция %s не рекомендуется\n"
#, c-format
msgid "Note: signatures using the %s algorithm are rejected\n"
-msgstr "Замечание: подписи с хэш-функцией %s игнорируются\n"
+msgstr "Замечание: подписи с хеш-функцией %s игнорируются\n"
#, c-format
msgid "(reported error: %s)\n"
#, c-format
msgid "unknown weak digest '%s'\n"
-msgstr "неизвестный слабый хэш '%s'\n"
+msgstr "неизвестный слабый хеш '%s'\n"
#, c-format
msgid "File '%s' exists. "
#, c-format
msgid "%s key %s uses an unsafe (%zu bit) hash\n"
-msgstr "ключ %s %s использует небезопасный (%zu-битный) хэш\n"
+msgstr "ключ %s %s использует небезопасный (%zu-битный) хеш\n"
#, c-format
msgid "%s key %s requires a %zu bit or larger hash (hash is %s)\n"
-msgstr "Ключ %s %s требует %zu-битного или более длинного хэша (хэш %s)\n"
+msgstr "Ключ %s %s требует %zu-битного или более длинного хеша (хеш %s)\n"
msgid "WARNING: signature digest conflict in message\n"
-msgstr "Внимание: конфликт хэшей подписей в сообщении\n"
+msgstr "Внимание: конфликт хешей подписей в сообщении\n"
#, c-format
msgid "WARNING: signing subkey %s is not cross-certified\n"
#, c-format
msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n"
msgstr ""
-"Ð\92нимание: не могÑ\83 Ñ\80азвеÑ\80нÑ\83Ñ\82Ñ\8c %% в пÑ\80имечании (слишком длинное).\n"
+"Ð\92нимание: не могÑ\83 Ñ\80азвеÑ\80нÑ\83Ñ\82Ñ\8c %% в замечании (слишком длинное).\n"
" Использую неразвернутым.\n"
#, c-format
msgid ""
"WARNING: forcing digest algorithm %s (%d) violates recipient preferences\n"
msgstr ""
-"Внимание: использование хэш-функции %s (%d) нарушает предпочтения "
+"Внимание: использование хеш-функции %s (%d) нарушает предпочтения "
"получателя\n"
msgid "signing:"
#, c-format
msgid "%s: failed to create hashtable: %s\n"
-msgstr "%s: сбой создания таблицы хэшей: %s\n"
+msgstr "%s: сбой создания таблицы хешей: %s\n"
#, c-format
msgid "%s: error updating version record: %s\n"
msgstr "ошибка обновления базы данных TOFU: %s\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "открытый ключ %s не найден: %s\n"
-
-#, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "ошибка установки уровня доверия привязки TOFU в %s\n"
-
-#, c-format
msgid "The binding %s is NOT known."
msgstr "Привязка %s неизвестна."
-#, fuzzy, c-format
-#| msgid ""
-#| "The key %s raised a conflict with this binding (%s). Since this "
-#| "binding's policy was 'auto', it was changed to 'ask'."
+#, c-format
msgid ""
"The key with fingerprint %s raised a conflict with the binding %s. Since "
"this binding's policy was 'auto', it was changed to 'ask'."
msgstr ""
-"Ключ %s противоречит этой привязке (%s). Поскольку правило привязки было "
-"'автоматически', оно изменилось на 'спрашивать'."
+"Ключ с отпечатком %s противоречит этой привязке %s. Поскольку правило "
+"привязки было 'автоматически', оно изменилось на 'спрашивать'."
#, c-format
msgid ""
msgstr[2] " за %ld прошедших месяцев."
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
"Обычно с конкретным адресом электронной почты связан только один ключ. "
"правомерен."
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr "gGaAuUrRbB"
"(G)Хороший, (A)Пока принять, (U)Неясно, (R)Пока отвергнуть, (B)Плохой? "
#, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "ошибка установки уровня доверия привязки TOFU в %s\n"
+
+#, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "ошибка при смене правила TOFU: %s\n"
#. TRANSLATORS: The tilde ('~') is used here to indicate a
#. * non-breakable space
-#, fuzzy, c-format
-#| msgid "%d year"
-#| msgid_plural "%d years"
+#, c-format
msgid "%d~year"
msgid_plural "%d~years"
-msgstr[0] "%d год"
-msgstr[1] "%d года"
-msgstr[2] "%d лет"
+msgstr[0] "%d~год"
+msgstr[1] "%d~года"
+msgstr[2] "%d~лет"
-#, fuzzy, c-format
-#| msgid "%d month"
-#| msgid_plural "%d months"
+#, c-format
msgid "%d~month"
msgid_plural "%d~months"
-msgstr[0] "%d месяц"
-msgstr[1] "%d месяца"
-msgstr[2] "%d месяцев"
+msgstr[0] "%d~месяц"
+msgstr[1] "%d~месяца"
+msgstr[2] "%d~месяцев"
#, c-format
msgid "%d~day"
msgid_plural "%d~days"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d~день"
+msgstr[1] "%d~дня"
+msgstr[2] "%d~дней"
-#, fuzzy, c-format
-#| msgid "%d hour"
-#| msgid_plural "%d hours"
+#, c-format
msgid "%d~hour"
msgid_plural "%d~hours"
-msgstr[0] "%d час"
-msgstr[1] "%d часа"
-msgstr[2] "%d часов"
+msgstr[0] "%d~час"
+msgstr[1] "%d~часа"
+msgstr[2] "%d~часов"
-#, fuzzy, c-format
-#| msgid "%d minute"
-#| msgid_plural "%d minutes"
+#, c-format
msgid "%d~minute"
msgid_plural "%d~minutes"
-msgstr[0] "%d минута"
-msgstr[1] "%d минуты"
-msgstr[2] "%d минут"
+msgstr[0] "%d~минута"
+msgstr[1] "%d~минуты"
+msgstr[2] "%d~минут"
-#, fuzzy, c-format
-#| msgid "%d second"
-#| msgid_plural "%d seconds"
+#, c-format
msgid "%d~second"
msgid_plural "%d~seconds"
-msgstr[0] "%d секунда"
-msgstr[1] "%d секунды"
-msgstr[2] "%d секунд"
+msgstr[0] "%d~секунда"
+msgstr[1] "%d~секунды"
+msgstr[2] "%d~секунд"
#, c-format
msgid "Have never verified a message signed by key %s!\n"
msgstr "Сообщения, подписанные ключом %s, никогда не проверялись!\n"
-#, fuzzy, c-format
-#| msgid "Failed to collect signature statistics for \"%s\" (key %s)\n"
+#, c-format
msgid ""
"Failed to collect signature statistics for \"%s\"\n"
"(key %s)\n"
-msgstr "Не удалось собрать статистику для \"%s\" (ключ %s)\n"
+msgstr ""
+"Не удалось собрать статистику подписей для \"%s\"\n"
+"(ключ %s)\n"
-#, fuzzy, c-format
-#| msgid "Verified 0 messages signed by \"%s\" (key: %s, policy: %s)."
+#, c-format
msgid "Verified %ld messages signed by \"%s\"."
-msgstr "Проверено 0 сообщений, подписанных \"%s\" (ключ: %s, правило: %s)."
-
-#, fuzzy, c-format
-#| msgid ""
-#| "Verified %ld message signed by \"%s\" (key: %s, policy: %s) in the past "
-#| "%s."
-#| msgid_plural ""
-#| "Verified %ld messages signed by \"%s\" (key: %s, policy: %s) in the past "
-#| "%s."
+msgstr "Проверено %ld сообщений, подписанных \"%s\"."
+
+#, c-format
msgid ""
"Verified %ld message signed by \"%s\"\n"
"in the past %s."
"Verified %ld messages signed by \"%s\"\n"
"in the past %s."
msgstr[0] ""
-"Проверено %ld сообщение, подписанное \"%s\" (ключ: %s, правило: %s) за %s."
+"Проверено %ld сообщение, подписанное \"%s\"\n"
+" за %s."
msgstr[1] ""
-"Проверены %ld сообщения, подписанные \"%s\" (ключ: %s, правило: %s) за %s."
+"Проверены %ld сообщения, подписанные \"%s\"\n"
+" за %s."
msgstr[2] ""
-"Проверено %ld сообщений, подписанных \"%s\" (ключ: %s, правило: %s) за %s."
+"Проверено %ld сообщений, подписанных \"%s\"\n"
+" за %s."
#, c-format
msgid "The most recent message was verified %s ago."
" %s\n"
"to mark it as being bad.\n"
msgstr[0] ""
+"Внимание: если вы видели больше %ld сообщения, подписанного этим ключом, "
+"этот ключ может быть подделкой! Внимательно проверьте, не внесены ли в адрес "
+"электронной почты небольшие изменения. В случае подозрений пометьте ключ как "
+"некачественный командой\n"
+" %s\n"
msgstr[1] ""
+"Внимание: если вы видели больше %ld сообщений, подписанных этим ключом, этот "
+"ключ может быть подделкой! Внимательно проверьте, не внесены ли в адрес "
+"электронной почты небольшие изменения. В случае подозрений пометьте ключ как "
+"некачественный командой\n"
+" %s\n"
msgstr[2] ""
+"Внимание: если вы видели больше %ld сообщений, подписанных этим ключом, этот "
+"ключ может быть подделкой! Внимательно проверьте, не внесены ли в адрес "
+"электронной почты небольшие изменения. В случае подозрений пометьте ключ как "
+"некачественный командой\n"
+" %s\n"
#, c-format
msgid "error opening TOFU database: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "обновлять таблицу доверия при модели доверия '%s' не нужно\n"
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "открытый ключ %s не найден: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "выполните --check-trustdb, пожалуйста\n"
msgid "[ undef ]"
msgstr "[неопределено]"
+#, fuzzy
+#| msgid "never"
+msgid "[ never ]"
+msgstr "никогда"
+
msgid "[marginal]"
msgstr "[ ограничено ]"
#, c-format
msgid "card does not support digest algorithm %s\n"
-msgstr "карта не поддерживает хэш-функцию %s\n"
+msgstr "карта не поддерживает хеш-функцию %s\n"
#, c-format
msgid "signatures created so far: %lu\n"
#, c-format
msgid "a %u bit hash is not valid for a %u bit %s key\n"
-msgstr "%u-битный хэш недопустим для %u-битного ключа %s\n"
+msgstr "%u-битный хеш недопустим для %u-битного ключа %s\n"
msgid "(this is the MD2 algorithm)\n"
msgstr "(это алгоритм MD2)\n"
#, c-format
msgid "line %d: invalid hash algorithm given\n"
-msgstr "строка %d: задана недопустимая хэш-функция\n"
+msgstr "строка %d: задана недопустимая хеш-функция\n"
#, c-format
msgid "line %d: invalid authority-key-id\n"
msgstr "|NAME|использовать алгоритм шифрования NAME"
msgid "|NAME|use message digest algorithm NAME"
-msgstr "|NAME|использовать хэш-функцию NAME"
+msgstr "|NAME|использовать хеш-функцию NAME"
msgid "Usage: @GPGSM@ [options] [files] (-h for help)"
msgstr "Вызов: @GPGSM@ [параметры] [файлы] (-h для подсказки)"
#, c-format
msgid "hash algorithm %d (%s) for signer %d not supported; using %s\n"
-msgstr "хэш-функция %d (%s) для %d не поддерживается; использую %s\n"
+msgstr "хеш-функция %d (%s) для %d не поддерживается; использую %s\n"
#, c-format
msgid "hash algorithm used for signer %d: %s (%s)\n"
-msgstr "хэш-функция для подписи %d: %s (%s)\n"
+msgstr "хеш-функция для подписи %d: %s (%s)\n"
#, c-format
msgid "checking for qualified certificate failed: %s\n"
msgid ""
"invalid signature: message digest attribute does not match computed one\n"
msgstr ""
-"недопустимая подпись: атрибут хэш-функции сообщения не соответствует "
+"недопустимая подпись: атрибут хеш-функции сообщения не соответствует "
"вычисленному\n"
msgid "Good signature from"
#, c-format
msgid "invalid issuer hash in '%s' line %u\n"
-msgstr "неправильный хэш издателя в '%s', строка %u\n"
+msgstr "неправильный хеш издателя в '%s', строка %u\n"
#, c-format
msgid "no issuer DN in '%s' line %u\n"
#, c-format
msgid "WARNING: invalid cache file hash in '%s' line %u\n"
-msgstr "Внимание: недопустимый хэш файла буфера в '%s', строка %u\n"
+msgstr "Внимание: недопустимый хеш файла буфера в '%s', строка %u\n"
msgid "detected errors in cache dir file\n"
msgstr "в файле каталога буфера обнаружены ошибки\n"
#, c-format
msgid "can't hash '%s': %s\n"
-msgstr "невозможно получить хэш '%s': %s\n"
+msgstr "невозможно получить хеш '%s': %s\n"
#, c-format
msgid "error setting up MD5 hash context: %s\n"
-msgstr "ошибка установки контекста хэша MD5: %s\n"
+msgstr "ошибка установки контекста хеша MD5: %s\n"
#, c-format
msgid "error hashing '%s': %s\n"
-msgstr "ошибка при получении хэша '%s': %s\n"
+msgstr "ошибка при получении хеша '%s': %s\n"
#, c-format
msgid "invalid formatted checksum for '%s'\n"
#, c-format
msgid "unknown hash algorithm '%s'\n"
-msgstr "недопустимая хэш-функция '%s'\n"
+msgstr "недопустимая хеш-функция '%s'\n"
#, c-format
msgid "gcry_md_open for algorithm %d failed: %s\n"
#, c-format
msgid "hashing the OCSP response for '%s' failed: %s\n"
-msgstr "сбой получения хэша ответа OCSP для '%s': %s\n"
+msgstr "сбой получения хеша ответа OCSP для '%s': %s\n"
msgid "not signed by a default OCSP signer's certificate"
msgstr "не подписано основным сертификатом подписывающего OCSP"
#, c-format
msgid "failed to establish a hashing context for OCSP: %s\n"
-msgstr "сбой при установлении контекста хэша для OCSP: %s\n"
+msgstr "сбой при установлении контекста хеша для OCSP: %s\n"
#, c-format
msgid "error getting OCSP status for target certificate: %s\n"
msgstr "хорошая цепочка сертификатов\n"
msgid "DSA requires the use of a 160 bit hash algorithm\n"
-msgstr "DSA требует 160-битной хэш-функции\n"
+msgstr "DSA требует 160-битной хеш-функции\n"
msgid "certificate should not have been used for CRL signing\n"
msgstr ""
msgstr "не разрешать повторное использование старых фраз-паролей"
msgid "|N|set the Pinentry timeout to N seconds"
-msgstr "|N|установить время ожидания ввода PIN N секунд"
+msgstr "|N|установить время ожидания ввода пароля N секунд"
msgid "|NAME|use NAME as default secret key"
msgstr "|NAME|использовать NAME как основной секретный ключ"
msgstr ""
"Синтаксис: gpg-check-pattern [параметры] файл_образцов\n"
"Проверить фразу-пароль, поступающую из stdin, по файлу образцов\n"
-
-#~ msgid "you found a bug ... (%s:%d)\n"
-#~ msgstr "Вы нашли ошибку в программе ... (%s:%d)\n"
-
-#~ msgid "%d user ID without valid self-signature detected\n"
-#~ msgid_plural "%d user IDs without valid self-signatures detected\n"
-#~ msgstr[0] "обнаружен %d ID пользователя без действительной самоподписи\n"
-#~ msgstr[1] "обнаружены %d ID пользователя без действительной самоподписи\n"
-#~ msgstr[2] "обнаружено %d ID пользователя без действительной самоподписи\n"
-
-#~ msgid "moving a key signature to the correct place\n"
-#~ msgstr "перемещение подписи ключа в нужное место\n"
-
-#~ msgid "%d day"
-#~ msgid_plural "%d days"
-#~ msgstr[0] "%d день"
-#~ msgstr[1] "%d дня"
-#~ msgstr[2] "%d дней"
-
-# I believe the translation produces an equivalent Russian output
-# for that code snippet in g10/tofu.c -- ineiev
-#~ msgid "TOFU: few signatures %d message %s"
-#~ msgid_plural "TOFU: few signatures %d messages %s"
-#~ msgstr[0] ""
-#~ "Внимание: если Вы думаете, что видели больше %d сообщения, подписанного "
-#~ "этим ключом, то этот ключ может быть подделкой! Проверьте внимательно, не "
-#~ "внесены ли в адрес электронной почты небольшие изменения (напр., "
-#~ "дополнительные пробелы). В случае подозрений отметьте его как плохой с "
-#~ "помощью '%s'.\n"
-#~ " "
-#~ msgstr[1] ""
-#~ "Внимание: если Вы думаете, что видели больше %d сообщений, подписанных "
-#~ "этим ключом, то этот ключ может быть подделкой! Проверьте внимательно, не "
-#~ "внесены ли в адрес электронной почты небольшие изменения (напр., "
-#~ "дополнительные пробелы). В случае подозрений отметьте его как плохой с "
-#~ "помощью '%s'.\n"
-#~ " "
-#~ msgstr[2] ""
-#~ "Внимание: если Вы думаете, что видели больше %d сообщений, подписанных "
-#~ "этим ключом, то этот ключ может быть подделкой! Проверьте внимательно, не "
-#~ "внесены ли в адрес электронной почты небольшие изменения (напр., "
-#~ "дополнительные пробелы). В случае подозрений отметьте его как плохой с "
-#~ "помощью '%s'.\n"
-#~ " "
-
-#~ msgid "key specification '%s' is ambiguous\n"
-#~ msgstr "спецификация ключа '%s' неоднозначна\n"
-
-#~ msgid "'%s' matches at least:\n"
-#~ msgstr "'%s' соответствует по меньшей мере:\n"
-
-#~ msgid "%d signatures not checked due to missing keys\n"
-#~ msgstr "%d подписей не проверено за отсутствием ключей\n"
-
-#~ msgid "%d signatures not checked due to errors\n"
-#~ msgstr "%d подписей не проверено из-за ошибок\n"
-
-#~ msgid "1 user ID without valid self-signature detected\n"
-#~ msgstr "обнаружен 1 ID пользователя без действительной самоподписи\n"
-
-#~ msgid "Deleted %d signatures.\n"
-#~ msgstr "Удалено %d подписей.\n"
-
-#~ msgid "User ID \"%s\": %d signatures removed\n"
-#~ msgstr "ID пользователя \"%s\": %d подписей удалено\n"
-
-#~ msgid ""
-#~ "You need a Passphrase to protect your secret key.\n"
-#~ "\n"
-#~ msgstr ""
-#~ "Для защиты секретного ключа необходима фраза-пароль.\n"
-#~ "\n"
-
-#~ msgid ""
-#~ "Please enter a passphrase to protect the off-card backup of the new "
-#~ "encryption key."
-#~ msgstr ""
-#~ "Введите фразу-пароль для защиты архивной копии нового ключа для "
-#~ "шифрования."
-
-#~ msgid "passphrase not correctly repeated; try again"
-#~ msgstr "фраза-пароль повторена неверно; попробуйте еще раз"
-
-#~ msgid "%s.\n"
-#~ msgstr "%s.\n"
-
-#~ msgid ""
-#~ "You don't want a passphrase - this is probably a *bad* idea!\n"
-#~ "I will do it anyway. You can change your passphrase at any time,\n"
-#~ "using this program with the option \"--edit-key\".\n"
-#~ "\n"
-#~ msgstr ""
-#~ "Хотите обойтись без фразы-пароля? Скорее всего, это ПЛОХАЯ мысль!\n"
-#~ "Работа будет продолжена. Вы можете сменить фразу-пароль в любое время,\n"
-#~ "запустив данную программу с параметром \"--edit-key\".\n"
-#~ "\n"
-
-#~ msgid "storing key onto card failed: %s\n"
-#~ msgstr "сбой сохранения ключа на карте: %s\n"
-
-#~ msgid "1 good signature\n"
-#~ msgstr "1 хорошая подпись\n"
-
-#~ msgid "renaming '%s' to '%s' failed: %s\n"
-#~ msgstr "сбой при переименовании '%s' в '%s': %s\n"
-
-#~ msgid "%lu keys cached (%lu signatures)\n"
-#~ msgstr "%lu ключей помещено в буфер (%lu подписей)\n"
-
-#~ msgid "refreshing 1 key from %s\n"
-#~ msgstr "обновление 1 ключа из %s\n"
-
-#~ msgid "sending key %s to %s server %s\n"
-#~ msgstr "отправка ключа %s на сервер %s %s\n"
-
-#~ msgid "public key %s is %lu seconds newer than the signature\n"
-#~ msgstr "открытый ключ %s на %lu секунд новее подписи\n"
-
-#~ msgid ""
-#~ "key %s was created %lu seconds in the future (time warp or clock "
-#~ "problem)\n"
-#~ msgstr ""
-#~ "ключ %s создан на %lu секунд в будущем (петля во времени или проблемы с "
-#~ "часами)\n"
-
-#~ msgid "%d marginal(s) needed, %d complete(s) needed, %s trust model\n"
-#~ msgstr ""
-#~ "требуется %d с ограниченным доверием, %d с полным, модель доверия %s\n"
-
-#~ msgid "cleared passphrase cached with ID: %s\n"
-#~ msgstr "в буфере сброшена фраза-пароль с индексом %s\n"
-
-#, fuzzy
-#~| msgid "failed to store the key: %s\n"
-#~ msgid "Failed to open the keyring DB.\n"
-#~ msgstr "сбой сохранения ключа: %s\n"
-
-#, fuzzy
-#~| msgid "failed to open '%s': %s\n"
-#~ msgid "Failed to parse '%s'.\n"
-#~ msgstr "не могу открыть '%s': %s\n"
-
-#, fuzzy
-#~| msgid "error locking keybox: %s\n"
-#~ msgid "error looking up secret key \"%s\": %s\n"
-#~ msgstr "ошибка блокировки щита с ключами: %s\n"
-
-#~ msgid "Please select at most one subkey.\n"
-#~ msgstr "Выделите не более одного подключа.\n"
-
-#~ msgid "apparently no running dirmngr\n"
-#~ msgstr "видимо, dirmngr не работает\n"
-
-#~ msgid "no running dirmngr - starting one\n"
-#~ msgstr "dirmngr не выполняется - запуск\n"
-
-#~ msgid "malformed %s environment variable\n"
-#~ msgstr "неправильная переменная окружения %s\n"
-
-#~ msgid "dirmngr protocol version %d is not supported\n"
-#~ msgstr "протокол dirmngr версии %d не поддерживается\n"
-
-#~ msgid "can't connect to the dirmngr - trying fall back\n"
-#~ msgstr "не могу подключиться к dirmngr - пробую запасной вариант\n"
-
-#~ msgid "export keys in an S-expression based format"
-#~ msgstr "экспортировать ключи в формате на основе S-выражений"
-
-#~ msgid "Directory Manager"
-#~ msgstr "Управление каталогами"
-
-#~ msgid "toggle between the secret and public key listings"
-#~ msgstr "переключение между просмотром открытых и закрытых ключей"
-
-#~ msgid "Please use the command \"toggle\" first.\n"
-#~ msgstr "Сначала воспользуйтесь командой \"toggle\".\n"
-
-#~ msgid "Passphrase"
-#~ msgstr "Фраза-пароль"
-
-#~ msgid "use temporary files to pass data to keyserver helpers"
-#~ msgstr "передавать данные в сервер с помощью временных файлов"
-
-#~ msgid "do not delete temporary files after using them"
-#~ msgstr "не удалять временные файлы после использования"
-
-#~ msgid "WARNING: keyserver option '%s' is not used on this platform\n"
-#~ msgstr ""
-#~ "ВНИМАНИЕ: параметр сервера ключей `%s' на данной платформе не "
-#~ "используется\n"
msgstr "chyba pri posielaní na `%s': %s\n"
#, fuzzy, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "VAROVANIE: prístupové práva pre %s nie sú nastavené bezpeène \"%s\"\n"
+
+#, fuzzy, c-format
msgid "listen() failed: %s\n"
msgstr "aktualizácia zlyhala: %s\n"
msgstr "%s: adresár vytvorený\n"
#, fuzzy, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "VAROVANIE: prístupové práva pre %s nie sú nastavené bezpeène \"%s\"\n"
-
-#, fuzzy, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "databáza dôvery: procedúra read() (n=%d) zlyhala: %s\n"
msgid "export keys"
msgstr "exportova» kµúèe"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "exportova» kµúèe na server kµúèov"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "importova» kµúèe zo servera kµúèov"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "vyhµada» kµúèe na serveri kµúèov"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|zapísa» informácie o stave do tohto FD"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Pou¾itie: gpgv [mo¾nosti] [súbory] (-h pre pomoc)"
msgid "No key with this keygrip\n"
msgstr "Neexistuje identifikátor u¾ívateµa s indexom %d\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "zaokrúhlené na %u bitov\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr ""
msgid "Requested keysize is %u bits\n"
msgstr "Po¾adovaná då¾ka kµúèa je %u bitov.\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "zaokrúhlené na %u bitov\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgid "error updating TOFU database: %s\n"
msgstr "chyba pri posielaní na `%s': %s\n"
-#, fuzzy, c-format
-msgid "public key %s not found: %s\n"
-msgstr "verejný kµúè %08lX nebol nájdený: %s\n"
-
-#, fuzzy, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "chyba pri èítaní `%s': %s\n"
-
#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "chyba pri èítaní `%s': %s\n"
+
+#, fuzzy, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "chyba pri vytváraní hesla: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "nie je nutné kontrolova» databázu dôvery\n"
+#, fuzzy, c-format
+msgid "public key %s not found: %s\n"
+msgstr "verejný kµúè %08lX nebol nájdený: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "prosím vykonajte --check-trustdb\n"
msgid "[ undef ]"
msgstr ""
+#, fuzzy
+msgid "[ never ]"
+msgstr "nikdy "
+
msgid "[marginal]"
msgstr ""
msgid "error binding socket to '%s': %s\n"
msgstr "fel när \"%s\" bands till uttag: %s\n"
+# Extension är vad? FIXME
+#, fuzzy, c-format
+#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
+msgid "can't set permissions of '%s': %s\n"
+msgstr "Varning: osäkra rättigheter på %s \"%s\"\n"
+
#, c-format
msgid "listen() failed: %s\n"
msgstr "listen() misslyckades: %s\n"
msgid "directory '%s' created\n"
msgstr "katalogen \"%s\" skapades\n"
-# Extension är vad? FIXME
-#, fuzzy, c-format
-#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
-msgid "can't set permissions of '%s': %s\n"
-msgstr "Varning: osäkra rättigheter på %s \"%s\"\n"
-
#, fuzzy, c-format
#| msgid "stat() failed for `%s': %s\n"
msgid "stat() failed for '%s': %s\n"
msgid "export keys"
msgstr "exportera nycklar"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "exportera nycklar till en nyckelserver"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "importera nycklar från en nyckelserver"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "sök efter nycklar hos en nyckelserver"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|skriv statusinformation till denna FD"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Användning: gpgv [flaggor] [filer] (-h för hjälp)"
msgid "No key with this keygrip\n"
msgstr "Ingen nyckel med denna nyckelhash\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "avrundade uppåt till %u bitar\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr "%s-nycklar kan vara mellan %u och %u bitar långa.\n"
msgid "Requested keysize is %u bits\n"
msgstr "Den efterfrågade nyckelstorleken är %u bitar\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "avrundade uppåt till %u bitar\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgstr "fel vid sändning av %s-kommando: %s\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "publika nyckeln %s hittades inte: %s\n"
-
-#, fuzzy, c-format
-#| msgid "error storing flags: %s\n"
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "fel vid lagring av flaggor: %s\n"
-
-#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+#| msgid "error storing flags: %s\n"
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "fel vid lagring av flaggor: %s\n"
+
+#, fuzzy, c-format
#| msgid "error creating a pipe: %s\n"
msgid "error changing TOFU policy: %s\n"
msgstr "fel när ett rör skapades: %s\n"
msgstr ""
"det behövs ingen uppdatering av tillitsdatabasen med tillitsmodellen \"%s\"\n"
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "publika nyckeln %s hittades inte: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "gör en kontroll av tillitsdatabasen --check-trustdb\n"
msgid "[ undef ]"
msgstr "[ odefinierad ]"
+#, fuzzy
+#| msgid "never"
+msgid "[ never ]"
+msgstr "aldrig"
+
msgid "[marginal]"
msgstr "[ marginell ]"
msgid "error binding socket to '%s': %s\n"
msgstr "soket `%s'e bağlanırken hata: %s\n"
+#, fuzzy, c-format
+#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
+msgid "can't set permissions of '%s': %s\n"
+msgstr "UYARI: %s üzerinde izinler güvensiz: \"%s\"\n"
+
#, c-format
msgid "listen() failed: %s\n"
msgstr "soket dinleme başarısız: %s\n"
msgstr "dizin `%s' oluşturuldu\n"
#, fuzzy, c-format
-#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
-msgid "can't set permissions of '%s': %s\n"
-msgstr "UYARI: %s üzerinde izinler güvensiz: \"%s\"\n"
-
-#, fuzzy, c-format
#| msgid "stat() failed for `%s': %s\n"
msgid "stat() failed for '%s': %s\n"
msgstr "%s için stat() başarısız oldu: %s\n"
msgid "export keys"
msgstr "anahtarları gönderir"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "anahtarları bir anahtar sunucusuna gönderir"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "anahtarları bir anahtar sunucusundan indirir"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "bir anahtar sunucusunda anahtarları arar"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|durum bilgisini bu FD'ye yazar"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Kullanımı: gpgv [seçenekler] [dosyalar] (yardım için -h)"
msgid "No key with this keygrip\n"
msgstr "%d indisli bir yardımcı anahtar yok\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "%u bite yuvarlandı\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr "%s anahtarları %u bit ile %u bit arasında olmalı.\n"
msgid "Requested keysize is %u bits\n"
msgstr "İstenen anahtar uzunluğu: %u bit\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "%u bite yuvarlandı\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgstr "%s komutu gönderilirken hata: %s\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "genel anahtar %s yok: %s\n"
-
-#, fuzzy, c-format
-#| msgid "error storing flags: %s\n"
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "bayraklar saklanırken hata: %s\n"
-
-#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+#| msgid "error storing flags: %s\n"
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "bayraklar saklanırken hata: %s\n"
+
+#, fuzzy, c-format
#| msgid "error creating a pipe: %s\n"
msgid "error changing TOFU policy: %s\n"
msgstr "boru oluşturulurken hata: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "`%s' güvence modelli güvence veritabanı güncellemesi için gereksiz\n"
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "genel anahtar %s yok: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "lütfen bir --check-trustdb yapın\n"
msgid "[ undef ]"
msgstr "[ tanımsız ]"
+#, fuzzy
+#| msgid "never"
+msgid "[ never ]"
+msgstr "asla "
+
msgid "[marginal]"
msgstr "[ şöyle böyle ]"
# Copyright (C) 2011 Free Software Foundation, Inc.
# This file is distributed under the same license as the GnuPG package.
#
-# Yuri Chornoivan <yurchor@ukr.net>, 2011, 2014, 2015.
+# Yuri Chornoivan <yurchor@ukr.net>, 2011, 2014, 2015, 2016.
msgid ""
msgstr ""
"Project-Id-Version: GNU gnupg 2.1.0\n"
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
-"PO-Revision-Date: 2015-10-23 19:33+0300\n"
+"PO-Revision-Date: 2016-05-10 18:21+0300\n"
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
"Language-Team: Ukrainian <kde-i18n-uk@kde.org>\n"
"Language: uk\n"
msgid "allow presetting passphrase"
msgstr "дозволити попереднє встановлення пароля"
-#, fuzzy
-#| msgid "allow caller to override the pinentry"
msgid "disallow caller to override the pinentry"
-msgstr "дозволити функції виклику перевизначати pinentry"
+msgstr "забоÑ\80онити функції виклику перевизначати pinentry"
msgid "allow passphrase to be prompted through Emacs"
msgstr "дозволити запит пароля з Emacs"
msgstr "помилка під час спроби прив’язування сокета до «%s»: %s\n"
#, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "не вдалося встановити права доступу до «%s»: %s\n"
+
+#, c-format
msgid "listen() failed: %s\n"
msgstr "помилка listen(): %s\n"
msgid "directory '%s' created\n"
msgstr "створено каталог «%s»\n"
-#, fuzzy, c-format
-#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
-msgid "can't set permissions of '%s': %s\n"
-msgstr "Увага: визначення прав доступу не є безпечним для %s — «%s»\n"
-
#, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "помилка stat() щодо «%s»: %s\n"
msgid "error forking process: %s\n"
msgstr "помилка під час спроби розгалужування процесу: %s\n"
-#, fuzzy, c-format
-#| msgid "waiting for process %d to terminate failed: %s\n"
+#, c-format
msgid "waiting for processes to terminate failed: %s\n"
-msgstr "не вдалоÑ\81Ñ\8f доÑ\87екаÑ\82иÑ\81Ñ\8f завеÑ\80Ñ\88еннÑ\8f пÑ\80оÑ\86еÑ\81Ñ\83 %d: %s\n"
+msgstr "не вдалоÑ\81Ñ\8f доÑ\87екаÑ\82иÑ\81Ñ\8f пеÑ\80еÑ\80иваннÑ\8f пÑ\80оÑ\86еÑ\81Ñ\83: %s\n"
#, c-format
msgid "error running '%s': probably not installed\n"
msgid "problem with the agent\n"
msgstr "проблема з агентом\n"
-#, fuzzy, c-format
-#| msgid "problem with the agent: %s\n"
+#, c-format
msgid "problem with the agent (unexpected response \"%s\")\n"
-msgstr "проблема з агентом: %s\n"
+msgstr "проблема із агентом (неочікувана відповідь «%s»)\n"
#, c-format
msgid "can't disable core dumps: %s\n"
"символи quoted printable у кодуванні ASCII — ймовірно, використано "
"помилковий MTA\n"
-#, fuzzy, c-format
-#| msgid "not human readable"
+#, c-format
msgid "[ not human readable (%zu bytes: %s%s) ]"
-msgstr "незручне для читання"
+msgstr "[ незручне для читання (%zu байтів: %s%s) ]"
msgid ""
"a notation name must have only printable characters or spaces, and end with "
msgid "a notation value must not use any control characters\n"
msgstr "у значенні примітки не повинно міститися керівних символів\n"
-#, fuzzy
-#| msgid "a notation name must not contain more than one '@' character\n"
msgid "a notation name may not contain an '=' character\n"
-msgstr "назва примітки не повинна містити більше за один символ «@»\n"
+msgstr "назва позначення не може містити символів «=»\n"
-#, fuzzy
-#| msgid ""
-#| "a notation name must have only printable characters or spaces, and end "
-#| "with an '='\n"
msgid "a notation name must have only printable characters or spaces\n"
-msgstr ""
-"назва примітки має складатися з друкованих символів або пробілів і "
-"завершуватися символом «=»\n"
+msgstr "назва примітки має складатися з друкованих символів або пробілів\n"
msgid "WARNING: invalid notation data found\n"
msgstr "УВАГА: виявлено некоректні дані примітки\n"
msgid "Enter passphrase: "
msgstr "Введіть пароль: "
-#, fuzzy, c-format
-#| msgid "error creating keyring '%s': %s\n"
+#, c-format
msgid "error getting version from '%s': %s\n"
-msgstr "помилка під час спроби створення сховища ключів «%s»: %s\n"
+msgstr "помилка під час спроби отримання даних щодо версії з «%s»: %s\n"
#, c-format
msgid "server '%s' is older than us (%s < %s)"
-msgstr ""
+msgstr "сервер «%s» має версію, старішу за нашу (%s < %s)"
-#, fuzzy, c-format
-#| msgid "WARNING: %s overrides %s\n"
+#, c-format
msgid "WARNING: %s\n"
-msgstr "УВАГА: %s перевизначає %s\n"
+msgstr "УВАГА: %s\n"
#, c-format
msgid "OpenPGP card not available: %s\n"
msgid "error reading keyblock: %s\n"
msgstr "помилка під час спроби читання блокування ключа: %s\n"
-#, fuzzy, c-format
-#| msgid "key \"%s\" not found: %s\n"
+#, c-format
msgid "key \"%s\" not found\n"
-msgstr "ключ «%s» не знайдено: %s\n"
+msgstr "ключ «%s» не знайдено\n"
msgid "(unless you specify the key by fingerprint)\n"
msgstr "(якщо ключ не задано відбитком)\n"
msgid "[User ID not found]"
msgstr "[Ідентифікатор не знайдено]"
-#, fuzzy, c-format
-#| msgid "missing argument for option \"%.50s\"\n"
+#, c-format
msgid "(check argument of option '%s')\n"
-msgstr "не вказано аргументу до параметра «%.50s»\n"
+msgstr "(перевірте аргумент параметра «%s»)\n"
#, c-format
msgid "Warning: '%s' should be a long key ID or a fingerprint\n"
msgstr ""
+"Попередження: «%s» має бути довгим ідентифікатором ключа або відбитком\n"
-#, fuzzy, c-format
-#| msgid "error closing %s: %s\n"
+#, c-format
msgid "error looking up: %s\n"
-msgstr "помилка під час спроби закрити %s: %s\n"
+msgstr "помилка під час пошуку: %s\n"
-#, fuzzy, c-format
-#| msgid "error creating keyring '%s': %s\n"
+#, c-format
msgid "Warning: %s appears in the keyring %d times\n"
-msgstr "помилка пÑ\96д Ñ\87аÑ\81 Ñ\81пÑ\80оби Ñ\81Ñ\82воÑ\80еннÑ\8f Ñ\81Ñ\85овиÑ\89а клÑ\8eÑ\87Ñ\96в «%s»: %s\n"
+msgstr "Ð\9fопеÑ\80едженнÑ\8f: запиÑ\81 %s наÑ\8fвний Ñ\83 Ñ\81Ñ\85овиÑ\89Ñ\96 %d Ñ\80азÑ\96в\n"
#, c-format
msgid "automatically retrieved '%s' via %s\n"
msgid "secret key \"%s\" not found: %s\n"
msgstr "закритий ключ «%s» не знайдено: %s\n"
-#, fuzzy, c-format
-#| msgid "|NAME|use NAME as default secret key"
+#, c-format
msgid "Warning: not using '%s' as default key: %s\n"
-msgstr "|NAME|використовувати вказаний типовий закритий ключ"
+msgstr "Попередження: «%s» не використовується як типовий ключ: %s\n"
-#, fuzzy, c-format
-#| msgid "|NAME|use NAME as default secret key"
+#, c-format
msgid "using \"%s\" as default secret key for signing\n"
-msgstr "|NAME|використовувати вказаний типовий закритий ключ"
+msgstr "використовуємо «%s» як типовий закритий ключ для підписування\n"
#, c-format
msgid "all values passed to '%s' ignored\n"
-msgstr ""
+msgstr "усі значення, передані «%s», проігноровано\n"
#, c-format
msgid "Invalid key %s made valid by --allow-non-selfsigned-uid\n"
msgid "export keys"
msgstr "експортувати ключі"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "експортувати ключі на сервер ключів"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "імпортувати ключі з сервера ключів"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "шукати ключі на сервері ключів"
msgid "update all keys from a keyserver"
msgid "run in server mode"
msgstr "запустити у режимі сервера"
-#, fuzzy
-#| msgid "|VALUE|set the TOFU policy for a key (good, unknown, bad, ask, auto)"
msgid "|VALUE|set the TOFU policy for a key"
-msgstr "встановити правила TOFU для ключа (good, unknown, bad, ask, auto)"
+msgstr "|VALUE|встановити вказане правило TOFU для ключа"
msgid "create ascii armored output"
msgstr "створити дані у форматі ASCII"
msgid "show expiration dates during signature listings"
msgstr "показувати дати завершення строків дії у списку підписів"
-#, fuzzy
-#| msgid "Available keys:\n"
msgid "available TOFU policies:\n"
-msgstr "Ð\94оÑ\81Ñ\82Ñ\83пнÑ\96 клÑ\8eÑ\87Ñ\96:\n"
+msgstr "можливÑ\96 ваÑ\80Ñ\96анÑ\82и пÑ\80авил TOFU:\n"
#, c-format
msgid "unknown TOFU policy '%s'\n"
msgstr "невідомі правила TOFU «%s»\n"
msgid "(use \"help\" to list choices)\n"
-msgstr ""
+msgstr "(команда «help» виводить список можливих варіантів)\n"
#, c-format
msgid "unknown TOFU DB format '%s'\n"
msgid "key export failed: %s\n"
msgstr "помилка під час спроби експортування ключа: %s\n"
-#, fuzzy, c-format
-#| msgid "key export failed: %s\n"
+#, c-format
msgid "export as ssh key failed: %s\n"
-msgstr "помилка під час спроби експортування ключа: %s\n"
+msgstr "спроба експортування ключа ssh зазнала невдачі: %s\n"
#, c-format
msgid "keyserver search failed: %s\n"
msgid "invalid hash algorithm '%s'\n"
msgstr "некоректний алгоритм хешування «%s»\n"
-#, fuzzy, c-format
-#| msgid "error loading certificate '%s': %s\n"
+#, c-format
msgid "error parsing key specification '%s': %s\n"
-msgstr "помилка пÑ\96д Ñ\87аÑ\81 Ñ\81пÑ\80оби заванÑ\82аженнÑ\8f Ñ\81еÑ\80Ñ\82иÑ\84Ñ\96каÑ\82а «%s»: %s\n"
+msgstr "помилка пÑ\96д Ñ\87аÑ\81 Ñ\81пÑ\80оби обÑ\80обки Ñ\81пеÑ\86иÑ\84Ñ\96каÑ\86Ñ\96Ñ\97 клÑ\8eÑ\87а «%s»: %s\n"
-#, fuzzy, c-format
-#| msgid ""
-#| "'%s' does not appear to be a valid key id, fingerprint or key grip.\n"
+#, c-format
msgid "'%s' does not appear to be a valid key ID, fingerprint or keygrip\n"
-msgstr "«%s» не є коректним ідентифікатором ключа, відбитком або keygrip.\n"
+msgstr "«%s» не є коректним ідентифікатором ключа, відбитком або кодом\n"
msgid "[filename]"
msgstr "[назва файла]"
msgid "|FD|write status info to this FD"
msgstr "записувати до дескриптора файла дані щодо стану"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "Використання: gpgv [параметри] [файли] (-h — довідка)"
#, c-format
msgid "To migrate '%s', with each smartcard, run: %s\n"
msgstr ""
+"Для перенесення «%s» на кожній із карток пам’яті слід виконати таку команду: "
+"%s\n"
#, c-format
msgid "key %s: no public key - can't apply revocation certificate\n"
msgid "keyblock resource '%s': %s\n"
msgstr "ресурс блоку ключів «%s»: %s\n"
-#, fuzzy, c-format
-#| msgid "error opening '%s': %s\n"
+#, c-format
msgid "error opening key DB: %s\n"
-msgstr "помилка під час відкриття «%s»: %s\n"
+msgstr "помилка під час спроби відкрити базу даних ключів: %s\n"
#, c-format
msgid "failed to rebuild keyring cache: %s\n"
msgid "[self-signature]"
msgstr "[самопідпис]"
-#, fuzzy, c-format
-#| msgid "key %s: unsupported public key algorithm\n"
+#, c-format
msgid "can't check signature with unsupported public-key algorithm (%d): %s.\n"
-msgstr "ключ %s: непідтримуваний алгоритм створення відкритого ключа\n"
+msgstr ""
+"неможливо перевірити підпис із непідтримуваним алгоритмом створення "
+"відкритого ключа (%d): %s.\n"
-#, fuzzy, c-format
-#| msgid "card does not support digest algorithm %s\n"
+#, c-format
msgid ""
"can't check signature with unsupported message-digest algorithm %d: %s.\n"
-msgstr "карткою не підтримується алгоритм контрольних сум %s\n"
+msgstr ""
+"неможливо перевірити підпис із непідтримуваним алгоритмом створення "
+"контрольної суми %d: %s.\n"
-#, fuzzy
-#| msgid "Good signature from"
msgid " (reordered signatures follow)"
-msgstr "Правильний підпис від"
+msgstr " (нижче наведено перевпорядковані підписи)"
-#, fuzzy, c-format
-#| msgid "key %s: %s\n"
+#, c-format
msgid "key %s:\n"
-msgstr "ключ %s: %s\n"
+msgstr "ключ %s:\n"
-#, fuzzy, c-format
-#| msgid "User ID \"%s\": %d signature removed\n"
+#, c-format
msgid "%d duplicate signature removed\n"
msgid_plural "%d duplicate signatures removed\n"
-msgstr[0] "Ð\86денÑ\82иÑ\84Ñ\96каÑ\82оÑ\80 коÑ\80иÑ\81Ñ\82Ñ\83ваÑ\87а «%s»: вилÑ\83Ñ\87ено %d пÑ\96дпиÑ\81\n"
-msgstr[1] "Ð\86денÑ\82иÑ\84Ñ\96каÑ\82оÑ\80 коÑ\80иÑ\81Ñ\82Ñ\83ваÑ\87а «%s»: вилÑ\83Ñ\87ено %d пÑ\96дпиÑ\81\n"
-msgstr[2] "Ð\86денÑ\82иÑ\84Ñ\96каÑ\82оÑ\80 коÑ\80иÑ\81Ñ\82Ñ\83ваÑ\87а «%s»: вилÑ\83Ñ\87ено %d пÑ\96дпиÑ\81\n"
+msgstr[0] "вилÑ\83Ñ\87ено %d дÑ\83блÑ\96каÑ\82 пÑ\96дпиÑ\81Ñ\83\n"
+msgstr[1] "вилÑ\83Ñ\87ено %d дÑ\83блÑ\96каÑ\82и пÑ\96дпиÑ\81Ñ\96в\n"
+msgstr[2] "вилÑ\83Ñ\87ено %d дÑ\83блÑ\96каÑ\82Ñ\96в пÑ\96дпиÑ\81Ñ\96в\n"
-#, fuzzy, c-format
-#| msgid "1 signature not checked due to a missing key\n"
+#, c-format
msgid "%d signature not checked due to a missing key\n"
msgid_plural "%d signatures not checked due to missing keys\n"
-msgstr[0] "1 підпис не перевірено через те, що немає ключа\n"
-msgstr[1] "1 підпис не перевірено через те, що немає ключа\n"
-msgstr[2] "1 підпис не перевірено через те, що немає ключа\n"
+msgstr[0] "%d підпис не перевірено через те, що немає ключа\n"
+msgstr[1] "%d підписи не перевірено через те, що немає ключа\n"
+msgstr[2] "%d підписів не перевірено через те, що немає ключа\n"
-#, fuzzy, c-format
-#| msgid "%d bad signatures\n"
+#, c-format
msgid "%d bad signature\n"
msgid_plural "%d bad signatures\n"
-msgstr[0] "%d помилкових підписів\n"
-msgstr[1] "%d помилкових підписів\n"
+msgstr[0] "%d помилкових підпис\n"
+msgstr[1] "%d помилкових підписи\n"
msgstr[2] "%d помилкових підписів\n"
-#, fuzzy, c-format
-#| msgid "Good signature from"
+#, c-format
msgid "%d signature reordered\n"
msgid_plural "%d signatures reordered\n"
-msgstr[0] "Ð\9fÑ\80авилÑ\8cний пÑ\96дпиÑ\81 вÑ\96д"
-msgstr[1] "Ð\9fÑ\80авилÑ\8cний пÑ\96дпиÑ\81 вÑ\96д"
-msgstr[2] "Ð\9fÑ\80авилÑ\8cний пÑ\96дпиÑ\81 вÑ\96д"
+msgstr[0] "пеÑ\80евпоÑ\80Ñ\8fдковано %d пÑ\96дпиÑ\81\n"
+msgstr[1] "пеÑ\80евпоÑ\80Ñ\8fдковано %d пÑ\96дпиÑ\81и\n"
+msgstr[2] "пеÑ\80евпоÑ\80Ñ\8fдковано %d пÑ\96дпиÑ\81Ñ\96в\n"
#, c-format
msgid ""
"Warning: errors found and only checked self-signatures, run '%s' to check "
"all signatures.\n"
msgstr ""
+"Попередження: виявлено помилки, перевірка виконувалася лише для "
+"самопідписування, віддайте команду «%s», щоб перевірити усі підписи.\n"
msgid ""
"Please decide how far you trust this user to correctly verify other users' "
#, c-format
msgid "Skipping user ID \"%s\", which is not a text ID.\n"
-msgstr ""
+msgstr "Пропускаємо ідентифікатор користувача «%s», який не є текстовим.\n"
#, c-format
msgid "User ID \"%s\" is revoked."
msgid "Really sign all user IDs? (y/N) "
msgstr "Підписати всі ідентифікатори користувача? (y/N або т/Н) "
-#, fuzzy
-#| msgid "Really sign all user IDs? (y/N) "
msgid "Really sign all text user IDs? (y/N) "
-msgstr "Підписати всі ідентифікатори користувача? (y/N або т/Н) "
+msgstr "Ð\9fÑ\96дпиÑ\81аÑ\82и вÑ\81Ñ\96 Ñ\82екÑ\81Ñ\82овÑ\96 Ñ\96денÑ\82иÑ\84Ñ\96каÑ\82оÑ\80и коÑ\80иÑ\81Ñ\82Ñ\83ваÑ\87а? (y/N або Ñ\82/Ð\9d) "
msgid "Hint: Select the user IDs to sign\n"
msgstr "Підказка: виберіть ідентифікатори користувача для підписування\n"
msgid "\"%s\" is not the primary fingerprint\n"
msgstr "«%s» не є основним відбитком\n"
-#, fuzzy, c-format
-#| msgid "invalid value\n"
+#, c-format
msgid "Invalid user ID '%s': %s\n"
-msgstr "некоÑ\80екÑ\82не знаÑ\87еннÑ\8f\n"
+msgstr "Ð\9dекоÑ\80екÑ\82ний Ñ\96денÑ\82иÑ\84Ñ\96каÑ\82оÑ\80 коÑ\80иÑ\81Ñ\82Ñ\83ваÑ\87а «%s»: %s\n"
msgid "No matching user IDs."
msgstr "Немає відповідних ідентифікаторів користувачів."
msgid "Really delete this self-signature? (y/N)"
msgstr "Вилучити цей самопідпис? (y/N або т/Н)"
-#, fuzzy, c-format
-#| msgid "Deleted %d signature.\n"
+#, c-format
msgid "Deleted %d signature.\n"
msgid_plural "Deleted %d signatures.\n"
msgstr[0] "Вилучено %d підпис.\n"
-msgstr[1] "Вилучено %d підпис.\n"
-msgstr[2] "Вилучено %d підпис.\n"
+msgstr[1] "Вилучено %d підписи.\n"
+msgstr[2] "Вилучено %d підписів.\n"
msgid "Nothing deleted.\n"
msgstr "Нічого не вилучено.\n"
msgid "User ID \"%s\" compacted: %s\n"
msgstr "Ідентифікатор користувача «%s» ущільнено: %s\n"
-#, fuzzy, c-format
-#| msgid "User ID \"%s\": %d signature removed\n"
+#, c-format
msgid "User ID \"%s\": %d signature removed\n"
msgid_plural "User ID \"%s\": %d signatures removed\n"
msgstr[0] "Ідентифікатор користувача «%s»: вилучено %d підпис\n"
-msgstr[1] "Ідентифікатор користувача «%s»: вилучено %d підпис\n"
-msgstr[2] "Ідентифікатор користувача «%s»: вилучено %d підпис\n"
+msgstr[1] "Ідентифікатор користувача «%s»: вилучено %d підписів\n"
+msgstr[2] "Ідентифікатор користувача «%s»: вилучено %d підписів\n"
#, c-format
msgid "User ID \"%s\": already minimized\n"
"Ви справді бажаєте призначити цей ключ як підписане відкликання? (y/N або т/"
"Н) "
-#, fuzzy
-#| msgid ""
-#| "Are you sure you want to appoint this key as a designated revoker? (y/N) "
msgid ""
"Are you sure you want to change the expiration time for multiple subkeys? (y/"
"N) "
msgstr ""
-"Ви справді бажаєте призначити цей ключ як підписане відкликання? (y/N або т/"
-"Н) "
+"Ви справді хочете змінити час вичерпання строку дії для декількох підключів? "
+"(y/N або т/Н) "
msgid "Changing expiration time for a subkey.\n"
msgstr "Зміна часу завершення строку дії для підключа.\n"
msgid "No user ID with hash %s\n"
msgstr "Ідентифікатора користувача з хешем %s не існує\n"
-#, fuzzy, c-format
-#| msgid "No subkey with index %d\n"
+#, c-format
msgid "No subkey with key ID '%s'.\n"
-msgstr "Ð\9fÑ\96дклÑ\8eÑ\87а з Ñ\96ндекÑ\81ом %d не Ñ\96Ñ\81нÑ\83Ñ\94\n"
+msgstr "Ð\9fÑ\96клÑ\8eÑ\87а Ñ\96з Ñ\96денÑ\82иÑ\84Ñ\96каÑ\82оÑ\80ом клÑ\8eÑ\87а «%s» не Ñ\96Ñ\81нÑ\83Ñ\94.\n"
#, c-format
msgid "No subkey with index %d\n"
msgstr "Немає ключів з таким значенням keygrip\n"
#, c-format
+msgid "rounded to %u bits\n"
+msgstr "округлено до %u бітів\n"
+
+#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr "ключі %s можуть мати довжину від %u до %u бітів.\n"
msgid "Requested keysize is %u bits\n"
msgstr "Запитана довжина ключа — %u бітів\n"
-#, c-format
-msgid "rounded to %u bits\n"
-msgstr "округлено до %u бітів\n"
-
msgid "Please select which elliptic curve you want:\n"
msgstr "Вкажіть потрібну вам еліптичну криву:\n"
#, c-format
msgid "The characters '%s' and '%s' may not appear in name\n"
-msgstr ""
+msgstr "Не можна використовувати символи «%s» і «%s» у назві\n"
msgid "Name may not start with a digit\n"
msgstr "Ім’я не може починатися з цифри\n"
msgid "Signature notation: "
msgstr "Примітка підпису: "
-#, fuzzy, c-format
-#| msgid "%d good signatures\n"
+#, c-format
msgid "%d good signature\n"
msgid_plural "%d good signatures\n"
-msgstr[0] "%d добрих підписів\n"
-msgstr[1] "%d добрих підписів\n"
+msgstr[0] "%d добрий підпис\n"
+msgstr[1] "%d добрих підписи\n"
msgstr[2] "%d добрих підписів\n"
-#, fuzzy, c-format
-#| msgid "1 signature not checked due to an error\n"
+#, c-format
msgid "%d signature not checked due to an error\n"
msgid_plural "%d signatures not checked due to errors\n"
-msgstr[0] "1 підпис не перевірено через помилку\n"
-msgstr[1] "1 підпис не перевірено через помилку\n"
-msgstr[2] "1 підпис не перевірено через помилку\n"
+msgstr[0] "%d підпис не перевірено через помилку\n"
+msgstr[1] "%d підписи не перевірено через помилку\n"
+msgstr[2] "%d підписів не перевірено через помилку\n"
-#, fuzzy, c-format
-#| msgid "Warning: %lu key(s) skipped due to their large size\n"
+#, c-format
msgid "Warning: %lu key skipped due to its large size\n"
msgid_plural "Warning: %lu keys skipped due to their large sizes\n"
-msgstr[0] ""
-"Попередження: %lu ключів пропущено через їхній надто великий розмір\n"
+msgstr[0] "Попередження: %lu ключ пропущено через надто великий розмір\n"
msgstr[1] ""
-"Попередження: %lu ключів пропущено через їхній надто великий розмір\n"
+"Попередження: %lu ключі пропущено через їхній надто великий розмір\n"
msgstr[2] ""
"Попередження: %lu ключів пропущено через їхній надто великий розмір\n"
msgid "caching keyring '%s'\n"
msgstr "кешування сховища ключів «%s»\n"
-#, fuzzy, c-format
-#| msgid "%lu keys cached so far (%lu signatures)\n"
+#, c-format
msgid "%lu keys cached so far (%lu signature)\n"
msgid_plural "%lu keys cached so far (%lu signatures)\n"
-msgstr[0] "зараз кешовано %lu ключів (%lu підписів)\n"
-msgstr[1] "зараз кешовано %lu ключів (%lu підписів)\n"
+msgstr[0] "зараз кешовано %lu ключів (%lu підпис)\n"
+msgstr[1] "зараз кешовано %lu ключів (%lu підписи)\n"
msgstr[2] "зараз кешовано %lu ключів (%lu підписів)\n"
-#, fuzzy, c-format
-#| msgid "flush the cache"
+#, c-format
msgid "%lu key cached"
msgid_plural "%lu keys cached"
-msgstr[0] "спорожнити кеш"
-msgstr[1] "спорожнити кеш"
-msgstr[2] "спорожнити кеш"
+msgstr[0] "кешовано %lu ключ"
+msgstr[1] "кешовано %lu ключі"
+msgstr[2] "кешовано %lu ключів"
-#, fuzzy, c-format
-#| msgid "1 bad signature\n"
+#, c-format
msgid " (%lu signature)\n"
msgid_plural " (%lu signatures)\n"
-msgstr[0] "1 помилковий підпис\n"
-msgstr[1] "1 помилковий підпис\n"
-msgstr[2] "1 помилковий підпис\n"
+msgstr[0] " (%lu підпис)\n"
+msgstr[1] " (%lu підписи)\n"
+msgstr[2] " (%lu підписів)\n"
#, c-format
msgid "%s: keyring created\n"
msgid "\"%s\" not a key ID: skipping\n"
msgstr "«%s» не є ідентифікатором ключа: пропускаємо\n"
-#, fuzzy, c-format
-#| msgid "refreshing %d keys from %s\n"
+#, c-format
msgid "refreshing %d key from %s\n"
msgid_plural "refreshing %d keys from %s\n"
-msgstr[0] "оновлюємо %d ключів з %s\n"
-msgstr[1] "оновлюємо %d ключів з %s\n"
+msgstr[0] "оновлюємо %d ключ з %s\n"
+msgstr[1] "оновлюємо %d ключі з %s\n"
msgstr[2] "оновлюємо %d ключів з %s\n"
#, c-format
msgid "requesting key %s from %s\n"
msgstr "надсилаємо запит щодо ключа %s з %s\n"
-#, fuzzy
-#| msgid "invalid keyserver options\n"
msgid "no keyserver known\n"
-msgstr "некоÑ\80екÑ\82нÑ\96 паÑ\80амеÑ\82Ñ\80и Ñ\81еÑ\80веÑ\80а ключів\n"
+msgstr "немаÑ\94 вÑ\96домиÑ\85 Ñ\81еÑ\80веÑ\80Ñ\96в ключів\n"
#, c-format
msgid "sending key %s to %s\n"
msgid "Note: signatures using the %s algorithm are rejected\n"
msgstr "Зауваження: підписи за допомогою алгоритму %s відкинуто\n"
-#, fuzzy, c-format
-#| msgid "%s:%u: read error: %s\n"
+#, c-format
msgid "(reported error: %s)\n"
-msgstr "%s:%u: помилка під час читання: %s\n"
+msgstr "(повідомлена помилка: %s)\n"
-#, fuzzy, c-format
-#| msgid "read error in '%s': %s\n"
+#, c-format
msgid "(reported error: %s <%s>)\n"
-msgstr "помилка читання у «%s»: %s\n"
+msgstr "(повідомлена помилка: %s <%s>)\n"
msgid "(further info: "
-msgstr ""
+msgstr "(подальша інформація: "
#, c-format
msgid "%s:%d: deprecated option \"%s\"\n"
msgstr ""
"Відкритий ключ ECDSA має зберігатися у кодуванні SEC кратному 8-бітовому\n"
-#, fuzzy, c-format
-#| msgid "Unknown signature type '%s'\n"
+#, c-format
msgid "unknown weak digest '%s'\n"
-msgstr "Ð\9dевÑ\96домий Ñ\82ип пÑ\96дпиÑ\81Ñ\83 «%s»\n"
+msgstr "невÑ\96дома Ñ\81лабка конÑ\82Ñ\80олÑ\8cна Ñ\81Ñ\83ма «%s»\n"
#, c-format
msgid "File '%s' exists. "
msgid "%s: skipped: public key already present\n"
msgstr "%s: пропущено: відкритий ключ вже існує\n"
-#, fuzzy, c-format
-#| msgid "can't connect to '%s': %s\n"
+#, c-format
msgid "can't encrypt to '%s'\n"
-msgstr "не вдалоÑ\81Ñ\8f вÑ\81Ñ\82ановиÑ\82и зâ\80\99Ñ\94днаннÑ\8f з «%s»: %s\n"
+msgstr "не вдалоÑ\81Ñ\8f заÑ\88иÑ\84Ñ\80Ñ\83ваÑ\82и до «%s»\n"
-#, fuzzy, c-format
-#| msgid "line %d: invalid date given\n"
+#, c-format
msgid "option '%s' given, but no valid default keys given\n"
-msgstr "рядок %d: вказано некоректну дату\n"
+msgstr "вказано параметр «%s», але не вказано коректних типових ключів\n"
-#, fuzzy, c-format
-#| msgid "line %d: invalid date given\n"
+#, c-format
msgid "option '%s' given, but option '%s' not given\n"
-msgstr "рядок %d: вказано некоректну дату\n"
+msgstr "вказано параметр «%s», але не вказано параметр «%s»\n"
msgid "You did not specify a user ID. (you may use \"-r\")\n"
msgstr ""
"declare that a key shall not anymore be used. It is not possible\n"
"to retract such a revocation certificate once it has been published."
msgstr ""
+"Сертифікат відкликання є своєрідним «апаратним вимикачем» для\n"
+"відкритого оголошення, що ключ не можна більше використовувати.\n"
+"Такий сертифікат відкликання не можна скасовувати після його\n"
+"оприлюднення."
-#, fuzzy
-#| msgid ""
-#| "Use it to revoke this key in case of a compromise or loss of\n"
-#| "the secret key. However, if the secret key is still accessible,\n"
-#| "it is better to generate a new revocation certificate and give\n"
-#| "a reason for the revocation."
msgid ""
"Use it to revoke this key in case of a compromise or loss of\n"
"the secret key. However, if the secret key is still accessible,\n"
"Скористайтеся цим для відкликання цього ключа у випадку його\n"
"компрометації або втрати закритої частини. Втім, якщо доступ до\n"
"закритого ключа не втрачено, краще створити новий сертифікат\n"
-"відкликання і вказати причину відкликання."
+"відкликання і вказати причину відкликання. Докладніший опис\n"
+"можна знайти у розділах підручника з GnuPG щодо команди\n"
+"gpg «--gen-revoke»."
-#, fuzzy
-#| msgid ""
-#| "To avoid an accidental use of this file, a colon has been inserted\n"
-#| "before the 5 dashes below. Remove this colon with a text editor\n"
-#| "before making use of this revocation certificate."
msgid ""
"To avoid an accidental use of this file, a colon has been inserted\n"
"before the 5 dashes below. Remove this colon with a text editor\n"
msgstr ""
"Щоб уникнути випадкового використання цього файла, перед п’ятьма\n"
"дефісами нижче додано двокрапку. Вилучіть цю двокрапку у текстовому\n"
-"редакторі, перш ніж скористатися цим сертифікатом відкликання."
+"редакторі, перш ніж імпортувати або оприлюднювати цей сертифікат\n"
+"відкликання."
-#, fuzzy, c-format
-#| msgid "Revocation certificate created.\n"
+#, c-format
msgid "revocation certificate stored as '%s.rev'\n"
-msgstr "Створено сертифікат відкликання.\n"
+msgstr "сертифікат відкликання збережено як «%s.rev»\n"
-#, fuzzy, c-format
-#| msgid "secret key \"%s\" not found: %s\n"
+#, c-format
msgid "secret key \"%s\" not found\n"
-msgstr "закритий ключ «%s» не знайдено: %s\n"
+msgstr "закритий ключ «%s» не знайдено\n"
#. TRANSLATORS: The %s prints a key specification which
#. for example has been given at the command line. Several lines
#. lines with secret key infos are printed after this message.
#, c-format
msgid "'%s' matches multiple secret keys:\n"
-msgstr ""
+msgstr "«%s» відповідає декільком закритим ключам:\n"
-#, fuzzy, c-format
-#| msgid "error creating keyring '%s': %s\n"
+#, c-format
msgid "error searching the keyring: %s\n"
-msgstr "помилка під час спроби створення сховища ключів «%s»: %s\n"
+msgstr "помилка під час спроби пошуку у сховищі ключів: %s\n"
msgid "Create a revocation certificate for this key? (y/N) "
msgstr "Створити сертифікат відкликання для цього ключа? (y/N або т/Н) "
msgstr ""
"УВАГА: підписування підключа %s містить некоректну перехресну сертифікацію\n"
-#, fuzzy, c-format
-#| msgid "public key %s is %lu second newer than the signature\n"
+#, c-format
msgid "public key %s is %lu second newer than the signature\n"
msgid_plural "public key %s is %lu seconds newer than the signature\n"
msgstr[0] "відкритий ключ %s є на %lu секунду новішим за підпис\n"
-msgstr[1] "відкритий ключ %s є на %lu секунду новішим за підпис\n"
-msgstr[2] "відкритий ключ %s є на %lu секунду новішим за підпис\n"
+msgstr[1] "відкритий ключ %s є на %lu секунди новішим за підпис\n"
+msgstr[2] "відкритий ключ %s є на %lu секунд новішим за підпис\n"
-#, fuzzy, c-format
-#| msgid "public key %s is %lu second newer than the signature\n"
+#, c-format
msgid "public key %s is %lu day newer than the signature\n"
msgid_plural "public key %s is %lu days newer than the signature\n"
-msgstr[0] "відкритий ключ %s є на %lu секунду новішим за підпис\n"
-msgstr[1] "відкритий ключ %s є на %lu секунду новішим за підпис\n"
-msgstr[2] "відкритий ключ %s є на %lu секунду новішим за підпис\n"
+msgstr[0] "відкритий ключ %s є на %lu день новішим за підпис\n"
+msgstr[1] "відкритий ключ %s є на %lu дні новішим за підпис\n"
+msgstr[2] "відкритий ключ %s є на %lu днів новішим за підпис\n"
-#, fuzzy, c-format
-#| msgid ""
-#| "key %s was created %lu second in the future (time warp or clock problem)\n"
+#, c-format
msgid ""
"key %s was created %lu second in the future (time warp or clock problem)\n"
msgid_plural ""
"ключ %s було створено з позначкою на %lu секунду у майбутньому (часова петля "
"або проблема з годинником)\n"
-#, fuzzy, c-format
-#| msgid ""
-#| "key %s was created %lu second in the future (time warp or clock problem)\n"
+#, c-format
msgid "key %s was created %lu day in the future (time warp or clock problem)\n"
msgid_plural ""
"key %s was created %lu days in the future (time warp or clock problem)\n"
msgstr[0] ""
-"ключ %s було створено з позначкою на %lu секунду у майбутньому (часова петля "
+"ключ %s було створено з позначкою на %lu день у майбутньому (часова петля "
"або проблема з годинником)\n"
msgstr[1] ""
-"ключ %s було створено з позначкою на %lu секунду у майбутньому (часова петля "
-"або пÑ\80облема з годинником)\n"
+"ключ %s було створено з позначкою на %lu дні у майбутньому (часова петля або "
+"проблема з годинником)\n"
msgstr[2] ""
-"ключ %s було створено з позначкою на %lu секунду у майбутньому (часова петля "
+"ключ %s було створено з позначкою на %lu днів у майбутньому (часова петля "
"або проблема з годинником)\n"
#, c-format
msgid "input line longer than %d characters\n"
msgstr "рядок вхідних даних довший за %d символів\n"
-#, fuzzy, c-format
-#| msgid "error sending standard options: %s\n"
+#, c-format
msgid "error beginning transaction on TOFU database: %s\n"
-msgstr "помилка під час спроби надсилання стандартних параметрів: %s\n"
+msgstr ""
+"помилка під час спроби розпочати внесення змін до бази даних TOFU: %s\n"
#, c-format
msgid "error committing transaction on TOFU database: %s\n"
-msgstr ""
+msgstr "помилка під час внесення змін до бази даних TOFU: %s\n"
#, c-format
msgid "error rolling back transaction on TOFU database: %s\n"
-msgstr ""
+msgstr "помилка під час скасовування змін у базі даних TOFU: %s\n"
-#, fuzzy, c-format
-#| msgid "unsupported algorithm: %s"
+#, c-format
msgid "unsupported TOFU database version: %s\n"
-msgstr "непÑ\96дÑ\82Ñ\80имÑ\83ваний алгоÑ\80иÑ\82м: %s"
+msgstr "непÑ\96дÑ\82Ñ\80имÑ\83вана веÑ\80Ñ\81Ñ\96Ñ\8f бази даниÑ\85 TOFU: %s\n"
-#, fuzzy, c-format
-#| msgid "error sending data: %s\n"
+#, c-format
msgid "error reading TOFU database: %s\n"
-msgstr "помилка під час спроби надсилання даних: %s\n"
+msgstr "помилка під час спроби читання бази даних TOFU: %s\n"
-#, fuzzy, c-format
-#| msgid "error writing base64 encoding: %s\n"
+#, c-format
msgid "error determining TOFU database's version: %s\n"
-msgstr "помилка пÑ\96д Ñ\87аÑ\81 Ñ\81пÑ\80оби запиÑ\81Ñ\83 Ñ\83 кодÑ\83ваннÑ\96 base64: %s\n"
+msgstr "помилка пÑ\96д Ñ\87аÑ\81 Ñ\81пÑ\80оби визнаÑ\87еннÑ\8f веÑ\80Ñ\81Ñ\96Ñ\97 бази даниÑ\85 TOFU: %s\n"
-#, fuzzy, c-format
-#| msgid "error initializing reader object: %s\n"
+#, c-format
msgid "error initializing TOFU database: %s\n"
-msgstr "помилка пÑ\96д Ñ\87аÑ\81 Ñ\81пÑ\80оби Ñ\96нÑ\96Ñ\86Ñ\96алÑ\96заÑ\86Ñ\96Ñ\97 обâ\80\99Ñ\94кÑ\82а Ñ\87иÑ\82аннÑ\8f: %s\n"
+msgstr "помилка пÑ\96д Ñ\87аÑ\81 Ñ\81пÑ\80оби Ñ\96нÑ\96Ñ\86Ñ\96алÑ\96заÑ\86Ñ\96Ñ\97 бази даниÑ\85 TOFU: %s\n"
-#, fuzzy, c-format
-#| msgid "error opening '%s': %s\n"
+#, c-format
msgid "error opening TOFU database '%s': %s\n"
-msgstr "помилка під час відкриття «%s»: %s\n"
+msgstr "помилка під час спроби відкрити бази даних TOFU «%s»: %s\n"
msgid "Warning: Home directory contains both tofu.db and tofu.d.\n"
msgstr ""
+"Попередження: у домашньому каталозі містяться як tofu.db, так і tofu.d.\n"
msgid "Using split format for TOFU database\n"
-msgstr ""
-
-#, fuzzy, c-format
-#| msgid "error sending data: %s\n"
-msgid "error updating TOFU database: %s\n"
-msgstr "помилка під час спроби надсилання даних: %s\n"
+msgstr "Використовуємо розділений формат для бази даних TOFU\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "відкритий ключ %s не знайдено: %s\n"
-
-#, fuzzy, c-format
-#| msgid "error setting OCSP target: %s\n"
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "помилка під час встановлення призначення за OCSP: %s\n"
+msgid "error updating TOFU database: %s\n"
+msgstr "помилка під час спроби оновлення бази даних TOFU: %s\n"
#, c-format
msgid "The binding %s is NOT known."
-msgstr ""
+msgstr "Прив’язка %s є невідомою."
#, c-format
msgid ""
"The key with fingerprint %s raised a conflict with the binding %s. Since "
"this binding's policy was 'auto', it was changed to 'ask'."
msgstr ""
+"Ключ із відбитком %s конфліктує із прив’язкою %s. Оскільки правилами цієї "
+"прив’язки визначалося «автоматично», їх змінено на «запитувати»."
#, c-format
msgid ""
"Please indicate whether you believe the binding %s%sis legitimate (the key "
"belongs to the stated owner) or a forgery (bad)."
msgstr ""
+"Будь ласка, вкажіть, чи вважаєте прив’язку %s%sчинною (ключ належить "
+"декларованому власнику) чи підробною (помилковою)."
-#, fuzzy, c-format
-#| msgid "error getting responder ID: %s\n"
+#, c-format
msgid "error gathering other user IDs: %s\n"
-msgstr "помилка під час спроби отримання ідентифікатора відповідача: %s\n"
+msgstr "помилка під час збирання інших ідентифікаторів користувачів: %s\n"
msgid "Known user IDs associated with this key:\n"
-msgstr ""
+msgstr "Відомі ідентифікатори користувачів, пов’язані із цим ключем:\n"
-#, fuzzy, c-format
-#| msgid "validity: %s"
+#, c-format
msgid "policy: %s"
-msgstr "чинність: %s"
+msgstr "правило: %s"
-#, fuzzy, c-format
-#| msgid "error getting stored flags: %s\n"
+#, c-format
msgid "error gathering signature stats: %s\n"
-msgstr "помилка під час спроби отримання збережених прапорців: %s\n"
+msgstr ""
+"помилка під час спроби зібрати статистичні дані щодо підписування: %s\n"
#, c-format
msgid "The email address \"%s\" is associated with %d key:\n"
msgid_plural "The email address \"%s\" is associated with %d keys:\n"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "Адресу електронної пошти «%s» пов’язано із %d ключем:\n"
+msgstr[1] "Адресу електронної пошти «%s» пов’язано із %d ключами:\n"
+msgstr[2] "Адресу електронної пошти «%s» пов’язано із %d ключами:\n"
#, c-format
msgid "Statistics for keys with the email address \"%s\":\n"
-msgstr ""
+msgstr "Статистичні дані для ключів із адресою електронної пошти «%s»:\n"
-#, fuzzy
-#| msgid "list keys"
msgid "this key"
-msgstr "показати список ключів"
+msgstr "цей ключ"
#, c-format
msgid "%ld message signed in the future."
msgid_plural "%ld messages signed in the future."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%ld повідомлення підписано у майбутньому."
+msgstr[1] "%ld повідомлення підписано у майбутньому."
+msgstr[2] "%ld повідомлень підписано у майбутньому."
-#, fuzzy, c-format
-#| msgid "print message digests"
+#, c-format
msgid "%ld message signed"
msgid_plural "%ld messages signed"
-msgstr[0] "показати контрольні суми повідомлень"
-msgstr[1] "показати контрольні суми повідомлень"
-msgstr[2] "показати контрольні суми повідомлень"
+msgstr[0] "підписано %ld повідомлення"
+msgstr[1] "підписано %ld повідомлення"
+msgstr[2] "підписано %ld повідомлень"
#, c-format
msgid " over the past %ld day."
msgid_plural " over the past %ld days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] " протягом %ld попереднього дня."
+msgstr[1] " протягом %ld попередніх днів."
+msgstr[2] " протягом %ld попередніх днів."
#, c-format
msgid " over the past %ld week."
msgid_plural " over the past %ld weeks."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] " протягом %ld попереднього тижня."
+msgstr[1] " протягом %ld попередніх тижнів."
+msgstr[2] " протягом %ld попередніх тижнів."
#, c-format
msgid " over the past %ld month."
msgid_plural " over the past %ld months."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] " протягом %ld попереднього місяця."
+msgstr[1] " протягом %ld попередніх місяців."
+msgstr[2] " протягом %ld попередніх місяців."
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
+"Зазвичай, з певною адресою електронної пошти пов’язано лише один ключ. Втім, "
+"іноді створюють новий ключ, коли, наприклад, ключ є надто застарілим або "
+"власник вважає, що ключ може бути скомпрометовано. Якщо ж таких обставин не "
+"передбачається, створення зайвого ключа може означати, що хтось намагається "
+"втрутитися і перехопити дані. Перш ніж приймати такий ключ, варто зв’язатися "
+"із власником і переконатися, що новий ключ є чинним."
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
-msgstr ""
+msgstr "gGaAuUrRbB"
msgid "(G)ood, (A)ccept once, (U)nknown, (R)eject once, (B)ad? "
msgstr ""
+"(G)Добрий, (A)Прийняти одноразово, (U)Невідомий, (R)Відкинути одноразово, "
+"(B)Поганий? "
-#, fuzzy, c-format
-#| msgid "error creating a pipe: %s\n"
+#, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr ""
+"помилка під час спроби встановлення рівня довіри до прив’язки TOFU до %s\n"
+
+#, c-format
msgid "error changing TOFU policy: %s\n"
-msgstr "помилка під час спроби створення каналу: %s\n"
+msgstr "помилка під час спроби змінити правила TOFU: %s\n"
#. TRANSLATORS: The tilde ('~') is used here to indicate a
#. * non-breakable space
#, c-format
msgid "%d~year"
msgid_plural "%d~years"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d~рік"
+msgstr[1] "%d~роки"
+msgstr[2] "%d~років"
#, c-format
msgid "%d~month"
msgid_plural "%d~months"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d~місяць"
+msgstr[1] "%d~місяці"
+msgstr[2] "%d~місяців"
#, c-format
msgid "%d~day"
msgid_plural "%d~days"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d~день"
+msgstr[1] "%d~дні"
+msgstr[2] "%d~днів"
#, c-format
msgid "%d~hour"
msgid_plural "%d~hours"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d~година"
+msgstr[1] "%d~години"
+msgstr[2] "%d~годин"
#, c-format
msgid "%d~minute"
msgid_plural "%d~minutes"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d~хвилина"
+msgstr[1] "%d~хвилини"
+msgstr[2] "%d~хвилин"
#, c-format
msgid "%d~second"
msgid_plural "%d~seconds"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d~секунда"
+msgstr[1] "%d~секунди"
+msgstr[2] "%d~секунд"
#, c-format
msgid "Have never verified a message signed by key %s!\n"
-msgstr ""
+msgstr "Ніколи не перевірялося повідомлення, підписане ключем %s!\n"
#, c-format
msgid ""
"Failed to collect signature statistics for \"%s\"\n"
"(key %s)\n"
msgstr ""
+"Не вдалося зібрати статистичні дані щодо підписування для «%s»\n"
+"(ключ %s)\n"
-#, fuzzy, c-format
-#| msgid "print message digests"
+#, c-format
msgid "Verified %ld messages signed by \"%s\"."
-msgstr "показаÑ\82и конÑ\82Ñ\80олÑ\8cнÑ\96 Ñ\81Ñ\83ми повÑ\96домленÑ\8c"
+msgstr "Ð\9fеÑ\80евÑ\96Ñ\80ено %ld повÑ\96домленÑ\8c, пÑ\96дпиÑ\81аниÑ\85 «%s»."
#, c-format
msgid ""
"Verified %ld messages signed by \"%s\"\n"
"in the past %s."
msgstr[0] ""
+"Перевірено %ld повідомлення, підписане «%s»,\n"
+"протягом такого строку: %s."
msgstr[1] ""
+"Перевірено %ld повідомлення, підписаних «%s»,\n"
+"протягом такого строку: %s."
msgstr[2] ""
+"Перевірено %ld повідомлень, підписаних «%s»,\n"
+"протягом такого строку: %s."
#, c-format
msgid "The most recent message was verified %s ago."
-msgstr ""
+msgstr "Останнє повідомлення було перевірено %s тому."
msgid "Warning: we've have yet to see a message signed by this key!\n"
-msgstr ""
+msgstr "Попередження: повідомлень, які було б підписано цим ключем, не було!\n"
msgid "Warning: we've only seen a single message signed by this key!\n"
-msgstr ""
+msgstr "Попередження: цим ключем було підписано лише одне повідомлення!\n"
#, c-format
msgid ""
" %s\n"
"to mark it as being bad.\n"
msgstr[0] ""
+"Попередження: якщо вам здається, що у вас було понад %ld повідомлення, "
+"підписане цим ключем, цей ключ може бути підробним! Уважно перевірте, чи "
+"точно вказано адресу електронної пошти. Якщо ключ є підозріливим, "
+"скористайтеся командою\n"
+" %s\n"
+"для позначення ключа як помилкового.\n"
msgstr[1] ""
+"Попередження: якщо вам здається, що у вас було понад %ld повідомлення, "
+"підписане цим ключем, цей ключ може бути підробним! Уважно перевірте, чи "
+"точно вказано адресу електронної пошти. Якщо ключ є підозріливим, "
+"скористайтеся командою\n"
+" %s\n"
+"для позначення ключа як помилкового.\n"
msgstr[2] ""
+"Попередження: якщо вам здається, що у вас було понад %ld повідомлень, "
+"підписане цим ключем, цей ключ може бути підробним! Уважно перевірте, чи "
+"точно вказано адресу електронної пошти. Якщо ключ є підозріливим, "
+"скористайтеся командою\n"
+" %s\n"
+"для позначення ключа як помилкового.\n"
-#, fuzzy, c-format
-#| msgid "error sending data: %s\n"
+#, c-format
msgid "error opening TOFU database: %s\n"
-msgstr "помилка пÑ\96д Ñ\87аÑ\81 Ñ\81пÑ\80оби надÑ\81иланнÑ\8f даниÑ\85: %s\n"
+msgstr "помилка пÑ\96д Ñ\87аÑ\81 Ñ\81пÑ\80оби вÑ\96дкÑ\80иÑ\82и бази даниÑ\85 TOFU: %s\n"
#, c-format
msgid "'%s' is not a valid long keyID\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "потреби у оновленні trustdb на основі моделі довіри «%s» немає\n"
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "відкритий ключ %s не знайдено: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "будь ласка, скористайтеся параметром --check-trustdb\n"
msgid "checking the trustdb\n"
msgstr "перевірка trustdb\n"
-#, fuzzy, c-format
-#| msgid "%lu keys processed so far\n"
+#, c-format
msgid "%d key processed"
msgid_plural "%d keys processed"
-msgstr[0] "оброблено %lu ключів\n"
-msgstr[1] "оброблено %lu ключів\n"
-msgstr[2] "оброблено %lu ключів\n"
+msgstr[0] "оброблено %d ключ"
+msgstr[1] "оброблено %d ключі"
+msgstr[2] "оброблено %d ключів"
-#, fuzzy, c-format
-#| msgid "%d keys processed (%d validity counts cleared)\n"
+#, c-format
msgid " (%d validity count cleared)\n"
msgid_plural " (%d validity counts cleared)\n"
-msgstr[0] "Оброблено %d ключів (очищено %d значень чинності)\n"
-msgstr[1] "Оброблено %d ключів (очищено %d значень чинності)\n"
-msgstr[2] "Оброблено %d ключів (очищено %d значень чинності)\n"
+msgstr[0] " (очищено %d значення чинності)\n"
+msgstr[1] " (очищено %d значення чинності)\n"
+msgstr[2] " (очищено %d значень чинності)\n"
msgid "no ultimately trusted keys found\n"
msgstr "не знайдено ключів з необмеженою довірою\n"
msgid "[ undef ]"
msgstr "[не визн.]"
+#, fuzzy
+#| msgid "never"
+msgid "[ never ]"
+msgstr "ніколи"
+
msgid "[marginal]"
msgstr "[неповна ]"
msgid "card is permanently locked!\n"
msgstr "картку заблоковано!\n"
-#, fuzzy, c-format
-#| msgid "%d Admin PIN attempts remaining before card is permanently locked\n"
+#, c-format
msgid "%d Admin PIN attempt remaining before card is permanently locked\n"
msgid_plural ""
"%d Admin PIN attempts remaining before card is permanently locked\n"
msgstr[0] ""
-"залиÑ\88илоÑ\81Ñ\8f %d Ñ\81пÑ\80об визначення адміністративного пінкоду перед тим, як "
+"залиÑ\88илаÑ\81Ñ\8f %d Ñ\81пÑ\80оба визначення адміністративного пінкоду перед тим, як "
"картку буде остаточно заблоковано\n"
msgstr[1] ""
-"залишилося %d спроб визначення адміністративного пінкоду перед тим, як "
+"залишилося %d спроби визначення адміністративного пінкоду перед тим, як "
"картку буде остаточно заблоковано\n"
msgstr[2] ""
"залишилося %d спроб визначення адміністративного пінкоду перед тим, як "
msgid "generating key failed\n"
msgstr "помилка під час створення ключа\n"
-#, fuzzy, c-format
-#| msgid "key generation completed (%d seconds)\n"
+#, c-format
msgid "key generation completed (%d second)\n"
msgid_plural "key generation completed (%d seconds)\n"
-msgstr[0] "створення ключа завершено (за %d секунд)\n"
-msgstr[1] "створення ключа завершено (за %d секунд)\n"
+msgstr[0] "створення ключа завершено (за %d секунду)\n"
+msgstr[1] "створення ключа завершено (за %d секунди)\n"
msgstr[2] "створення ключа завершено (за %d секунд)\n"
msgid "invalid structure of OpenPGP card (DO 0x93)\n"
msgid "do not allow the reuse of old passphrases"
msgstr "не дозволяти повторне використання старих паролів"
-#, fuzzy
-#| msgid "|N|set LDAP timeout to N seconds"
msgid "|N|set the Pinentry timeout to N seconds"
-msgstr "|N|встановити вказаний час очікування даних від LDAP"
+msgstr "|N|встановити вказаний час очікування Pinentry у секундах"
msgid "|NAME|use NAME as default secret key"
msgstr "|NAME|використовувати вказаний типовий закритий ключ"
msgstr "在‘%s’中寻找信任度记录时出错:%s\n"
#, fuzzy, c-format
+msgid "can't set permissions of '%s': %s\n"
+msgstr "警告:扩展模块‘%s’权限不安全\n"
+
+#, fuzzy, c-format
msgid "listen() failed: %s\n"
msgstr "更新失败:%s\n"
msgstr "已创建目录‘%s’\n"
#, fuzzy, c-format
-msgid "can't set permissions of '%s': %s\n"
-msgstr "警告:扩展模块‘%s’权限不安全\n"
-
-#, fuzzy, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "fstat(%d) 在 %s 中出错:%s\n"
msgid "export keys"
msgstr "导出密钥"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "把密钥导出到某个公钥服务器上"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "从公钥服务器上导入密钥"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "在公钥服务器上搜寻密钥"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|FD|把状态信息写入文件描述符 FD"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "用法:gpgv [选项] [文件] (用 -h 求助)"
msgid "No key with this keygrip\n"
msgstr "没有索引为 %d 的子钥\n"
+#, fuzzy, c-format
+#| msgid "rounded up to %u bits\n"
+msgid "rounded to %u bits\n"
+msgstr "舍入到 %u 位\n"
+
#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr "%s 密钥长度应在 %u 位与 %u 位之间。\n"
msgid "Requested keysize is %u bits\n"
msgstr "您所要求的密钥尺寸是 %u 位\n"
-#, fuzzy, c-format
-#| msgid "rounded up to %u bits\n"
-msgid "rounded to %u bits\n"
-msgstr "舍入到 %u 位\n"
-
#, fuzzy
#| msgid "Please select what kind of key you want:\n"
msgid "Please select which elliptic curve you want:\n"
msgstr "读取‘%s’时出错:%s\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "找不到公钥 %s:%s\n"
-
-#, fuzzy, c-format
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "读取‘%s’时出错:%s\n"
-
-#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[1] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "读取‘%s’时出错:%s\n"
+
+#, fuzzy, c-format
msgid "error changing TOFU policy: %s\n"
msgstr "生成密码的时候发生错误:%s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "使用‘%s’信任模型时不需要更新信任度数据库\n"
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "找不到公钥 %s:%s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "请执行一次 --check-trustdb\n"
msgid "[ undef ]"
msgstr "[未定义]"
+#, fuzzy
+#| msgid "never"
+msgid "[ never ]"
+msgstr "从不"
+
msgid "[marginal]"
msgstr "[ 勉强 ]"
msgid "error binding socket to '%s': %s\n"
msgstr "綁定 socket 至 '%s' 時出錯: %s\n"
+#, fuzzy, c-format
+#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
+msgid "can't set permissions of '%s': %s\n"
+msgstr "警告: %s 的權限 \"%s\" 並不安全\n"
+
#, c-format
msgid "listen() failed: %s\n"
msgstr "listen() 失敗: %s\n"
msgid "directory '%s' created\n"
msgstr "目錄 '%s' 已建立\n"
-#, fuzzy, c-format
-#| msgid "Warning: unsafe permissions on %s \"%s\"\n"
-msgid "can't set permissions of '%s': %s\n"
-msgstr "警告: %s 的權限 \"%s\" 並不安全\n"
-
#, c-format
msgid "stat() failed for '%s': %s\n"
msgstr "'%s' 的 stat() 失敗: %s\n"
msgid "export keys"
msgstr "匯出金鑰"
-msgid "export keys to a key server"
+msgid "export keys to a keyserver"
msgstr "把金鑰匯出至金鑰伺服器"
-msgid "import keys from a key server"
+msgid "import keys from a keyserver"
msgstr "從金鑰伺服器匯入金鑰"
-msgid "search for keys on a key server"
+msgid "search for keys on a keyserver"
msgstr "在金鑰伺服器上搜尋金鑰"
msgid "update all keys from a keyserver"
msgid "|FD|write status info to this FD"
msgstr "|檔案描述|把狀態資訊寫入此指定檔案描述"
+msgid "|ALGO|reject signatures made with ALGO"
+msgstr ""
+
msgid "Usage: gpgv [options] [files] (-h for help)"
msgstr "用法: gpgv [選項] [檔案] (或用 -h 求助)"
msgstr "沒有金鑰有此金鑰鑰柄\n"
#, c-format
+msgid "rounded to %u bits\n"
+msgstr "加大到 %u 位元\n"
+
+#, c-format
msgid "%s keys may be between %u and %u bits long.\n"
msgstr "%s 金鑰的長度可能介於 %u 位元和 %u 位元之間.\n"
msgid "Requested keysize is %u bits\n"
msgstr "你所要求的金鑰尺寸是 %u 位元\n"
-#, c-format
-msgid "rounded to %u bits\n"
-msgstr "加大到 %u 位元\n"
-
msgid "Please select which elliptic curve you want:\n"
msgstr "請選擇你要使用的橢圓曲線:\n"
msgstr "送出資料時出錯: %s\n"
#, c-format
-msgid "public key %s not found: %s\n"
-msgstr "找不到公鑰 %s: %s\n"
-
-#, fuzzy, c-format
-#| msgid "error setting OCSP target: %s\n"
-msgid "error setting TOFU binding's trust level to %s\n"
-msgstr "設定 OCSP 目標時出錯: %s\n"
-
-#, c-format
msgid "The binding %s is NOT known."
msgstr ""
msgstr[0] ""
#. TRANSLATORS: Please translate the text found in the source
-#. file below. We don't directly internationalize that text
-#. so that we can tweak it without breaking translations.
+#. * file below. We don't directly internationalize that text so
+#. * that we can tweak it without breaking translations.
msgid "TOFU detected a binding conflict"
msgstr ""
#. TRANSLATORS: Two letters (normally the lower and upper case
-#. version of the hotkey) for each of the five choices. If
-#. there is only one choice in your language, repeat it.
+#. * version of the hotkey) for each of the five choices. If
+#. * there is only one choice in your language, repeat it.
msgid "gGaAuUrRbB"
msgstr ""
msgstr ""
#, fuzzy, c-format
+#| msgid "error setting OCSP target: %s\n"
+msgid "error setting TOFU binding's trust level to %s\n"
+msgstr "設定 OCSP 目標時出錯: %s\n"
+
+#, fuzzy, c-format
#| msgid "error creating a pipe: %s\n"
msgid "error changing TOFU policy: %s\n"
msgstr "建立管道時出錯: %s\n"
msgid "no need for a trustdb update with '%s' trust model\n"
msgstr "在 '%s' 信任模型中並不需要更新信任資料庫\n"
+#, c-format
+msgid "public key %s not found: %s\n"
+msgstr "找不到公鑰 %s: %s\n"
+
msgid "please do a --check-trustdb\n"
msgstr "請做一次 --check-trustdb\n"
msgid "[ undef ]"
msgstr ""
+#, fuzzy
+#| msgid "never "
+msgid "[ never ]"
+msgstr "永遠不過期"
+
msgid "[marginal]"
msgstr ""
depends on how client sessions will associate the reader
status with their session. */
snprintf (templ, sizeof templ, "reader_%d.status", vr->slot);
- fname = make_filename (opt.homedir, templ, NULL );
+ fname = make_filename (gnupg_homedir (), templ, NULL );
fp = fopen (fname, "w");
if (fp)
{
char *homestr, *envstr;
gpg_error_t err;
- homestr = make_filename (opt.homedir, NULL);
+ homestr = make_filename (gnupg_homedir (), NULL);
if (gpgrt_asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
log_error ("out of core while building environment\n");
else
(status & 2)? "PRESENT": "NOCARD");
args[8] = NULL;
- fname = make_filename (opt.homedir, "scd-event", NULL);
+ fname = make_filename (gnupg_homedir (), "scd-event", NULL);
err = gnupg_spawn_process_detached (fname, args, envs);
if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
log_error ("failed to run event handler '%s': %s\n",
if (socket_name && *socket_name)
{
char *name;
- char *p;
name = redir_socket_name? redir_socket_name : socket_name;
gnupg_remove (name);
- p = strrchr (name, '/');
- if (p)
- {
- *p = 0;
- rmdir (name);
- *p = '/';
- }
*socket_name = 0;
}
}
if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
csh_style = 1;
- opt.homedir = default_homedir ();
-
/* Check whether we have a config file on the commandline */
orig_argc = argc;
orig_argv = argv;
else if (pargs.r_opt == oNoOptions)
default_config = 0; /* --no-options */
else if (pargs.r_opt == oHomedir)
- opt.homedir = pargs.r.ret_str;
+ gnupg_set_homedir (pargs.r.ret_str);
}
/* initialize the secure memory. */
if (default_config)
- configname = make_filename (opt.homedir, SCDAEMON_NAME EXTSEP_S "conf",
+ configname = make_filename (gnupg_homedir (), SCDAEMON_NAME EXTSEP_S "conf",
NULL );
case oNoGreeting: nogreeting = 1; break;
case oNoVerbose: opt.verbose = 0; break;
case oNoOptions: break; /* no-options */
- case oHomedir: opt.homedir = pargs.r.ret_str; break;
+ case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
case oNoDetach: nodetach = 1; break;
case oLogFile: logfile = pargs.r.ret_str; break;
case oCsh: csh_style = 1; break;
if (config_filename)
filename = xstrdup (config_filename);
else
- filename = make_filename (opt.homedir, SCDAEMON_NAME EXTSEP_S "conf",
- NULL);
+ filename = make_filename (gnupg_homedir (),
+ SCDAEMON_NAME EXTSEP_S "conf", NULL);
filename_esc = percent_escape (filename, NULL);
es_printf ("%s-%s.conf:%lu:\"%s\n",
{
char *name;
- name = make_filename (opt.homedir, standard_name, NULL);
+ name = make_filename (gnupg_socketdir (), standard_name, NULL);
if (strchr (name, PATHSEP_C))
{
log_error (("'%s' are not allowed in the socket name\n"), PATHSEP_S);
scd_exit (2);
}
+ if (gnupg_chmod (unaddr->sun_path, "-rwx"))
+ log_error (_("can't set permissions of '%s': %s\n"),
+ unaddr->sun_path, strerror (errno));
+
if (listen (FD2INT(fd), 5 ) == -1)
{
log_error (_("listen() failed: %s\n"),
int quiet; /* Be as quiet as possible. */
int dry_run; /* Don't change any persistent data. */
int batch; /* Batch mode. */
- const char *homedir; /* Configuration directory name. */
const char *ctapi_driver; /* Library to access the ctAPI. */
const char *pcsc_driver; /* Library to access the PC/SC system. */
const char *reader_port; /* NULL or reder port to use. */
{
rc = start_new_gpg_agent (&agent_ctx,
GPG_ERR_SOURCE_DEFAULT,
- opt.homedir,
opt.agent_program,
opt.lc_ctype, opt.lc_messages,
opt.session_env,
to take care of the implicit option sending caching. */
err = start_new_dirmngr (&ctx, GPG_ERR_SOURCE_DEFAULT,
- opt.homedir, opt.dirmngr_program,
+ opt.dirmngr_program,
opt.autostart, opt.verbose, DBG_IPC,
gpgsm_status2, ctrl);
if (!opt.autostart && gpg_err_code (err) == GPG_ERR_NO_DIRMNGR)
ARGPARSE_c (aKeygen, "gen-key", N_("generate a new key pair")),
ARGPARSE_c (aDeleteKey, "delete-keys",
N_("remove keys from the public keyring")),
-/*ARGPARSE_c (aSendKeys, "send-keys", N_("export keys to a key server")),*/
-/*ARGPARSE_c (aRecvKeys, "recv-keys", N_("import keys from a key server")),*/
+/*ARGPARSE_c (aSendKeys, "send-keys", N_("export keys to a keyserver")),*/
+/*ARGPARSE_c (aRecvKeys, "recv-keys", N_("import keys from a keyserver")),*/
ARGPARSE_c (aImport, "import", N_("import certificates")),
ARGPARSE_c (aExport, "export", N_("export certificates")),
break;
case 31: p = "\nHome: "; break;
- case 32: p = opt.homedir; break;
+ case 32: p = gnupg_homedir (); break;
case 33: p = _("\nSupported algorithms:\n"); break;
case 34:
if (!ciphers)
remember to update the Gpgconflist entry as well. */
opt.def_cipher_algoid = DEFAULT_CIPHER_ALGO;
- opt.homedir = default_homedir ();
-
/* First check whether we have a config file on the commandline */
orig_argc = argc;
opt.no_homedir_creation = 1;
}
else if (pargs.r_opt == oHomedir)
- opt.homedir = pargs.r.ret_str;
+ gnupg_set_homedir (pargs.r.ret_str);
else if (pargs.r_opt == aCallProtectTool)
break; /* This break makes sure that --version and --help are
passed to the protect-tool. */
/* Set the default option file */
if (default_config )
- configname = make_filename (opt.homedir, GPGSM_NAME EXTSEP_S "conf", NULL);
+ configname = make_filename (gnupg_homedir (),
+ GPGSM_NAME EXTSEP_S "conf", NULL);
/* Set the default policy file */
- opt.policy_file = make_filename (opt.homedir, "policies.txt", NULL);
+ opt.policy_file = make_filename (gnupg_homedir (), "policies.txt", NULL);
argc = orig_argc;
argv = orig_argv;
}
break;
case oNoOptions: opt.no_homedir_creation = 1; break; /* no-options */
- case oHomedir: opt.homedir = pargs.r.ret_str; break;
+ case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
case oDisplay:
configname = NULL;
if (!opt.config_filename)
- opt.config_filename = make_filename (opt.homedir,
+ opt.config_filename = make_filename (gnupg_homedir (),
GPGSM_NAME EXTSEP_S "conf",
NULL);
else if (!strcmp (opt.def_cipher_algoid, "AES")
|| !strcmp (opt.def_cipher_algoid, "AES128"))
opt.def_cipher_algoid = "2.16.840.1.101.3.4.1.2";
+ else if (!strcmp (opt.def_cipher_algoid, "AES192") )
+ opt.def_cipher_algoid = "2.16.840.1.101.3.4.1.22";
else if (!strcmp (opt.def_cipher_algoid, "AES256") )
opt.def_cipher_algoid = "2.16.840.1.101.3.4.1.42";
else if (!strcmp (opt.def_cipher_algoid, "SERPENT")
opt.def_cipher_algoid = "1.3.6.1.4.1.11591.13.2.2";
else if (!strcmp (opt.def_cipher_algoid, "SERPENT192") )
opt.def_cipher_algoid = "1.3.6.1.4.1.11591.13.2.22";
- else if (!strcmp (opt.def_cipher_algoid, "SERPENT192") )
+ else if (!strcmp (opt.def_cipher_algoid, "SERPENT256") )
opt.def_cipher_algoid = "1.3.6.1.4.1.11591.13.2.42";
else if (!strcmp (opt.def_cipher_algoid, "SEED") )
opt.def_cipher_algoid = "1.2.410.200004.1.4";
/* Set the random seed file. */
if (use_random_seed)
{
- char *p = make_filename (opt.homedir, "random_seed", NULL);
+ char *p = make_filename (gnupg_homedir (), "random_seed", NULL);
gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
xfree(p);
}
int dry_run; /* don't change any persistent data */
int no_homedir_creation;
- const char *homedir; /* Configuration directory name */
const char *config_filename; /* Name of the used config file. */
const char *agent_program;
if (strchr(resname, DIRSEP_C) )
filename = make_filename (resname, NULL);
else
- filename = make_filename (opt.homedir, resname, NULL);
+ filename = make_filename (gnupg_homedir (), resname, NULL);
}
else
filename = xstrdup (resname);
}
if (opt.verbose || opt.debug)
{
- char *tmp = NULL;
+ char *tmp;
/* Fixme: Use the really used socket name. */
if (asprintf (&tmp,
"Config: %s\n"
"DirmngrInfo: %s\n"
"%s",
- opt.homedir,
+ gnupg_homedir (),
opt.config_filename,
(dirmngr_user_socket_name ()
? dirmngr_user_socket_name ()
import.test ecc.test 4gb-packet.test \
$(sqlite3_dependent_tests) \
gpgtar.test use-exact-key.test default-key.test \
+ export.test \
finish.test
*.test.log gpg_dearmor gpg.conf gpg-agent.conf S.gpg-agent \
pubring.gpg pubring.gpg~ pubring.kbx pubring.kbx~ \
secring.gpg pubring.pkr secring.skr \
- gnupg-test.stop random_seed gpg-agent.log tofu.db
+ gnupg-test.stop random_seed gpg-agent.log tofu.db \
+ passphrases
clean-local:
-rm -rf private-keys-v1.d openpgp-revocs.d tofu.d gpgtar.d
--- /dev/null
+#!/bin/sh
+
+. $srcdir/defs.inc || exit 3
+
+check_exported_public_key()
+{
+ $GPG --list-packets $1 >$1.packets
+ grep '^:public key packet:' $1.packets >/dev/null
+ grep "^ keyid: .*$KEY$" $1.packets >/dev/null
+ grep '^:user ID packet:' $1.packets >/dev/null
+ grep "^:signature packet:.*keyid.*$KEY" $1.packets >/dev/null
+ rm $1.packets
+}
+
+check_armored_public_key()
+{
+ grep '^-----BEGIN PGP PUBLIC KEY BLOCK-----$' $1 >/dev/null
+ grep '^-----END PGP PUBLIC KEY BLOCK-----$' $1 >/dev/null
+ check_exported_public_key $1
+}
+
+check_exported_private_key()
+{
+ $GPG --list-packets $1 >$1.packets
+ grep '^:secret key packet:' $1.packets >/dev/null
+ grep "^ keyid: .*$KEY$" $1.packets >/dev/null
+ grep '^:user ID packet:' $1.packets >/dev/null
+ grep "^:signature packet:.*keyid.*$KEY" $1.packets >/dev/null
+ rm $1.packets
+}
+
+check_armored_private_key()
+{
+ grep '^-----BEGIN PGP PRIVATE KEY BLOCK-----$' $1 >/dev/null
+ grep '^-----END PGP PRIVATE KEY BLOCK-----$' $1 >/dev/null
+ check_exported_private_key $1
+}
+
+logfile="`pwd`/pinentry.log"
+ppfile="`pwd`/passphrases"
+rm -f -- $logfile $ppfile
+touch $ppfile
+
+prepare_passphrase()
+{
+ echo $* >>$ppfile
+}
+
+prepare_passphrase_confirm()
+{
+ echo "fake-entry being started to CONFIRM the weak phrase" >>$ppfile
+}
+
+assert_passphrases_consumed()
+{
+ if test -s $ppfile; then
+ echo "Expected $ppfile to be empty, but these are enqueued:" >&2
+ cat "$ppfile" >&2
+ exit 1
+ fi
+ rm -f -- $logfile
+}
+
+export PINENTRY_USER_DATA="--logfile=$logfile --passphrasefile=$ppfile"
+
+info "Checking key export."
+for KEY in D74C5F22 C40FDECF ECABF51D
+do
+ progress $KEY
+
+ $GPG --export $KEY >$KEY.public
+ check_exported_public_key $KEY.public
+ rm $KEY.public
+
+ $GPG --armor --export $KEY >$KEY.public
+ check_armored_public_key $KEY.public
+ rm $KEY.public
+
+ # test without --armor:
+
+ if [ $KEY = D74C5F22 ]; then
+ # Key D74C5F22 is protected by a passphrase. Prepare this
+ # one. Currently, GnuPG does not ask for an export passphrase
+ # in this case.
+ prepare_passphrase "$usrpass1"
+ fi
+
+ $GPG --export-secret-keys $KEY >$KEY.private
+ check_exported_private_key $KEY.private
+ rm $KEY.private
+
+ assert_passphrases_consumed
+
+ # test with --armor:
+
+ if [ $KEY = D74C5F22 ]; then
+ # Key D74C5F22 is protected by a passphrase. Prepare this
+ # one. Currently, GnuPG does not ask for an export passphrase
+ # in this case.
+ prepare_passphrase "$usrpass1"
+ fi
+
+ $GPG --armor --export-secret-keys $KEY >$KEY.private
+ check_armored_private_key $KEY.private
+ rm $KEY.private
+
+ assert_passphrases_consumed
+done
+
+progress_end
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <stdarg.h>
+
+FILE *log_stream;
+
+int
+reply (const char *fmt, ...)
+{
+ int result;
+ va_list ap;
+
+ if (log_stream)
+ {
+ fprintf (log_stream, "> ");
+ va_start (ap, fmt);
+ vfprintf (log_stream, fmt, ap);
+ va_end (ap);
+ }
+ va_start (ap, fmt);
+ result = vprintf (fmt, ap);
+ va_end (ap);
+
+ return result;
+}
+
+/* Return the first line from FNAME, removing it from the file. */
+char *
+get_passphrase (const char *fname)
+{
+ char *passphrase = NULL;
+ size_t fname_len;
+ char *fname_new;
+ FILE *source, *sink;
+ char linebuf[80];
+
+ fname_len = strlen (fname);
+ fname_new = malloc (fname_len + 5);
+ if (fname_new == NULL)
+ {
+ perror ("malloc");
+ exit (1);
+ }
+ snprintf (fname_new, fname_len + 5, "%s.new", fname);
+
+ source = fopen (fname, "r");
+ if (! source)
+ {
+ perror (fname);
+ exit (1);
+ }
+
+ sink = fopen (fname_new, "w");
+ if (! sink)
+ {
+ perror (fname_new);
+ exit (1);
+ }
+
+ while (fgets (linebuf, sizeof linebuf, source))
+ {
+ linebuf[sizeof linebuf - 1] = 0;
+ if (passphrase == NULL)
+ {
+ passphrase = strdup (linebuf);
+ if (passphrase == NULL)
+ {
+ perror ("strdup");
+ exit (1);
+ }
+ }
+ else
+ fputs (linebuf, sink);
+ }
+
+ if (ferror (source))
+ {
+ perror (fname);
+ exit (1);
+ }
+
+ if (ferror (sink))
+ {
+ perror (fname_new);
+ exit (1);
+ }
+
+ fclose (source);
+ fclose (sink);
+ rename (fname_new, fname);
+ return passphrase;
+}
+
+\f
+#define spacep(p) (*(p) == ' ' || *(p) == '\t')
+
+/* Skip over options in LINE.
+
+ Blanks after the options are also removed. Options are indicated
+ by two leading dashes followed by a string consisting of non-space
+ characters. The special option "--" indicates an explicit end of
+ options; all what follows will not be considered an option. The
+ first no-option string also indicates the end of option parsing. */
+char *
+skip_options (const char *line)
+{
+ while (spacep (line))
+ line++;
+ while (*line == '-' && line[1] == '-')
+ {
+ while (*line && !spacep (line))
+ line++;
+ while (spacep (line))
+ line++;
+ }
+ return (char*) line;
+}
+
+
+/* Return a pointer to the argument of the option with NAME. If such
+ an option is not given, NULL is returned. */
+char *
+option_value (const char *line, const char *name)
+{
+ char *s;
+ int n = strlen (name);
+
+ s = strstr (line, name);
+ if (s && s >= skip_options (line))
+ return NULL;
+ if (s && (s == line || spacep (s-1))
+ && s[n] && (spacep (s+n) || s[n] == '='))
+ {
+ s += n + 1;
+ s += strspn (s, " ");
+ if (*s && !spacep(s))
+ return s;
+ }
+ return NULL;
+}
int
main (int argc, char **argv)
{
- static char *passphrase;
- char *p;
+ char *args;
+ char *logfile;
+ char *passphrasefile;
+ char *passphrase;
+ /* We get our options via PINENTRY_USER_DATA. */
(void) argc, (void) argv;
setvbuf (stdin, NULL, _IOLBF, BUFSIZ);
setvbuf (stdout, NULL, _IOLBF, BUFSIZ);
- if (!passphrase)
+ args = getenv ("PINENTRY_USER_DATA");
+ if (! args)
+ args = "";
+
+ logfile = option_value (args, "--logfile");
+ if (logfile)
+ {
+ char *p = logfile, more;
+ while (*p && ! spacep (p))
+ p++;
+ more = !! *p;
+ *p = 0;
+ args = more ? p+1 : p;
+
+ log_stream = fopen (logfile, "a");
+ if (! log_stream)
+ {
+ perror (logfile);
+ return 1;
+ }
+ }
+
+ passphrasefile = option_value (args, "--passphrasefile");
+ if (passphrasefile)
{
- passphrase = getenv ("PINENTRY_USER_DATA");
- if (!passphrase)
- passphrase = "";
- for (p=passphrase; *p; p++)
- if (*p == '\r' || *p == '\n')
- *p = '.';
- printf ("# Passphrase='%s'\n", passphrase);
+ char *p = passphrasefile, more;
+ while (*p && ! spacep (p))
+ p++;
+ more = !! *p;
+ *p = 0;
+ args = more ? p+1 : p;
+
+ passphrase = get_passphrase (passphrasefile);
+ if (! passphrase)
+ {
+ reply ("# Passphrasefile '%s' is empty. Terminating.\n",
+ passphrasefile);
+ return 1;
+ }
+
+ p = passphrase + strlen (passphrase) - 1;
+ if (*p == '\n')
+ *p = 0;
}
+ else
+ passphrase = skip_options (args);
- printf ("OK - what's up?\n");
+ reply ("# fake-pinentry started. Passphrase='%s'.\n", passphrase);
+ reply ("OK - what's up?\n");
while (! feof (stdin))
{
if (fgets (buffer, sizeof buffer, stdin) == NULL)
break;
+ if (log_stream)
+ fprintf (log_stream, "< %s", buffer);
+
if (strncmp (buffer, "GETPIN", 6) == 0)
- printf ("D %s\nOK\n", passphrase);
+ reply ("D %s\n", passphrase);
else if (strncmp (buffer, "BYE", 3) == 0)
{
- printf ("OK\n");
+ reply ("OK\n");
break;
}
- else
- printf ("OK\n");
+
+ reply ("OK\n");
}
+
+ reply ("# Connection terminated.\n");
+ if (log_stream)
+ fclose (log_stream);
+
return 0;
}
# along with this program; if not, see <http://www.gnu.org/licenses/>.
EXTRA_DIST = \
- Manifest watchgnupg.c \
+ Manifest watchgnupg.c no-libgcrypt.c \
addgnupghome applygnupgdefaults \
lspgpot mail-signed-keys convert-from-106 sockprox.c \
ccidmon.c ChangeLog-2011 gpg-connect-agent-w32info.rc
$(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \
$(ZLIBS) $(LIBINTL) $(NETLIBS) $(LIBICONV)
-gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c
+gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c
# common sucks in gpg-error, will they, nil they (some compilers
# do not eliminate the supposed-to-be-unused-inline-functions).
gpgconf_LDADD = $(maybe_commonpth_libs) $(opt_libassuan_libs) \
- $(LIBINTL) $(GPG_ERROR_LIBS) $(NETLIBS) \
+ $(LIBINTL) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
$(LIBICONV) $(W32SOCKLIBS)
gpgconf_LDFLAGS = $(extra_bin_ldflags)
watchgnupg_SOURCES = watchgnupg.c
watchgnupg_LDADD = $(NETLIBS)
-gpg_connect_agent_SOURCES = gpg-connect-agent.c no-libgcrypt.c
-# FIXME: remove PTH_LIBS (why do we need them at all?)
+gpg_connect_agent_SOURCES = gpg-connect-agent.c
+# FIXME: remove NPTH_LIBS (why do we need them at all?)
gpg_connect_agent_LDADD = ../common/libgpgrl.a $(common_libs) \
- $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBASSUAN_LIBS) $(LIBGCRYPT_LIBS) \
+ $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
$(LIBREADLINE) $(LIBINTL) $(NETLIBS) $(LIBICONV) \
$(resource_objs)
gpgtar.c gpgtar.h \
gpgtar-create.c \
gpgtar-extract.c \
- gpgtar-list.c \
- no-libgcrypt.c
+ gpgtar-list.c
gpgtar_CFLAGS = $(GPG_ERROR_CFLAGS)
-gpgtar_LDADD = $(libcommon) $(GPG_ERROR_LIBS) \
+gpgtar_LDADD = $(libcommon) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \
$(LIBINTL) $(NETLIBS) $(LIBICONV) $(W32SOCKLIBS)
setup_libgcrypt_logging ();
gcry_control (GCRYCTL_INIT_SECMEM, 4096, 0);
- opt.homedir = default_homedir ();
-
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1; /* (do not remove the args) */
switch (pargs.r_opt)
{
case oVerbose: opt.verbose++; break;
- case oHomedir: opt.homedir = pargs.r.ret_str; break;
+ case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
case oCheck: opt.checkonly = 1; break;
case oNull: opt.null = 1; break;
"Connect to a running agent and send commands\n");
break;
case 31: p = "\nHome: "; break;
- case 32: p = opt.homedir; break;
+ case 32: p = gnupg_homedir (); break;
case 33: p = "\n"; break;
default: p = NULL; break;
log_error ("getcwd failed: %s\n", strerror (errno));
}
else if (!strcmp (s, "homedir"))
- result = make_filename (opt.homedir, NULL);
+ result = xstrdup (gnupg_homedir ());
else if (!strcmp (s, "sysconfdir"))
result = xstrdup (gnupg_sysconfdir ());
else if (!strcmp (s, "bindir"))
assuan_set_gpg_err_source (0);
- opt.homedir = default_homedir ();
opt.autostart = 1;
opt.connect_flags = 1;
case oQuiet: opt.quiet = 1; break;
case oVerbose: opt.verbose++; break;
case oNoVerbose: opt.verbose = 0; break;
- case oHomedir: opt.homedir = pargs.r.ret_str; break;
+ case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break;
case oNoAutostart: opt.autostart = 0; break;
in particular handy on Windows. */
if (opt.use_uiserver)
{
- opt.raw_socket = make_absfilename (opt.homedir, "S.uiserver", NULL);
+ opt.raw_socket = make_absfilename (gnupg_homedir (), "S.uiserver", NULL);
}
/* Print a warning if an argument looks like an option. */
if (opt.use_dirmngr)
err = start_new_dirmngr (&ctx,
GPG_ERR_SOURCE_DEFAULT,
- opt.homedir,
opt.dirmngr_program,
opt.autostart,
!opt.quiet, 0,
else
err = start_new_gpg_agent (&ctx,
GPG_ERR_SOURCE_DEFAULT,
- opt.homedir,
opt.agent_program,
NULL, NULL,
session_env,
result = 0;
errlines = NULL;
- err = gnupg_spawn_process (pgmname, argv, GPG_ERR_SOURCE_DEFAULT, NULL, 0,
+ err = gnupg_spawn_process (pgmname, argv, NULL, NULL, 0,
NULL, NULL, &errfp, &pid);
if (err)
result |= 1; /* Program could not be run. */
argv[0] = "--gpgconf-list";
argv[1] = NULL;
- err = gnupg_spawn_process (pgmname, argv, GPG_ERR_SOURCE_DEFAULT, NULL, 0,
+ err = gnupg_spawn_process (pgmname, argv, NULL, NULL, 0,
NULL, &outfp, NULL, &pid);
if (err)
{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "gpgconf.h"
#include "i18n.h"
aListDirs,
aLaunch,
aKill,
+ aCreateSocketDir,
+ aRemoveSocketDir,
aReload
};
{ aReload, "reload", 256, N_("reload all or a given component")},
{ aLaunch, "launch", 256, N_("launch a given component")},
{ aKill, "kill", 256, N_("kill a given component")},
+ { aCreateSocketDir, "create-socketdir", 256, "@"},
+ { aRemoveSocketDir, "remove-socketdir", 256, "@"},
{ 301, NULL, 0, N_("@\nOptions:\n ") },
{ oDryRun, "dry-run", 0, N_("do not make any changes") },
{ oRuntime, "runtime", 0, N_("activate changes at runtime, if possible") },
/* hidden options */
+ { oHomedir, "homedir", 2, "@" },
{ oNoVerbose, "no-verbose", 0, "@"},
{0}
};
break;
case oVerbose: opt.verbose++; break;
case oNoVerbose: opt.verbose = 0; break;
+ case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
case aListDirs:
case aListComponents:
case aReload:
case aLaunch:
case aKill:
+ case aCreateSocketDir:
+ case aRemoveSocketDir:
cmd = pargs.r_opt;
break;
}
{
- char *tmp = make_filename (default_homedir (),
+ char *tmp = make_filename (gnupg_socketdir (),
GPG_AGENT_SOCK_NAME, NULL);
es_fprintf (outfp, "agent-socket:%s\n", gc_percent_escape (tmp));
xfree (tmp);
}
{
- /* We need to use make_filename to expand a possible "~/". */
- char *tmp = make_filename (default_homedir (), NULL);
+ char *tmp = xstrdup (gnupg_homedir ());
es_fprintf (outfp, "homedir:%s\n", gc_percent_escape (tmp));
xfree (tmp);
}
break;
+
+ case aCreateSocketDir:
+ {
+ char *socketdir;
+ unsigned int flags;
+
+ /* Make sure that the top /run/user/UID/gnupg dir has been
+ * created. */
+ gnupg_socketdir ();
+
+ /* Check the /var/run dir. */
+ socketdir = _gnupg_socketdir_internal (1, &flags);
+ if ((flags & 64) && !opt.dry_run)
+ {
+ /* No sub dir - create it. */
+ if (gnupg_mkdir (socketdir, "-rwx"))
+ gc_error (1, errno, "error creating '%s'", socketdir);
+ /* Try again. */
+ socketdir = _gnupg_socketdir_internal (1, &flags);
+ }
+
+ /* Give some info. */
+ if ( (flags & ~32) || opt.verbose || opt.dry_run)
+ {
+ log_info ("socketdir is '%s'\n", socketdir);
+ if ((flags & 1)) log_info ("\tgeneral error\n");
+ if ((flags & 2)) log_info ("\tno /run/user dir\n");
+ if ((flags & 4)) log_info ("\tbad permissions\n");
+ if ((flags & 8)) log_info ("\tbad permissions (subdir)\n");
+ if ((flags & 16)) log_info ("\tmkdir failed\n");
+ if ((flags & 32)) log_info ("\tnon-default homedir\n");
+ if ((flags & 64)) log_info ("\tno such subdir\n");
+ if ((flags & 128)) log_info ("\tusing homedir as fallback\n");
+ }
+
+ if ((flags & ~32) && !opt.dry_run)
+ gc_error (1, 0, "error creating socket directory");
+
+ xfree (socketdir);
+ }
+ break;
+
+ case aRemoveSocketDir:
+ {
+ char *socketdir;
+ unsigned int flags;
+
+ /* Check the /var/run dir. */
+ socketdir = _gnupg_socketdir_internal (1, &flags);
+ if ((flags & 128))
+ log_info ("ignoring request to remove non /run/user socket dir\n");
+ else if (opt.dry_run)
+ ;
+ else if (rmdir (socketdir))
+ gc_error (1, errno, "error removing '%s'", socketdir);
+
+ xfree (socketdir);
+ }
+ break;
+
}
if (outfp != es_stdout)
#include "i18n.h"
#include "../common/exectool.h"
#include "../common/sysutils.h"
+#include "../common/ccparray.h"
#include "gpgtar.h"
#ifndef HAVE_LSTAT
if (encrypt || sign)
{
- int i;
strlist_t arg;
+ ccparray_t ccp;
const char **argv;
err = es_fseek (outstream, 0, SEEK_SET);
/* '--encrypt' may be combined with '--symmetric', but 'encrypt'
is set either way. Clear it if no recipients are specified.
XXX: Fix command handling. */
- if (opt.symmetric && opt.recipients == NULL)
- encrypt = 0;
-
- argv = xtrycalloc (strlist_length (opt.gpg_arguments)
- + 2 * strlist_length (opt.recipients)
- + 1 + !!encrypt + !!sign + 2 * !!opt.user
- + !!opt.symmetric,
- sizeof *argv);
- if (argv == NULL)
- {
- err = gpg_error_from_syserror ();
- goto leave;
- }
- i = 0;
+ if (opt.symmetric && opt.recipients == NULL)
+ encrypt = 0;
+
+ ccparray_init (&ccp, 0);
if (encrypt)
- argv[i++] = "--encrypt";
+ ccparray_put (&ccp, "--encrypt");
if (sign)
- argv[i++] = "--sign";
+ ccparray_put (&ccp, "--sign");
if (opt.user)
{
- argv[i++] = "--local-user";
- argv[i++] = opt.user;
+ ccparray_put (&ccp, "--local-user");
+ ccparray_put (&ccp, opt.user);
}
if (opt.symmetric)
- argv[i++] = "--symmetric";
+ ccparray_put (&ccp, "--symmetric");
for (arg = opt.recipients; arg; arg = arg->next)
{
- argv[i++] = "--recipient";
- argv[i++] = arg->d;
+ ccparray_put (&ccp, "--recipient");
+ ccparray_put (&ccp, arg->d);
}
for (arg = opt.gpg_arguments; arg; arg = arg->next)
- argv[i++] = arg->d;
- argv[i++] = NULL;
- assert (i == strlist_length (opt.gpg_arguments)
- + 2 * strlist_length (opt.recipients)
- + 1 + !!encrypt + !!sign + 2 * !!opt.user
- + !!opt.symmetric);
+ ccparray_put (&ccp, arg->d);
+
+ ccparray_put (&ccp, NULL);
+ argv = ccparray_get (&ccp, NULL);
+ if (!argv)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
err = gnupg_exec_tool_stream (opt.gpg_program, argv,
- outstream, cipher_stream);
+ outstream, NULL, cipher_stream, NULL, NULL);
xfree (argv);
if (err)
goto leave;
#include "i18n.h"
#include "../common/exectool.h"
#include "../common/sysutils.h"
+#include "../common/ccparray.h"
#include "gpgtar.h"
if (decrypt)
{
- int i;
strlist_t arg;
+ ccparray_t ccp;
const char **argv;
cipher_stream = stream;
goto leave;
}
- argv = xtrycalloc (strlist_length (opt.gpg_arguments) + 2,
- sizeof *argv);
- if (argv == NULL)
+ ccparray_init (&ccp, 0);
+
+ ccparray_put (&ccp, "--decrypt");
+ for (arg = opt.gpg_arguments; arg; arg = arg->next)
+ ccparray_put (&ccp, arg->d);
+
+ ccparray_put (&ccp, NULL);
+ argv = ccparray_get (&ccp, NULL);
+ if (!argv)
{
err = gpg_error_from_syserror ();
goto leave;
}
- i = 0;
- argv[i++] = "--decrypt";
- for (arg = opt.gpg_arguments; arg; arg = arg->next)
- argv[i++] = arg->d;
- argv[i++] = NULL;
- assert (i == strlist_length (opt.gpg_arguments) + 2);
err = gnupg_exec_tool_stream (opt.gpg_program, argv,
- cipher_stream, stream);
+ cipher_stream, NULL, stream, NULL, NULL);
xfree (argv);
if (err)
goto leave;
#include "i18n.h"
#include "gpgtar.h"
#include "../common/exectool.h"
+#include "../common/ccparray.h"
\f
if (decrypt)
{
- int i;
strlist_t arg;
+ ccparray_t ccp;
const char **argv;
cipher_stream = stream;
goto leave;
}
- argv = xtrycalloc (strlist_length (opt.gpg_arguments) + 2,
- sizeof *argv);
- if (argv == NULL)
+ ccparray_init (&ccp, 0);
+
+ ccparray_put (&ccp, "--decrypt");
+ for (arg = opt.gpg_arguments; arg; arg = arg->next)
+ ccparray_put (&ccp, arg->d);
+
+ ccparray_put (&ccp, NULL);
+ argv = ccparray_get (&ccp, NULL);
+ if (!argv)
{
err = gpg_error_from_syserror ();
goto leave;
}
- i = 0;
- argv[i++] = "--decrypt";
- for (arg = opt.gpg_arguments; arg; arg = arg->next)
- argv[i++] = arg->d;
- argv[i++] = NULL;
- assert (i == strlist_length (opt.gpg_arguments) + 2);
err = gnupg_exec_tool_stream (opt.gpg_program, argv,
- cipher_stream, stream);
+ cipher_stream, NULL, stream, NULL, NULL);
xfree (argv);
if (err)
goto leave;
{
rfc822parse_field_t ctx;
part_t save_part; /* ugly hack - we should have a function to
- get part inforation. */
+ get part information. */
const char *s;
save_part = msg->current_part;
case RFC822PARSE_T2BODY: s= "T2Body"; break;
case RFC822PARSE_FINISH: s= "Finish"; break;
case RFC822PARSE_RCVD_SEEN: s= "Rcvd_Seen"; break;
+ case RFC822PARSE_LEVEL_DOWN: s= "Level_Down"; break;
+ case RFC822PARSE_LEVEL_UP: s= "Level_Up"; break;
case RFC822PARSE_BOUNDARY: s= "Boundary"; break;
case RFC822PARSE_LAST_BOUNDARY: s= "Last_Boundary"; break;
+ case RFC822PARSE_BEGIN_HEADER: s= "Begin_Header"; break;
+ case RFC822PARSE_PREAMBLE: s= "Preamble"; break;
+ case RFC822PARSE_EPILOGUE: s= "Epilogue"; break;
default: s= "***invalid event***"; break;
}
printf ("*** got RFC822 event %s\n", s);
"Call a simple symmetric encryption tool\n");
break;
case 31: p = "\nHome: "; break;
- case 32: p = opt.homedir; break;
+ case 32: p = gnupg_homedir (); break;
case 33: p = "\n"; break;
default: p = NULL; break;
i18n_init();
init_common_subsystems (&argc, &argv);
- opt.homedir = default_homedir ();
-
/* Check whether we have a config file given on the commandline */
orig_argc = argc;
orig_argv = argv;
else if (pargs.r_opt == oNoOptions)
default_config = 0; /* --no-options */
else if (pargs.r_opt == oHomedir)
- opt.homedir = pargs.r.ret_str;
+ gnupg_set_homedir (pargs.r.ret_str);
}
if (default_config)
- configname = make_filename (opt.homedir, "symcryptrun.conf", NULL );
+ configname = make_filename (gnupg_homedir (), "symcryptrun.conf", NULL );
argc = orig_argc;
argv = orig_argv;
/* Tell simple-pwquery about the the standard socket name. */
{
- char *tmp = make_filename (opt.homedir, GPG_AGENT_SOCK_NAME, NULL);
+ char *tmp = make_filename (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
simple_pw_set_socket (tmp);
xfree (tmp);
}