mirror of
git://git.gnupg.org/gnupg.git
synced 2025-03-12 23:01:14 +01:00
* no-pth.c, Makefile.am: Removed.
* call-scd.c: Seirialized all scdaeom access when using Pth. * cache.c: Made the cache Pth-thread-safe. (agent_unlock_cache_entry): New. * findkey.c (unprotect): Unlock the returned cache value. * command.c (cmd_get_passphrase): Ditto. * gpg-agent.c (main): Register pth_read/write with Assuan.
This commit is contained in:
parent
72f48d9e8a
commit
b209c17be9
@ -1,3 +1,25 @@
|
|||||||
|
2002-05-23 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* call-scd.c: Seirialized all scdaeom access when using Pth.
|
||||||
|
|
||||||
|
* cache.c: Made the cache Pth-thread-safe.
|
||||||
|
(agent_unlock_cache_entry): New.
|
||||||
|
* findkey.c (unprotect): Unlock the returned cache value.
|
||||||
|
* command.c (cmd_get_passphrase): Ditto.
|
||||||
|
|
||||||
|
* gpg-agent.c (main): Register pth_read/write with Assuan.
|
||||||
|
|
||||||
|
2002-05-22 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* query.c: Serialized all pinentry access when using Pth.
|
||||||
|
|
||||||
|
* gpg-agent.c (handle_signal,start_connection_thread)
|
||||||
|
(handle_connections): New
|
||||||
|
(main): Use the new Pth stuff to allow concurrent connections.
|
||||||
|
* command.c (start_command_handler): Add new arg FD so that the
|
||||||
|
fucntion can also be used for an already connected socket.
|
||||||
|
* Makefile.am: Link with Pth.
|
||||||
|
|
||||||
2002-05-14 Werner Koch <wk@gnupg.org>
|
2002-05-14 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
* cache.c (housekeeping, agent_put_cache): Use our time() wrapper.
|
* cache.c (housekeeping, agent_put_cache): Use our time() wrapper.
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
bin_PROGRAMS = gpg-agent
|
bin_PROGRAMS = gpg-agent
|
||||||
noinst_PROGRAMS = protect-tool
|
noinst_PROGRAMS = protect-tool
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(top_srcdir)/common $(LIBGCRYPT_CFLAGS)
|
AM_CPPFLAGS = -I$(top_srcdir)/common $(LIBGCRYPT_CFLAGS) $(PTH_CFLAGS)
|
||||||
LDFLAGS = @LDFLAGS@
|
LDFLAGS = @LDFLAGS@
|
||||||
|
|
||||||
gpg_agent_SOURCES = \
|
gpg_agent_SOURCES = \
|
||||||
@ -43,7 +43,7 @@ gpg_agent_SOURCES = \
|
|||||||
|
|
||||||
|
|
||||||
gpg_agent_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a \
|
gpg_agent_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a \
|
||||||
../common/libcommon.a $(LIBGCRYPT_LIBS)
|
../common/libcommon.a $(LIBGCRYPT_LIBS) $(PTH_LIBS)
|
||||||
|
|
||||||
protect_tool_SOURCES = \
|
protect_tool_SOURCES = \
|
||||||
protect-tool.c \
|
protect-tool.c \
|
||||||
|
@ -104,7 +104,7 @@ void agent_exit (int rc); /* also implemented in other tools */
|
|||||||
const char *trans (const char *text);
|
const char *trans (const char *text);
|
||||||
|
|
||||||
/*-- command.c --*/
|
/*-- command.c --*/
|
||||||
void start_command_handler (int);
|
void start_command_handler (int, int);
|
||||||
|
|
||||||
/*-- findkey.c --*/
|
/*-- findkey.c --*/
|
||||||
int agent_write_private_key (const unsigned char *grip,
|
int agent_write_private_key (const unsigned char *grip,
|
||||||
@ -124,8 +124,8 @@ int agent_get_confirmation (const char *desc, const char *ok,
|
|||||||
|
|
||||||
/*-- cache.c --*/
|
/*-- cache.c --*/
|
||||||
int agent_put_cache (const char *key, const char *data, int ttl);
|
int agent_put_cache (const char *key, const char *data, int ttl);
|
||||||
const char *agent_get_cache (const char *key);
|
const char *agent_get_cache (const char *key, void **cache_id);
|
||||||
|
void agent_unlock_cache_entry (void **cache_id);
|
||||||
|
|
||||||
|
|
||||||
/*-- pksign.c --*/
|
/*-- pksign.c --*/
|
||||||
|
@ -40,6 +40,7 @@ struct cache_item_s {
|
|||||||
time_t created;
|
time_t created;
|
||||||
time_t accessed;
|
time_t accessed;
|
||||||
int ttl; /* max. lifetime given in seonds */
|
int ttl; /* max. lifetime given in seonds */
|
||||||
|
int lockcount;
|
||||||
struct secret_data_s *pw;
|
struct secret_data_s *pw;
|
||||||
char key[1];
|
char key[1];
|
||||||
};
|
};
|
||||||
@ -87,7 +88,7 @@ housekeeping (void)
|
|||||||
/* first expire the actual data */
|
/* first expire the actual data */
|
||||||
for (r=thecache; r; r = r->next)
|
for (r=thecache; r; r = r->next)
|
||||||
{
|
{
|
||||||
if (r->pw && r->accessed + r->ttl < current)
|
if (!r->lockcount && r->pw && r->accessed + r->ttl < current)
|
||||||
{
|
{
|
||||||
if (DBG_CACHE)
|
if (DBG_CACHE)
|
||||||
log_debug (" expired `%s' (%ds after last access)\n",
|
log_debug (" expired `%s' (%ds after last access)\n",
|
||||||
@ -99,10 +100,10 @@ housekeeping (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* second, make sure that we also remove them based on the created stamp so
|
/* second, make sure that we also remove them based on the created stamp so
|
||||||
that the used has to enter it from time to time. We do this every hour */
|
that the user has to enter it from time to time. We do this every hour */
|
||||||
for (r=thecache; r; r = r->next)
|
for (r=thecache; r; r = r->next)
|
||||||
{
|
{
|
||||||
if (r->pw && r->created + 60*60 < current)
|
if (!r->lockcount && r->pw && r->created + 60*60 < current)
|
||||||
{
|
{
|
||||||
if (DBG_CACHE)
|
if (DBG_CACHE)
|
||||||
log_debug (" expired `%s' (1h after creation)\n", r->key);
|
log_debug (" expired `%s' (1h after creation)\n", r->key);
|
||||||
@ -117,6 +118,17 @@ housekeeping (void)
|
|||||||
for (rprev=NULL, r=thecache; r; )
|
for (rprev=NULL, r=thecache; r; )
|
||||||
{
|
{
|
||||||
if (!r->pw && r->accessed + 60*30 < current)
|
if (!r->pw && r->accessed + 60*30 < current)
|
||||||
|
{
|
||||||
|
if (r->lockcount)
|
||||||
|
{
|
||||||
|
log_error ("can't remove unused cache entry `%s' due to"
|
||||||
|
" lockcount=%d\n",
|
||||||
|
r->key, r->lockcount);
|
||||||
|
r->accessed += 60*10; /* next error message in 10 minutes */
|
||||||
|
rprev = r;
|
||||||
|
r = r->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ITEM r2 = r->next;
|
ITEM r2 = r->next;
|
||||||
if (DBG_CACHE)
|
if (DBG_CACHE)
|
||||||
@ -128,6 +140,7 @@ housekeeping (void)
|
|||||||
rprev->next = r2;
|
rprev->next = r2;
|
||||||
r = r2;
|
r = r2;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rprev = r;
|
rprev = r;
|
||||||
@ -158,7 +171,7 @@ agent_put_cache (const char *key, const char *data, int ttl)
|
|||||||
|
|
||||||
for (r=thecache; r; r = r->next)
|
for (r=thecache; r; r = r->next)
|
||||||
{
|
{
|
||||||
if ( !strcmp (r->key, key))
|
if (!r->lockcount && !strcmp (r->key, key))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (r)
|
if (r)
|
||||||
@ -206,34 +219,67 @@ agent_put_cache (const char *key, const char *data, int ttl)
|
|||||||
|
|
||||||
/* Try to find an item in the cache */
|
/* Try to find an item in the cache */
|
||||||
const char *
|
const char *
|
||||||
agent_get_cache (const char *key)
|
agent_get_cache (const char *key, void **cache_id)
|
||||||
{
|
{
|
||||||
ITEM r;
|
ITEM r;
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
if (DBG_CACHE)
|
if (DBG_CACHE)
|
||||||
log_debug ("agent_get_cache `%s'...\n", key);
|
log_debug ("agent_get_cache `%s'...\n", key);
|
||||||
housekeeping ();
|
housekeeping ();
|
||||||
|
|
||||||
/* FIXME: Returning pointers is not thread safe - add a reference
|
/* first try to find one with no locks - this is an updated cache
|
||||||
counter */
|
entry: We might have entries with a lockcount and without a
|
||||||
for (r=thecache; r; r = r->next, count++)
|
lockcount. */
|
||||||
|
for (r=thecache; r; r = r->next)
|
||||||
{
|
{
|
||||||
if (r->pw && !strcmp (r->key, key))
|
if (!r->lockcount && r->pw && !strcmp (r->key, key))
|
||||||
{
|
{
|
||||||
/* put_cache does only put strings into the cache, so we
|
/* put_cache does only put strings into the cache, so we
|
||||||
don't need the lengths */
|
don't need the lengths */
|
||||||
r->accessed = gnupg_get_time ();
|
r->accessed = gnupg_get_time ();
|
||||||
if (DBG_CACHE)
|
if (DBG_CACHE)
|
||||||
log_debug ("... hit\n");
|
log_debug ("... hit\n");
|
||||||
|
r->lockcount++;
|
||||||
|
*cache_id = r;
|
||||||
|
return r->pw->data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* again, but this time get even one with a lockcount set */
|
||||||
|
for (r=thecache; r; r = r->next)
|
||||||
|
{
|
||||||
|
if (r->pw && !strcmp (r->key, key))
|
||||||
|
{
|
||||||
|
r->accessed = gnupg_get_time ();
|
||||||
|
if (DBG_CACHE)
|
||||||
|
log_debug ("... hit (locked)\n");
|
||||||
|
r->lockcount++;
|
||||||
|
*cache_id = r;
|
||||||
return r->pw->data;
|
return r->pw->data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (DBG_CACHE)
|
if (DBG_CACHE)
|
||||||
log_debug ("... miss\n");
|
log_debug ("... miss\n");
|
||||||
|
|
||||||
|
*cache_id = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
agent_unlock_cache_entry (void **cache_id)
|
||||||
|
{
|
||||||
|
ITEM r;
|
||||||
|
|
||||||
|
for (r=thecache; r; r = r->next)
|
||||||
|
{
|
||||||
|
if (r == *cache_id)
|
||||||
|
{
|
||||||
|
if (!r->lockcount)
|
||||||
|
log_error ("trying to unlock non-locked cache entry `%s'\n",
|
||||||
|
r->key);
|
||||||
|
else
|
||||||
|
r->lockcount--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -18,6 +18,12 @@
|
|||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Fixme: For now we have serialized all access to the scdaemon which
|
||||||
|
make sense becuase the scdaemon can't handle concurrent connections
|
||||||
|
right now. We should however keep a list of connections and lock
|
||||||
|
just that connection - it migth make sense to implemtn parts of
|
||||||
|
this in Assuan.*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -27,6 +33,9 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#ifdef USE_GNU_PTH
|
||||||
|
# include <pth.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "agent.h"
|
#include "agent.h"
|
||||||
#include "../assuan/assuan.h"
|
#include "../assuan/assuan.h"
|
||||||
@ -38,6 +47,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static ASSUAN_CONTEXT scd_ctx = NULL;
|
static ASSUAN_CONTEXT scd_ctx = NULL;
|
||||||
|
#ifdef USE_GNU_PTH
|
||||||
|
static pth_mutex_t scd_lock = PTH_MUTEX_INIT;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* callback parameter for learn card */
|
/* callback parameter for learn card */
|
||||||
struct learn_parm_s {
|
struct learn_parm_s {
|
||||||
@ -60,7 +72,7 @@ struct membuf {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* A simple implemnation of a dynamic buffer. Use init_membuf() to
|
/* A simple implementation of a dynamic buffer. Use init_membuf() to
|
||||||
create a buffer, put_membuf to append bytes and get_membuf to
|
create a buffer, put_membuf to append bytes and get_membuf to
|
||||||
release and return the buffer. Allocation errors are detected but
|
release and return the buffer. Allocation errors are detected but
|
||||||
only returned at the final get_membuf(), this helps not to clutter
|
only returned at the final get_membuf(), this helps not to clutter
|
||||||
@ -122,6 +134,20 @@ get_membuf (struct membuf *mb, size_t *len)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
unlock_scd (int rc)
|
||||||
|
{
|
||||||
|
#ifdef USE_GNU_PTH
|
||||||
|
if (!pth_mutex_release (&scd_lock))
|
||||||
|
{
|
||||||
|
log_error ("failed to release the SCD lock\n");
|
||||||
|
if (!rc)
|
||||||
|
rc = GNUPG_Internal_Error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fork off the SCdaemon if this has not already been done */
|
/* Fork off the SCdaemon if this has not already been done */
|
||||||
static int
|
static int
|
||||||
start_scd (void)
|
start_scd (void)
|
||||||
@ -131,6 +157,14 @@ start_scd (void)
|
|||||||
ASSUAN_CONTEXT ctx;
|
ASSUAN_CONTEXT ctx;
|
||||||
const char *argv[3];
|
const char *argv[3];
|
||||||
|
|
||||||
|
#ifdef USE_GNU_PTH
|
||||||
|
if (!pth_mutex_acquire (&scd_lock, 0, NULL))
|
||||||
|
{
|
||||||
|
log_error ("failed to acquire the SCD lock\n");
|
||||||
|
return GNUPG_Internal_Error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (scd_ctx)
|
if (scd_ctx)
|
||||||
return 0; /* No need to serialize things because the agent is
|
return 0; /* No need to serialize things because the agent is
|
||||||
expected to tun as a single-thread (or may be in
|
expected to tun as a single-thread (or may be in
|
||||||
@ -142,7 +176,7 @@ start_scd (void)
|
|||||||
if (fflush (NULL))
|
if (fflush (NULL))
|
||||||
{
|
{
|
||||||
log_error ("error flushing pending output: %s\n", strerror (errno));
|
log_error ("error flushing pending output: %s\n", strerror (errno));
|
||||||
return seterr (Write_Error);
|
return unlock_scd (seterr (Write_Error));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: change the default location of the program */
|
/* FIXME: change the default location of the program */
|
||||||
@ -163,7 +197,7 @@ start_scd (void)
|
|||||||
{
|
{
|
||||||
log_error ("can't connect to the SCdaemon: %s\n",
|
log_error ("can't connect to the SCdaemon: %s\n",
|
||||||
assuan_strerror (rc));
|
assuan_strerror (rc));
|
||||||
return seterr (No_Scdaemon);
|
return unlock_scd (seterr (No_Scdaemon));
|
||||||
}
|
}
|
||||||
scd_ctx = ctx;
|
scd_ctx = ctx;
|
||||||
|
|
||||||
@ -218,9 +252,9 @@ agent_card_learn (void (*kpinfo_cb)(void*, const char *), void *kpinfo_cb_arg)
|
|||||||
NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL,
|
||||||
learn_status_cb, &parm);
|
learn_status_cb, &parm);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_scd (map_assuan_err (rc));
|
||||||
|
|
||||||
return 0;
|
return unlock_scd (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -274,7 +308,7 @@ agent_card_serialno (char **r_serialno)
|
|||||||
this is really SCdaemon's duty */
|
this is really SCdaemon's duty */
|
||||||
rc = assuan_transact (scd_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
|
rc = assuan_transact (scd_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_scd (map_assuan_err (rc));
|
||||||
|
|
||||||
rc = assuan_transact (scd_ctx, "SERIALNO",
|
rc = assuan_transact (scd_ctx, "SERIALNO",
|
||||||
NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL,
|
||||||
@ -282,10 +316,10 @@ agent_card_serialno (char **r_serialno)
|
|||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
xfree (serialno);
|
xfree (serialno);
|
||||||
return map_assuan_err (rc);
|
return unlock_scd (map_assuan_err (rc));
|
||||||
}
|
}
|
||||||
*r_serialno = serialno;
|
*r_serialno = serialno;
|
||||||
return 0;
|
return unlock_scd (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -354,7 +388,7 @@ agent_card_pksign (const char *keyid,
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (indatalen*2 + 50 > DIM(line))
|
if (indatalen*2 + 50 > DIM(line))
|
||||||
return seterr (General_Error);
|
return unlock_scd (seterr (General_Error));
|
||||||
|
|
||||||
sprintf (line, "SETDATA ");
|
sprintf (line, "SETDATA ");
|
||||||
p = line + strlen (line);
|
p = line + strlen (line);
|
||||||
@ -362,7 +396,7 @@ agent_card_pksign (const char *keyid,
|
|||||||
sprintf (p, "%02X", indata[i]);
|
sprintf (p, "%02X", indata[i]);
|
||||||
rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_scd (map_assuan_err (rc));
|
||||||
|
|
||||||
init_membuf (&data, 1024);
|
init_membuf (&data, 1024);
|
||||||
inqparm.ctx = scd_ctx;
|
inqparm.ctx = scd_ctx;
|
||||||
@ -377,7 +411,7 @@ agent_card_pksign (const char *keyid,
|
|||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
xfree (get_membuf (&data, &len));
|
xfree (get_membuf (&data, &len));
|
||||||
return map_assuan_err (rc);
|
return unlock_scd (map_assuan_err (rc));
|
||||||
}
|
}
|
||||||
sigbuf = get_membuf (&data, &sigbuflen);
|
sigbuf = get_membuf (&data, &sigbuflen);
|
||||||
|
|
||||||
@ -388,7 +422,7 @@ agent_card_pksign (const char *keyid,
|
|||||||
if (!*r_buf)
|
if (!*r_buf)
|
||||||
{
|
{
|
||||||
xfree (*r_buf);
|
xfree (*r_buf);
|
||||||
return GNUPG_Out_Of_Core;
|
return unlock_scd (GNUPG_Out_Of_Core);
|
||||||
}
|
}
|
||||||
p = stpcpy (*r_buf, "(7:sig-val(3:rsa(1:s" );
|
p = stpcpy (*r_buf, "(7:sig-val(3:rsa(1:s" );
|
||||||
sprintf (p, "%u:", (unsigned int)sigbuflen);
|
sprintf (p, "%u:", (unsigned int)sigbuflen);
|
||||||
@ -399,7 +433,7 @@ agent_card_pksign (const char *keyid,
|
|||||||
xfree (sigbuf);
|
xfree (sigbuf);
|
||||||
|
|
||||||
assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
|
assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
|
||||||
return 0;
|
return unlock_scd (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decipher INDATA using the current card. Note that the returned value is */
|
/* Decipher INDATA using the current card. Note that the returned value is */
|
||||||
@ -423,7 +457,7 @@ agent_card_pkdecrypt (const char *keyid,
|
|||||||
|
|
||||||
/* FIXME: use secure memory where appropriate */
|
/* FIXME: use secure memory where appropriate */
|
||||||
if (indatalen*2 + 50 > DIM(line))
|
if (indatalen*2 + 50 > DIM(line))
|
||||||
return seterr (General_Error);
|
return unlock_scd (seterr (General_Error));
|
||||||
|
|
||||||
sprintf (line, "SETDATA ");
|
sprintf (line, "SETDATA ");
|
||||||
p = line + strlen (line);
|
p = line + strlen (line);
|
||||||
@ -431,7 +465,7 @@ agent_card_pkdecrypt (const char *keyid,
|
|||||||
sprintf (p, "%02X", indata[i]);
|
sprintf (p, "%02X", indata[i]);
|
||||||
rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_scd (map_assuan_err (rc));
|
||||||
|
|
||||||
init_membuf (&data, 1024);
|
init_membuf (&data, 1024);
|
||||||
inqparm.ctx = scd_ctx;
|
inqparm.ctx = scd_ctx;
|
||||||
@ -446,13 +480,13 @@ agent_card_pkdecrypt (const char *keyid,
|
|||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
xfree (get_membuf (&data, &len));
|
xfree (get_membuf (&data, &len));
|
||||||
return map_assuan_err (rc);
|
return unlock_scd (map_assuan_err (rc));
|
||||||
}
|
}
|
||||||
*r_buf = get_membuf (&data, r_buflen);
|
*r_buf = get_membuf (&data, r_buflen);
|
||||||
if (!*r_buf)
|
if (!*r_buf)
|
||||||
return GNUPG_Out_Of_Core;
|
return unlock_scd (GNUPG_Out_Of_Core);
|
||||||
|
|
||||||
return 0;
|
return unlock_scd (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -481,13 +515,13 @@ agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen)
|
|||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
xfree (get_membuf (&data, &len));
|
xfree (get_membuf (&data, &len));
|
||||||
return map_assuan_err (rc);
|
return unlock_scd (map_assuan_err (rc));
|
||||||
}
|
}
|
||||||
*r_buf = get_membuf (&data, r_buflen);
|
*r_buf = get_membuf (&data, r_buflen);
|
||||||
if (!*r_buf)
|
if (!*r_buf)
|
||||||
return GNUPG_Out_Of_Core;
|
return unlock_scd (GNUPG_Out_Of_Core);
|
||||||
|
|
||||||
return 0;
|
return unlock_scd (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -517,19 +551,19 @@ agent_card_readkey (const char *id, unsigned char **r_buf)
|
|||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
xfree (get_membuf (&data, &len));
|
xfree (get_membuf (&data, &len));
|
||||||
return map_assuan_err (rc);
|
return unlock_scd (map_assuan_err (rc));
|
||||||
}
|
}
|
||||||
*r_buf = get_membuf (&data, &buflen);
|
*r_buf = get_membuf (&data, &buflen);
|
||||||
if (!*r_buf)
|
if (!*r_buf)
|
||||||
return GNUPG_Out_Of_Core;
|
return unlock_scd (GNUPG_Out_Of_Core);
|
||||||
|
|
||||||
if (!gcry_sexp_canon_len (*r_buf, buflen, NULL, NULL))
|
if (!gcry_sexp_canon_len (*r_buf, buflen, NULL, NULL))
|
||||||
{
|
{
|
||||||
xfree (*r_buf); *r_buf = NULL;
|
xfree (*r_buf); *r_buf = NULL;
|
||||||
return GNUPG_Invalid_Value;
|
return unlock_scd (GNUPG_Invalid_Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return unlock_scd (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -370,6 +370,7 @@ cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
char *response;
|
char *response;
|
||||||
char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
|
char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
|
||||||
char *p;
|
char *p;
|
||||||
|
void *cache_marker;
|
||||||
|
|
||||||
/* parse the stuff */
|
/* parse the stuff */
|
||||||
for (p=line; *p == ' '; p++)
|
for (p=line; *p == ' '; p++)
|
||||||
@ -417,17 +418,18 @@ cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
desc = NULL;
|
desc = NULL;
|
||||||
|
|
||||||
/* Note: we store the hexified versions in the cache. */
|
/* Note: we store the hexified versions in the cache. */
|
||||||
pw = cacheid ? agent_get_cache (cacheid) : NULL;
|
pw = cacheid ? agent_get_cache (cacheid, &cache_marker) : NULL;
|
||||||
if (pw)
|
if (pw)
|
||||||
{
|
{
|
||||||
assuan_begin_confidential (ctx);
|
assuan_begin_confidential (ctx);
|
||||||
rc = assuan_set_okay_line (ctx, pw);
|
rc = assuan_set_okay_line (ctx, pw);
|
||||||
|
agent_unlock_cache_entry (&cache_marker);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Note, that we only need to repalce the + characters and
|
/* Note, that we only need to replace the + characters and
|
||||||
should leave the other escaping in place becuase the escaped
|
should leave the other escaping in place because the escaped
|
||||||
sting is send verbatim to the pinentry which does the
|
string is send verbatim to the pinentry which does the
|
||||||
unescaping (but not the + replacing) */
|
unescaping (but not the + replacing) */
|
||||||
if (errtext)
|
if (errtext)
|
||||||
plus_to_blank (errtext);
|
plus_to_blank (errtext);
|
||||||
@ -593,10 +595,10 @@ register_commands (ASSUAN_CONTEXT ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Startup the server. If LISTEN_FD is given as -1, this is a simple
|
/* Startup the server. If LISTEN_FD and FD is given as -1, this is a simple
|
||||||
piper server, otherwise it is a regular server */
|
piper server, otherwise it is a regular server */
|
||||||
void
|
void
|
||||||
start_command_handler (int listen_fd)
|
start_command_handler (int listen_fd, int fd)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
ASSUAN_CONTEXT ctx;
|
ASSUAN_CONTEXT ctx;
|
||||||
@ -604,8 +606,7 @@ start_command_handler (int listen_fd)
|
|||||||
|
|
||||||
memset (&ctrl, 0, sizeof ctrl);
|
memset (&ctrl, 0, sizeof ctrl);
|
||||||
|
|
||||||
|
if (listen_fd == -1 && fd == -1)
|
||||||
if (listen_fd == -1)
|
|
||||||
{
|
{
|
||||||
int filedes[2];
|
int filedes[2];
|
||||||
|
|
||||||
@ -613,10 +614,14 @@ start_command_handler (int listen_fd)
|
|||||||
filedes[1] = 1;
|
filedes[1] = 1;
|
||||||
rc = assuan_init_pipe_server (&ctx, filedes);
|
rc = assuan_init_pipe_server (&ctx, filedes);
|
||||||
}
|
}
|
||||||
else
|
else if (listen_fd != -1)
|
||||||
{
|
{
|
||||||
rc = assuan_init_socket_server (&ctx, listen_fd);
|
rc = assuan_init_socket_server (&ctx, listen_fd);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = assuan_init_connected_socket_server (&ctx, fd);
|
||||||
|
}
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_error ("failed to initialize the server: %s\n",
|
log_error ("failed to initialize the server: %s\n",
|
||||||
@ -664,5 +669,3 @@ start_command_handler (int listen_fd)
|
|||||||
assuan_deinit_server (ctx);
|
assuan_deinit_server (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,10 +106,12 @@ unprotect (unsigned char **keybuf, const unsigned char *grip)
|
|||||||
/* first try to get it from the cache - if there is none or we can't
|
/* first try to get it from the cache - if there is none or we can't
|
||||||
unprotect it, we fall back to ask the user */
|
unprotect it, we fall back to ask the user */
|
||||||
{
|
{
|
||||||
const char *pw = agent_get_cache (hexgrip);
|
void *cache_marker;
|
||||||
|
const char *pw = agent_get_cache (hexgrip, &cache_marker);
|
||||||
if (pw)
|
if (pw)
|
||||||
{
|
{
|
||||||
rc = agent_unprotect (*keybuf, pw, &result, &resultlen);
|
rc = agent_unprotect (*keybuf, pw, &result, &resultlen);
|
||||||
|
agent_unlock_cache_entry (&cache_marker);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
xfree (*keybuf);
|
xfree (*keybuf);
|
||||||
|
@ -33,6 +33,9 @@
|
|||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#ifdef USE_GNU_PTH
|
||||||
|
# include <pth.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <gcrypt.h>
|
#include <gcrypt.h>
|
||||||
|
|
||||||
@ -113,7 +116,13 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef USE_GNU_PTH
|
||||||
static volatile int caught_fatal_sig = 0;
|
static volatile int caught_fatal_sig = 0;
|
||||||
|
#endif /*!USE_GNU_PTH*/
|
||||||
|
|
||||||
|
/* flag to indicate that a shutdown was requested */
|
||||||
|
static int shutdown_pending;
|
||||||
|
|
||||||
|
|
||||||
/* It is possible that we are currently running under setuid permissions */
|
/* It is possible that we are currently running under setuid permissions */
|
||||||
static int maybe_setuid = 1;
|
static int maybe_setuid = 1;
|
||||||
@ -122,6 +131,11 @@ static int maybe_setuid = 1;
|
|||||||
static char socket_name[128];
|
static char socket_name[128];
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_GNU_PTH
|
||||||
|
static void handle_connections (int listen_fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
my_strusage (int level)
|
my_strusage (int level)
|
||||||
@ -205,6 +219,7 @@ cleanup (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef USE_GNU_PTH
|
||||||
static RETSIGTYPE
|
static RETSIGTYPE
|
||||||
cleanup_sh (int sig)
|
cleanup_sh (int sig)
|
||||||
{
|
{
|
||||||
@ -226,6 +241,7 @@ cleanup_sh (int sig)
|
|||||||
#endif
|
#endif
|
||||||
raise( sig );
|
raise( sig );
|
||||||
}
|
}
|
||||||
|
#endif /*!USE_GNU_PTH*/
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv )
|
main (int argc, char **argv )
|
||||||
@ -265,6 +281,9 @@ main (int argc, char **argv )
|
|||||||
}
|
}
|
||||||
|
|
||||||
assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
|
assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
|
||||||
|
#ifdef USE_GNU_PTH
|
||||||
|
assuan_set_io_func (pth_read, pth_write);
|
||||||
|
#endif
|
||||||
gcry_set_log_handler (my_gcry_logger, NULL);
|
gcry_set_log_handler (my_gcry_logger, NULL);
|
||||||
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
|
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
|
||||||
|
|
||||||
@ -447,7 +466,7 @@ main (int argc, char **argv )
|
|||||||
|
|
||||||
if (pipe_server)
|
if (pipe_server)
|
||||||
{ /* this is the simple pipe based server */
|
{ /* this is the simple pipe based server */
|
||||||
start_command_handler (-1);
|
start_command_handler (-1, -1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* regular server mode */
|
{ /* regular server mode */
|
||||||
@ -574,6 +593,7 @@ main (int argc, char **argv )
|
|||||||
/*NEVER REACHED*/
|
/*NEVER REACHED*/
|
||||||
} /* end parent */
|
} /* end parent */
|
||||||
|
|
||||||
|
|
||||||
/* this is the child */
|
/* this is the child */
|
||||||
|
|
||||||
/* detach from tty and put process into a new session */
|
/* detach from tty and put process into a new session */
|
||||||
@ -592,6 +612,22 @@ main (int argc, char **argv )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (chdir("/"))
|
||||||
|
{
|
||||||
|
log_error ("chdir to / failed: %s\n", strerror (errno));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_GNU_PTH
|
||||||
|
if (!pth_init ())
|
||||||
|
{
|
||||||
|
log_error ("failed to initialize the Pth library\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
signal (SIGPIPE, SIG_IGN);
|
||||||
|
handle_connections (fd);
|
||||||
|
#else /*!USE_GNU_PTH*/
|
||||||
/* setup signals */
|
/* setup signals */
|
||||||
{
|
{
|
||||||
struct sigaction oact, nact;
|
struct sigaction oact, nact;
|
||||||
@ -610,15 +646,8 @@ main (int argc, char **argv )
|
|||||||
sigaction (SIGPIPE, &nact, NULL);
|
sigaction (SIGPIPE, &nact, NULL);
|
||||||
sigaction (SIGINT, &nact, NULL);
|
sigaction (SIGINT, &nact, NULL);
|
||||||
}
|
}
|
||||||
|
start_command_handler (fd, -1);
|
||||||
if (chdir("/"))
|
#endif /*!USE_GNU_PTH*/
|
||||||
{
|
|
||||||
log_error ("chdir to / failed: %s\n", strerror (errno));
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
start_command_handler (fd);
|
|
||||||
|
|
||||||
close (fd);
|
close (fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,10 +657,7 @@ main (int argc, char **argv )
|
|||||||
void
|
void
|
||||||
agent_exit (int rc)
|
agent_exit (int rc)
|
||||||
{
|
{
|
||||||
#if 0
|
/*FIXME: update_random_seed_file();*/
|
||||||
#warning no update_random_seed_file
|
|
||||||
update_random_seed_file();
|
|
||||||
#endif
|
|
||||||
#if 0
|
#if 0
|
||||||
/* at this time a bit annoying */
|
/* at this time a bit annoying */
|
||||||
if (opt.debug & DBG_MEMSTAT_VALUE)
|
if (opt.debug & DBG_MEMSTAT_VALUE)
|
||||||
@ -647,3 +673,144 @@ agent_exit (int rc)
|
|||||||
exit (rc);
|
exit (rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
reread_configuration (void)
|
||||||
|
{
|
||||||
|
/* FIXME: Move parts of the option parsing to here. */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_GNU_PTH
|
||||||
|
static void
|
||||||
|
handle_signal (int signo)
|
||||||
|
{
|
||||||
|
switch (signo)
|
||||||
|
{
|
||||||
|
case SIGHUP:
|
||||||
|
log_info ("SIGHUP received - re-reading configuration\n");
|
||||||
|
reread_configuration ();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIGUSR1:
|
||||||
|
if (opt.verbose < 5)
|
||||||
|
opt.verbose++;
|
||||||
|
log_info ("SIGUSR1 received - verbosity set to %d\n", opt.verbose);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIGUSR2:
|
||||||
|
if (opt.verbose)
|
||||||
|
opt.verbose--;
|
||||||
|
log_info ("SIGUSR2 received - verbosity set to %d\n", opt.verbose );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIGTERM:
|
||||||
|
if (!shutdown_pending)
|
||||||
|
log_info ("SIGTERM received - shutting down ...\n");
|
||||||
|
else
|
||||||
|
log_info ("SIGTERM received - still %ld running threads\n",
|
||||||
|
pth_ctrl( PTH_CTRL_GETTHREADS ));
|
||||||
|
shutdown_pending++;
|
||||||
|
if (shutdown_pending > 2)
|
||||||
|
{
|
||||||
|
log_info ("shutdown forced\n");
|
||||||
|
log_info ("%s %s stopped\n", strusage(11), strusage(13) );
|
||||||
|
cleanup ();
|
||||||
|
agent_exit (0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIGINT:
|
||||||
|
log_info ("SIGINT received - immediate shutdown\n");
|
||||||
|
log_info( "%s %s stopped\n", strusage(11), strusage(13));
|
||||||
|
cleanup ();
|
||||||
|
agent_exit (0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log_info ("signal %d received - no action defined\n", signo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
start_connection_thread (void *arg)
|
||||||
|
{
|
||||||
|
int fd = (int)arg;
|
||||||
|
|
||||||
|
if (opt.verbose)
|
||||||
|
log_info ("handler for fd %d started\n", fd);
|
||||||
|
start_command_handler (-1, fd);
|
||||||
|
if (opt.verbose)
|
||||||
|
log_info ("handler for fd %d terminated\n", fd);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_connections (int listen_fd)
|
||||||
|
{
|
||||||
|
pth_attr_t tattr;
|
||||||
|
pth_event_t ev;
|
||||||
|
sigset_t sigs;
|
||||||
|
int signo;
|
||||||
|
struct sockaddr_un paddr;
|
||||||
|
socklen_t plen = sizeof( paddr );
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
tattr = pth_attr_new();
|
||||||
|
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
|
||||||
|
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 32*1024);
|
||||||
|
pth_attr_set (tattr, PTH_ATTR_NAME, "gpg-agent");
|
||||||
|
|
||||||
|
sigemptyset (&sigs );
|
||||||
|
sigaddset (&sigs, SIGHUP);
|
||||||
|
sigaddset (&sigs, SIGUSR1);
|
||||||
|
sigaddset (&sigs, SIGUSR2);
|
||||||
|
sigaddset (&sigs, SIGINT);
|
||||||
|
sigaddset (&sigs, SIGTERM);
|
||||||
|
ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (shutdown_pending)
|
||||||
|
{
|
||||||
|
if (pth_ctrl (PTH_CTRL_GETTHREADS) == 1)
|
||||||
|
break; /* ready */
|
||||||
|
|
||||||
|
/* Do not accept anymore connections and wait for existing
|
||||||
|
connections to terminate */
|
||||||
|
signo = 0;
|
||||||
|
pth_wait (ev);
|
||||||
|
if (pth_event_occurred (ev) && signo)
|
||||||
|
handle_signal (signo);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
if (pth_event_occurred (ev))
|
||||||
|
{
|
||||||
|
handle_signal (signo);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
log_error ("accept failed: %s - waiting 1s\n", strerror (errno));
|
||||||
|
pth_sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pth_spawn (tattr, start_connection_thread, (void*)fd))
|
||||||
|
{
|
||||||
|
log_error ("error spawning connection handler: %s\n",
|
||||||
|
strerror (errno) );
|
||||||
|
close (fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pth_event_free (ev, PTH_FREE_ALL);
|
||||||
|
cleanup ();
|
||||||
|
log_info ("%s %s stopped\n", strusage(11), strusage(13));
|
||||||
|
}
|
||||||
|
#endif /*USE_GNU_PTH*/
|
||||||
|
@ -27,6 +27,9 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#ifdef USE_GNU_PTH
|
||||||
|
# include <pth.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "agent.h"
|
#include "agent.h"
|
||||||
#include "../assuan/assuan.h"
|
#include "../assuan/assuan.h"
|
||||||
@ -38,6 +41,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static ASSUAN_CONTEXT entry_ctx = NULL;
|
static ASSUAN_CONTEXT entry_ctx = NULL;
|
||||||
|
#ifdef USE_GNU_PTH
|
||||||
|
static pth_mutex_t entry_lock = PTH_MUTEX_INIT;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* data to be passed to our callbacks */
|
/* data to be passed to our callbacks */
|
||||||
struct entry_parm_s {
|
struct entry_parm_s {
|
||||||
@ -49,7 +55,24 @@ struct entry_parm_s {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Fork off the pin entry if this has not already been done */
|
static int
|
||||||
|
unlock_pinentry (int rc)
|
||||||
|
{
|
||||||
|
#ifdef USE_GNU_PTH
|
||||||
|
if (!pth_mutex_release (&entry_lock))
|
||||||
|
{
|
||||||
|
log_error ("failed to release the entry lock\n");
|
||||||
|
if (!rc)
|
||||||
|
rc = GNUPG_Internal_Error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fork off the pin entry if this has not already been done. Note,
|
||||||
|
that this function must always be used to aquire the lock for the
|
||||||
|
pinentry - we will serialize _all_ pinentry calls.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
start_pinentry (void)
|
start_pinentry (void)
|
||||||
{
|
{
|
||||||
@ -58,10 +81,16 @@ start_pinentry (void)
|
|||||||
ASSUAN_CONTEXT ctx;
|
ASSUAN_CONTEXT ctx;
|
||||||
const char *argv[5];
|
const char *argv[5];
|
||||||
|
|
||||||
|
#ifdef USE_GNU_PTH
|
||||||
|
if (!pth_mutex_acquire (&entry_lock, 0, NULL))
|
||||||
|
{
|
||||||
|
log_error ("failed to acquire the entry lock\n");
|
||||||
|
return GNUPG_Internal_Error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (entry_ctx)
|
if (entry_ctx)
|
||||||
return 0; /* No need to serialize things becuase the agent is
|
return 0;
|
||||||
expected to tun as a single-thread (or may be in
|
|
||||||
future using libpth) */
|
|
||||||
|
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
log_info ("no running PIN Entry - starting it\n");
|
log_info ("no running PIN Entry - starting it\n");
|
||||||
@ -69,7 +98,7 @@ start_pinentry (void)
|
|||||||
if (fflush (NULL))
|
if (fflush (NULL))
|
||||||
{
|
{
|
||||||
log_error ("error flushing pending output: %s\n", strerror (errno));
|
log_error ("error flushing pending output: %s\n", strerror (errno));
|
||||||
return seterr (Write_Error);
|
return unlock_pinentry (seterr (Write_Error));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: change the default location of the program */
|
/* FIXME: change the default location of the program */
|
||||||
@ -80,6 +109,7 @@ start_pinentry (void)
|
|||||||
else
|
else
|
||||||
pgmname++;
|
pgmname++;
|
||||||
|
|
||||||
|
/* FIXME: We must do this thread specific */
|
||||||
argv[0] = pgmname;
|
argv[0] = pgmname;
|
||||||
if (opt.display)
|
if (opt.display)
|
||||||
{
|
{
|
||||||
@ -96,7 +126,7 @@ start_pinentry (void)
|
|||||||
{
|
{
|
||||||
log_error ("can't connect to the PIN entry module: %s\n",
|
log_error ("can't connect to the PIN entry module: %s\n",
|
||||||
assuan_strerror (rc));
|
assuan_strerror (rc));
|
||||||
return seterr (No_PIN_Entry);
|
return unlock_pinentry (seterr (No_PIN_Entry));
|
||||||
}
|
}
|
||||||
entry_ctx = ctx;
|
entry_ctx = ctx;
|
||||||
|
|
||||||
@ -107,47 +137,47 @@ start_pinentry (void)
|
|||||||
opt.no_grab? "OPTION no-grab":"OPTION grab",
|
opt.no_grab? "OPTION no-grab":"OPTION grab",
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
if (opt.ttyname)
|
if (opt.ttyname)
|
||||||
{
|
{
|
||||||
char *optstr;
|
char *optstr;
|
||||||
if (asprintf (&optstr, "OPTION ttyname=%s", opt.ttyname) < 0 )
|
if (asprintf (&optstr, "OPTION ttyname=%s", opt.ttyname) < 0 )
|
||||||
return GNUPG_Out_Of_Core;
|
return unlock_pinentry (GNUPG_Out_Of_Core);
|
||||||
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL);
|
NULL);
|
||||||
free (optstr);
|
free (optstr);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
}
|
}
|
||||||
if (opt.ttytype)
|
if (opt.ttytype)
|
||||||
{
|
{
|
||||||
char *optstr;
|
char *optstr;
|
||||||
if (asprintf (&optstr, "OPTION ttytype=%s", opt.ttytype) < 0 )
|
if (asprintf (&optstr, "OPTION ttytype=%s", opt.ttytype) < 0 )
|
||||||
return GNUPG_Out_Of_Core;
|
return unlock_pinentry (GNUPG_Out_Of_Core);
|
||||||
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL);
|
NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
}
|
}
|
||||||
if (opt.lc_ctype)
|
if (opt.lc_ctype)
|
||||||
{
|
{
|
||||||
char *optstr;
|
char *optstr;
|
||||||
if (asprintf (&optstr, "OPTION lc-ctype=%s", opt.lc_ctype) < 0 )
|
if (asprintf (&optstr, "OPTION lc-ctype=%s", opt.lc_ctype) < 0 )
|
||||||
return GNUPG_Out_Of_Core;
|
return unlock_pinentry (GNUPG_Out_Of_Core);
|
||||||
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL);
|
NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
}
|
}
|
||||||
if (opt.lc_messages)
|
if (opt.lc_messages)
|
||||||
{
|
{
|
||||||
char *optstr;
|
char *optstr;
|
||||||
if (asprintf (&optstr, "OPTION lc-messages=%s", opt.lc_messages) < 0 )
|
if (asprintf (&optstr, "OPTION lc-messages=%s", opt.lc_messages) < 0 )
|
||||||
return GNUPG_Out_Of_Core;
|
return unlock_pinentry (GNUPG_Out_Of_Core);
|
||||||
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL);
|
NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -213,14 +243,14 @@ agent_askpin (const char *desc_text, const char *start_err_text,
|
|||||||
line[DIM(line)-1] = 0;
|
line[DIM(line)-1] = 0;
|
||||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
|
|
||||||
rc = assuan_transact (entry_ctx,
|
rc = assuan_transact (entry_ctx,
|
||||||
pininfo->min_digits? "SETPROMPT PIN:"
|
pininfo->min_digits? "SETPROMPT PIN:"
|
||||||
: "SETPROMPT Passphrase:",
|
: "SETPROMPT Passphrase:",
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
|
|
||||||
for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
|
for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
|
||||||
{
|
{
|
||||||
@ -242,7 +272,7 @@ agent_askpin (const char *desc_text, const char *start_err_text,
|
|||||||
line[DIM(line)-1] = 0;
|
line[DIM(line)-1] = 0;
|
||||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
errtext = NULL;
|
errtext = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,9 +281,9 @@ agent_askpin (const char *desc_text, const char *start_err_text,
|
|||||||
errtext = pininfo->min_digits? trans ("PIN too long")
|
errtext = pininfo->min_digits? trans ("PIN too long")
|
||||||
: trans ("Passphrase too long");
|
: trans ("Passphrase too long");
|
||||||
else if (rc)
|
else if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
if (!errtext && !pininfo->min_digits)
|
if (!errtext && !pininfo->min_digits)
|
||||||
return 0; /* okay, got a passphrase */
|
return unlock_pinentry (0); /* okay, got a passphrase */
|
||||||
if (!errtext && !all_digitsp (pininfo->pin))
|
if (!errtext && !all_digitsp (pininfo->pin))
|
||||||
errtext = trans ("Invalid characters in PIN");
|
errtext = trans ("Invalid characters in PIN");
|
||||||
if (!errtext && pininfo->max_digits
|
if (!errtext && pininfo->max_digits
|
||||||
@ -264,10 +294,11 @@ agent_askpin (const char *desc_text, const char *start_err_text,
|
|||||||
errtext = trans ("PIN too short");
|
errtext = trans ("PIN too short");
|
||||||
|
|
||||||
if (!errtext)
|
if (!errtext)
|
||||||
return 0; /* okay, got a PIN */
|
return unlock_pinentry (0); /* okay, got a PIN */
|
||||||
}
|
}
|
||||||
|
|
||||||
return pininfo->min_digits? GNUPG_Bad_PIN : GNUPG_Bad_Passphrase;
|
return unlock_pinentry (pininfo->min_digits? GNUPG_Bad_PIN
|
||||||
|
: GNUPG_Bad_Passphrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -301,13 +332,13 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
|
|||||||
line[DIM(line)-1] = 0;
|
line[DIM(line)-1] = 0;
|
||||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
|
|
||||||
snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt? prompt : "Passphrase");
|
snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt? prompt : "Passphrase");
|
||||||
line[DIM(line)-1] = 0;
|
line[DIM(line)-1] = 0;
|
||||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
|
|
||||||
if (errtext)
|
if (errtext)
|
||||||
{
|
{
|
||||||
@ -315,28 +346,28 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
|
|||||||
line[DIM(line)-1] = 0;
|
line[DIM(line)-1] = 0;
|
||||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
}
|
}
|
||||||
|
|
||||||
memset (&parm, 0, sizeof parm);
|
memset (&parm, 0, sizeof parm);
|
||||||
parm.size = ASSUAN_LINELENGTH/2 - 5;
|
parm.size = ASSUAN_LINELENGTH/2 - 5;
|
||||||
parm.buffer = gcry_malloc_secure (parm.size+10);
|
parm.buffer = gcry_malloc_secure (parm.size+10);
|
||||||
if (!parm.buffer)
|
if (!parm.buffer)
|
||||||
return seterr (Out_Of_Core);
|
return unlock_pinentry (seterr (Out_Of_Core));
|
||||||
|
|
||||||
assuan_begin_confidential (entry_ctx);
|
assuan_begin_confidential (entry_ctx);
|
||||||
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL);
|
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
xfree (parm.buffer);
|
xfree (parm.buffer);
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
}
|
}
|
||||||
|
|
||||||
hexstring = gcry_malloc_secure (strlen (parm.buffer)*2+1);
|
hexstring = gcry_malloc_secure (strlen (parm.buffer)*2+1);
|
||||||
if (!hexstring)
|
if (!hexstring)
|
||||||
{
|
{
|
||||||
xfree (parm.buffer);
|
xfree (parm.buffer);
|
||||||
return seterr (Out_Of_Core);
|
return unlock_pinentry (seterr (Out_Of_Core));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0, p=parm.buffer; *p; p++, i += 2)
|
for (i=0, p=parm.buffer; *p; p++, i += 2)
|
||||||
@ -344,7 +375,7 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
|
|||||||
|
|
||||||
xfree (parm.buffer);
|
xfree (parm.buffer);
|
||||||
*retpass = hexstring;
|
*retpass = hexstring;
|
||||||
return 0;
|
return unlock_pinentry (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -370,7 +401,7 @@ agent_get_confirmation (const char *desc, const char *ok, const char *cancel)
|
|||||||
line[DIM(line)-1] = 0;
|
line[DIM(line)-1] = 0;
|
||||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
@ -378,7 +409,7 @@ agent_get_confirmation (const char *desc, const char *ok, const char *cancel)
|
|||||||
line[DIM(line)-1] = 0;
|
line[DIM(line)-1] = 0;
|
||||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
}
|
}
|
||||||
if (cancel)
|
if (cancel)
|
||||||
{
|
{
|
||||||
@ -386,11 +417,11 @@ agent_get_confirmation (const char *desc, const char *ok, const char *cancel)
|
|||||||
line[DIM(line)-1] = 0;
|
line[DIM(line)-1] = 0;
|
||||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
|
rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
return map_assuan_err (rc);
|
return unlock_pinentry (map_assuan_err (rc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2002-05-23 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* no-pth.c, Makefile.am: Removed.
|
||||||
|
|
||||||
2002-05-22 Werner Koch <wk@gnupg.org>
|
2002-05-22 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
* mkdtemp.c: Replaced byte by unsigned char because it is no longer
|
* mkdtemp.c: Replaced byte by unsigned char because it is no longer
|
||||||
|
@ -32,7 +32,6 @@ libcommon_a_SOURCES = \
|
|||||||
errors.c errors.h \
|
errors.c errors.h \
|
||||||
maperror.c \
|
maperror.c \
|
||||||
sysutils.c sysutils.h \
|
sysutils.c sysutils.h \
|
||||||
no-pth.c \
|
|
||||||
cryptmiss.c \
|
cryptmiss.c \
|
||||||
gettime.c
|
gettime.c
|
||||||
|
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
/* no-pth.c - stubs to avoid linking against PTH
|
|
||||||
* Copyright (C) 2002 Free Software Foundation, Inc.
|
|
||||||
*
|
|
||||||
* This file is part of GnuPG.
|
|
||||||
*
|
|
||||||
* GnuPG is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* GnuPG is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#ifdef USE_GNU_PTH /*we need the stubs only in this case */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <pth.h>
|
|
||||||
|
|
||||||
#if PTH_SYSCALL_SOFT
|
|
||||||
# error this file cannot be used with PTH syscall divertion
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
pth_read (int a, void *b , size_t c)
|
|
||||||
{
|
|
||||||
return read (a, b, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
pth_write (int a, const void *b, size_t c)
|
|
||||||
{
|
|
||||||
return write (a, b, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pth_accept (int a, struct sockaddr *b, socklen_t *c)
|
|
||||||
{
|
|
||||||
return accept (a, b, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*USE_GNU_PTH*/
|
|
Loading…
x
Reference in New Issue
Block a user