Fix standard directories for Wince.
[gnupg.git] / agent / cache.c
1 /* cache.c - keep a cache of passphrases
2  * Copyright (C) 2002, 2010 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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 3 of the License, or
9  * (at your option) any later version.
10  *
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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <assert.h>
27 #include <pth.h>
28
29 #include "agent.h"
30
31 /* The size of the encryption key in bytes.  */
32 #define ENCRYPTION_KEYSIZE (128/8)
33
34 /* A mutex used to protect the encryption.  This is required because
35    we use one context to do all encryption and decryption.  */
36 static pth_mutex_t encryption_lock;
37 /* The encryption context.  This is the only place where the
38    encryption key for all cached entries is available.  It would be nice
39    to keep this (or just the key) in some hardware device, for example
40    a TPM.  Libgcrypt could be extended to provide such a service.
41    With the current scheme it is easy to retrieve the cached entries
42    if access to Libgcrypt's memory is available.  The encryption
43    merely avoids grepping for clear texts in the memory.  Nevertheless
44    the encryption provides the necessary infrastructure to make it
45    more secure.  */
46 static gcry_cipher_hd_t encryption_handle;
47
48
49 struct secret_data_s {
50   int  totallen; /* This includes the padding and space for AESWRAP. */
51   char data[1];  /* A string.  */
52 };
53
54 typedef struct cache_item_s *ITEM;
55 struct cache_item_s {
56   ITEM next;
57   time_t created;
58   time_t accessed;
59   int ttl;  /* max. lifetime given in seconds, -1 one means infinite */
60   struct secret_data_s *pw;
61   cache_mode_t cache_mode;
62   char key[1];
63 };
64
65 /* The cache himself.  */
66 static ITEM thecache;
67
68
69 /* This function must be called once to initialize this module. It
70    has to be done before a second thread is spawned.  */
71 void
72 initialize_module_cache (void)
73 {
74   static int initialized;
75   gpg_error_t err;
76   void *key;
77
78   if (!pth_mutex_init (&encryption_lock))
79     err = gpg_error_from_syserror ();
80   else
81     err = gcry_cipher_open (&encryption_handle, GCRY_CIPHER_AES128,
82                             GCRY_CIPHER_MODE_AESWRAP, GCRY_CIPHER_SECURE);
83   if (!err)
84     {
85       key = gcry_random_bytes (ENCRYPTION_KEYSIZE, GCRY_STRONG_RANDOM);
86       if (!key)
87         err = gpg_error_from_syserror ();
88       else
89         {
90           err = gcry_cipher_setkey (encryption_handle, key, ENCRYPTION_KEYSIZE);
91           xfree (key);
92         }
93     }
94   if (err)
95     log_fatal ("error initializing cache encryption context: %s\n",
96              gpg_strerror (err));
97   initialized = 1;
98 }
99
100
101 void
102 deinitialize_module_cache (void)
103 {
104   gcry_cipher_close (encryption_handle);
105   encryption_handle = NULL;
106 }
107
108
109 static void
110 release_data (struct secret_data_s *data)
111 {
112    xfree (data);
113 }
114
115 static gpg_error_t
116 new_data (const char *string, struct secret_data_s **r_data)
117 {
118   gpg_error_t err;
119   struct secret_data_s *d, *d_enc;
120   size_t length;
121   int total;
122   
123   *r_data = NULL;
124
125   if (!encryption_handle)
126     return gpg_error (GPG_ERR_NOT_INITIALIZED);
127
128   length = strlen (string) + 1;
129
130   /* We pad the data to 32 bytes so that it get more complicated
131      finding something out by watching allocation patterns.  This is
132      usally not possible but we better assume nothing about our secure
133      storage provider.  To support the AESWRAP mode we need to add 8
134      extra bytes as well. */
135   total = (length + 8) + 32 - ((length+8) % 32);
136
137   d = xtrymalloc_secure (sizeof *d + total - 1);
138   if (!d)
139     return gpg_error_from_syserror ();
140   memcpy (d->data, string, length);
141
142   d_enc = xtrymalloc (sizeof *d_enc + total - 1);
143   if (!d_enc)
144     {
145       err = gpg_error_from_syserror ();
146       xfree (d);
147       return err;
148     }
149
150   d_enc->totallen = total;
151   if (!pth_mutex_acquire (&encryption_lock, 0, NULL))
152     log_fatal ("failed to acquire cache encryption mutex\n");
153   err = gcry_cipher_encrypt (encryption_handle, d_enc->data, total,
154                              d->data, total - 8);
155   xfree (d);
156   if (!pth_mutex_release (&encryption_lock))
157     log_fatal ("failed to release cache encryption mutex\n");
158   if (err)
159     {
160       xfree (d_enc);
161       return err;
162     }
163   *r_data = d_enc;
164   return 0;
165 }
166
167
168
169 /* Check whether there are items to expire.  */
170 static void
171 housekeeping (void)
172 {
173   ITEM r, rprev;
174   time_t current = gnupg_get_time ();
175
176   /* First expire the actual data */
177   for (r=thecache; r; r = r->next)
178     {
179       if (r->pw && r->ttl >= 0 && r->accessed + r->ttl < current)
180         {
181           if (DBG_CACHE)
182             log_debug ("  expired `%s' (%ds after last access)\n",
183                        r->key, r->ttl);
184           release_data (r->pw);
185           r->pw = NULL;
186           r->accessed = current;
187         }
188     }
189
190   /* Second, make sure that we also remove them based on the created stamp so
191      that the user has to enter it from time to time. */
192   for (r=thecache; r; r = r->next)
193     {
194       unsigned long maxttl;
195       
196       switch (r->cache_mode)
197         {
198         case CACHE_MODE_SSH: maxttl = opt.max_cache_ttl_ssh; break;
199         default: maxttl = opt.max_cache_ttl; break;
200         }
201       if (r->pw && r->created + maxttl < current)
202         {
203           if (DBG_CACHE)
204             log_debug ("  expired `%s' (%lus after creation)\n",
205                        r->key, opt.max_cache_ttl);
206           release_data (r->pw);
207           r->pw = NULL;
208           r->accessed = current;
209         }
210     }
211
212   /* Third, make sure that we don't have too many items in the list.
213      Expire old and unused entries after 30 minutes */
214   for (rprev=NULL, r=thecache; r; )
215     {
216       if (!r->pw && r->ttl >= 0 && r->accessed + 60*30 < current)
217         {
218           ITEM r2 = r->next;
219           if (DBG_CACHE)
220             log_debug ("  removed `%s' (mode %d) (slot not used for 30m)\n",
221                        r->key, r->cache_mode);
222           xfree (r);
223           if (!rprev)
224             thecache = r2;
225           else
226             rprev->next = r2;
227           r = r2;
228         }
229       else
230         {
231           rprev = r;
232           r = r->next;
233         }
234     }
235 }
236
237
238 void
239 agent_flush_cache (void)
240 {
241   ITEM r;
242
243   if (DBG_CACHE)
244     log_debug ("agent_flush_cache\n");
245
246   for (r=thecache; r; r = r->next)
247     {
248       if (r->pw)
249         {
250           if (DBG_CACHE)
251             log_debug ("  flushing `%s'\n", r->key);
252           release_data (r->pw);
253           r->pw = NULL;
254           r->accessed = 0;
255         }
256     }
257 }
258
259
260
261 /* Store the string DATA in the cache under KEY and mark it with a
262    maximum lifetime of TTL seconds.  If there is already data under
263    this key, it will be replaced.  Using a DATA of NULL deletes the
264    entry.  A TTL of 0 is replaced by the default TTL and a TTL of -1
265    set infinite timeout.  CACHE_MODE is stored with the cache entry
266    and used to select different timeouts.  */
267 int
268 agent_put_cache (const char *key, cache_mode_t cache_mode,
269                  const char *data, int ttl)
270 {
271   gpg_error_t err = 0;
272   ITEM r;
273
274   if (DBG_CACHE)
275     log_debug ("agent_put_cache `%s' (mode %d) requested ttl=%d\n",
276                key, cache_mode, ttl);
277   housekeeping ();
278
279   if (!ttl)
280     {
281       switch(cache_mode)
282         {
283         case CACHE_MODE_SSH: ttl = opt.def_cache_ttl_ssh; break;
284         default: ttl = opt.def_cache_ttl; break;
285         }
286     }
287   if (!ttl || cache_mode == CACHE_MODE_IGNORE)
288     return 0;
289
290   for (r=thecache; r; r = r->next)
291     {
292       if (((cache_mode != CACHE_MODE_USER
293             && cache_mode != CACHE_MODE_NONCE)
294            || r->cache_mode == cache_mode)
295           && !strcmp (r->key, key))
296         break;
297     }
298   if (r) /* Replace.  */
299     {
300       if (r->pw)
301         {
302           release_data (r->pw);
303           r->pw = NULL;
304         }
305       if (data)
306         {
307           r->created = r->accessed = gnupg_get_time (); 
308           r->ttl = ttl;
309           r->cache_mode = cache_mode;
310           err = new_data (data, &r->pw);
311           if (err)
312             log_error ("error replacing cache item: %s\n", gpg_strerror (err));
313         }
314     }
315   else if (data) /* Insert.  */
316     {
317       r = xtrycalloc (1, sizeof *r + strlen (key));
318       if (!r)
319         err = gpg_error_from_syserror ();
320       else
321         {
322           strcpy (r->key, key);
323           r->created = r->accessed = gnupg_get_time (); 
324           r->ttl = ttl;
325           r->cache_mode = cache_mode;
326           err = new_data (data, &r->pw);
327           if (err)
328             xfree (r);
329           else
330             {
331               r->next = thecache;
332               thecache = r;
333             }
334         }
335       if (err)
336         log_error ("error inserting cache item: %s\n", gpg_strerror (err));
337     }
338   return err;
339 }
340
341
342 /* Try to find an item in the cache.  Note that we currently don't
343    make use of CACHE_MODE except for CACHE_MODE_NONCE and
344    CACHE_MODE_USER.  */
345 char *
346 agent_get_cache (const char *key, cache_mode_t cache_mode)
347 {
348   gpg_error_t err;
349   ITEM r;
350   char *value = NULL;
351
352   if (cache_mode == CACHE_MODE_IGNORE)
353     return NULL;
354
355   if (DBG_CACHE)
356     log_debug ("agent_get_cache `%s' (mode %d) ...\n", key, cache_mode);
357   housekeeping ();
358
359   for (r=thecache; r; r = r->next)
360     {
361       if (r->pw
362           && ((cache_mode != CACHE_MODE_USER
363                && cache_mode != CACHE_MODE_NONCE)
364               || r->cache_mode == cache_mode)
365           && !strcmp (r->key, key))
366         {
367           r->accessed = gnupg_get_time ();
368           if (DBG_CACHE)
369             log_debug ("... hit\n");
370           if (r->pw->totallen < 32)
371             err = gpg_error (GPG_ERR_INV_LENGTH);
372           else if (!encryption_handle)
373             err = gpg_error (GPG_ERR_NOT_INITIALIZED);
374           else if (!(value = xtrymalloc_secure (r->pw->totallen - 8)))
375             err = gpg_error_from_syserror ();
376           else
377             {
378               if (!pth_mutex_acquire (&encryption_lock, 0, NULL))
379                 log_fatal ("failed to acquire cache encryption mutex\n");
380               err = gcry_cipher_decrypt (encryption_handle,
381                                          value, r->pw->totallen - 8,
382                                          r->pw->data, r->pw->totallen);
383               if (!pth_mutex_release (&encryption_lock))
384                 log_fatal ("failed to release cache encryption mutex\n");
385             }
386           if (err)
387             {
388               xfree (value);
389               value = NULL;
390               log_error ("retrieving cache entry `%s' failed: %s\n",
391                          key, gpg_strerror (err));
392             }
393           return value;
394         }
395     }
396   if (DBG_CACHE)
397     log_debug ("... miss\n");
398
399   return NULL;
400 }
401