1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Preparing an interim release

This commit is contained in:
Werner Koch 2005-11-28 11:52:25 +00:00
parent 000a38ccf2
commit 6a13cf2c3d
32 changed files with 785 additions and 171 deletions

View file

@ -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.

View file

@ -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);

View file

@ -633,26 +633,43 @@ 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]))
{
line += 7;
while (*line == ' ')
line++;
pinlen = 90;
pin = gcry_malloc_secure (pinlen);
if (!pin)
return ASSUAN_Out_Of_Core;
rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen);
if (rc)
rc = ASSUAN_Canceled;
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);
return ASSUAN_Inquire_Unknown;
rc = ASSUAN_Inquire_Unknown;
}
line += 7;
while (*line == ' ')
line++;
pinlen = 90;
pin = gcry_malloc_secure (pinlen);
if (!pin)
return ASSUAN_Out_Of_Core;
rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen);
if (rc)
rc = ASSUAN_Canceled;
if (!rc)
rc = assuan_send_data (parm->ctx, pin, pinlen);
xfree (pin);
return rc;
}

View file

@ -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);

View file

@ -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

View file

@ -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))
@ -936,10 +937,17 @@ 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)))
{
p += DIM(oid_data);
n -= DIM(oid_data);
len -= DIM(oid_data);
return parse_bag_data (p, n, (p-buffer), pw);
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);
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;
}

View file

@ -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*/
{
if (pth_mutex_init (&entry_lock))
initialized = 1;
}
}
@ -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,13 +179,10 @@ start_pinentry (CTRL ctrl)
const char *argv[5];
int no_close_list[3];
int i;
pth_event_t evt;
#ifdef USE_GNU_PTH
{
pth_event_t evt;
evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
if (!pth_mutex_acquire (&entry_lock, 0, evt))
evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
if (!pth_mutex_acquire (&entry_lock, 0, evt))
{
if (pth_event_occurred (evt))
rc = gpg_error (GPG_ERR_TIMEOUT);
@ -170,9 +193,9 @@ start_pinentry (CTRL ctrl)
gpg_strerror (rc));
return rc;
}
pth_event_free (evt, PTH_FREE_THIS);
}
#endif
pth_event_free (evt, PTH_FREE_THIS);
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);
}

View file

@ -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)
{