* gpg-agent.c (main): Disable core dumps.

* cache.c: New.
* command.c (cmd_get_passphrase): Use the cache.
(cmd_clear_passphrase): Ditto.

* gpg-agent.c:  Removed unused cruft and implement the socket
based server.
(my_strusage): Take bug report address from configure.ac.
* command.c (start_command_handler): Add an argument to start as
regular server.
(start_command_handler): Enable Assuan logging.
This commit is contained in:
Werner Koch 2002-01-19 20:59:19 +00:00
parent 0e06a31d58
commit eac306fc90
6 changed files with 312 additions and 14 deletions

View File

@ -1,5 +1,11 @@
2002-01-19 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main): Disable core dumps.
* cache.c: New.
* command.c (cmd_get_passphrase): Use the cache.
(cmd_clear_passphrase): Ditto.
* gpg-agent.c: Removed unused cruft and implement the socket
based server.
(my_strusage): Take bug report address from configure.ac.

View File

@ -27,6 +27,7 @@ gpg_agent_SOURCES = \
gpg-agent.c agent.h \
command.c \
query.c \
cache.c \
trans.c \
findkey.c \
pksign.c \

View File

@ -100,6 +100,12 @@ int agent_get_passphrase (char **retpass,
const char *desc, const char *prompt,
const char *errtext);
/*-- cache.c --*/
int agent_put_cache (const char *key, const char *data, int ttl);
const char *agent_get_cache (const char *key);
/*-- pksign.c --*/
int agent_pksign (CTRL ctrl, FILE *outfp);

220
agent/cache.c Normal file
View File

@ -0,0 +1,220 @@
/* cache.c - keep a cache of passphrases
* 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>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include "agent.h"
struct secret_data_s {
int totallen; /* this includes the padding */
int datalen; /* actual data length */
char data[1];
};
typedef struct cache_item_s *ITEM;
struct cache_item_s {
ITEM next;
time_t created;
time_t accessed;
int ttl; /* max. lifetime given in seonds */
struct secret_data_s *pw;
char key[1];
};
static ITEM thecache;
static void
release_data (struct secret_data_s *data)
{
xfree (data);
}
static struct secret_data_s *
new_data (const void *data, size_t length)
{
struct secret_data_s *d;
int total;
/* we pad the data to 32 bytes so that it get more complicated
finding something out by watching allocation patterns. This is
usally not possible but we better assume nothing about our
secure storage provider*/
total = length + 32 - (length % 32);
d = gcry_malloc_secure (sizeof d + total - 1);
if (d)
{
d->totallen = total;
d->datalen = length;
memcpy (d->data, data, length);
}
return d;
}
/* check whether there are items to expire */
static void
housekeeping (void)
{
ITEM r, rprev;
time_t current = time (NULL);
/* first expire the actual data */
for (r=thecache; r; r = r->next)
{
if (r->pw && r->accessed + r->ttl < current)
{
release_data (r->pw);
r->pw = NULL;
r->accessed = current;
}
}
/* 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 */
for (r=thecache; r; r = r->next)
{
if (r->pw && r->created + 60*60 < current)
{
release_data (r->pw);
r->pw = NULL;
r->accessed = current;
}
}
/* third, make sure that we don't have too many items in the list.
Expire old and unused entries after 30 minutes */
for (rprev=NULL, r=thecache; r; )
{
if (!r->pw && r->accessed + 60*30 < current)
{
ITEM r2 = r->next;
xfree (r);
if (!rprev)
thecache = r2;
else
rprev = r2;
r = r2;
}
else
{
rprev = r;
r = r->next;
}
}
}
/* Store DATA of length DATALEN in the cache under KEY and mark it
with a maxiumum lifetime of TTL seconds. If tehre is already data
under this key, it will be replaced. Using a DATA of NULL deletes
the entry */
int
agent_put_cache (const char *key, const char *data, int ttl)
{
ITEM r;
housekeeping ();
if (ttl < 1)
ttl = 60*5; /* default is 5 minutes */
for (r=thecache; r; r = r->next)
{
if ( !strcmp (r->key, key))
break;
}
if (r)
{ /* replace */
if (r->pw)
{
release_data (r->pw);
r->pw = NULL;
}
if (data)
{
r->pw = new_data (data, strlen (data)+1);
if (!r->pw)
log_error ("out of core while allocating new cache item\n");
}
}
else if (data)
{ /* simply insert */
r = xtrycalloc (1, sizeof *r + strlen (key));
if (!r)
log_error ("out of core while allocating new cache control\n");
else
{
strcpy (r->key, key);
r->created = r->accessed = time (NULL);
r->ttl = ttl;
r->pw = new_data (data, strlen (data)+1);
if (!r->pw)
{
log_error ("out of core while allocating new cache item\n");
xfree (r);
}
else
{
r->next = thecache;
thecache = r;
}
}
}
return 0;
}
/* Try to find an item in the cache */
const char *
agent_get_cache (const char *key)
{
ITEM r;
int count = 0;
housekeeping ();
/* FIXME: Returning pointers is not thread safe - add a referencense
counter */
for (r=thecache; r; r = r->next, count++)
{
if (r->pw && !strcmp (r->key, key))
{
/* put_cache does onlu put strings into the cache, so we
don't need the lengths */
r->accessed = time (NULL);
return r->pw->data;
}
}
return NULL;
}

View File

@ -281,20 +281,74 @@ static int
cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
{
int rc;
const char *pw;
char *response;
char *desc, *prompt, *errtext;
char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
char *p;
/* FIXME: Parse that stuff */
desc = "We need a passphrase";
prompt = NULL;
errtext = NULL;
/* parse the stuff */
for (p=line; *p == ' '; p++)
;
cacheid = p;
p = strchr (cacheid, ' ');
if (p)
{
*p++ = 0;
while (*p == ' ')
p++;
errtext = p;
p = strchr (errtext, ' ');
if (p)
{
*p++ = 0;
while (*p == ' ')
p++;
prompt = p;
p = strchr (prompt, ' ');
if (p)
{
*p++ = 0;
while (*p == ' ')
p++;
desc = p;
p = strchr (desc, ' ');
if (p)
*p = 0; /* ignore garbage */
}
}
}
if (!cacheid || !*cacheid || strlen (cacheid) > 50)
return set_error (Parameter_Error, "invalid length of cacheID");
if (!desc)
return set_error (Parameter_Error, "no description given");
rc = agent_get_passphrase (&response, desc, prompt, errtext);
if (!rc)
if (!strcmp (cacheid, "X"))
cacheid = NULL;
if (!strcmp (errtext, "X"))
errtext = NULL;
if (!strcmp (prompt, "X"))
prompt = NULL;
if (!strcmp (desc, "X"))
desc = NULL;
/* Note: we store the hexified versions in the cache. */
pw = cacheid ? agent_get_cache (cacheid) : NULL;
if (pw)
{
assuan_begin_confidential (ctx);
rc = assuan_set_okay_line (ctx, response);
xfree (response);
rc = assuan_set_okay_line (ctx, pw);
}
else
{
rc = agent_get_passphrase (&response, desc, prompt, errtext);
if (!rc)
{
if (cacheid)
agent_put_cache (cacheid, response, 0);
assuan_begin_confidential (ctx);
rc = assuan_set_okay_line (ctx, response);
xfree (response);
}
}
return map_to_assuan_status (rc);
@ -310,12 +364,21 @@ cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
static int
cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line)
{
int rc;
char *cacheid = NULL;
char *p;
/* fixme: no caching yet. so return with OK */
rc = 0;
/* parse the stuff */
for (p=line; *p == ' '; p++)
;
cacheid = p;
p = strchr (cacheid, ' ');
if (p)
*p = 0; /* ignore garbage */
if (!cacheid || !*cacheid || strlen (cacheid) > 50)
return set_error (Parameter_Error, "invalid length of cacheID");
return map_to_assuan_status (rc);
agent_put_cache (cacheid, NULL, 0);
return 0;
}

View File

@ -40,6 +40,8 @@
#include "agent.h"
#include "../assuan/assuan.h" /* malloc hooks */
#include "sysutils.h"
#define N_(a) a
#define _(a) a
@ -252,7 +254,7 @@ main (int argc, char **argv )
gcry_set_log_handler (my_gcry_logger, NULL);
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
may_coredump = 0/* FIXME: disable_core_dumps()*/;
may_coredump = disable_core_dumps ();
shell = getenv ("SHELL");
if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )