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 48 : initialize_module_cache (void)
76 : {
77 : int err;
78 :
79 48 : err = npth_mutex_init (&encryption_lock, NULL);
80 :
81 48 : if (err)
82 0 : log_fatal ("error initializing cache module: %s\n", strerror (err));
83 48 : }
84 :
85 :
86 : void
87 93 : deinitialize_module_cache (void)
88 : {
89 93 : gcry_cipher_close (encryption_handle);
90 93 : encryption_handle = NULL;
91 93 : }
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 316 : init_encryption (void)
102 : {
103 : gpg_error_t err;
104 : void *key;
105 : int res;
106 :
107 316 : if (encryption_handle)
108 275 : return 0; /* Shortcut - Already initialized. */
109 :
110 41 : res = npth_mutex_lock (&encryption_lock);
111 41 : if (res)
112 0 : log_fatal ("failed to acquire cache encryption mutex: %s\n", strerror (res));
113 :
114 41 : err = gcry_cipher_open (&encryption_handle, GCRY_CIPHER_AES128,
115 : GCRY_CIPHER_MODE_AESWRAP, GCRY_CIPHER_SECURE);
116 41 : if (!err)
117 : {
118 41 : key = gcry_random_bytes (ENCRYPTION_KEYSIZE, GCRY_STRONG_RANDOM);
119 41 : if (!key)
120 0 : err = gpg_error_from_syserror ();
121 : else
122 : {
123 41 : err = gcry_cipher_setkey (encryption_handle, key, ENCRYPTION_KEYSIZE);
124 41 : xfree (key);
125 : }
126 41 : if (err)
127 : {
128 0 : gcry_cipher_close (encryption_handle);
129 0 : encryption_handle = NULL;
130 : }
131 : }
132 41 : if (err)
133 0 : log_error ("error initializing cache encryption context: %s\n",
134 : gpg_strerror (err));
135 :
136 41 : res = npth_mutex_unlock (&encryption_lock);
137 41 : if (res)
138 0 : log_fatal ("failed to release cache encryption mutex: %s\n", strerror (res));
139 :
140 41 : return err? gpg_error (GPG_ERR_NOT_INITIALIZED) : 0;
141 : }
142 :
143 :
144 :
145 : static void
146 2 : release_data (struct secret_data_s *data)
147 : {
148 2 : xfree (data);
149 2 : }
150 :
151 : static gpg_error_t
152 177 : 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 177 : *r_data = NULL;
161 :
162 177 : err = init_encryption ();
163 177 : if (err)
164 0 : return err;
165 :
166 177 : 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 : usually 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 177 : total = (length + 8) + 32 - ((length+8) % 32);
174 :
175 177 : d = xtrymalloc_secure (sizeof *d + total - 1);
176 177 : if (!d)
177 0 : return gpg_error_from_syserror ();
178 177 : memcpy (d->data, string, length);
179 :
180 177 : d_enc = xtrymalloc (sizeof *d_enc + total - 1);
181 177 : if (!d_enc)
182 : {
183 0 : err = gpg_error_from_syserror ();
184 0 : xfree (d);
185 0 : return err;
186 : }
187 :
188 177 : d_enc->totallen = total;
189 177 : res = npth_mutex_lock (&encryption_lock);
190 177 : if (res)
191 0 : log_fatal ("failed to acquire cache encryption mutex: %s\n",
192 : strerror (res));
193 :
194 354 : err = gcry_cipher_encrypt (encryption_handle, d_enc->data, total,
195 354 : d->data, total - 8);
196 177 : xfree (d);
197 177 : res = npth_mutex_unlock (&encryption_lock);
198 177 : if (res)
199 0 : log_fatal ("failed to release cache encryption mutex: %s\n", strerror (res));
200 177 : if (err)
201 : {
202 0 : xfree (d_enc);
203 0 : return err;
204 : }
205 177 : *r_data = d_enc;
206 177 : return 0;
207 : }
208 :
209 :
210 :
211 : /* Check whether there are items to expire. */
212 : static void
213 345 : housekeeping (void)
214 : {
215 : ITEM r, rprev;
216 345 : time_t current = gnupg_get_time ();
217 :
218 : /* First expire the actual data */
219 1574 : for (r=thecache; r; r = r->next)
220 : {
221 1229 : 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 1574 : for (r=thecache; r; r = r->next)
235 : {
236 : unsigned long maxttl;
237 :
238 1229 : switch (r->cache_mode)
239 : {
240 6 : case CACHE_MODE_SSH: maxttl = opt.max_cache_ttl_ssh; break;
241 1223 : default: maxttl = opt.max_cache_ttl; break;
242 : }
243 1229 : 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 1919 : for (rprev=NULL, r=thecache; r; )
257 : {
258 1229 : 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 1229 : rprev = r;
274 1229 : r = r->next;
275 : }
276 : }
277 345 : }
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 : /* Compare two cache modes. */
303 : static int
304 8 : cache_mode_equal (cache_mode_t a, cache_mode_t b)
305 : {
306 : /* CACHE_MODE_ANY matches any mode other than CACHE_MODE_IGNORE. */
307 13 : return ((a == CACHE_MODE_ANY && b != CACHE_MODE_IGNORE)
308 11 : || (b == CACHE_MODE_ANY && a != CACHE_MODE_IGNORE) || a == b);
309 : }
310 :
311 :
312 : /* Store the string DATA in the cache under KEY and mark it with a
313 : maximum lifetime of TTL seconds. If there is already data under
314 : this key, it will be replaced. Using a DATA of NULL deletes the
315 : entry. A TTL of 0 is replaced by the default TTL and a TTL of -1
316 : set infinite timeout. CACHE_MODE is stored with the cache entry
317 : and used to select different timeouts. */
318 : int
319 179 : agent_put_cache (const char *key, cache_mode_t cache_mode,
320 : const char *data, int ttl)
321 : {
322 179 : gpg_error_t err = 0;
323 : ITEM r;
324 :
325 179 : if (DBG_CACHE)
326 0 : log_debug ("agent_put_cache '%s' (mode %d) requested ttl=%d\n",
327 : key, cache_mode, ttl);
328 179 : housekeeping ();
329 :
330 179 : if (!ttl)
331 : {
332 6 : switch(cache_mode)
333 : {
334 4 : case CACHE_MODE_SSH: ttl = opt.def_cache_ttl_ssh; break;
335 2 : default: ttl = opt.def_cache_ttl; break;
336 : }
337 : }
338 179 : if ((!ttl && data) || cache_mode == CACHE_MODE_IGNORE)
339 1 : return 0;
340 :
341 493 : for (r=thecache; r; r = r->next)
342 : {
343 317 : if (((cache_mode != CACHE_MODE_USER
344 317 : && cache_mode != CACHE_MODE_NONCE)
345 6 : || cache_mode_equal (r->cache_mode, cache_mode))
346 317 : && !strcmp (r->key, key))
347 2 : break;
348 : }
349 178 : if (r) /* Replace. */
350 : {
351 2 : if (r->pw)
352 : {
353 2 : release_data (r->pw);
354 2 : r->pw = NULL;
355 : }
356 2 : if (data)
357 : {
358 1 : r->created = r->accessed = gnupg_get_time ();
359 1 : r->ttl = ttl;
360 1 : r->cache_mode = cache_mode;
361 1 : err = new_data (data, &r->pw);
362 1 : if (err)
363 0 : log_error ("error replacing cache item: %s\n", gpg_strerror (err));
364 : }
365 : }
366 176 : else if (data) /* Insert. */
367 : {
368 176 : r = xtrycalloc (1, sizeof *r + strlen (key));
369 176 : if (!r)
370 0 : err = gpg_error_from_syserror ();
371 : else
372 : {
373 176 : strcpy (r->key, key);
374 176 : r->created = r->accessed = gnupg_get_time ();
375 176 : r->ttl = ttl;
376 176 : r->cache_mode = cache_mode;
377 176 : err = new_data (data, &r->pw);
378 176 : if (err)
379 0 : xfree (r);
380 : else
381 : {
382 176 : r->next = thecache;
383 176 : thecache = r;
384 : }
385 : }
386 176 : if (err)
387 0 : log_error ("error inserting cache item: %s\n", gpg_strerror (err));
388 : }
389 178 : return err;
390 : }
391 :
392 :
393 : /* Try to find an item in the cache. Note that we currently don't
394 : make use of CACHE_MODE except for CACHE_MODE_NONCE and
395 : CACHE_MODE_USER. */
396 : char *
397 166 : agent_get_cache (const char *key, cache_mode_t cache_mode)
398 : {
399 : gpg_error_t err;
400 : ITEM r;
401 166 : char *value = NULL;
402 : int res;
403 166 : int last_stored = 0;
404 :
405 166 : if (cache_mode == CACHE_MODE_IGNORE)
406 0 : return NULL;
407 :
408 166 : if (!key)
409 : {
410 0 : key = last_stored_cache_key;
411 0 : if (!key)
412 0 : return NULL;
413 0 : last_stored = 1;
414 : }
415 :
416 :
417 166 : if (DBG_CACHE)
418 0 : log_debug ("agent_get_cache '%s' (mode %d)%s ...\n",
419 : key, cache_mode,
420 : last_stored? " (stored cache key)":"");
421 166 : housekeeping ();
422 :
423 447 : for (r=thecache; r; r = r->next)
424 : {
425 420 : if (r->pw
426 417 : && ((cache_mode != CACHE_MODE_USER
427 416 : && cache_mode != CACHE_MODE_NONCE)
428 2 : || cache_mode_equal (r->cache_mode, cache_mode))
429 417 : && !strcmp (r->key, key))
430 : {
431 : /* Note: To avoid races KEY may not be accessed anymore below. */
432 139 : r->accessed = gnupg_get_time ();
433 139 : if (DBG_CACHE)
434 0 : log_debug ("... hit\n");
435 139 : if (r->pw->totallen < 32)
436 0 : err = gpg_error (GPG_ERR_INV_LENGTH);
437 139 : else if ((err = init_encryption ()))
438 : ;
439 139 : else if (!(value = xtrymalloc_secure (r->pw->totallen - 8)))
440 0 : err = gpg_error_from_syserror ();
441 : else
442 : {
443 139 : res = npth_mutex_lock (&encryption_lock);
444 139 : if (res)
445 0 : log_fatal ("failed to acquire cache encryption mutex: %s\n",
446 : strerror (res));
447 278 : err = gcry_cipher_decrypt (encryption_handle,
448 139 : value, r->pw->totallen - 8,
449 278 : r->pw->data, r->pw->totallen);
450 139 : res = npth_mutex_unlock (&encryption_lock);
451 139 : if (res)
452 0 : log_fatal ("failed to release cache encryption mutex: %s\n",
453 : strerror (res));
454 : }
455 139 : if (err)
456 : {
457 0 : xfree (value);
458 0 : value = NULL;
459 0 : log_error ("retrieving cache entry '%s' failed: %s\n",
460 : key, gpg_strerror (err));
461 : }
462 139 : return value;
463 : }
464 : }
465 27 : if (DBG_CACHE)
466 0 : log_debug ("... miss\n");
467 :
468 27 : return NULL;
469 : }
470 :
471 :
472 : /* Store the key for the last successful cache hit. That value is
473 : used by agent_get_cache if the requested KEY is given as NULL.
474 : NULL may be used to remove that key. */
475 : void
476 136 : agent_store_cache_hit (const char *key)
477 : {
478 136 : xfree (last_stored_cache_key);
479 136 : last_stored_cache_key = key? xtrystrdup (key) : NULL;
480 136 : }
|