+Noteworthy changes in version 2.2.10 (2018-08-30)
+-------------------------------------------------
+
+ gpg: Refresh expired keys originating from the WKD. [#2917]
+
+ gpg: Use a 256 KiB limit for a WKD imported key.
+
+ gpg: New option --known-notation. [#4060]
+
+ scd: Add support for the Trustica Cryptoucan reader.
+
+ agent: Speed up starting during on-demand launching. [#3490]
+
+ dirmngr: Validate SRV records in WKD queries.
+
+ Release-info: https://dev.gnupg.org/T4112
+ See-also: gnupg-announce/2018q3/000428.html
+
+
Noteworthy changes in version 2.2.9 (2018-07-12)
------------------------------------------------
* gpg: New "usage" property for the drop-subkey filters. [#4019]
Release-info: https://dev.gnupg.org/T4036
-
See-also: gnupg-announce/2018q3/000427.html
}
}
+static gpg_error_t
+wait_for_sock (int secs, const char *name, const char *sockname, int verbose, assuan_context_t ctx, int *did_success_msg)
+{
+ gpg_error_t err = 0;
+ int target_us = secs * 1000000;
+ int elapsed_us = 0;
+ /*
+ * 977us * 1024 = just a little more than 1s.
+ * so we will double this timeout 10 times in the first
+ * second, and then switch over to 1s checkins.
+ */
+ int next_sleep_us = 977;
+ int lastalert = secs+1;
+ int secsleft;
+
+ while (elapsed_us < target_us)
+ {
+ if (verbose)
+ {
+ secsleft = (target_us - elapsed_us + 999999)/1000000;
+ /* log_clock ("left=%d last=%d targ=%d elap=%d next=%d\n", */
+ /* secsleft, lastalert, target_us, elapsed_us, */
+ /* next_sleep_us); */
+ if (secsleft < lastalert)
+ {
+ log_info (_("waiting for the %s to come up ... (%ds)\n"),
+ name, secsleft);
+ lastalert = secsleft;
+ }
+ }
+ gnupg_usleep (next_sleep_us);
+ elapsed_us += next_sleep_us;
+ err = assuan_socket_connect (ctx, sockname, 0, 0);
+ if (!err)
+ {
+ if (verbose)
+ {
+ log_info (_("connection to %s established\n"),
+ name);
+ *did_success_msg = 1;
+ }
+ break;
+ }
+ next_sleep_us *= 2;
+ if (next_sleep_us > 1000000)
+ next_sleep_us = 1000000;
+ }
+ return err;
+}
+
/* Try to connect to the agent via socket or start it if it is not
running and AUTOSTART is set. Handle the server's initial
greeting. Returns a new assuan context at R_CTX or an error
log_error ("failed to start agent '%s': %s\n",
agent_program, gpg_strerror (err));
else
- {
- for (i=0; i < SECS_TO_WAIT_FOR_AGENT; i++)
- {
- if (verbose)
- log_info (_("waiting for the agent to come up ... (%ds)\n"),
- SECS_TO_WAIT_FOR_AGENT - i);
- gnupg_sleep (1);
- err = assuan_socket_connect (ctx, sockname, 0, 0);
- if (!err)
- {
- if (verbose)
- {
- log_info (_("connection to agent established\n"));
- did_success_msg = 1;
- }
- break;
- }
- }
- }
+ err = wait_for_sock (SECS_TO_WAIT_FOR_AGENT, "agent",
+ sockname, verbose, ctx, &did_success_msg);
}
unlock_spawning (&lock, "agent");
log_error ("failed to start the dirmngr '%s': %s\n",
dirmngr_program, gpg_strerror (err));
else
- {
- int i;
-
- for (i=0; i < SECS_TO_WAIT_FOR_DIRMNGR; i++)
- {
- if (verbose)
- log_info (_("waiting for the dirmngr "
- "to come up ... (%ds)\n"),
- SECS_TO_WAIT_FOR_DIRMNGR - i);
- gnupg_sleep (1);
- err = assuan_socket_connect (ctx, sockname, 0, 0);
- if (!err)
- {
- if (verbose)
- {
- log_info (_("connection to the dirmngr"
- " established\n"));
- did_success_msg = 1;
- }
- break;
- }
- }
- }
+ err = wait_for_sock (SECS_TO_WAIT_FOR_DIRMNGR, "dirmngr",
+ sockname, verbose, ctx, &did_success_msg);
}
unlock_spawning (&lock, "dirmngr");
return 1;
}
+
+
+/* Returns true if STRING is a valid domain name according to the LDH
+ * rule. */
+int
+is_valid_domain_name (const char *string)
+{
+ static char const ldh_chars[] =
+ "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-";
+ const char *s;
+
+ /* Note that we do not check the length limit of a label or the
+ * entire name */
+
+ for (s=string; *s; s++)
+ if (*s == '.')
+ {
+ if (string == s)
+ return 0; /* Dot at the start of the string. */
+ /* (may also be at the end like in ".") */
+ if (s[1] == '.')
+ return 0; /* No - double dot. */
+ }
+ else if (!strchr (ldh_chars, *s))
+ return 0;
+ else if (*s == '-')
+ {
+ if (string == s)
+ return 0; /* Leading hyphen. */
+ if (s[-1] == '.')
+ return 0; /* Hyphen at begin of a label. */
+ if (s[1] == '.')
+ return 0; /* Hyphen at start of a label. */
+ if (!s[1])
+ return 0; /* Trailing hyphen. */
+ }
+
+ return !!*string;
+}
int is_valid_mailbox_mem (const void *buffer, size_t length);
char *mailbox_from_userid (const char *userid);
int is_valid_user_id (const char *uid);
+int is_valid_domain_name (const char *string);
#endif /*GNUPG_COMMON_MBOX_UTIL_H*/
struct timespec req;
struct timespec rem;
- req.tv_sec = 0;
- req.tv_nsec = usecs * 1000;
-
+ req.tv_sec = usecs / 1000000;
+ req.tv_nsec = (usecs % 1000000) * 1000;
while (nanosleep (&req, &rem) < 0 && errno == EINTR)
- req = rem;
+ req = rem;
}
#else /*Standard Unix*/
static void
-run_test (void)
+run_mbox_test (void)
{
static struct
{
}
+static void
+run_dns_test (void)
+{
+ static struct
+ {
+ const char *name;
+ int valid;
+ } testtbl[] =
+ {
+ { "", 0 },
+ { ".", 0 },
+ { "-", 0 },
+ { "a", 1 },
+ { "ab", 1 },
+ { "a.b", 1 },
+ { "a.b.", 1 },
+ { ".a.b.", 0 },
+ { ".a.b", 0 },
+ { "-a.b", 0 },
+ { "a-.b", 0 },
+ { "a.-b", 0 },
+ { "a.b-", 0 },
+ { "a.b-.", 0 },
+ { "a..b", 0 },
+ { "ab.c", 1 },
+ { "a-b.c", 1 },
+ { "a-b-.c", 0 },
+ { "-a-b.c", 0 },
+ { "example.org", 1 },
+ { "x.example.org", 1 },
+ { "xy.example.org", 1 },
+ { "Xy.example.org", 1 },
+ { "-Xy.example.org", 0 },
+ { "Xy.example-.org", 0 },
+ { "foo.example.org..", 0 },
+ { "foo.example.org.", 1 },
+ { ".foo.example.org.", 0 },
+ { "..foo.example.org.", 0 },
+ { NULL, 0 }
+ };
+ int idx;
+
+ for (idx=0; testtbl[idx].name; idx++)
+ {
+ if (is_valid_domain_name (testtbl[idx].name) != testtbl[idx].valid)
+ fail (idx);
+ }
+}
+
+
int
main (int argc, char **argv)
{
(void)argc;
(void)argv;
- run_test ();
+ run_mbox_test ();
+ run_dns_test ();
return 0;
}
m4_define([mym4_package],[gnupg])
m4_define([mym4_major], [2])
m4_define([mym4_minor], [2])
-m4_define([mym4_micro], [9])
+m4_define([mym4_micro], [10])
# 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
current_logfile = xstrdup (logfile);
}
+ if (debug_wait)
+ {
+ log_debug ("waiting for debugger - my pid is %u .....\n",
+ (unsigned int)getpid());
+ gnupg_sleep (debug_wait);
+ log_debug ("... okay\n");
+ }
+
#ifndef HAVE_W32_SYSTEM
if (strchr (socket_name, ':'))
{
if (err)
goto leave;
+ /* Check for rogue DNS names. */
+ for (i = 0; i < srvscount; i++)
+ {
+ if (!is_valid_domain_name (srvs[i].target))
+ {
+ err = gpg_error (GPG_ERR_DNS_ADDRESS);
+ log_error ("rogue openpgpkey SRV record for '%s'\n", domain);
+ xfree (srvs);
+ goto leave;
+ }
+ }
+
/* Find the first target which also ends in DOMAIN or is equal
* to DOMAIN. */
domainlen = strlen (domain);
for it. To create a key without any protection @code{--passphrase ''}
may be used.
+Note that it is possible to create a primary key and a subkey using
+non-default algorithms by using ``default'' and changing the default
+parameters using the option @option{--default-new-key-algo}.
+
@item --quick-set-expire @var{fpr} @var{expire} [*|@var{subfprs}]
@opindex quick-set-expire
With two arguments given, directly set the expiration time of the
with the default key length; a string ``rsa4096'' requests that the
key length is 4096 bits. The string ``future-default'' is an alias
for the algorithm which will likely be used as default algorithm in
-future versions of gpg.
+future versions of gpg. To list the supported ECC curves the command
+@code{gpg --with-colons --list-config curve} can be used.
Depending on the given @var{algo} the subkey may either be an
encryption subkey or a signing subkey. If an algorithm is capable of
meaningful when making a key signature (certification), and %c is only
meaningful when using the OpenPGP smartcard.
+@item --known-notation @var{name}
+@opindex known-notation
+Adds @var{name} to a list of known critical signature notations. The
+effect of this is that gpg will not mark a signature with a critical
+signature notation of that name as bad. Note that gpg already knows
+by default about a few critical signatures notation names.
+
@item --sig-policy-url @var{string}
@itemx --cert-policy-url @var{string}
@itemx --set-policy-url @var{string}
@opindex override-session-key
Don't use the public key but the session key @var{string} respective
the session key taken from the first line read from file descriptor
-@var{fd}. The format of this string is the same as the one printed
-by @option{--show-session-key}. This option is normally not used but
+@var{fd}. The format of this string is the same as the one printed by
+@option{--show-session-key}. This option is normally not used but
comes handy in case someone forces you to reveal the content of an
encrypted message; using this option you can do this without handing
out the secret key. Note that using @option{--override-session-key}
may reveal the session key to all local users via the global process
-table.
+table. Often it is useful to combine this option with
+@option{--no-keyring}.
@item --ask-sig-expire
@itemx --no-ask-sig-expire
@end table
+When calling the gpg-agent component @command{@gpgname} sends a set of
+environment variables to gpg-agent. The names of these variables can
+be listed using the command:
+
+@example
+ gpg-connect-agent 'getinfo std_env_names' /bye | awk '$1=="D" @{print $2@}'
+@end example
+
+
@c *******************************************
@c *************** ****************
#include "call-dirmngr.h"
+/* Keys retrieved from the web key directory should be small. There
+ * is only one UID and we can expect that the number of subkeys is
+ * reasonable. So we set a generous limit of 256 KiB. */
+#define MAX_WKD_RESULT_LENGTH (256 * 1024)
+
+
/* Parameter structure used to gather status info. Note that it is
* also used for WKD requests. */
struct ks_status_parm_s
goto leave;
}
- parm.memfp = es_fopenmem (0, "rwb");
+ parm.memfp = es_fopenmem (MAX_WKD_RESULT_LENGTH, "rwb");
if (!parm.memfp)
{
err = gpg_error_from_syserror ();
}
err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
NULL, NULL, ks_status_cb, &stparm);
+ if (gpg_err_code (err) == GPG_ERR_ENOSPC)
+ err = gpg_error (GPG_ERR_TOO_LARGE);
if (err)
goto leave;
their address used in ITEMS. */
strlist_t extra_list;
+ /* Hack to return the mechanism (AKL_foo) used to find the key. */
+ int found_via_akl;
+
/* Part of the search criteria: The low-level search specification
as passed to keydb_search. */
int nitems;
}
-void
-pubkey_free (pubkey_t key)
-{
- if (key)
- {
- xfree (key->pk);
- release_kbnode (key->keyblock);
- xfree (key);
- }
-}
-
+/* Free a list of pubkey_t objects. */
void
pubkeys_free (pubkey_t keys)
{
while (keys)
{
pubkey_t next = keys->next;
- pubkey_free (keys);
+ xfree (keys->pk);
+ release_kbnode (keys->keyblock);
+ xfree (keys);
keys = next;
}
}
-/* Returns all keys that match the search specification SEARCH_TERMS.
- *
- * This function also checks for and warns about duplicate entries in
- * the keydb, which can occur if the user has configured multiple
- * keyrings or keyboxes or if a keyring or keybox was corrupted.
- *
- * Note: SEARCH_TERMS will not be expanded (i.e., it may not be a
- * group).
- *
- * USE is the operation for which the key is required. It must be
- * either PUBKEY_USAGE_ENC, PUBKEY_USAGE_SIG, PUBKEY_USAGE_CERT or
- * PUBKEY_USAGE_AUTH.
- *
- * INCLUDE_UNUSABLE indicates whether disabled keys are allowed.
- * (Recipients specified with --encrypt-to and --hidden-encrypt-to may
- * be disabled. It is possible to edit disabled keys.)
- *
- * SOURCE is the context in which SEARCH_TERMS was specified, e.g.,
- * "--encrypt-to", etc. If this function is called interactively,
- * then this should be NULL.
- *
- * If WARN_POSSIBLY_AMBIGUOUS is set, then emits a warning if the user
- * does not specify a long key id or a fingerprint.
- *
- * The results are placed in *KEYS. *KEYS must be NULL!
- *
- * Fixme: Currently, only PUBKEY_USAGE_ENC and PUBKEY_USAGE_SIG are
- * implemented. */
-gpg_error_t
-get_pubkeys (ctrl_t ctrl,
- char *search_terms, int use, int include_unusable, char *source,
- int warn_possibly_ambiguous,
- pubkey_t *r_keys)
-{
- /* We show a warning when a key appears multiple times in the DB.
- * This can happen for two reasons:
- *
- * - The user has configured multiple keyrings or keyboxes.
- *
- * - The keyring or keybox has been corrupted in some way, e.g., a
- * bug or a random process changing them.
- *
- * For each duplicate, we only want to show the key once. Hence,
- * this list. */
- static strlist_t key_dups;
- gpg_error_t err;
- char *use_str; /* USE transformed to a string. */
- KEYDB_SEARCH_DESC desc;
- GETKEY_CTX ctx;
- pubkey_t results = NULL;
- pubkey_t r;
- int count;
- char fingerprint[2 * MAX_FINGERPRINT_LEN + 1];
-
- if (DBG_LOOKUP)
- {
- log_debug ("\n");
- log_debug ("%s: Checking %s=%s\n",
- __func__, source ? source : "user input", search_terms);
- }
-
- if (*r_keys)
- log_bug ("%s: KEYS should be NULL!\n", __func__);
-
- switch (use)
- {
- case PUBKEY_USAGE_ENC: use_str = "encrypt"; break;
- case PUBKEY_USAGE_SIG: use_str = "sign"; break;
- case PUBKEY_USAGE_CERT: use_str = "cetify"; break;
- case PUBKEY_USAGE_AUTH: use_str = "authentication"; break;
- default: log_bug ("%s: Bad value for USE (%d)\n", __func__, use);
- }
-
- if (use == PUBKEY_USAGE_CERT || use == PUBKEY_USAGE_AUTH)
- log_bug ("%s: use=%s is unimplemented.\n", __func__, use_str);
-
- err = classify_user_id (search_terms, &desc, 1);
- if (err)
- {
- log_info (_("key \"%s\" not found: %s\n"),
- search_terms, gpg_strerror (err));
- if (!opt.quiet && source)
- log_info (_("(check argument of option '%s')\n"), source);
- goto leave;
- }
-
- if (warn_possibly_ambiguous
- && ! (desc.mode == KEYDB_SEARCH_MODE_LONG_KID
- || desc.mode == KEYDB_SEARCH_MODE_FPR16
- || desc.mode == KEYDB_SEARCH_MODE_FPR20
- || desc.mode == KEYDB_SEARCH_MODE_FPR))
- {
- log_info (_("Warning: '%s' should be a long key ID or a fingerprint\n"),
- search_terms);
- if (!opt.quiet && source)
- log_info (_("(check argument of option '%s')\n"), source);
- }
-
- /* Gather all of the results. */
- ctx = NULL;
- count = 0;
- do
- {
- PKT_public_key *pk;
- KBNODE kb;
-
- pk = xtrycalloc (1, sizeof *pk);
- if (!pk)
- {
- err = gpg_error_from_syserror ();
- goto leave;
- }
-
- pk->req_usage = use;
-
- if (! ctx)
- err = get_pubkey_byname (ctrl, &ctx, pk, search_terms, &kb, NULL,
- include_unusable, 1);
- else
- err = getkey_next (ctrl, ctx, pk, &kb);
-
- if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) /* No more results. */
- {
- xfree (pk);
- break;
- }
- else if (err) /* An error (other than "not found"). */
- {
- log_error (_("error looking up: %s\n"), gpg_strerror (err));
- xfree (pk);
- break;
- }
-
- /* Another result! */
- count ++;
-
- r = xtrycalloc (1, sizeof (*r));
- if (!r)
- {
- err = gpg_error_from_syserror ();
- xfree (pk);
- goto leave;
- }
- r->pk = pk;
- r->keyblock = kb;
- r->next = results;
- results = r;
- }
- while (ctx);
- getkey_end (ctrl, ctx);
-
- if (DBG_LOOKUP)
- {
- log_debug ("%s resulted in %d matches.\n", search_terms, count);
- for (r = results; r; r = r->next)
- log_debug (" %s\n",
- hexfingerprint (r->keyblock->pkt->pkt.public_key,
- fingerprint, sizeof (fingerprint)));
- }
-
- if (! results && gpg_err_code (err) == GPG_ERR_NOT_FOUND)
- { /* No match. */
- if (DBG_LOOKUP)
- log_debug ("%s: '%s' not found.\n", __func__, search_terms);
-
- log_info (_("key \"%s\" not found\n"), search_terms);
- if (!opt.quiet && source)
- log_info (_("(check argument of option '%s')\n"), source);
-
- goto leave;
- }
- else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
- ; /* No more matches. */
- else if (err)
- { /* Some other error. An error message was already printed out.
- * Free RESULTS and continue. */
- goto leave;
- }
-
- /* Check for duplicates. */
- if (DBG_LOOKUP)
- log_debug ("%s: Checking results of %s='%s' for dups\n",
- __func__, source ? source : "user input", search_terms);
- count = 0;
- for (r = results; r; r = r->next)
- {
- pubkey_t *prevp;
- pubkey_t next;
- pubkey_t r2;
- int dups = 0;
-
- prevp = &r->next;
- next = r->next;
- while ((r2 = next))
- {
- if (cmp_public_keys (r->keyblock->pkt->pkt.public_key,
- r2->keyblock->pkt->pkt.public_key) != 0)
- { /* Not a dup. */
- prevp = &r2->next;
- next = r2->next;
- continue;
- }
-
- dups ++;
- count ++;
-
- /* Remove R2 from the list. */
- *prevp = r2->next;
- release_kbnode (r2->keyblock);
- next = r2->next;
- xfree (r2);
- }
-
- if (dups)
- {
- hexfingerprint (r->keyblock->pkt->pkt.public_key,
- fingerprint, sizeof fingerprint);
- if (! strlist_find (key_dups, fingerprint))
- {
- char fingerprint_formatted[MAX_FORMATTED_FINGERPRINT_LEN + 1];
-
- log_info (_("Warning: %s appears in the keyring %d times\n"),
- format_hexfingerprint (fingerprint,
- fingerprint_formatted,
- sizeof fingerprint_formatted),
- 1 + dups);
- add_to_strlist (&key_dups, fingerprint);
- }
- }
- }
-
- if (DBG_LOOKUP && count)
- {
- log_debug ("After removing %d dups:\n", count);
- for (r = results, count = 0; r; r = r->next)
- log_debug (" %d: %s\n",
- count,
- hexfingerprint (r->keyblock->pkt->pkt.public_key,
- fingerprint, sizeof fingerprint));
- }
-
- leave:
- if (err)
- pubkeys_free (results);
- else
- *r_keys = results;
-
- return err;
-}
-
-
static void
pk_from_block (PKT_public_key *pk, kbnode_t keyblock, kbnode_t found_key)
{
int is_mbox;
int nodefault = 0;
int anylocalfirst = 0;
+ int mechanism_type = AKL_NODEFAULT;
/* If RETCTX is not NULL, then RET_KDBHD must be NULL. */
log_assert (retctx == NULL || ret_kdbhd == NULL);
size_t fpr_len;
int did_akl_local = 0;
int no_fingerprint = 0;
- const char *mechanism = "?";
+ const char *mechanism_string = "?";
- switch (akl->type)
+ mechanism_type = akl->type;
+ switch (mechanism_type)
{
case AKL_NODEFAULT:
/* This is a dummy mechanism. */
- mechanism = "None";
+ mechanism_string = "None";
rc = GPG_ERR_NO_PUBKEY;
break;
case AKL_LOCAL:
- mechanism = "Local";
+ mechanism_string = "Local";
did_akl_local = 1;
if (retctx)
{
break;
case AKL_CERT:
- mechanism = "DNS CERT";
+ mechanism_string = "DNS CERT";
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_cert (ctrl, name, 0, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--;
break;
case AKL_PKA:
- mechanism = "PKA";
+ mechanism_string = "PKA";
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_pka (ctrl, name, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--;
break;
case AKL_DANE:
- mechanism = "DANE";
+ mechanism_string = "DANE";
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_cert (ctrl, name, 1, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--;
break;
case AKL_WKD:
- mechanism = "WKD";
+ mechanism_string = "WKD";
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_wkd (ctrl, name, 0, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--;
break;
case AKL_LDAP:
- mechanism = "LDAP";
+ mechanism_string = "LDAP";
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_ldap (ctrl, name, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--;
* and getting a whole lot of keys back. */
if (keyserver_any_configured (ctrl))
{
- mechanism = "keyserver";
+ mechanism_string = "keyserver";
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_name (ctrl, name, &fpr, &fpr_len,
opt.keyserver);
}
else
{
- mechanism = "Unconfigured keyserver";
+ mechanism_string = "Unconfigured keyserver";
rc = GPG_ERR_NO_PUBKEY;
}
break;
{
struct keyserver_spec *keyserver;
- mechanism = akl->spec->uri;
+ mechanism_string = akl->spec->uri;
keyserver = keyserver_match (akl->spec);
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_name (ctrl,
/* Key found. */
if (opt.verbose)
log_info (_("automatically retrieved '%s' via %s\n"),
- name, mechanism);
+ name, mechanism_string);
break;
}
if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY
|| opt.verbose || no_fingerprint)
log_info (_("error retrieving '%s' via %s: %s\n"),
- name, mechanism,
+ name, mechanism_string,
no_fingerprint ? _("No fingerprint") : gpg_strerror (rc));
}
}
{
log_assert (!(*retctx)->extra_list);
(*retctx)->extra_list = namelist;
+ (*retctx)->found_via_akl = mechanism_type;
}
else
free_strlist (namelist);
return ! sub->flags.revoked && sub->flags.valid && ! sub->flags.disabled;
}
+/* Return true if KEYBLOCK has only expired encryption subkyes. Note
+ * that the function returns false if the key has no encryption
+ * subkeys at all or the subkecys are revoked. */
+static int
+only_expired_enc_subkeys (kbnode_t keyblock)
+{
+ kbnode_t node;
+ PKT_public_key *sub;
+ int any = 0;
+
+ for (node = find_next_kbnode (keyblock, PKT_PUBLIC_SUBKEY);
+ node; node = find_next_kbnode (node, PKT_PUBLIC_SUBKEY))
+ {
+ sub = node->pkt->pkt.public_key;
+
+ if (!(sub->pubkey_usage & PUBKEY_USAGE_ENC))
+ continue;
+
+ if (!subkey_is_ok (sub))
+ continue;
+
+ any = 1;
+ if (!sub->has_expired)
+ return 0;
+ }
+
+ return any? 1 : 0;
+}
/* Finally this function compares a NEW key to the former candidate
* OLD. Returns < 0 if the old key is worse, > 0 if the old key is
gpg_error_t
get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk,
const char *name, KBNODE *ret_keyblock,
- int include_unusable, int no_akl)
+ int include_unusable)
{
gpg_error_t err;
struct getkey_ctx_s *ctx = NULL;
+ int is_mbox = is_valid_mailbox (name);
+ int wkd_tried = 0;
if (retctx)
*retctx = NULL;
+ start_over:
+ if (ctx) /* Clear in case of a start over. */
+ {
+ if (ret_keyblock)
+ {
+ release_kbnode (*ret_keyblock);
+ *ret_keyblock = NULL;
+ }
+ getkey_end (ctrl, ctx);
+ ctx = NULL;
+ }
err = get_pubkey_byname (ctrl, &ctx, pk, name, ret_keyblock,
- NULL, include_unusable, no_akl);
+ NULL, include_unusable, 0);
if (err)
{
getkey_end (ctrl, ctx);
return err;
}
- if (is_valid_mailbox (name) && ctx)
+ /* If the keyblock was retrieved from the local database and the key
+ * has expired, do further checks. However, we can do this only if
+ * the caller requested a keyblock. */
+ if (is_mbox && ctx && ctx->found_via_akl == AKL_LOCAL && ret_keyblock)
+ {
+ u32 now = make_timestamp ();
+ PKT_public_key *pk2 = (*ret_keyblock)->pkt->pkt.public_key;
+ int found;
+
+ /* If the key has expired and its origin was the WKD then try to
+ * get a fresh key from the WKD. We also try this if the key
+ * has any only expired encryption subkeys. In case we checked
+ * for a fresh copy in the last 3 hours we won't do that again.
+ * Unfortunately that does not yet work because KEYUPDATE is
+ * only updated during import iff the key has actually changed
+ * (see import.c:import_one). */
+ if (!wkd_tried && pk2->keyorg == KEYORG_WKD
+ && (pk2->keyupdate + 3*3600) < now
+ && (pk2->has_expired || only_expired_enc_subkeys (*ret_keyblock)))
+ {
+ if (opt.verbose)
+ log_info (_("checking for a fresh copy of an expired key via %s\n"),
+ "WKD");
+ wkd_tried = 1;
+ glo_ctrl.in_auto_key_retrieve++;
+ found = !keyserver_import_wkd (ctrl, name, 0, NULL, NULL);
+ glo_ctrl.in_auto_key_retrieve--;
+ if (found)
+ goto start_over;
+ }
+ }
+
+ if (is_mbox && ctx)
{
/* Rank results and return only the most relevant key. */
struct pubkey_cmp_cookie best = { 0 };
oCertNotation,
oShowNotation,
oNoShowNotation,
+ oKnownNotation,
aEncrFiles,
aEncrSym,
aDecryptFiles,
ARGPARSE_s_s (oSetNotation, "set-notation", "@"),
ARGPARSE_s_s (oSigNotation, "sig-notation", "@"),
ARGPARSE_s_s (oCertNotation, "cert-notation", "@"),
+ ARGPARSE_s_s (oKnownNotation, "known-notation", "@"),
ARGPARSE_group (302, N_(
"@\n(See the man page for a complete listing of all commands and options)\n"
break;
case oSigNotation: add_notation_data( pargs.r.ret_str, 0 ); break;
case oCertNotation: add_notation_data( pargs.r.ret_str, 1 ); break;
+ case oKnownNotation: register_known_notation (pargs.r.ret_str); break;
case oShowNotation:
deprecated_warning(configname,configlineno,"--show-notation",
"--list-options ","show-notations");
keydb_release (hd);
hd = NULL;
- /* Fixme: we do not track the time we last checked a key for
+ /* FIXME: We do not track the time we last checked a key for
* updates. To do this we would need to rewrite even the
- * keys which have no changes. */
+ * keys which have no changes. Adding this would be useful
+ * for the automatic update of expired keys via the WKD in
+ * case the WKD still carries the expired key. See
+ * get_best_pubkey_byname. */
same_key = 1;
if (is_status_enabled ())
print_import_ok (pk, 0);
};
typedef struct pubkey_s *pubkey_t;
-/* Free a single key. This does not remove key from any list! */
-void pubkey_free (pubkey_t key);
-
/* Free a list of public keys. */
void pubkeys_free (pubkey_t keys);
-/* Returns all keys that match the search specification SEARCH_TERMS.
- The returned keys should be freed using pubkeys_free. */
-gpg_error_t
-get_pubkeys (ctrl_t ctrl,
- char *search_terms, int use, int include_unusable, char *source,
- int warn_possibly_ambiguous,
- pubkey_t *r_keys);
-
/* Find a public key identified by NAME. */
int get_pubkey_byname (ctrl_t ctrl,
GETKEY_CTX *retctx, PKT_public_key *pk,
gpg_error_t get_best_pubkey_byname (ctrl_t ctrl,
GETKEY_CTX *retctx, PKT_public_key *pk,
const char *name, KBNODE *ret_keyblock,
- int include_unusable, int no_akl);
+ int include_unusable);
/* Get a public key directly from file FNAME. */
gpg_error_t get_pubkey_fromfile (ctrl_t ctrl,
if (opt.batch && card_serialno)
{
- /* We don't yet support unattended key generation. */
+ /* We don't yet support unattended key generation with a card
+ * serial number. */
log_error (_("can't do this in batch mode\n"));
+ print_further_info ("key generation with card serial number");
return;
}
for (sl = names; sl; sl = sl->next)
{
- rc = get_best_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, 1, 0);
+ rc = get_best_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, 1);
if (rc)
{
if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
/*-- parse-packet.c --*/
+
+void register_known_notation (const char *string);
+
/* Sets the packet list mode to MODE (i.e., whether we are dumping a
packet or not). Returns the current mode. This allows for
temporarily suspending dumping by doing the following:
#define MAX_COMMENT_PACKET_LENGTH ( 64 * 1024)
#define MAX_ATTR_PACKET_LENGTH ( 16 * 1024*1024)
-
static int mpi_print_mode;
static int list_mode;
static estream_t listfp;
+/* A linked list of known notation names. Note that the FLAG is used
+ * to store the length of the name to speed up the check. */
+static strlist_t known_notations_list;
+
+
static int parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts,
off_t * retpos, int *skip, IOBUF out, int do_skip
#if DEBUG_PARSE_PACKET
}
+/* Register STRING as a known critical notation name. */
+void
+register_known_notation (const char *string)
+{
+ strlist_t sl;
+
+ if (!known_notations_list)
+ {
+ sl = add_to_strlist (&known_notations_list,
+ "preferred-email-encoding@pgp.com");
+ sl->flags = 32;
+ sl = add_to_strlist (&known_notations_list, "pka-address@gnupg.org");
+ sl->flags = 21;
+ }
+ if (!string)
+ return; /* Only initialized the default known notations. */
+
+ /* In --set-notation we use an exclamation mark to indicate a
+ * critical notation. As a convenience skip this here. */
+ if (*string == '!')
+ string++;
+
+ if (!*string || strlist_find (known_notations_list, string))
+ return; /* Empty string or already registered. */
+
+ sl = add_to_strlist (&known_notations_list, string);
+ sl->flags = strlen (string);
+}
+
+
int
set_packet_list_mode (int mode)
{
}
if (s2kmode == 3)
{
- k->s2k.count = iobuf_get (inp);
+ k->s2k.count = iobuf_get_noeof (inp);
pktlen--;
}
k->seskeylen = seskeylen;
/* Return true if we understand the critical notation. */
static int
-can_handle_critical_notation (const byte * name, size_t len)
+can_handle_critical_notation (const byte *name, size_t len)
{
- if (len == 32 && memcmp (name, "preferred-email-encoding@pgp.com", 32) == 0)
- return 1;
- if (len == 21 && memcmp (name, "pka-address@gnupg.org", 21) == 0)
- return 1;
+ strlist_t sl;
- return 0;
+ register_known_notation (NULL); /* Make sure it is initialized. */
+
+ for (sl = known_notations_list; sl; sl = sl->next)
+ if (sl->flags == len && !memcmp (sl->d, name, len))
+ return 1; /* Known */
+
+ if (opt.verbose)
+ {
+ log_info(_("Unknown critical signature notation: ") );
+ print_utf8_buffer (log_get_stream(), name, len);
+ log_printf ("\n");
+ }
+
+ return 0; /* Unknown. */
}
err = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
- ski->s2k.count = iobuf_get (inp);
+ ski->s2k.count = iobuf_get_noeof (inp);
pktlen--;
if (list_mode)
es_fprintf (listfp, "\tprotect count: %lu (%lu)\n",
if (from_file)
rc = get_pubkey_fromfile (ctrl, pk, name);
else
- rc = get_best_pubkey_byname (ctrl, NULL, pk, name, &keyblock, 0, 0);
+ rc = get_best_pubkey_byname (ctrl, NULL, pk, name, &keyblock, 0);
if (rc)
{
int code;
msgstr ""
"Project-Id-Version: gnupg-2.1.0\n"
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
-"PO-Revision-Date: 2018-07-12 14:48+0200\n"
+"PO-Revision-Date: 2018-08-30 09:44+0200\n"
"Last-Translator: Werner Koch <wk@gnupg.org>\n"
"Language-Team: German <de@li.org>\n"
"Language: de\n"
msgid "unknown debug flag '%s' ignored\n"
msgstr "Unbekanntes Debug Flag '%s' wird ignoriert\n"
-#, c-format
-msgid "no running gpg-agent - starting '%s'\n"
-msgstr "Kein aktiver gpg-agent - `%s' wird gestartet\n"
-
-#, c-format
-msgid "waiting for the agent to come up ... (%ds)\n"
+#, fuzzy, c-format
+#| msgid "waiting for the agent to come up ... (%ds)\n"
+msgid "waiting for the %s to come up ... (%ds)\n"
msgstr "Warte bis der gpg-agent bereit ist ... (%ds)\n"
-#, c-format
-msgid "connection to agent established\n"
+#, fuzzy, c-format
+#| msgid "connection to agent established\n"
+msgid "connection to %s established\n"
msgstr "Verbindung zum gpg-agent aufgebaut\n"
#, c-format
+msgid "no running gpg-agent - starting '%s'\n"
+msgstr "Kein aktiver gpg-agent - `%s' wird gestartet\n"
+
+#, c-format
msgid "connection to agent is in restricted mode\n"
msgstr "Verbindung zum gpg-agent ist im eingeschränkten Modus.\n"
msgid "no running Dirmngr - starting '%s'\n"
msgstr "Kein aktiver Dirmngr - `%s' wird gestartet\n"
-#, c-format
-msgid "waiting for the dirmngr to come up ... (%ds)\n"
-msgstr "Warte bis der Dirmngr bereit ist ... (%ds)\n"
-
-#, c-format
-msgid "connection to the dirmngr established\n"
-msgstr "Verbindung zum Dirmngr aufgebaut\n"
-
#. TRANSLATORS: Copy the prefix between the vertical bars
#. verbatim. It will not be printed.
msgid "|audit-log-result|Good"
msgstr "[User-ID nicht gefunden]"
#, c-format
-msgid "(check argument of option '%s')\n"
-msgstr "(Prüfe das Argument der Option '%s')\n"
-
-#, c-format
-msgid "Warning: '%s' should be a long key ID or a fingerprint\n"
-msgstr ""
-"WARNUNG: '%s' sollte eine lange Schlüssel-ID oder ein Fingerabdruck sein\n"
-
-#, c-format
-msgid "error looking up: %s\n"
-msgstr "Fehler beim Nachschlagen von: %s\n"
-
-#, c-format
-msgid "Warning: %s appears in the keyring %d times\n"
-msgstr "WARNUNG: %s ist %d mal im Schlüsselbund vorhanden\n"
-
-#, c-format
msgid "automatically retrieved '%s' via %s\n"
msgstr "`%s' automatisch via %s geholt\n"
msgstr "Kein Fingerabdruck vorhanden"
#, c-format
+msgid "checking for a fresh copy of an expired key via %s\n"
+msgstr "Prüfe auf eine aktuellere Kopie eines abgelaufenen Schlüssels über %s\n"
+
+#, c-format
msgid "secret key \"%s\" not found: %s\n"
msgstr "Geheimer Schlüssel \"%s\" nicht gefunden: %s\n"
#, c-format
+msgid "(check argument of option '%s')\n"
+msgstr "(Prüfe das Argument der Option '%s')\n"
+
+#, c-format
msgid "Warning: not using '%s' as default key: %s\n"
msgstr ""
"WARNUNG: \"%s\" wird nicht als voreingestellter geheimer Schlüssel benutzt: "
"WARNUNG: Möglicherweise unsicherer symmetrisch verschlüsselter "
"Sitzungsschlüssel\n"
+#, fuzzy, c-format
+#| msgid "Critical signature notation: "
+msgid "Unknown critical signature notation: "
+msgstr "Entscheidender Beglaubigungs-\"Notation\": "
+
#, c-format
msgid "subpacket of type %d has critical bit set\n"
msgstr "Im Unterpaket des Typs %d ist das \"critical bit\" gesetzt\n"
msgid "this key"
msgstr "dieser Schlüssel"
-#, fuzzy, c-format
-#| msgid "Verified %ld messages signed by \"%s\"."
+#, c-format
msgid "Verified %d message."
msgid_plural "Verified %d messages."
-msgstr[0] "%ld überprüfte Nachrichten von \"%s\"."
-msgstr[1] "%ld überprüfte Nachrichten von \"%s\"."
+msgstr[0] "%d überprüfte Nachricht."
+msgstr[1] "%d überprüfte Nachrichten."
-#, fuzzy, c-format
-#| msgid "encrypted with %lu passphrases\n"
+#, c-format
msgid "Encrypted %d message."
msgid_plural "Encrypted %d messages."
-msgstr[0] "Verschlüsselt mit %lu Passphrases\n"
-msgstr[1] "Verschlüsselt mit %lu Passphrases\n"
+msgstr[0] "%d Nachricht wurde verschlüsselt."
+msgstr[1] "%d Nachrichten wurden verschlüsselt."
#, fuzzy, c-format
#| msgid "%ld message signed in the future."
"Syntax: gpg-check-pattern [optionen] Musterdatei\n"
"Die von stdin gelesene Passphrase gegen die Musterdatei prüfen\n"
+#~ msgid "waiting for the dirmngr to come up ... (%ds)\n"
+#~ msgstr "Warte bis der Dirmngr bereit ist ... (%ds)\n"
+
+#~ msgid "connection to the dirmngr established\n"
+#~ msgstr "Verbindung zum Dirmngr aufgebaut\n"
+
+#~ msgid "Warning: '%s' should be a long key ID or a fingerprint\n"
+#~ msgstr ""
+#~ "WARNUNG: '%s' sollte eine lange Schlüssel-ID oder ein Fingerabdruck sein\n"
+
+#~ msgid "error looking up: %s\n"
+#~ msgstr "Fehler beim Nachschlagen von: %s\n"
+
+#~ msgid "Warning: %s appears in the keyring %d times\n"
+#~ msgstr "WARNUNG: %s ist %d mal im Schlüsselbund vorhanden\n"
+
#~ msgid "using \"http\" instead of \"https\"\n"
#~ msgstr "Es wird \"HTTP\" anstatt \"HTTPS\" verwendet\n"
#
msgid ""
msgstr ""
-"Project-Id-Version: gnupg 2.2.6\n"
+"Project-Id-Version: gnupg 2.2.9\n"
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
-"PO-Revision-Date: 2018-04-12 10:51+0900\n"
+"PO-Revision-Date: 2018-08-22 17:43+0900\n"
"Last-Translator: NIIBE Yutaka <gniibe@fsij.org>\n"
"Language-Team: none\n"
"Language: ja\n"
"likely that this message is legitimate. This is because back\n"
"then integrity protection was not widely used.\n"
msgstr ""
+"ヒント: もし、このメッセージが2003年以前に作成されたのであれば、\n"
+"このメッセージはおそらく正当でしょう。当時、整合性の保護機能は\n"
+"広く使われてはいなかったためです。\n"
#, c-format
msgid "Use the option '%s' to decrypt anyway.\n"
-msgstr ""
+msgstr "それでも復号するにはオプション '%s' を使います。\n"
-#, fuzzy, c-format
-#| msgid "decryption failed: %s\n"
+#, c-format
msgid "decryption forced to fail!\n"
-msgstr "復å\8f·ã\81«å¤±æ\95\97ã\81\97ã\81¾ã\81\97ã\81\9f: %s\n"
+msgstr "復å\8f·ã\81¯å¼·å\88¶ç\9a\84ã\81«å¤±æ\95\97ã\81¨ã\81\95ã\82\8cã\81¾ã\81\97ã\81\9f!\n"
#, c-format
msgid "decryption okay\n"
msgid "bad key signature from key %s: %s (0x%02x, 0x%x)\n"
msgstr "鍵%sによる不正な鍵への署名: %s (0x%02x, 0x%x)\n"
-#, fuzzy, c-format
-#| msgid "bad key signature from key %s: %s (0x%02x, 0x%x)\n"
+#, c-format
msgid "bad data signature from key %s: %s (0x%02x, 0x%x)\n"
-msgstr "鍵%sによる不正な鍵への署名: %s (0x%02x, 0x%x)\n"
+msgstr "鍵%sによる不正なデータへの署名: %s (0x%02x, 0x%x)\n"
#, c-format
msgid "assuming bad signature from key %s due to an unknown critical bit\n"
# !-- no such user (2011-01-11)
# Thanks Pawel I. Shajdo <pshajdo@gmail.com>.
# Thanks Cmecb for the inspiration.
-# Ineiev <ineiev@gnu.org>, 2014, 2015, 2016, 2017
+# Ineiev <ineiev@gnu.org>, 2014, 2015, 2016, 2017, 2018
#
# Designated-Translator: none
msgid ""
msgstr ""
"Project-Id-Version: GnuPG 2.2.0\n"
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
-"PO-Revision-Date: 2018-05-05 17:41+0100\n"
+"PO-Revision-Date: 2018-07-14 17:41+0100\n"
"Last-Translator: Ineiev <ineiev@gnu.org>\n"
"Language-Team: Russian <gnupg-ru@gnupg.org>\n"
"Language: ru\n"
msgstr "неизвестный отладочный флаг '%s' игнорируется\n"
#, c-format
-msgid "no running gpg-agent - starting '%s'\n"
-msgstr "агенÑ\82 gpg не Ñ\80абоÑ\82аеÑ\82 - запÑ\83Ñ\81каем '%s'\n"
+msgid "waiting for the %s to come up ... (%ds)\n"
+msgstr "ожидаÑ\8e подклÑ\8eÑ\87ениÑ\8f %s ... (%iÑ\81)\n"
#, c-format
-msgid "waiting for the agent to come up ... (%ds)\n"
-msgstr "ожидаю подключения агента ... (%iс)\n"
+msgid "connection to %s established\n"
+msgstr "соединение с %s установлено\n"
#, c-format
-msgid "connection to agent established\n"
-msgstr "соединение с агентом установлено\n"
+msgid "no running gpg-agent - starting '%s'\n"
+msgstr "агент gpg не работает - запускаем '%s'\n"
#, c-format
msgid "connection to agent is in restricted mode\n"
msgid "no running Dirmngr - starting '%s'\n"
msgstr "Dirmngr не выполняется - запуск '%s'\n"
-#, c-format
-msgid "waiting for the dirmngr to come up ... (%ds)\n"
-msgstr "ожидаю подключения dirmngr ... (%iс)\n"
-
-#, c-format
-msgid "connection to the dirmngr established\n"
-msgstr "соединение с dirmngr установлено\n"
-
#. TRANSLATORS: Copy the prefix between the vertical bars
#. verbatim. It will not be printed.
msgid "|audit-log-result|Good"
msgstr "[Идентификатор пользователя не найден]"
#, c-format
-msgid "(check argument of option '%s')\n"
-msgstr "(проверьте аргумент параметра '%s')\n"
-
-#, c-format
-msgid "Warning: '%s' should be a long key ID or a fingerprint\n"
-msgstr ""
-"Внимание: '%s' должно быть длинным идентификатором или отпечатком ключа\n"
-
-#, c-format
-msgid "error looking up: %s\n"
-msgstr "ошибка поиска: %s\n"
-
-#, c-format
-msgid "Warning: %s appears in the keyring %d times\n"
-msgstr "Внимание: %s включено в таблицу ключей %d раз\n"
-
-#, c-format
msgid "automatically retrieved '%s' via %s\n"
msgstr "автоматически получили '%s' через %s\n"
msgstr "Нет отпечатка"
#, c-format
+msgid "checking for a fresh copy of an expired key via %s\n"
+msgstr "поиск обновленной копии просроченного ключа по %s\n"
+
+#, c-format
msgid "secret key \"%s\" not found: %s\n"
msgstr "секретный ключ \"%s\" не найден: %s\n"
#, c-format
+msgid "(check argument of option '%s')\n"
+msgstr "(проверьте аргумент параметра '%s')\n"
+
+#, c-format
msgid "Warning: not using '%s' as default key: %s\n"
msgstr "Внимание: '%s' не используется в качестве основного ключа: %s\n"
"likely that this message is legitimate. This is because back\n"
"then integrity protection was not widely used.\n"
msgstr ""
+"Подсказка: если это сообщение создано до 2003 года, вероятно, что\n"
+"оно правомерно, поскольку в те времена защита целостности широко\n"
+"не применялась.\n"
#, c-format
msgid "Use the option '%s' to decrypt anyway.\n"
-msgstr ""
+msgstr "Воспользуйтесь параметром '%s', чтобы тем не менее расшифровать.\n"
-#, fuzzy, c-format
-#| msgid "decryption failed: %s\n"
+#, c-format
msgid "decryption forced to fail!\n"
-msgstr "сбой расшифровки: %s\n"
+msgstr "принудительный сбой расшифровки!\n"
#, c-format
msgid "decryption okay\n"
" зашифрованный симметричным шифром\n"
#, c-format
+msgid "Unknown critical signature notation: "
+msgstr "Неизвестное критическое замечание к подписи: "
+
+#, c-format
msgid "subpacket of type %d has critical bit set\n"
msgstr "в подпакете типа %d установлен критический бит\n"
#, c-format
msgid "bad key signature from key %s: %s (0x%02x, 0x%x)\n"
-msgstr "плохая подпись ключом %s: %s (0x%02x 0x%x)\n"
+msgstr "плоÑ\85аÑ\8f подпиÑ\81Ñ\8c клÑ\8eÑ\87а клÑ\8eÑ\87ом %s: %s (0x%02x 0x%x)\n"
-#, fuzzy, c-format
-#| msgid "bad key signature from key %s: %s (0x%02x, 0x%x)\n"
+#, c-format
msgid "bad data signature from key %s: %s (0x%02x, 0x%x)\n"
-msgstr "плохая подпись ключом %s: %s (0x%02x 0x%x)\n"
+msgstr "плоÑ\85аÑ\8f подпиÑ\81Ñ\8c даннÑ\8bÑ\85 клÑ\8eÑ\87ом %s: %s (0x%02x 0x%x)\n"
#, c-format
msgid "assuming bad signature from key %s due to an unknown critical bit\n"
else if (strstr (reader_table[slot].rdrname, "cyberJack")
|| strstr (reader_table[slot].rdrname, "DIGIPASS")
|| strstr (reader_table[slot].rdrname, "Gnuk")
- || strstr (reader_table[slot].rdrname, "KAAN"))
+ || strstr (reader_table[slot].rdrname, "KAAN")
+ || strstr (reader_table[slot].rdrname, "Trustica"))
reader_table[slot].pinpad_varlen_supported = 1;
}
else if (vendor == 0x0c4b /* Tested with Reiner cyberJack GO */
|| vendor == 0x1a44 /* Tested with Vasco DIGIPASS 920 */
|| vendor == 0x234b /* Tested with FSIJ Gnuk Token */
- || vendor == 0x0d46 /* Tested with KAAN Advanced??? */)
+ || vendor == 0x0d46 /* Tested with KAAN Advanced??? */
+ || (vendor == 0x1fc9 && product == 0x81e6) /* Tested with Trustica Cryptoucan */)
reader_table[slot].pinpad_varlen_supported = 1;
return 0;
if (handle->id_product != CHERRY_ST2000)
cherry_mode = 1;
break;
+ case VENDOR_NXP:
+ if (handle->id_product == CRYPTOUCAN){
+ pininfo->maxlen = 25;
+ enable_varlen = 1;
+ }
+ break;
default:
if ((handle->id_vendor == VENDOR_GEMPC &&
handle->id_product == GEMPC_PINPAD)
VENDOR_REINER = 0x0c4b,
VENDOR_KAAN = 0x0d46,
VENDOR_FSIJ = 0x234b,
- VENDOR_VASCO = 0x1a44
+ VENDOR_VASCO = 0x1a44,
+ VENDOR_NXP = 0x1fc9,
};
#define GEMPC_CT30 0x3437
#define VEGA_ALPHA 0x0008
#define CYBERJACK_GO 0x0504
+#define CRYPTOUCAN 0x81e6
#endif /*CCID_DRIVER_INCLUDE_USB_IDS*/