mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Preparing an interim release
This commit is contained in:
parent
000a38ccf2
commit
6a13cf2c3d
16
ChangeLog
16
ChangeLog
@ -1,3 +1,19 @@
|
||||
2005-11-28 Werner Koch <wk@g10code.com>
|
||||
|
||||
* configure.ac: Append the revision to the version string.
|
||||
|
||||
2005-11-13 Werner Koch <wk@g10code.com>
|
||||
|
||||
* am/cmacros.am (-DGNUPG_SYSCONFDIR): Define it.
|
||||
|
||||
2005-11-11 Werner Koch <wk@g10code.com>
|
||||
|
||||
* configure.ac (NEED_KSBA_VERSION: Require 0.9.13.
|
||||
|
||||
2005-09-12 Werner Koch <wk@g10code.com>
|
||||
|
||||
Released 1.9.19.
|
||||
|
||||
2005-08-01 Werner Koch <wk@g10code.com>
|
||||
|
||||
Released 1.9.18.
|
||||
|
7
NEWS
7
NEWS
@ -1,3 +1,10 @@
|
||||
Noteworthy changes in version 1.9.20
|
||||
-------------------------------------------------
|
||||
|
||||
* [scdaemon] Support for keypads of some readers. Tested only with
|
||||
SPR532. New option --disable-keypad.
|
||||
|
||||
|
||||
Noteworthy changes in version 1.9.19 (2005-09-12)
|
||||
-------------------------------------------------
|
||||
|
||||
|
1
TODO
1
TODO
@ -26,7 +26,6 @@ might want to have an agent context for each service request
|
||||
* sm/gpgsm.c
|
||||
** Support --output for all commands
|
||||
** mark all unimplemented commands and options.
|
||||
** Print a hint when MD2 is the cause for a problem.
|
||||
** Implement --default-key
|
||||
** support the anyPolicy semantic
|
||||
** Check that we are really following the verification procedures in rfc3280.
|
||||
|
@ -1,3 +1,20 @@
|
||||
2005-11-24 Werner Koch <wk@g10code.com>
|
||||
|
||||
* minip12.c (p12_parse): Fixed for case that the key object comes
|
||||
prior to the certificate.
|
||||
|
||||
2005-10-19 Werner Koch <wk@g10code.com>
|
||||
|
||||
* divert-scd.c (getpin_cb): Hack to use it for a keypad message.
|
||||
|
||||
* call-scd.c (inq_needpin): Reworked to support the new KEYPADINFO.
|
||||
|
||||
* query.c (start_pinentry): Keep track of the owner.
|
||||
(popup_message_thread, agent_popup_message_start)
|
||||
(agent_popup_message_stop, agent_reset_query): New.
|
||||
* command.c (start_command_handler): Make sure a popup window gets
|
||||
closed.
|
||||
|
||||
2005-10-08 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* Makefile.am (gpg_protect_tool_LDADD): Add ../gl/libgnu.a.
|
||||
|
@ -133,7 +133,7 @@ struct server_control_s
|
||||
int have_keygrip;
|
||||
|
||||
int use_auth_call; /* Hack to send the PKAUTH command instead of the
|
||||
PKSIGN command tro scdaemon. */
|
||||
PKSIGN command to the scdaemon. */
|
||||
};
|
||||
typedef struct server_control_s *CTRL;
|
||||
typedef struct server_control_s *ctrl_t;
|
||||
@ -200,6 +200,7 @@ int agent_key_available (const unsigned char *grip);
|
||||
/*-- query.c --*/
|
||||
void initialize_module_query (void);
|
||||
void agent_query_dump_state (void);
|
||||
void agent_reset_query (ctrl_t ctrl);
|
||||
int agent_askpin (ctrl_t ctrl,
|
||||
const char *desc_text, const char *prompt_text,
|
||||
const char *inital_errtext,
|
||||
@ -209,6 +210,10 @@ int agent_get_passphrase (ctrl_t ctrl, char **retpass,
|
||||
const char *errtext);
|
||||
int agent_get_confirmation (ctrl_t ctrl, const char *desc, const char *ok,
|
||||
const char *cancel);
|
||||
int agent_popup_message_start (ctrl_t ctrl, const char *desc,
|
||||
const char *ok_btn, const char *cancel_btn);
|
||||
void agent_popup_message_stop (ctrl_t ctrl);
|
||||
|
||||
|
||||
/*-- cache.c --*/
|
||||
void agent_flush_cache (void);
|
||||
|
@ -633,11 +633,8 @@ inq_needpin (void *opaque, const char *line)
|
||||
size_t pinlen;
|
||||
int rc;
|
||||
|
||||
if (!(!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7])))
|
||||
if (!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7]))
|
||||
{
|
||||
log_error ("unsupported inquiry `%s'\n", line);
|
||||
return ASSUAN_Inquire_Unknown;
|
||||
}
|
||||
line += 7;
|
||||
while (*line == ' ')
|
||||
line++;
|
||||
@ -653,6 +650,26 @@ inq_needpin (void *opaque, const char *line)
|
||||
if (!rc)
|
||||
rc = assuan_send_data (parm->ctx, pin, pinlen);
|
||||
xfree (pin);
|
||||
}
|
||||
else if (!strncmp (line, "KEYPADINFO", 10) && (line[10] == ' ' || !line[10]))
|
||||
{
|
||||
size_t code;
|
||||
char *endp;
|
||||
|
||||
code = strtoul (line+10, &endp, 10);
|
||||
line = endp;
|
||||
while (*line == ' ')
|
||||
line++;
|
||||
|
||||
rc = parm->getpin_cb (parm->getpin_cb_arg, line, NULL, code);
|
||||
if (rc)
|
||||
rc = ASSUAN_Canceled;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error ("unsupported inquiry `%s'\n", line);
|
||||
rc = ASSUAN_Inquire_Unknown;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -316,11 +316,11 @@ cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
|
||||
this command is not used a default text will be used. Note, that
|
||||
this description implictly selects the label used for the entry
|
||||
box; if the string contains the string PIN (which in general will
|
||||
not be translated), "PIN" is used, other wiese the translation of
|
||||
not be translated), "PIN" is used, otherwise the translation of
|
||||
'passphrase" is used. The description string should not contain
|
||||
blanks unless they are percent or '+' escaped.
|
||||
|
||||
The descrition is only valid for the next PKSIGN or PKDECRYPT
|
||||
The description is only valid for the next PKSIGN or PKDECRYPT
|
||||
operation.
|
||||
*/
|
||||
static int
|
||||
@ -399,7 +399,7 @@ cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
|
||||
/* PKSIGN <options>
|
||||
|
||||
Perform the actual sign operation. Neither input nor output are
|
||||
sensitive to eavesdropping */
|
||||
sensitive to eavesdropping. */
|
||||
static int
|
||||
cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
@ -1085,6 +1085,9 @@ start_command_handler (int listen_fd, int fd)
|
||||
/* Reset the SCD if needed. */
|
||||
agent_reset_scd (&ctrl);
|
||||
|
||||
/* Reset the pinentry (in case of popup messages). */
|
||||
agent_reset_query (&ctrl);
|
||||
|
||||
assuan_deinit_server (ctx);
|
||||
if (ctrl.display)
|
||||
free (ctrl.display);
|
||||
|
@ -204,7 +204,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
|
||||
const char *again_text = NULL;
|
||||
const char *prompt = "PIN";
|
||||
|
||||
if (maxbuf < 2)
|
||||
if (buf && maxbuf < 2)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
/* Parse the flags. */
|
||||
@ -223,6 +223,23 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
|
||||
else if (info && *info == '|')
|
||||
log_debug ("pin_cb called without proper PIN info hack\n");
|
||||
|
||||
/* If BUF has been passed as NULL, we are in keypad mode: The
|
||||
callback opens the popup and immediatley returns. */
|
||||
if (!buf)
|
||||
{
|
||||
if (maxbuf == 0) /* Close the pinentry. */
|
||||
{
|
||||
agent_popup_message_stop (ctrl);
|
||||
rc = 0;
|
||||
}
|
||||
else if (maxbuf == 1) /* Open the pinentry. */
|
||||
{
|
||||
rc = agent_popup_message_start (ctrl, info, NULL, NULL);
|
||||
}
|
||||
else
|
||||
rc = gpg_error (GPG_ERR_INV_VALUE);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* FIXME: keep PI and TRIES in OPAQUE. Frankly this is a whole
|
||||
mess because we should call the card's verify function from the
|
||||
|
@ -511,7 +511,7 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length,
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
/* Loop over all certificates inside the bab. */
|
||||
/* Loop over all certificates inside the bag. */
|
||||
while (n)
|
||||
{
|
||||
int isbag = 0;
|
||||
@ -860,6 +860,7 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw,
|
||||
size_t n = length;
|
||||
const char *where;
|
||||
int bagseqlength, len;
|
||||
gcry_mpi_t *result = NULL;
|
||||
|
||||
where = "pfx";
|
||||
if (parse_tag (&p, &n, &ti))
|
||||
@ -935,11 +936,18 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw,
|
||||
}
|
||||
else if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_data)
|
||||
&& !memcmp (p, oid_data, DIM(oid_data)))
|
||||
{
|
||||
if (result)
|
||||
log_info ("already got an data object, skipping next one\n");
|
||||
else
|
||||
{
|
||||
p += DIM(oid_data);
|
||||
n -= DIM(oid_data);
|
||||
len -= DIM(oid_data);
|
||||
return parse_bag_data (p, n, (p-buffer), pw);
|
||||
result = parse_bag_data (p, n, (p-buffer), pw);
|
||||
if (!result)
|
||||
goto bailout;
|
||||
}
|
||||
}
|
||||
else
|
||||
log_info ( "unknown bag type - skipped\n");
|
||||
@ -950,9 +958,10 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw,
|
||||
n -= len;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return result;
|
||||
bailout:
|
||||
log_error ("error at \"%s\", offset %u\n", where, (p - buffer));
|
||||
/* fixme: need to release RESULT. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
184
agent/query.c
184
agent/query.c
@ -27,9 +27,10 @@
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef USE_GNU_PTH
|
||||
# include <pth.h>
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
#include <pth.h>
|
||||
|
||||
#include "agent.h"
|
||||
#include "i18n.h"
|
||||
@ -48,14 +49,30 @@
|
||||
time. */
|
||||
#define LOCK_TIMEOUT (1*60)
|
||||
|
||||
/* The assuan context of the current pinentry. */
|
||||
static assuan_context_t entry_ctx;
|
||||
|
||||
static assuan_context_t entry_ctx = NULL;
|
||||
#ifdef USE_GNU_PTH
|
||||
/* The control variable of the connection owning the current pinentry.
|
||||
This is only valid if ENTRY_CTX is not NULL. Note, that we care
|
||||
only about the value of the pointer and that it should never be
|
||||
dereferenced. */
|
||||
static ctrl_t entry_owner;
|
||||
|
||||
/* A mutex used to serialize access to the pinentry. */
|
||||
static pth_mutex_t entry_lock;
|
||||
#endif
|
||||
|
||||
/* data to be passed to our callbacks */
|
||||
struct entry_parm_s {
|
||||
/* The thread ID of the popup working thread. */
|
||||
static pth_t popup_tid;
|
||||
|
||||
/* A flag used in communication between the popup working thread and
|
||||
its stop function. */
|
||||
static int popup_finished;
|
||||
|
||||
|
||||
|
||||
/* Data to be passed to our callbacks, */
|
||||
struct entry_parm_s
|
||||
{
|
||||
int lines;
|
||||
size_t size;
|
||||
unsigned char *buffer;
|
||||
@ -67,17 +84,17 @@ struct entry_parm_s {
|
||||
/* This function must be called once to initialize this module. This
|
||||
has to be done before a second thread is spawned. We can't do the
|
||||
static initialization because Pth emulation code might not be able
|
||||
to do a static init; in particualr, it is not possible for W32. */
|
||||
to do a static init; in particular, it is not possible for W32. */
|
||||
void
|
||||
initialize_module_query (void)
|
||||
{
|
||||
#ifdef USE_GNU_PTH
|
||||
static int initialized;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
if (pth_mutex_init (&entry_lock))
|
||||
initialized = 1;
|
||||
#endif /*USE_GNU_PTH*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -102,8 +119,19 @@ agent_query_dump_state (void)
|
||||
log_info ("agent_query_dump_state: entry_lock=");
|
||||
dump_mutex_state (&entry_lock);
|
||||
log_printf ("\n");
|
||||
log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld\n",
|
||||
entry_ctx, (long)assuan_get_pid (entry_ctx));
|
||||
log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n",
|
||||
entry_ctx, (long)assuan_get_pid (entry_ctx), popup_tid);
|
||||
}
|
||||
|
||||
/* Called to make sure that a popup window owned by the current
|
||||
connection gets closed. */
|
||||
void
|
||||
agent_reset_query (ctrl_t ctrl)
|
||||
{
|
||||
if (entry_ctx && popup_tid && entry_owner == ctrl)
|
||||
{
|
||||
agent_popup_message_stop (ctrl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -117,14 +145,12 @@ unlock_pinentry (int rc)
|
||||
assuan_context_t ctx = entry_ctx;
|
||||
|
||||
entry_ctx = NULL;
|
||||
#ifdef USE_GNU_PTH
|
||||
if (!pth_mutex_release (&entry_lock))
|
||||
{
|
||||
log_error ("failed to release the entry lock\n");
|
||||
if (!rc)
|
||||
rc = gpg_error (GPG_ERR_INTERNAL);
|
||||
}
|
||||
#endif
|
||||
assuan_disconnect (ctx);
|
||||
return rc;
|
||||
}
|
||||
@ -145,7 +171,7 @@ atfork_cb (void *opaque, int where)
|
||||
pinentry - we will serialize _all_ pinentry calls.
|
||||
*/
|
||||
static int
|
||||
start_pinentry (CTRL ctrl)
|
||||
start_pinentry (ctrl_t ctrl)
|
||||
{
|
||||
int rc;
|
||||
const char *pgmname;
|
||||
@ -153,9 +179,6 @@ start_pinentry (CTRL ctrl)
|
||||
const char *argv[5];
|
||||
int no_close_list[3];
|
||||
int i;
|
||||
|
||||
#ifdef USE_GNU_PTH
|
||||
{
|
||||
pth_event_t evt;
|
||||
|
||||
evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
|
||||
@ -171,8 +194,8 @@ start_pinentry (CTRL ctrl)
|
||||
return rc;
|
||||
}
|
||||
pth_event_free (evt, PTH_FREE_THIS);
|
||||
}
|
||||
#endif
|
||||
|
||||
entry_owner = ctrl;
|
||||
|
||||
if (entry_ctx)
|
||||
return 0;
|
||||
@ -436,7 +459,7 @@ agent_askpin (ctrl_t ctrl,
|
||||
passphrase is returned in RETPASS as an hex encoded string to be
|
||||
freed by the caller */
|
||||
int
|
||||
agent_get_passphrase (CTRL ctrl,
|
||||
agent_get_passphrase (ctrl_t ctrl,
|
||||
char **retpass, const char *desc, const char *prompt,
|
||||
const char *errtext)
|
||||
{
|
||||
@ -517,11 +540,11 @@ agent_get_passphrase (CTRL ctrl,
|
||||
|
||||
|
||||
/* Pop up the PIN-entry, display the text and the prompt and ask the
|
||||
user to confirm this. We return 0 for success, ie. the used
|
||||
user to confirm this. We return 0 for success, ie. the user
|
||||
confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
|
||||
other error. */
|
||||
int
|
||||
agent_get_confirmation (CTRL ctrl,
|
||||
agent_get_confirmation (ctrl_t ctrl,
|
||||
const char *desc, const char *ok, const char *cancel)
|
||||
{
|
||||
int rc;
|
||||
@ -562,4 +585,119 @@ agent_get_confirmation (CTRL ctrl,
|
||||
}
|
||||
|
||||
|
||||
/* The thread running the popup message. */
|
||||
static void *
|
||||
popup_message_thread (void *arg)
|
||||
{
|
||||
assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
popup_finished = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Pop up a message window similar to the confirm one but keep it open
|
||||
until agent_popup_message_stop has been called. It is crucial for
|
||||
the caller to make sure that the stop function gets called as soon
|
||||
as the message is not anymore required becuase the message is
|
||||
system modal and all other attempts to use the pinentry will fail
|
||||
(after a timeout). */
|
||||
int
|
||||
agent_popup_message_start (ctrl_t ctrl, const char *desc,
|
||||
const char *ok_btn, const char *cancel_btn)
|
||||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
pth_attr_t tattr;
|
||||
|
||||
rc = start_pinentry (ctrl);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (desc)
|
||||
snprintf (line, DIM(line)-1, "SETDESC %s", desc);
|
||||
else
|
||||
snprintf (line, DIM(line)-1, "RESET");
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
|
||||
if (ok_btn)
|
||||
{
|
||||
snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
}
|
||||
if (cancel_btn)
|
||||
{
|
||||
snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel_btn);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
}
|
||||
|
||||
tattr = pth_attr_new();
|
||||
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
|
||||
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
|
||||
pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
|
||||
|
||||
popup_finished = 0;
|
||||
popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
|
||||
if (!popup_tid)
|
||||
{
|
||||
rc = gpg_error_from_errno (errno);
|
||||
log_error ("error spawning popup message handler: %s\n",
|
||||
strerror (errno) );
|
||||
pth_attr_destroy (tattr);
|
||||
return unlock_pinentry (rc);
|
||||
}
|
||||
pth_attr_destroy (tattr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Close a popup window. */
|
||||
void
|
||||
agent_popup_message_stop (ctrl_t ctrl)
|
||||
{
|
||||
int rc;
|
||||
pid_t pid;
|
||||
|
||||
if (!popup_tid || !entry_ctx)
|
||||
{
|
||||
log_debug ("agent_popup_message_stop called with no active popup\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pid = assuan_get_pid (entry_ctx);
|
||||
if (pid == (pid_t)(-1))
|
||||
; /* No pid available can't send a kill. */
|
||||
else if (popup_finished)
|
||||
; /* Already finished and ready for joining. */
|
||||
else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
|
||||
{ /* The daemon already died. No need to send a kill. However
|
||||
because we already waited for the process, we need to tell
|
||||
assuan that it should not wait again (done by
|
||||
unlock_pinentry). */
|
||||
if (rc == pid)
|
||||
assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
|
||||
}
|
||||
else
|
||||
kill (pid, SIGINT);
|
||||
|
||||
/* Now wait for the thread to terminate. */
|
||||
rc = pth_join (popup_tid, NULL);
|
||||
if (!rc)
|
||||
log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
|
||||
strerror (errno));
|
||||
popup_tid = NULL;
|
||||
entry_owner = NULL;
|
||||
|
||||
/* Now we can close the connection. */
|
||||
unlock_pinentry (0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -173,7 +173,8 @@ test_agent_protect (void)
|
||||
|
||||
for (i = 0; i < DIM (specs); i++)
|
||||
{
|
||||
ret = agent_protect (specs[i].key, specs[i].passphrase,
|
||||
ret = agent_protect ((const unsigned char*)specs[i].key,
|
||||
specs[i].passphrase,
|
||||
&specs[i].result, &specs[i].resultlen);
|
||||
if (gpg_err_code (ret) != specs[i].ret_expected)
|
||||
{
|
||||
|
@ -25,7 +25,8 @@ if ! HAVE_DOSISH_SYSTEM
|
||||
AM_CPPFLAGS += -DGNUPG_BINDIR="\"$(bindir)\"" \
|
||||
-DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" \
|
||||
-DGNUPG_LIBDIR="\"$(libdir)/@PACKAGE@\"" \
|
||||
-DGNUPG_DATADIR="\"$(datadir)/@PACKAGE@\""
|
||||
-DGNUPG_DATADIR="\"$(datadir)/@PACKAGE@\"" \
|
||||
-DGNUPG_SYSCONFDIR="\"$(sysconfdir)/@PACKAGE@\""
|
||||
endif
|
||||
|
||||
if GNUPG_AGENT_PGM
|
||||
|
11
configure.ac
11
configure.ac
@ -22,9 +22,12 @@
|
||||
AC_PREREQ(2.52)
|
||||
min_automake_version="1.9.3"
|
||||
|
||||
# Version number: Remember to change it immediately *after* a release.
|
||||
# Add a "-cvs" prefix for non-released code.
|
||||
AC_INIT(gnupg, 1.9.19, gnupg-devel@gnupg.org)
|
||||
# Remember to change the version number immediately *after* a release.
|
||||
# Uncomment the my_iscvs macro for non-released code.
|
||||
m4_define(my_version, [1.9.20])
|
||||
m4_define(my_iscvs, yes)
|
||||
AC_INIT([gnupg], my_version[]m4_ifdef([my_iscvs], [-cvs[]m4_translit(
|
||||
[$Revision$],[Ra-z $:])]), [gnupg-devel@gnupg.org])
|
||||
# Set development_version to yes if the minor number is odd or you
|
||||
# feel that the default check for a development version is not
|
||||
# sufficient.
|
||||
@ -36,7 +39,7 @@ NEED_LIBGCRYPT_VERSION=1.1.94
|
||||
|
||||
NEED_LIBASSUAN_VERSION=0.6.10
|
||||
|
||||
NEED_KSBA_VERSION=0.9.12
|
||||
NEED_KSBA_VERSION=0.9.13
|
||||
|
||||
|
||||
PACKAGE=$PACKAGE_NAME
|
||||
|
@ -61,7 +61,7 @@ X.509 specific are noted like [X.509: xxx]
|
||||
u32 offset to the n-th key's keyID (a keyID is always 8 byte)
|
||||
or 0 if not known which is the case only for X509.
|
||||
u16 special key flags
|
||||
bit 0 =
|
||||
bit 0 = qualified signature (not yet implemented}
|
||||
u16 reserved
|
||||
u16 size of serialnumber(may be zero)
|
||||
n u16 (see above) bytes of serial number
|
||||
|
@ -17,6 +17,7 @@ kbx/kbxutil.c
|
||||
|
||||
scd/scdaemon.c
|
||||
scd/app-openpgp.c
|
||||
scd/app-nks.c
|
||||
|
||||
sm/base64.c
|
||||
sm/call-agent.c
|
||||
|
16
po/de.po
16
po/de.po
@ -10,8 +10,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnupg2 1.9.18\n"
|
||||
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
|
||||
"POT-Creation-Date: 2005-11-23 13:00+0100\n"
|
||||
"PO-Revision-Date: 2005-11-23 13:02+0100\n"
|
||||
"POT-Creation-Date: 2005-11-28 12:14+0100\n"
|
||||
"PO-Revision-Date: 2005-11-28 12:16+0100\n"
|
||||
"Last-Translator: Werner Koch <wk@gnupg.org>\n"
|
||||
"Language-Team: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -766,6 +766,10 @@ msgstr ""
|
||||
msgid "can't access %s - invalid OpenPGP card?\n"
|
||||
msgstr "Zugriff auf %s nicht möglich - ungültige OpenPGP Karte?\n"
|
||||
|
||||
#: scd/app-nks.c:344
|
||||
msgid "the NullPIN has not yet been changed\n"
|
||||
msgstr "Die Nullpin wurde noch nicht geändert\n"
|
||||
|
||||
#: sm/base64.c:317
|
||||
#, c-format
|
||||
msgid "invalid radix64 character %02x skipped\n"
|
||||
@ -1369,7 +1373,7 @@ msgstr "Signieren mit `%s' nicht möglich: %s\n"
|
||||
|
||||
#: sm/gpgsm.c:1475
|
||||
msgid "this command has not yet been implemented\n"
|
||||
msgstr "Diee Kommando wurde noch nicht implementiert\n"
|
||||
msgstr "Dieses Kommando wurde noch nicht implementiert\n"
|
||||
|
||||
#: sm/gpgsm.c:1705 sm/gpgsm.c:1742 sm/qualified.c:73
|
||||
#, c-format
|
||||
@ -1548,10 +1552,10 @@ msgid ""
|
||||
msgstr ""
|
||||
"Sie sind dabei, eine Signatur mit dem Zertifikat:\n"
|
||||
"\"%s\"\n"
|
||||
"zu erzeugen. Dies wird einen qualifizierte Signatur erzeugen, \n"
|
||||
"die gesetzlich einer handgeschriebene gleichgestellt ist.\n"
|
||||
"zu erzeugen. Dies wird eine qualifizierte Signatur erzeugen, \n"
|
||||
"die gesetzlich einer handgeschriebenen gleichgestellt ist.\n"
|
||||
"\n"
|
||||
"%s%sSind Sie wirklich sicher, da Sie dies möchten?"
|
||||
"%s%sSind Sie wirklich sicher, daß Sie dies möchten?"
|
||||
|
||||
#: sm/qualified.c:224
|
||||
msgid ""
|
||||
|
@ -1,8 +1,63 @@
|
||||
2005-11-23 Werner Koch <wk@g10code.com>
|
||||
|
||||
* app-nks.c (verify_pin): Give a special error message for a Nullpin.
|
||||
|
||||
2005-10-29 Werner Koch <wk@g10code.com>
|
||||
|
||||
* ccid-driver.c (send_escape_cmd): New args RESULT, RESULTLEN and
|
||||
RESULTMAX. Changed all callers.
|
||||
(ccid_transceive_escape): New.
|
||||
|
||||
2005-10-27 Werner Koch <wk@g10code.com>
|
||||
|
||||
* apdu.c [__CYGWIN__]: Make cygwin environment similar to _WIN32.
|
||||
Suggested by John P. Clizbe.
|
||||
* scdaemon.c [__CYGWIN__]: Set default PC/SC driver to winscard.dll.
|
||||
|
||||
2005-10-19 Werner Koch <wk@g10code.com>
|
||||
|
||||
* ccid-driver.h (CCID_DRIVER_ERR_NO_KEYPAD): New.
|
||||
* apdu.h (SW_HOST_NO_KEYPAD): New.
|
||||
* iso7816.h (struct iso7816_pininfo_s): New.
|
||||
* iso7816.c (map_sw): Support new code.
|
||||
(iso7816_check_keypad): New.
|
||||
(iso7816_verify_kp, iso7816_change_reference_data_kp)
|
||||
(iso7816_reset_retry_counter_kp): New. Extended versions of the
|
||||
original functions.
|
||||
* apdu.c (host_sw_string): Support new code.
|
||||
(reader_table_s): New field CHECK_KEYPAD.
|
||||
(new_reader_slot, open_ct_reader, open_pcsc_reader)
|
||||
(open_ccid_reader, open_rapdu_reader): Initialize it.
|
||||
(check_ccid_keypad): New.
|
||||
(apdu_check_keypad): New.
|
||||
(apdu_send_le): Factored all code out to ...
|
||||
(send_le): .. new. Takes an additional arg; changed all callers
|
||||
of the orginal function to use this one with a NULL for the new
|
||||
arg.
|
||||
(apdu_send_simple_kp): New.
|
||||
(ct_send_apdu, pcsc_send_apdu, my_rapdu_send_apdu)
|
||||
(send_apdu_ccid): New arg PININFO.
|
||||
(send_apdu_ccid): Use the new arg.
|
||||
|
||||
* scdaemon.c: New option --disable-keypad.
|
||||
|
||||
2005-10-08 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* Makefile.am (scdaemon_LDADD): Add ../gl/libgnu.a after
|
||||
../common/libcommon.a.
|
||||
|
||||
2005-09-20 Werner Koch <wk@g10code.com>
|
||||
|
||||
* app-dinsig.c (verify_pin): Try ISO 9564 BCD encoding.
|
||||
|
||||
* iso7816.c (iso7816_select_application): Add arg FLAGS. Changed
|
||||
all callers to pass 0.
|
||||
* app-openpgp.c (app_select_openpgp): But this one requires a
|
||||
special flag.
|
||||
|
||||
* app-p15.c (app_select_p15): Don't use select application for the
|
||||
BELPIC.
|
||||
|
||||
2005-09-09 Werner Koch <wk@g10code.com>
|
||||
|
||||
* pcsc-wrapper.c (main): Removed bogus free.
|
||||
|
168
scd/apdu.c
168
scd/apdu.c
@ -66,10 +66,10 @@
|
||||
#include "ccid-driver.h"
|
||||
|
||||
|
||||
/* To to conflicting use of threading libraries we usually can't link
|
||||
/* Due to conflicting use of threading libraries we usually can't link
|
||||
against libpcsclite. Instead we use a wrapper program. */
|
||||
#ifdef USE_GNU_PTH
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
#if !defined(HAVE_W32_SYSTEM) && !defined(__CYGWIN__)
|
||||
#define NEED_PCSC_WRAPPER 1
|
||||
#endif
|
||||
#endif
|
||||
@ -78,7 +78,7 @@
|
||||
#define MAX_READER 4 /* Number of readers we support concurrently. */
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define DLSTDCALL __stdcall
|
||||
#else
|
||||
#define DLSTDCALL
|
||||
@ -90,6 +90,14 @@
|
||||
#define MAX_OPEN_FDS 20
|
||||
#endif
|
||||
|
||||
/* Helper to pass patrameters related to keypad based operations. */
|
||||
struct pininfo_s
|
||||
{
|
||||
int mode;
|
||||
int minlen;
|
||||
int maxlen;
|
||||
int padlen;
|
||||
};
|
||||
|
||||
/* A structure to collect information pertaining to one reader
|
||||
slot. */
|
||||
@ -103,7 +111,8 @@ struct reader_table_s {
|
||||
int (*reset_reader)(int);
|
||||
int (*get_status_reader)(int, unsigned int *);
|
||||
int (*send_apdu_reader)(int,unsigned char *,size_t,
|
||||
unsigned char *, size_t *);
|
||||
unsigned char *, size_t *, struct pininfo_s *);
|
||||
int (*check_keypad)(int, int, int, int, int, int);
|
||||
void (*dump_status_reader)(int);
|
||||
|
||||
struct {
|
||||
@ -320,6 +329,7 @@ new_reader_slot (void)
|
||||
reader_table[reader].reset_reader = NULL;
|
||||
reader_table[reader].get_status_reader = NULL;
|
||||
reader_table[reader].send_apdu_reader = NULL;
|
||||
reader_table[reader].check_keypad = NULL;
|
||||
reader_table[reader].dump_status_reader = NULL;
|
||||
|
||||
reader_table[reader].used = 1;
|
||||
@ -372,6 +382,7 @@ host_sw_string (long err)
|
||||
case SW_HOST_GENERAL_ERROR: return "general error";
|
||||
case SW_HOST_NO_READER: return "no reader";
|
||||
case SW_HOST_ABORTED: return "aborted";
|
||||
case SW_HOST_NO_KEYPAD: return "no keypad";
|
||||
default: return "unknown host status error";
|
||||
}
|
||||
}
|
||||
@ -533,7 +544,7 @@ ct_get_status (int slot, unsigned int *status)
|
||||
set to BUFLEN. Returns: CT API error code. */
|
||||
static int
|
||||
ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen)
|
||||
unsigned char *buffer, size_t *buflen, struct pininfo_s *pininfo)
|
||||
{
|
||||
int rc;
|
||||
unsigned char dad[1], sad[1];
|
||||
@ -596,6 +607,7 @@ open_ct_reader (int port)
|
||||
reader_table[reader].reset_reader = reset_ct_reader;
|
||||
reader_table[reader].get_status_reader = ct_get_status;
|
||||
reader_table[reader].send_apdu_reader = ct_send_apdu;
|
||||
reader_table[reader].check_keypad = NULL;
|
||||
reader_table[reader].dump_status_reader = ct_dump_reader_status;
|
||||
|
||||
dump_reader_status (reader);
|
||||
@ -1082,7 +1094,8 @@ pcsc_get_status (int slot, unsigned int *status)
|
||||
set to BUFLEN. Returns: CT API error code. */
|
||||
static int
|
||||
pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen)
|
||||
unsigned char *buffer, size_t *buflen,
|
||||
struct pininfo_s *pininfo)
|
||||
{
|
||||
#ifdef NEED_PCSC_WRAPPER
|
||||
long err;
|
||||
@ -1479,6 +1492,7 @@ open_pcsc_reader (const char *portstr)
|
||||
reader_table[slot].reset_reader = reset_pcsc_reader;
|
||||
reader_table[slot].get_status_reader = pcsc_get_status;
|
||||
reader_table[slot].send_apdu_reader = pcsc_send_apdu;
|
||||
reader_table[slot].check_keypad = NULL;
|
||||
reader_table[slot].dump_status_reader = dump_pcsc_reader_status;
|
||||
|
||||
/* Read the status so that IS_T0 will be set. */
|
||||
@ -1625,6 +1639,7 @@ open_pcsc_reader (const char *portstr)
|
||||
reader_table[slot].reset_reader = reset_pcsc_reader;
|
||||
reader_table[slot].get_status_reader = pcsc_get_status;
|
||||
reader_table[slot].send_apdu_reader = pcsc_send_apdu;
|
||||
reader_table[slot].check_keypad = NULL;
|
||||
reader_table[slot].dump_status_reader = dump_pcsc_reader_status;
|
||||
|
||||
/* log_debug ("state from pcsc_status: 0x%lx\n", card_state); */
|
||||
@ -1713,7 +1728,8 @@ get_status_ccid (int slot, unsigned int *status)
|
||||
set to BUFLEN. Returns: Internal CCID driver error code. */
|
||||
static int
|
||||
send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen)
|
||||
unsigned char *buffer, size_t *buflen,
|
||||
struct pininfo_s *pininfo)
|
||||
{
|
||||
long err;
|
||||
size_t maxbuflen;
|
||||
@ -1727,6 +1743,15 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
|
||||
log_printhex (" APDU_data:", apdu, apdulen);
|
||||
|
||||
maxbuflen = *buflen;
|
||||
if (pininfo)
|
||||
err = ccid_transceive_secure (reader_table[slot].ccid.handle,
|
||||
apdu, apdulen,
|
||||
pininfo->mode,
|
||||
pininfo->minlen,
|
||||
pininfo->maxlen,
|
||||
pininfo->padlen,
|
||||
buffer, maxbuflen, buflen);
|
||||
else
|
||||
err = ccid_transceive (reader_table[slot].ccid.handle,
|
||||
apdu, apdulen,
|
||||
buffer, maxbuflen, buflen);
|
||||
@ -1737,6 +1762,24 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Check whether the CCID reader supports the ISO command code COMMAND
|
||||
on the keypad. Return 0 on success. For a description of the pin
|
||||
parameters, see ccid-driver.c */
|
||||
static int
|
||||
check_ccid_keypad (int slot, int command, int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen)
|
||||
{
|
||||
unsigned char apdu[] = { 0, 0, 0, 0x81 };
|
||||
|
||||
apdu[1] = command;
|
||||
return ccid_transceive_secure (reader_table[slot].ccid.handle,
|
||||
apdu, sizeof apdu,
|
||||
pin_mode, pinlen_min, pinlen_max, pin_padlen,
|
||||
NULL, 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Open the reader and try to read an ATR. */
|
||||
static int
|
||||
open_ccid_reader (const char *portstr)
|
||||
@ -1776,6 +1819,7 @@ open_ccid_reader (const char *portstr)
|
||||
reader_table[slot].reset_reader = reset_ccid_reader;
|
||||
reader_table[slot].get_status_reader = get_status_ccid;
|
||||
reader_table[slot].send_apdu_reader = send_apdu_ccid;
|
||||
reader_table[slot].check_keypad = check_ccid_keypad;
|
||||
reader_table[slot].dump_status_reader = dump_ccid_reader_status;
|
||||
|
||||
dump_reader_status (slot);
|
||||
@ -1932,7 +1976,8 @@ my_rapdu_get_status (int slot, unsigned int *status)
|
||||
set to BUFLEN. Returns: APDU error code. */
|
||||
static int
|
||||
my_rapdu_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen)
|
||||
unsigned char *buffer, size_t *buflen,
|
||||
struct pininfo_s *pininfo)
|
||||
{
|
||||
int err;
|
||||
reader_table_t slotp;
|
||||
@ -2063,6 +2108,7 @@ open_rapdu_reader (int portno,
|
||||
reader_table[slot].reset_reader = reset_rapdu_reader;
|
||||
reader_table[slot].get_status_reader = my_rapdu_get_status;
|
||||
reader_table[slot].send_apdu_reader = my_rapdu_send_apdu;
|
||||
reader_table[slot].check_keypad = NULL;
|
||||
reader_table[slot].dump_status_reader = NULL;
|
||||
|
||||
dump_reader_status (slot);
|
||||
@ -2198,28 +2244,28 @@ apdu_open_reader (const char *portstr)
|
||||
pcsc_establish_context = dlsym (handle, "SCardEstablishContext");
|
||||
pcsc_release_context = dlsym (handle, "SCardReleaseContext");
|
||||
pcsc_list_readers = dlsym (handle, "SCardListReaders");
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
if (!pcsc_list_readers)
|
||||
pcsc_list_readers = dlsym (handle, "SCardListReadersA");
|
||||
#endif
|
||||
pcsc_get_status_change = dlsym (handle, "SCardGetStatusChange");
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
if (!pcsc_get_status_change)
|
||||
pcsc_get_status_change = dlsym (handle, "SCardGetStatusChangeA");
|
||||
#endif
|
||||
pcsc_connect = dlsym (handle, "SCardConnect");
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
if (!pcsc_connect)
|
||||
pcsc_connect = dlsym (handle, "SCardConnectA");
|
||||
#endif
|
||||
pcsc_reconnect = dlsym (handle, "SCardReconnect");
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
if (!pcsc_reconnect)
|
||||
pcsc_reconnect = dlsym (handle, "SCardReconnectA");
|
||||
#endif
|
||||
pcsc_disconnect = dlsym (handle, "SCardDisconnect");
|
||||
pcsc_status = dlsym (handle, "SCardStatus");
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
if (!pcsc_status)
|
||||
pcsc_status = dlsym (handle, "SCardStatusA");
|
||||
#endif
|
||||
@ -2492,11 +2538,30 @@ apdu_get_status (int slot, int hang,
|
||||
}
|
||||
|
||||
|
||||
/* Check whether the reader supports the ISO command code COMMAND on
|
||||
the keypad. Return 0 on success. For a description of the pin
|
||||
parameters, see ccid-driver.c */
|
||||
int
|
||||
apdu_check_keypad (int slot, int command, int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen)
|
||||
{
|
||||
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
|
||||
return SW_HOST_NO_DRIVER;
|
||||
|
||||
if (reader_table[slot].check_keypad)
|
||||
return reader_table[slot].check_keypad (slot, command,
|
||||
pin_mode, pinlen_min, pinlen_max,
|
||||
pin_padlen);
|
||||
else
|
||||
return SW_HOST_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
/* Dispatcher for the actual send_apdu function. Note, that this
|
||||
function should be called in locked state. */
|
||||
static int
|
||||
send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen)
|
||||
unsigned char *buffer, size_t *buflen, struct pininfo_s *pininfo)
|
||||
{
|
||||
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
|
||||
return SW_HOST_NO_DRIVER;
|
||||
@ -2504,24 +2569,20 @@ send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
||||
if (reader_table[slot].send_apdu_reader)
|
||||
return reader_table[slot].send_apdu_reader (slot,
|
||||
apdu, apdulen,
|
||||
buffer, buflen);
|
||||
buffer, buflen, pininfo);
|
||||
else
|
||||
return SW_HOST_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Send an APDU to the card in SLOT. The APDU is created from all
|
||||
given parameters: CLASS, INS, P0, P1, LC, DATA, LE. A value of -1
|
||||
for LC won't sent this field and the data field; in this case DATA
|
||||
must also be passed as NULL. The return value is the status word
|
||||
or -1 for an invalid SLOT or other non card related error. If
|
||||
RETBUF is not NULL, it will receive an allocated buffer with the
|
||||
returned data. The length of that data will be put into
|
||||
*RETBUFLEN. The caller is reponsible for releasing the buffer even
|
||||
in case of errors. */
|
||||
int
|
||||
apdu_send_le(int slot, int class, int ins, int p0, int p1,
|
||||
|
||||
/* Core APDU trabceiver function. Parameters are described at
|
||||
apdu_send_le with the exception of PININFO which indicates keypad
|
||||
related operations if not NULL. */
|
||||
static int
|
||||
send_le (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data, int le,
|
||||
unsigned char **retbuf, size_t *retbuflen)
|
||||
unsigned char **retbuf, size_t *retbuflen,
|
||||
struct pininfo_s *pininfo)
|
||||
{
|
||||
#define RESULTLEN 256
|
||||
unsigned char result[RESULTLEN+10]; /* 10 extra in case of bugs in
|
||||
@ -2570,7 +2631,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1,
|
||||
/* As safeguard don't pass any garbage from the stack to the driver. */
|
||||
memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
|
||||
resultlen = RESULTLEN;
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen, pininfo);
|
||||
if (rc || resultlen < 2)
|
||||
{
|
||||
log_error ("apdu_send_simple(%d) failed: %s\n",
|
||||
@ -2638,7 +2699,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1,
|
||||
apdu[apdulen++] = len;
|
||||
memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
|
||||
resultlen = RESULTLEN;
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen, NULL);
|
||||
if (rc || resultlen < 2)
|
||||
{
|
||||
log_error ("apdu_send_simple(%d) for get response failed: %s\n",
|
||||
@ -2703,6 +2764,27 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1,
|
||||
#undef RESULTLEN
|
||||
}
|
||||
|
||||
/* Send an APDU to the card in SLOT. The APDU is created from all
|
||||
given parameters: CLASS, INS, P0, P1, LC, DATA, LE. A value of -1
|
||||
for LC won't sent this field and the data field; in this case DATA
|
||||
must also be passed as NULL. The return value is the status word
|
||||
or -1 for an invalid SLOT or other non card related error. If
|
||||
RETBUF is not NULL, it will receive an allocated buffer with the
|
||||
returned data. The length of that data will be put into
|
||||
*RETBUFLEN. The caller is reponsible for releasing the buffer even
|
||||
in case of errors. */
|
||||
int
|
||||
apdu_send_le(int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data, int le,
|
||||
unsigned char **retbuf, size_t *retbuflen)
|
||||
{
|
||||
return send_le (slot, class, ins, p0, p1,
|
||||
lc, data, le,
|
||||
retbuf, retbuflen,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Send an APDU to the card in SLOT. The APDU is created from all
|
||||
given parameters: CLASS, INS, P0, P1, LC, DATA. A value of -1 for
|
||||
LC won't sent this field and the data field; in this case DATA must
|
||||
@ -2716,8 +2798,8 @@ int
|
||||
apdu_send (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data, unsigned char **retbuf, size_t *retbuflen)
|
||||
{
|
||||
return apdu_send_le (slot, class, ins, p0, p1, lc, data, 256,
|
||||
retbuf, retbuflen);
|
||||
return send_le (slot, class, ins, p0, p1, lc, data, 256,
|
||||
retbuf, retbuflen, NULL);
|
||||
}
|
||||
|
||||
/* Send an APDU to the card in SLOT. The APDU is created from all
|
||||
@ -2730,7 +2812,25 @@ int
|
||||
apdu_send_simple (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data)
|
||||
{
|
||||
return apdu_send_le (slot, class, ins, p0, p1, lc, data, -1, NULL, NULL);
|
||||
return send_le (slot, class, ins, p0, p1, lc, data, -1, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Same as apdu_send_simple but uses the keypad of the reader. */
|
||||
int
|
||||
apdu_send_simple_kp (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data,
|
||||
int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen)
|
||||
{
|
||||
struct pininfo_s pininfo;
|
||||
|
||||
pininfo.mode = pin_mode;
|
||||
pininfo.minlen = pinlen_min;
|
||||
pininfo.maxlen = pinlen_max;
|
||||
pininfo.padlen = pin_padlen;
|
||||
return send_le (slot, class, ins, p0, p1, lc, data, -1,
|
||||
NULL, NULL, &pininfo);
|
||||
}
|
||||
|
||||
|
||||
@ -2771,7 +2871,7 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen,
|
||||
class = apdulen? *apdu : 0;
|
||||
|
||||
resultlen = RESULTLEN;
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen, NULL);
|
||||
if (rc || resultlen < 2)
|
||||
{
|
||||
log_error ("apdu_send_direct(%d) failed: %s\n",
|
||||
@ -2825,7 +2925,7 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen,
|
||||
apdu[apdulen++] = len;
|
||||
memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
|
||||
resultlen = RESULTLEN;
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen, NULL);
|
||||
if (rc || resultlen < 2)
|
||||
{
|
||||
log_error ("apdu_send_direct(%d) for get response failed: %s\n",
|
||||
|
@ -63,7 +63,8 @@ enum {
|
||||
SW_HOST_CARD_IO_ERROR = 0x1000a,
|
||||
SW_HOST_GENERAL_ERROR = 0x1000b,
|
||||
SW_HOST_NO_READER = 0x1000c,
|
||||
SW_HOST_ABORTED = 0x1000d
|
||||
SW_HOST_ABORTED = 0x1000d,
|
||||
SW_HOST_NO_KEYPAD = 0x1000e
|
||||
};
|
||||
|
||||
|
||||
@ -96,8 +97,14 @@ int apdu_activate (int slot);
|
||||
int apdu_reset (int slot);
|
||||
int apdu_get_status (int slot, int hang,
|
||||
unsigned int *status, unsigned int *changed);
|
||||
int apdu_check_keypad (int slot, int command, int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen);
|
||||
int apdu_send_simple (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data);
|
||||
int apdu_send_simple_kp (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data,
|
||||
int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen);
|
||||
int apdu_send (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data,
|
||||
unsigned char **retbuf, size_t *retbuflen);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* app-dinsig.c - The DINSIG (DIN V 66291-1) card application.
|
||||
* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -280,6 +280,7 @@ verify_pin (app_t app,
|
||||
{
|
||||
if (!app->did_chv1 || app->force_chv1 )
|
||||
{
|
||||
const char *s;
|
||||
char *pinvalue;
|
||||
int rc;
|
||||
|
||||
@ -291,8 +292,16 @@ verify_pin (app_t app,
|
||||
}
|
||||
|
||||
/* We require the PIN to be at least 6 and at max 8 bytes.
|
||||
According to the specs, this should all be ASCII but we don't
|
||||
check this. */
|
||||
According to the specs, this should all be ASCII. */
|
||||
for (s=pinvalue; digitp (s); s++)
|
||||
;
|
||||
if (*s)
|
||||
{
|
||||
log_error ("Non-numeric digits found in PIN\n");
|
||||
xfree (pinvalue);
|
||||
return gpg_error (GPG_ERR_BAD_PIN);
|
||||
}
|
||||
|
||||
if (strlen (pinvalue) < 6)
|
||||
{
|
||||
log_error ("PIN is too short; minimum length is 6\n");
|
||||
@ -307,6 +316,28 @@ verify_pin (app_t app,
|
||||
}
|
||||
|
||||
rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
|
||||
if (gpg_err_code (rc) == GPG_ERR_INV_VALUE)
|
||||
{
|
||||
/* We assume that ISO 9564-1 encoding is used and we failed
|
||||
because the first nibble we passed was 3 and not 2. DIN
|
||||
says something about looking up such an encoding in the
|
||||
SSD but I was not able to find any tag relevant to
|
||||
this. */
|
||||
char paddedpin[8];
|
||||
int i, ndigits;
|
||||
|
||||
for (ndigits=0, s=pinvalue; *s; ndigits++, s++)
|
||||
;
|
||||
i = 0;
|
||||
paddedpin[i++] = 0x20 | (ndigits & 0x0f);
|
||||
for (s=pinvalue; i < sizeof paddedpin && *s && s[1]; s = s+2 )
|
||||
paddedpin[i++] = (((*s - '0') << 4) | ((s[1] - '0') & 0x0f));
|
||||
if (i < sizeof paddedpin && *s)
|
||||
paddedpin[i++] = (((*s - '0') << 4) | 0x0f);
|
||||
while (i < sizeof paddedpin)
|
||||
paddedpin[i++] = 0xff;
|
||||
rc = iso7816_verify (app->slot, 0x81, paddedpin, sizeof paddedpin);
|
||||
}
|
||||
if (rc)
|
||||
{
|
||||
log_error ("verify PIN failed\n");
|
||||
@ -404,7 +435,7 @@ app_select_dinsig (APP app)
|
||||
int slot = app->slot;
|
||||
int rc;
|
||||
|
||||
rc = iso7816_select_application (slot, aid, sizeof aid);
|
||||
rc = iso7816_select_application (slot, aid, sizeof aid, 0);
|
||||
if (!rc)
|
||||
{
|
||||
app->apptype = "DINSIG";
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <time.h>
|
||||
|
||||
#include "scdaemon.h"
|
||||
|
||||
#include "i18n.h"
|
||||
#include "iso7816.h"
|
||||
#include "app-common.h"
|
||||
#include "tlv.h"
|
||||
@ -320,7 +320,7 @@ verify_pin (app_t app,
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* The follwoing limits are due to TCOS but also defined in the
|
||||
/* The following limits are due to TCOS but also defined in the
|
||||
NKS specs. */
|
||||
if (strlen (pinvalue) < 6)
|
||||
{
|
||||
@ -340,6 +340,9 @@ verify_pin (app_t app,
|
||||
rc = iso7816_verify (app->slot, 0, pinvalue, strlen (pinvalue));
|
||||
if (rc)
|
||||
{
|
||||
if ( gpg_error (rc) == GPG_ERR_USE_CONDITIONS )
|
||||
log_error (_("the NullPIN has not yet been changed\n"));
|
||||
else
|
||||
log_error ("verify PIN failed\n");
|
||||
xfree (pinvalue);
|
||||
return rc;
|
||||
@ -492,7 +495,7 @@ app_select_nks (APP app)
|
||||
int slot = app->slot;
|
||||
int rc;
|
||||
|
||||
rc = iso7816_select_application (slot, aid, sizeof aid);
|
||||
rc = iso7816_select_application (slot, aid, sizeof aid, 0);
|
||||
if (!rc)
|
||||
{
|
||||
app->apptype = "NKS";
|
||||
|
@ -1284,6 +1284,11 @@ verify_chv2 (app_t app,
|
||||
if (!app->did_chv2)
|
||||
{
|
||||
char *pinvalue;
|
||||
iso7816_pininfo_t pininfo;
|
||||
|
||||
memset (&pininfo, 0, sizeof pininfo);
|
||||
pininfo.mode = 1;
|
||||
pininfo.minlen = 6;
|
||||
|
||||
rc = pincb (pincb_arg, "PIN", &pinvalue);
|
||||
if (rc)
|
||||
@ -2455,7 +2460,9 @@ app_select_openpgp (app_t app)
|
||||
size_t buflen;
|
||||
void *relptr;
|
||||
|
||||
rc = iso7816_select_application (slot, aid, sizeof aid);
|
||||
/* Note that the card can't cope with P2=0xCO, thus we need to pass a
|
||||
special flag value. */
|
||||
rc = iso7816_select_application (slot, aid, sizeof aid, 0x0001);
|
||||
if (!rc)
|
||||
{
|
||||
unsigned int manufacturer;
|
||||
|
@ -3268,18 +3268,15 @@ app_select_p15 (app_t app)
|
||||
int direct = 0;
|
||||
int is_belpic = 0;
|
||||
|
||||
rc = iso7816_select_application (slot, pkcs15_aid, sizeof pkcs15_aid);
|
||||
if (rc)
|
||||
{
|
||||
rc = iso7816_select_application (slot, pkcs15be_aid,sizeof pkcs15be_aid);
|
||||
if (!rc)
|
||||
is_belpic = 1;
|
||||
}
|
||||
rc = iso7816_select_application (slot, pkcs15_aid, sizeof pkcs15_aid, 0);
|
||||
if (rc)
|
||||
{ /* Not found: Try to locate it from 2F00. We use direct path
|
||||
selection here because it seems that the Belgian eID card
|
||||
does only allow for that. Many other cards supports this
|
||||
selection method too. */
|
||||
selection method too. Note, that we don't use
|
||||
select_application above for the Belgian card - the call
|
||||
works but it seems that it did not switch to the correct DF.
|
||||
Using the 2f02 just works. */
|
||||
unsigned short path[1] = { 0x2f00 };
|
||||
|
||||
rc = iso7816_select_path (app->slot, path, 1, NULL, NULL);
|
||||
|
@ -1240,7 +1240,9 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
|
||||
if (CCID_COMMAND_FAILED (buffer))
|
||||
print_command_failed (buffer);
|
||||
|
||||
/* Check whether a card is at all available. */
|
||||
/* Check whether a card is at all available. Note: If you add new
|
||||
error codes here, check whether they need to be ignored in
|
||||
send_escape_cmd. */
|
||||
switch ((buffer[7] & 0x03))
|
||||
{
|
||||
case 0: /* no error */ break;
|
||||
@ -1253,16 +1255,23 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
|
||||
|
||||
|
||||
/* Note that this function won't return the error codes NO_CARD or
|
||||
CARD_INACTIVE */
|
||||
CARD_INACTIVE. IF RESULT is not NULL, the result from the
|
||||
operation will get returned in RESULT and its length in RESULTLEN.
|
||||
If the response is larger than RESULTMAX, an error is returned and
|
||||
the required buffer length returned in RESULTLEN. */
|
||||
static int
|
||||
send_escape_cmd (ccid_driver_t handle,
|
||||
const unsigned char *data, size_t datalen)
|
||||
const unsigned char *data, size_t datalen,
|
||||
unsigned char *result, size_t resultmax, size_t *resultlen)
|
||||
{
|
||||
int i, rc;
|
||||
unsigned char msg[100];
|
||||
size_t msglen;
|
||||
unsigned char seqno;
|
||||
|
||||
if (resultlen)
|
||||
*resultlen = 0;
|
||||
|
||||
if (datalen > sizeof msg - 10)
|
||||
return CCID_DRIVER_ERR_INV_VALUE; /* Escape data too large. */
|
||||
|
||||
@ -1285,11 +1294,42 @@ send_escape_cmd (ccid_driver_t handle,
|
||||
return rc;
|
||||
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape,
|
||||
seqno, 5000, 0);
|
||||
if (result)
|
||||
switch (rc)
|
||||
{
|
||||
/* We need to ignore certain errorcode here. */
|
||||
case 0:
|
||||
case CCID_DRIVER_ERR_CARD_INACTIVE:
|
||||
case CCID_DRIVER_ERR_NO_CARD:
|
||||
{
|
||||
if (msglen > resultmax)
|
||||
rc = CCID_DRIVER_ERR_INV_VALUE; /* Response too large. */
|
||||
else
|
||||
{
|
||||
memcpy (result, msg, msglen);
|
||||
*resultlen = msglen;
|
||||
}
|
||||
rc = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ccid_transceive_escape (ccid_driver_t handle,
|
||||
const unsigned char *data, size_t datalen,
|
||||
unsigned char *resp, size_t maxresplen, size_t *nresp)
|
||||
{
|
||||
return send_escape_cmd (handle, data, datalen, resp, maxresplen, nresp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* experimental */
|
||||
int
|
||||
ccid_poll (ccid_driver_t handle)
|
||||
@ -1445,7 +1485,8 @@ ccid_get_atr (ccid_driver_t handle,
|
||||
{
|
||||
tried_iso = 1;
|
||||
/* Try switching to ISO mode. */
|
||||
if (!send_escape_cmd (handle, (const unsigned char*)"\xF1\x01", 2))
|
||||
if (!send_escape_cmd (handle, (const unsigned char*)"\xF1\x01", 2,
|
||||
NULL, 0, NULL))
|
||||
goto again;
|
||||
}
|
||||
else if (CCID_COMMAND_FAILED (msg))
|
||||
@ -1957,14 +1998,16 @@ ccid_transceive (ccid_driver_t handle,
|
||||
}
|
||||
|
||||
|
||||
/* Send the CCID Secure command to the reader. APDU_BUF should contain the APDU template. PIN_MODE defines now the pin gets formatted:
|
||||
/* Send the CCID Secure command to the reader. APDU_BUF should
|
||||
contain the APDU template. PIN_MODE defines how the pin gets
|
||||
formatted:
|
||||
|
||||
1 := The PIN is ASCII encoded and of variable length. The
|
||||
length of the PIN entered will be put into Lc by the reader.
|
||||
The APDU should me made up of 4 bytes without Lc.
|
||||
|
||||
PINLEN_MIN and PINLEN_MAX define the limits for the pin length. 0
|
||||
may be used t enable usbale defaults. PIN_PADLEN should be 0
|
||||
may be used t enable reasonable defaults. PIN_PADLEN should be 0.
|
||||
|
||||
When called with RESP and NRESP set to NULL, the function will
|
||||
merely check whether the reader supports the secure command for the
|
||||
@ -1996,7 +2039,7 @@ ccid_transceive_secure (ccid_driver_t handle,
|
||||
else if (apdu_buflen >= 4 && apdu_buf[1] == 0x24 && (handle->has_pinpad & 2))
|
||||
return CCID_DRIVER_ERR_NOT_SUPPORTED; /* Not yet by our code. */
|
||||
else
|
||||
return CCID_DRIVER_ERR_NOT_SUPPORTED;
|
||||
return CCID_DRIVER_ERR_NO_KEYPAD;
|
||||
|
||||
if (pin_mode != 1)
|
||||
return CCID_DRIVER_ERR_NOT_SUPPORTED;
|
||||
@ -2027,7 +2070,8 @@ ccid_transceive_secure (ccid_driver_t handle,
|
||||
if (handle->id_vendor == VENDOR_SCM)
|
||||
{
|
||||
DEBUGOUT ("sending escape sequence to switch to a case 1 APDU\n");
|
||||
rc = send_escape_cmd (handle, (const unsigned char*)"\x80\x02\x00", 3);
|
||||
rc = send_escape_cmd (handle, (const unsigned char*)"\x80\x02\x00", 3,
|
||||
NULL, 0, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
@ -2044,7 +2088,7 @@ ccid_transceive_secure (ccid_driver_t handle,
|
||||
if (handle->id_vendor == VENDOR_SCM)
|
||||
{
|
||||
/* For the SPR532 the next 2 bytes need to be zero. We do this
|
||||
for all SCM product. Kudos to to Martin Paljak for this
|
||||
for all SCM product. Kudos to Martin Paljak for this
|
||||
hint. */
|
||||
msg[13] = msg[14] = 0;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@
|
||||
#ifndef CCID_DRIVER_H
|
||||
#define CCID_DRIVER_H
|
||||
|
||||
/* The CID driver returns the same error codes as the statsu words
|
||||
/* The CID driver returns the same error codes as the status words
|
||||
used by GnuPG's apdu.h. For ease of maintenance they should always
|
||||
match. */
|
||||
#define CCID_DRIVER_ERR_OUT_OF_CORE 0x10001
|
||||
@ -74,6 +74,7 @@
|
||||
#define CCID_DRIVER_ERR_GENERAL_ERROR 0x1000b
|
||||
#define CCID_DRIVER_ERR_NO_READER 0x1000c
|
||||
#define CCID_DRIVER_ERR_ABORTED 0x1000d
|
||||
#define CCID_DRIVER_ERR_NO_KEYPAD 0x1000e
|
||||
|
||||
struct ccid_driver_s;
|
||||
typedef struct ccid_driver_s *ccid_driver_t;
|
||||
@ -94,6 +95,10 @@ int ccid_transceive_secure (ccid_driver_t handle,
|
||||
int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen,
|
||||
unsigned char *resp, size_t maxresplen, size_t *nresp);
|
||||
int ccid_transceive_escape (ccid_driver_t handle,
|
||||
const unsigned char *data, size_t datalen,
|
||||
unsigned char *resp, size_t maxresplen,
|
||||
size_t *nresp);
|
||||
|
||||
|
||||
|
||||
|
105
scd/iso7816.c
105
scd/iso7816.c
@ -47,9 +47,9 @@
|
||||
|
||||
|
||||
#define CMD_SELECT_FILE 0xA4
|
||||
#define CMD_VERIFY 0x20
|
||||
#define CMD_CHANGE_REFERENCE_DATA 0x24
|
||||
#define CMD_RESET_RETRY_COUNTER 0x2C
|
||||
#define CMD_VERIFY ISO7816_VERIFY
|
||||
#define CMD_CHANGE_REFERENCE_DATA ISO7816_CHANGE_REFERENCE_DATA
|
||||
#define CMD_RESET_RETRY_COUNTER ISO7816_RESET_RETRY_COUNTER
|
||||
#define CMD_GET_DATA 0xCA
|
||||
#define CMD_PUT_DATA 0xDA
|
||||
#define CMD_MSE 0x22
|
||||
@ -95,6 +95,7 @@ map_sw (int sw)
|
||||
case SW_HOST_GENERAL_ERROR: ec = GPG_ERR_GENERAL; break;
|
||||
case SW_HOST_NO_READER: ec = GPG_ERR_ENODEV; break;
|
||||
case SW_HOST_ABORTED: ec = GPG_ERR_CANCELED; break;
|
||||
case SW_HOST_NO_KEYPAD: ec = GPG_ERR_NOT_SUPPORTED; break;
|
||||
|
||||
default:
|
||||
if ((sw & 0x010000))
|
||||
@ -124,12 +125,15 @@ iso7816_map_sw (int sw)
|
||||
requested application ID. The function can't be used to enumerate
|
||||
AIDs and won't return the AID on success. The return value is 0
|
||||
for okay or a GPG error code. Note that ISO error codes are
|
||||
internally mapped. */
|
||||
internally mapped. Bit 0 of FLAGS should be set if the card does
|
||||
not understand P2=0xC0. */
|
||||
gpg_error_t
|
||||
iso7816_select_application (int slot, const char *aid, size_t aidlen)
|
||||
iso7816_select_application (int slot, const char *aid, size_t aidlen,
|
||||
unsigned int flags)
|
||||
{
|
||||
int sw;
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4, 0, aidlen, aid);
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4,
|
||||
(flags&1)? 0 :0x0c, aidlen, aid);
|
||||
return map_sw (sw);
|
||||
}
|
||||
|
||||
@ -221,27 +225,59 @@ iso7816_list_directory (int slot, int list_dirs,
|
||||
}
|
||||
|
||||
|
||||
/* Check whether the reader supports the ISO command code COMMAND on
|
||||
the keypad. Returns 0 on success. */
|
||||
gpg_error_t
|
||||
iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo)
|
||||
{
|
||||
int sw;
|
||||
|
||||
sw = apdu_check_keypad (slot, command,
|
||||
pininfo->mode, pininfo->minlen, pininfo->maxlen,
|
||||
pininfo->padlen);
|
||||
return map_sw (sw);
|
||||
}
|
||||
|
||||
|
||||
/* Perform a VERIFY command on SLOT using the card holder verification
|
||||
vector CHVNO with a CHV of lenght CHVLEN. With PININFO non-NULL
|
||||
the keypad of the reader will be used. Returns 0 on success. */
|
||||
gpg_error_t
|
||||
iso7816_verify_kp (int slot, int chvno, const char *chv, size_t chvlen,
|
||||
iso7816_pininfo_t *pininfo)
|
||||
{
|
||||
int sw;
|
||||
|
||||
if (pininfo && pininfo->mode)
|
||||
sw = apdu_send_simple_kp (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv,
|
||||
pininfo->mode,
|
||||
pininfo->minlen,
|
||||
pininfo->maxlen,
|
||||
pininfo->padlen);
|
||||
else
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv);
|
||||
return map_sw (sw);
|
||||
}
|
||||
|
||||
/* Perform a VERIFY command on SLOT using the card holder verification
|
||||
vector CHVNO with a CHV of lenght CHVLEN. Returns 0 on success. */
|
||||
gpg_error_t
|
||||
iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
|
||||
{
|
||||
int sw;
|
||||
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv);
|
||||
return map_sw (sw);
|
||||
return iso7816_verify_kp (slot, chvno, chv, chvlen, NULL);
|
||||
}
|
||||
|
||||
/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
|
||||
verification vector CHVNO. If the OLDCHV is NULL (and OLDCHVLEN
|
||||
0), a "change reference data" is done, otherwise an "exchange
|
||||
reference data". The new reference data is expected in NEWCHV of
|
||||
length NEWCHVLEN. */
|
||||
length NEWCHVLEN. With PININFO non-NULL the keypad of the reader
|
||||
will be used. */
|
||||
gpg_error_t
|
||||
iso7816_change_reference_data (int slot, int chvno,
|
||||
iso7816_change_reference_data_kp (int slot, int chvno,
|
||||
const char *oldchv, size_t oldchvlen,
|
||||
const char *newchv, size_t newchvlen)
|
||||
const char *newchv, size_t newchvlen,
|
||||
iso7816_pininfo_t *pininfo)
|
||||
{
|
||||
int sw;
|
||||
char *buf;
|
||||
@ -258,6 +294,14 @@ iso7816_change_reference_data (int slot, int chvno,
|
||||
memcpy (buf, oldchv, oldchvlen);
|
||||
memcpy (buf+oldchvlen, newchv, newchvlen);
|
||||
|
||||
if (pininfo && pininfo->mode)
|
||||
sw = apdu_send_simple_kp (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
|
||||
oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf,
|
||||
pininfo->mode,
|
||||
pininfo->minlen,
|
||||
pininfo->maxlen,
|
||||
pininfo->padlen);
|
||||
else
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
|
||||
oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf);
|
||||
xfree (buf);
|
||||
@ -265,21 +309,54 @@ iso7816_change_reference_data (int slot, int chvno,
|
||||
|
||||
}
|
||||
|
||||
/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
|
||||
verification vector CHVNO. If the OLDCHV is NULL (and OLDCHVLEN
|
||||
0), a "change reference data" is done, otherwise an "exchange
|
||||
reference data". The new reference data is expected in NEWCHV of
|
||||
length NEWCHVLEN. */
|
||||
gpg_error_t
|
||||
iso7816_reset_retry_counter (int slot, int chvno,
|
||||
iso7816_change_reference_data (int slot, int chvno,
|
||||
const char *oldchv, size_t oldchvlen,
|
||||
const char *newchv, size_t newchvlen)
|
||||
{
|
||||
return iso7816_change_reference_data_kp (slot, chvno, oldchv, oldchvlen,
|
||||
newchv, newchvlen, NULL);
|
||||
}
|
||||
|
||||
|
||||
gpg_error_t
|
||||
iso7816_reset_retry_counter_kp (int slot, int chvno,
|
||||
const char *newchv, size_t newchvlen,
|
||||
iso7816_pininfo_t *pininfo)
|
||||
{
|
||||
int sw;
|
||||
|
||||
if (!newchv || !newchvlen )
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
if (pininfo && pininfo->mode)
|
||||
sw = apdu_send_simple_kp (slot, 0x00, CMD_RESET_RETRY_COUNTER,
|
||||
2, chvno, newchvlen, newchv,
|
||||
pininfo->mode,
|
||||
pininfo->minlen,
|
||||
pininfo->maxlen,
|
||||
pininfo->padlen);
|
||||
else
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_RESET_RETRY_COUNTER,
|
||||
2, chvno, newchvlen, newchv);
|
||||
return map_sw (sw);
|
||||
}
|
||||
|
||||
|
||||
gpg_error_t
|
||||
iso7816_reset_retry_counter (int slot, int chvno,
|
||||
const char *newchv, size_t newchvlen)
|
||||
{
|
||||
return iso7816_reset_retry_counter_kp (slot, chvno, newchv, newchvlen, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Perform a GET DATA command requesting TAG and storing the result in
|
||||
a newly allocated buffer at the address passed by RESULT. Return
|
||||
the length of this data at the address of RESULTLEN. */
|
||||
|
@ -28,10 +28,30 @@
|
||||
#include "cardglue.h"
|
||||
#endif
|
||||
|
||||
/* Command codes used by iso7816_check_keypad. */
|
||||
#define ISO7816_VERIFY 0x20
|
||||
#define ISO7816_CHANGE_REFERENCE_DATA 0x24
|
||||
#define ISO7816_RESET_RETRY_COUNTER 0x2C
|
||||
|
||||
|
||||
/* Information to be passed to keypad equipped readers. See
|
||||
ccid-driver.c for details. */
|
||||
struct iso7816_pininfo_s
|
||||
{
|
||||
int mode; /* A mode of 0 means: Do not use the keypad. */
|
||||
int minlen;
|
||||
int maxlen;
|
||||
int padlen;
|
||||
int padchar;
|
||||
};
|
||||
typedef struct iso7816_pininfo_s iso7816_pininfo_t;
|
||||
|
||||
|
||||
gpg_error_t iso7816_map_sw (int sw);
|
||||
|
||||
gpg_error_t iso7816_select_application (int slot,
|
||||
const char *aid, size_t aidlen);
|
||||
const char *aid, size_t aidlen,
|
||||
unsigned int flags);
|
||||
gpg_error_t iso7816_select_file (int slot, int tag, int is_dir,
|
||||
unsigned char **result, size_t *resultlen);
|
||||
gpg_error_t iso7816_select_path (int slot,
|
||||
@ -39,13 +59,26 @@ gpg_error_t iso7816_select_path (int slot,
|
||||
unsigned char **result, size_t *resultlen);
|
||||
gpg_error_t iso7816_list_directory (int slot, int list_dirs,
|
||||
unsigned char **result, size_t *resultlen);
|
||||
gpg_error_t iso7816_check_keypad (int slot, int command,
|
||||
iso7816_pininfo_t *pininfo);
|
||||
gpg_error_t iso7816_verify (int slot,
|
||||
int chvno, const char *chv, size_t chvlen);
|
||||
gpg_error_t iso7816_verify_kp (int slot,
|
||||
int chvno, const char *chv, size_t chvlen,
|
||||
iso7816_pininfo_t *pininfo);
|
||||
gpg_error_t iso7816_change_reference_data (int slot, int chvno,
|
||||
const char *oldchv, size_t oldchvlen,
|
||||
const char *newchv, size_t newchvlen);
|
||||
gpg_error_t iso7816_change_reference_data_kp (int slot, int chvno,
|
||||
const char *oldchv, size_t oldchvlen,
|
||||
const char *newchv, size_t newchvlen,
|
||||
iso7816_pininfo_t *pininfo);
|
||||
gpg_error_t iso7816_reset_retry_counter (int slot, int chvno,
|
||||
const char *newchv, size_t newchvlen);
|
||||
gpg_error_t iso7816_reset_retry_counter_kp (int slot, int chvno,
|
||||
const char *newchv,
|
||||
size_t newchvlen,
|
||||
iso7816_pininfo_t *pininfo);
|
||||
gpg_error_t iso7816_get_data (int slot, int tag,
|
||||
unsigned char **result, size_t *resultlen);
|
||||
gpg_error_t iso7816_put_data (int slot, int tag,
|
||||
|
@ -84,6 +84,7 @@ enum cmd_and_opt_values
|
||||
opcscDriver,
|
||||
oDisableCCID,
|
||||
oDisableOpenSC,
|
||||
oDisableKeypad,
|
||||
oAllowAdmin,
|
||||
oDenyAdmin,
|
||||
oDisableApplication,
|
||||
@ -126,6 +127,7 @@ static ARGPARSE_OPTS opts[] = {
|
||||
"@"
|
||||
#endif
|
||||
/* end --disable-ccid */},
|
||||
{ oDisableKeypad, "disable-keypad", 0, N_("do not use a reader's keypad")},
|
||||
{ oAllowAdmin, "allow-admin", 0, N_("allow the use of admin card commands")},
|
||||
{ oDenyAdmin, "deny-admin", 0, "@" },
|
||||
{ oDisableApplication, "disable-application", 2, "@"},
|
||||
@ -135,7 +137,7 @@ static ARGPARSE_OPTS opts[] = {
|
||||
|
||||
|
||||
/* The card dirver we use by default for PC/SC. */
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
#if defined(HAVE_W32_SYSTEM) || defined(__CYGWIN__)
|
||||
#define DEFAULT_PCSC_DRIVER "winscard.dll"
|
||||
#else
|
||||
#define DEFAULT_PCSC_DRIVER "libpcsclite.so"
|
||||
@ -489,6 +491,8 @@ main (int argc, char **argv )
|
||||
case oDisableCCID: opt.disable_ccid = 1; break;
|
||||
case oDisableOpenSC: break;
|
||||
|
||||
case oDisableKeypad: opt.disable_keypad = 1; break;
|
||||
|
||||
case oAllowAdmin: opt.allow_admin = 1; break;
|
||||
case oDenyAdmin: opt.allow_admin = 0; break;
|
||||
|
||||
|
@ -39,21 +39,22 @@
|
||||
|
||||
#define MAX_DIGEST_LEN 24
|
||||
|
||||
/* A large struct name "opt" to keep global flags */
|
||||
/* A large struct name "opt" to keep global flags. */
|
||||
struct {
|
||||
unsigned int debug; /* debug flags (DBG_foo_VALUE) */
|
||||
int verbose; /* verbosity level */
|
||||
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 */
|
||||
unsigned int debug; /* Debug flags (DBG_foo_VALUE). */
|
||||
int verbose; /* Verbosity level. */
|
||||
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. */
|
||||
int disable_ccid; /* Disable the use of the internal CCID driver. */
|
||||
int disable_keypad; /* Do not use a keypad. */
|
||||
int allow_admin; /* Allow the use of admin commands for certain
|
||||
cards. */
|
||||
strlist_t disabled_applications; /* card applications we do not
|
||||
strlist_t disabled_applications; /* Card applications we do not
|
||||
want to use. */
|
||||
} opt;
|
||||
|
||||
|
@ -1,3 +1,11 @@
|
||||
2005-10-19 Werner Koch <wk@g10code.com>
|
||||
|
||||
* gpgconf-comp.c (gc_options_scdaemon): New option --disable-keypad.
|
||||
|
||||
2005-09-22 Werner Koch <wk@g10code.com>
|
||||
|
||||
* rfc822parse.c (parse_field): Tread Content-Disposition special.
|
||||
|
||||
2005-10-08 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* Makefile.am (watchgnupg_LDADD): New variable.
|
||||
|
@ -528,7 +528,9 @@ static gc_option_t gc_options_scdaemon[] =
|
||||
{ "disable-ccid", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
|
||||
"gnupg", "do not use the internal CCID driver",
|
||||
GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
|
||||
|
||||
{ "disable-keypad", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
|
||||
"gnupg", "do not use a reader's keypad",
|
||||
GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
|
||||
|
||||
{ "Debug",
|
||||
GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
|
||||
@ -2447,7 +2449,8 @@ gc_component_change_options (int component, FILE *in)
|
||||
{
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
/* FIXME: Won't work becuase W32 doesn't silently
|
||||
overwrite. */
|
||||
overwrite. Fix it by creating a backup copy and
|
||||
deliting the orginal file first. */
|
||||
err = rename (src_pathname[i], dest_pathname[i]);
|
||||
#else /*!HAVE_W32_SYSTEM*/
|
||||
/* This is a bit safer than rename() because we
|
||||
|
@ -766,6 +766,7 @@ parse_field (HDR_LINE hdr)
|
||||
} tspecial_header[] = {
|
||||
{ "Content-Type", 12},
|
||||
{ "Content-Transfer-Encoding", 25},
|
||||
{ "Content-Disposition", 19},
|
||||
{ NULL, 0}
|
||||
};
|
||||
const char *delimiters;
|
||||
|
Loading…
x
Reference in New Issue
Block a user