mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
* 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:
parent
0e06a31d58
commit
eac306fc90
@ -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.
|
||||
|
@ -27,6 +27,7 @@ gpg_agent_SOURCES = \
|
||||
gpg-agent.c agent.h \
|
||||
command.c \
|
||||
query.c \
|
||||
cache.c \
|
||||
trans.c \
|
||||
findkey.c \
|
||||
pksign.c \
|
||||
|
@ -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
220
agent/cache.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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") )
|
||||
|
Loading…
x
Reference in New Issue
Block a user