1
/* cache.c - keep a cache of passphrases
2
* Copyright (C) 2002 Free Software Foundation, Inc.
4
* This file is part of GnuPG.
6
* GnuPG is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* GnuPG is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
31
struct secret_data_s {
32
int totallen; /* this includes the padding */
33
int datalen; /* actual data length */
37
typedef struct cache_item_s *ITEM;
42
int ttl; /* max. lifetime given in seconds, -1 one means infinite */
44
struct secret_data_s *pw;
53
release_data (struct secret_data_s *data)
58
static struct secret_data_s *
59
new_data (const void *data, size_t length)
61
struct secret_data_s *d;
64
/* we pad the data to 32 bytes so that it get more complicated
65
finding something out by watching allocation patterns. This is
66
usally not possible but we better assume nothing about our
67
secure storage provider*/
68
total = length + 32 - (length % 32);
70
d = gcry_malloc_secure (sizeof *d + total - 1);
75
memcpy (d->data, data, length);
81
/* check whether there are items to expire */
86
time_t current = gnupg_get_time ();
88
/* first expire the actual data */
89
for (r=thecache; r; r = r->next)
91
if (!r->lockcount && r->pw
92
&& r->ttl >= 0 && r->accessed + r->ttl < current)
95
log_debug (" expired `%s' (%ds after last access)\n",
99
r->accessed = current;
103
/* second, make sure that we also remove them based on the created stamp so
104
that the user has to enter it from time to time. We do this every hour */
105
for (r=thecache; r; r = r->next)
107
if (!r->lockcount && r->pw && r->created + opt.max_cache_ttl < current)
110
log_debug (" expired `%s' (%lus after creation)\n",
111
r->key, opt.max_cache_ttl);
112
release_data (r->pw);
114
r->accessed = current;
118
/* third, make sure that we don't have too many items in the list.
119
Expire old and unused entries after 30 minutes */
120
for (rprev=NULL, r=thecache; r; )
122
if (!r->pw && r->ttl >= 0 && r->accessed + 60*30 < current)
126
log_error ("can't remove unused cache entry `%s' due to"
128
r->key, r->lockcount);
129
r->accessed += 60*10; /* next error message in 10 minutes */
137
log_debug (" removed `%s' (slot not used for 30m)\n", r->key);
156
agent_flush_cache (void)
161
log_debug ("agent_flush_cache\n");
163
for (r=thecache; r; r = r->next)
165
if (!r->lockcount && r->pw)
168
log_debug (" flushing `%s'\n", r->key);
169
release_data (r->pw);
173
else if (r->lockcount && r->pw)
176
log_debug (" marked `%s' for flushing\n", r->key);
185
/* Store DATA of length DATALEN in the cache under KEY and mark it
186
with a maximum lifetime of TTL seconds. If there is already data
187
under this key, it will be replaced. Using a DATA of NULL deletes
188
the entry. A TTL of 0 is replaced by the default TTL and a TTL of
189
-1 set infinite timeout. */
191
agent_put_cache (const char *key, const char *data, int ttl)
196
log_debug ("agent_put_cache `%s' requested ttl=%d\n", key, ttl);
200
ttl = opt.def_cache_ttl;
204
for (r=thecache; r; r = r->next)
206
if (!r->lockcount && !strcmp (r->key, key))
213
release_data (r->pw);
218
r->created = r->accessed = gnupg_get_time ();
220
r->pw = new_data (data, strlen (data)+1);
222
log_error ("out of core while allocating new cache item\n");
226
{ /* simply insert */
227
r = xtrycalloc (1, sizeof *r + strlen (key));
229
log_error ("out of core while allocating new cache control\n");
232
strcpy (r->key, key);
233
r->created = r->accessed = gnupg_get_time ();
235
r->pw = new_data (data, strlen (data)+1);
238
log_error ("out of core while allocating new cache item\n");
252
/* Try to find an item in the cache */
254
agent_get_cache (const char *key, void **cache_id)
259
log_debug ("agent_get_cache `%s'...\n", key);
262
/* first try to find one with no locks - this is an updated cache
263
entry: We might have entries with a lockcount and without a
265
for (r=thecache; r; r = r->next)
267
if (!r->lockcount && r->pw && !strcmp (r->key, key))
269
/* put_cache does only put strings into the cache, so we
270
don't need the lengths */
271
r->accessed = gnupg_get_time ();
273
log_debug ("... hit\n");
279
/* again, but this time get even one with a lockcount set */
280
for (r=thecache; r; r = r->next)
282
if (r->pw && !strcmp (r->key, key))
284
r->accessed = gnupg_get_time ();
286
log_debug ("... hit (locked)\n");
293
log_debug ("... miss\n");
301
agent_unlock_cache_entry (void **cache_id)
305
for (r=thecache; r; r = r->next)
310
log_error ("trying to unlock non-locked cache entry `%s'\n",