mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-17 15:44:34 +02: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>
|
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
|
* gpg-agent.c: Removed unused cruft and implement the socket
|
||||||
based server.
|
based server.
|
||||||
(my_strusage): Take bug report address from configure.ac.
|
(my_strusage): Take bug report address from configure.ac.
|
||||||
|
@ -27,6 +27,7 @@ gpg_agent_SOURCES = \
|
|||||||
gpg-agent.c agent.h \
|
gpg-agent.c agent.h \
|
||||||
command.c \
|
command.c \
|
||||||
query.c \
|
query.c \
|
||||||
|
cache.c \
|
||||||
trans.c \
|
trans.c \
|
||||||
findkey.c \
|
findkey.c \
|
||||||
pksign.c \
|
pksign.c \
|
||||||
|
@ -100,6 +100,12 @@ int agent_get_passphrase (char **retpass,
|
|||||||
const char *desc, const char *prompt,
|
const char *desc, const char *prompt,
|
||||||
const char *errtext);
|
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 --*/
|
/*-- pksign.c --*/
|
||||||
int agent_pksign (CTRL ctrl, FILE *outfp);
|
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)
|
cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
const char *pw;
|
||||||
char *response;
|
char *response;
|
||||||
char *desc, *prompt, *errtext;
|
char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
|
||||||
|
char *p;
|
||||||
|
|
||||||
/* FIXME: Parse that stuff */
|
/* parse the stuff */
|
||||||
desc = "We need a passphrase";
|
for (p=line; *p == ' '; p++)
|
||||||
prompt = NULL;
|
;
|
||||||
errtext = NULL;
|
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 (!strcmp (cacheid, "X"))
|
||||||
if (!rc)
|
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);
|
assuan_begin_confidential (ctx);
|
||||||
rc = assuan_set_okay_line (ctx, response);
|
rc = assuan_set_okay_line (ctx, pw);
|
||||||
xfree (response);
|
}
|
||||||
|
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);
|
return map_to_assuan_status (rc);
|
||||||
@ -310,12 +364,21 @@ cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
static int
|
static int
|
||||||
cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line)
|
cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line)
|
||||||
{
|
{
|
||||||
int rc;
|
char *cacheid = NULL;
|
||||||
|
char *p;
|
||||||
|
|
||||||
/* fixme: no caching yet. so return with OK */
|
/* parse the stuff */
|
||||||
rc = 0;
|
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 "agent.h"
|
||||||
#include "../assuan/assuan.h" /* malloc hooks */
|
#include "../assuan/assuan.h" /* malloc hooks */
|
||||||
|
|
||||||
|
#include "sysutils.h"
|
||||||
|
|
||||||
|
|
||||||
#define N_(a) a
|
#define N_(a) a
|
||||||
#define _(a) a
|
#define _(a) a
|
||||||
@ -252,7 +254,7 @@ main (int argc, char **argv )
|
|||||||
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);
|
||||||
|
|
||||||
may_coredump = 0/* FIXME: disable_core_dumps()*/;
|
may_coredump = disable_core_dumps ();
|
||||||
|
|
||||||
shell = getenv ("SHELL");
|
shell = getenv ("SHELL");
|
||||||
if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
|
if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user