Line data Source code
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 <npth.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 npth_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 : /* NULL or the last cache key stored by agent_store_cache_hit. */
69 : static char *last_stored_cache_key;
70 :
71 :
72 : /* This function must be called once to initialize this module. It
73 : has to be done before a second thread is spawned. */
74 : void
75 1 : initialize_module_cache (void)
76 : {
77 : int err;
78 :
79 1 : err = npth_mutex_init (&encryption_lock, NULL);
80 :
81 1 : if (err)
82 0 : log_fatal ("error initializing cache module: %s\n", strerror (err));
83 1 : }
84 :
85 :
86 : void
87 4 : deinitialize_module_cache (void)
88 : {
89 4 : gcry_cipher_close (encryption_handle);
90 4 : encryption_handle = NULL;
91 4 : }
92 :
93 :
94 : /* We do the encryption init on the fly. We can't do it in the module
95 : init code because that is run before we listen for connections and
96 : in case we are started on demand by gpg etc. it will only wait for
97 : a few seconds to decide whether the agent may now accept
98 : connections. Thus we should get into listen state as soon as
99 : possible. */
100 : static gpg_error_t
101 130 : init_encryption (void)
102 : {
103 : gpg_error_t err;
104 : void *key;
105 : int res;
106 :
107 130 : if (encryption_handle)
108 129 : return 0; /* Shortcut - Already initialized. */
109 :
110 1 : res = npth_mutex_lock (&encryption_lock);
111 1 : if (res)
112 0 : log_fatal ("failed to acquire cache encryption mutex: %s\n", strerror (res));
113 :
114 1 : err = gcry_cipher_open (&encryption_handle, GCRY_CIPHER_AES128,
115 : GCRY_CIPHER_MODE_AESWRAP, GCRY_CIPHER_SECURE);
116 1 : if (!err)
117 : {
118 1 : key = gcry_random_bytes (ENCRYPTION_KEYSIZE, GCRY_STRONG_RANDOM);
119 1 : if (!key)
120 0 : err = gpg_error_from_syserror ();
121 : else
122 : {
123 1 : err = gcry_cipher_setkey (encryption_handle, key, ENCRYPTION_KEYSIZE);
124 1 : xfree (key);
125 : }
126 1 : if (err)
127 : {
128 0 : gcry_cipher_close (encryption_handle);
129 0 : encryption_handle = NULL;
130 : }
131 : }
132 1 : if (err)
133 0 : log_error ("error initializing cache encryption context: %s\n",
134 : gpg_strerror (err));
135 :
136 1 : res = npth_mutex_unlock (&encryption_lock);
137 1 : if (res)
138 0 : log_fatal ("failed to release cache encryption mutex: %s\n", strerror (res));
139 :
140 1 : return err? gpg_error (GPG_ERR_NOT_INITIALIZED) : 0;
141 : }
142 :
143 :
144 :
145 : static void
146 0 : release_data (struct secret_data_s *data)
147 : {
148 0 : xfree (data);
149 0 : }
150 :
151 : static gpg_error_t
152 10 : new_data (const char *string, struct secret_data_s **r_data)
153 : {
154 : gpg_error_t err;
155 : struct secret_data_s *d, *d_enc;
156 : size_t length;
157 : int total;
158 : int res;
159 :
160 10 : *r_data = NULL;
161 :
162 10 : err = init_encryption ();
163 10 : if (err)
164 0 : return err;
165 :
166 10 : length = strlen (string) + 1;
167 :
168 : /* We pad the data to 32 bytes so that it get more complicated
169 : finding something out by watching allocation patterns. This is
170 : usally not possible but we better assume nothing about our secure
171 : storage provider. To support the AESWRAP mode we need to add 8
172 : extra bytes as well. */
173 10 : total = (length + 8) + 32 - ((length+8) % 32);
174 :
175 10 : d = xtrymalloc_secure (sizeof *d + total - 1);
176 10 : if (!d)
177 0 : return gpg_error_from_syserror ();
178 10 : memcpy (d->data, string, length);
179 :
180 10 : d_enc = xtrymalloc (sizeof *d_enc + total - 1);
181 10 : if (!d_enc)
182 : {
183 0 : err = gpg_error_from_syserror ();
184 0 : xfree (d);
185 0 : return err;
186 : }
187 :
188 10 : d_enc->totallen = total;
189 10 : res = npth_mutex_lock (&encryption_lock);
190 10 : if (res)
191 0 : log_fatal ("failed to acquire cache encryption mutex: %s\n",
192 : strerror (res));
193 :
194 20 : err = gcry_cipher_encrypt (encryption_handle, d_enc->data, total,
195 20 : d->data, total - 8);
196 10 : xfree (d);
197 10 : res = npth_mutex_unlock (&encryption_lock);
198 10 : if (res)
199 0 : log_fatal ("failed to release cache encryption mutex: %s\n", strerror (res));
200 10 : if (err)
201 : {
202 0 : xfree (d_enc);
203 0 : return err;
204 : }
205 10 : *r_data = d_enc;
206 10 : return 0;
207 : }
208 :
209 :
210 :
211 : /* Check whether there are items to expire. */
212 : static void
213 130 : housekeeping (void)
214 : {
215 : ITEM r, rprev;
216 130 : time_t current = gnupg_get_time ();
217 :
218 : /* First expire the actual data */
219 925 : for (r=thecache; r; r = r->next)
220 : {
221 795 : if (r->pw && r->ttl >= 0 && r->accessed + r->ttl < current)
222 : {
223 0 : if (DBG_CACHE)
224 0 : log_debug (" expired '%s' (%ds after last access)\n",
225 0 : r->key, r->ttl);
226 0 : release_data (r->pw);
227 0 : r->pw = NULL;
228 0 : r->accessed = current;
229 : }
230 : }
231 :
232 : /* Second, make sure that we also remove them based on the created stamp so
233 : that the user has to enter it from time to time. */
234 925 : for (r=thecache; r; r = r->next)
235 : {
236 : unsigned long maxttl;
237 :
238 795 : switch (r->cache_mode)
239 : {
240 0 : case CACHE_MODE_SSH: maxttl = opt.max_cache_ttl_ssh; break;
241 795 : default: maxttl = opt.max_cache_ttl; break;
242 : }
243 795 : if (r->pw && r->created + maxttl < current)
244 : {
245 0 : if (DBG_CACHE)
246 0 : log_debug (" expired '%s' (%lus after creation)\n",
247 0 : r->key, opt.max_cache_ttl);
248 0 : release_data (r->pw);
249 0 : r->pw = NULL;
250 0 : r->accessed = current;
251 : }
252 : }
253 :
254 : /* Third, make sure that we don't have too many items in the list.
255 : Expire old and unused entries after 30 minutes */
256 1055 : for (rprev=NULL, r=thecache; r; )
257 : {
258 795 : if (!r->pw && r->ttl >= 0 && r->accessed + 60*30 < current)
259 0 : {
260 0 : ITEM r2 = r->next;
261 0 : if (DBG_CACHE)
262 0 : log_debug (" removed '%s' (mode %d) (slot not used for 30m)\n",
263 0 : r->key, r->cache_mode);
264 0 : xfree (r);
265 0 : if (!rprev)
266 0 : thecache = r2;
267 : else
268 0 : rprev->next = r2;
269 0 : r = r2;
270 : }
271 : else
272 : {
273 795 : rprev = r;
274 795 : r = r->next;
275 : }
276 : }
277 130 : }
278 :
279 :
280 : void
281 0 : agent_flush_cache (void)
282 : {
283 : ITEM r;
284 :
285 0 : if (DBG_CACHE)
286 0 : log_debug ("agent_flush_cache\n");
287 :
288 0 : for (r=thecache; r; r = r->next)
289 : {
290 0 : if (r->pw)
291 : {
292 0 : if (DBG_CACHE)
293 0 : log_debug (" flushing '%s'\n", r->key);
294 0 : release_data (r->pw);
295 0 : r->pw = NULL;
296 0 : r->accessed = 0;
297 : }
298 : }
299 0 : }
300 :
301 :
302 :
303 : /* Store the string DATA in the cache under KEY and mark it with a
304 : maximum lifetime of TTL seconds. If there is already data under
305 : this key, it will be replaced. Using a DATA of NULL deletes the
306 : entry. A TTL of 0 is replaced by the default TTL and a TTL of -1
307 : set infinite timeout. CACHE_MODE is stored with the cache entry
308 : and used to select different timeouts. */
309 : int
310 10 : agent_put_cache (const char *key, cache_mode_t cache_mode,
311 : const char *data, int ttl)
312 : {
313 10 : gpg_error_t err = 0;
314 : ITEM r;
315 :
316 10 : if (DBG_CACHE)
317 0 : log_debug ("agent_put_cache '%s' (mode %d) requested ttl=%d\n",
318 : key, cache_mode, ttl);
319 10 : housekeeping ();
320 :
321 10 : if (!ttl)
322 : {
323 0 : switch(cache_mode)
324 : {
325 0 : case CACHE_MODE_SSH: ttl = opt.def_cache_ttl_ssh; break;
326 0 : default: ttl = opt.def_cache_ttl; break;
327 : }
328 : }
329 10 : if ((!ttl && data) || cache_mode == CACHE_MODE_IGNORE)
330 0 : return 0;
331 :
332 55 : for (r=thecache; r; r = r->next)
333 : {
334 45 : if (((cache_mode != CACHE_MODE_USER
335 45 : && cache_mode != CACHE_MODE_NONCE)
336 0 : || r->cache_mode == cache_mode)
337 45 : && !strcmp (r->key, key))
338 0 : break;
339 : }
340 10 : if (r) /* Replace. */
341 : {
342 0 : if (r->pw)
343 : {
344 0 : release_data (r->pw);
345 0 : r->pw = NULL;
346 : }
347 0 : if (data)
348 : {
349 0 : r->created = r->accessed = gnupg_get_time ();
350 0 : r->ttl = ttl;
351 0 : r->cache_mode = cache_mode;
352 0 : err = new_data (data, &r->pw);
353 0 : if (err)
354 0 : log_error ("error replacing cache item: %s\n", gpg_strerror (err));
355 : }
356 : }
357 10 : else if (data) /* Insert. */
358 : {
359 10 : r = xtrycalloc (1, sizeof *r + strlen (key));
360 10 : if (!r)
361 0 : err = gpg_error_from_syserror ();
362 : else
363 : {
364 10 : strcpy (r->key, key);
365 10 : r->created = r->accessed = gnupg_get_time ();
366 10 : r->ttl = ttl;
367 10 : r->cache_mode = cache_mode;
368 10 : err = new_data (data, &r->pw);
369 10 : if (err)
370 0 : xfree (r);
371 : else
372 : {
373 10 : r->next = thecache;
374 10 : thecache = r;
375 : }
376 : }
377 10 : if (err)
378 0 : log_error ("error inserting cache item: %s\n", gpg_strerror (err));
379 : }
380 10 : return err;
381 : }
382 :
383 :
384 : /* Try to find an item in the cache. Note that we currently don't
385 : make use of CACHE_MODE except for CACHE_MODE_NONCE and
386 : CACHE_MODE_USER. */
387 : char *
388 120 : agent_get_cache (const char *key, cache_mode_t cache_mode)
389 : {
390 : gpg_error_t err;
391 : ITEM r;
392 120 : char *value = NULL;
393 : int res;
394 120 : int last_stored = 0;
395 :
396 120 : if (cache_mode == CACHE_MODE_IGNORE)
397 0 : return NULL;
398 :
399 120 : if (!key)
400 : {
401 0 : key = last_stored_cache_key;
402 0 : if (!key)
403 0 : return NULL;
404 0 : last_stored = 1;
405 : }
406 :
407 :
408 120 : if (DBG_CACHE)
409 0 : log_debug ("agent_get_cache '%s' (mode %d)%s ...\n",
410 : key, cache_mode,
411 : last_stored? " (stored cache key)":"");
412 120 : housekeeping ();
413 :
414 309 : for (r=thecache; r; r = r->next)
415 : {
416 309 : if (r->pw
417 309 : && ((cache_mode != CACHE_MODE_USER
418 309 : && cache_mode != CACHE_MODE_NONCE)
419 0 : || r->cache_mode == cache_mode)
420 309 : && !strcmp (r->key, key))
421 : {
422 : /* Note: To avoid races KEY may not be accessed anymore below. */
423 120 : r->accessed = gnupg_get_time ();
424 120 : if (DBG_CACHE)
425 0 : log_debug ("... hit\n");
426 120 : if (r->pw->totallen < 32)
427 0 : err = gpg_error (GPG_ERR_INV_LENGTH);
428 120 : else if ((err = init_encryption ()))
429 : ;
430 120 : else if (!(value = xtrymalloc_secure (r->pw->totallen - 8)))
431 0 : err = gpg_error_from_syserror ();
432 : else
433 : {
434 120 : res = npth_mutex_lock (&encryption_lock);
435 120 : if (res)
436 0 : log_fatal ("failed to acquire cache encryption mutex: %s\n",
437 : strerror (res));
438 240 : err = gcry_cipher_decrypt (encryption_handle,
439 120 : value, r->pw->totallen - 8,
440 240 : r->pw->data, r->pw->totallen);
441 120 : res = npth_mutex_unlock (&encryption_lock);
442 120 : if (res)
443 0 : log_fatal ("failed to release cache encryption mutex: %s\n",
444 : strerror (res));
445 : }
446 120 : if (err)
447 : {
448 0 : xfree (value);
449 0 : value = NULL;
450 0 : log_error ("retrieving cache entry '%s' failed: %s\n",
451 : key, gpg_strerror (err));
452 : }
453 120 : return value;
454 : }
455 : }
456 0 : if (DBG_CACHE)
457 0 : log_debug ("... miss\n");
458 :
459 0 : return NULL;
460 : }
461 :
462 :
463 : /* Store the key for the last successful cache hit. That value is
464 : used by agent_get_cache if the requested KEY is given as NULL.
465 : NULL may be used to remove that key. */
466 : void
467 120 : agent_store_cache_hit (const char *key)
468 : {
469 120 : xfree (last_stored_cache_key);
470 120 : last_stored_cache_key = key? xtrystrdup (key) : NULL;
471 120 : }
|