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 <https://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 50 : initialize_module_cache (void)
76 : {
77 : int err;
78 :
79 50 : err = npth_mutex_init (&encryption_lock, NULL);
80 :
81 50 : if (err)
82 0 : log_fatal ("error initializing cache module: %s\n", strerror (err));
83 50 : }
84 :
85 :
86 : void
87 100 : deinitialize_module_cache (void)
88 : {
89 100 : gcry_cipher_close (encryption_handle);
90 100 : encryption_handle = NULL;
91 100 : }
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 294 : init_encryption (void)
102 : {
103 : gpg_error_t err;
104 : void *key;
105 : int res;
106 :
107 294 : if (encryption_handle)
108 259 : return 0; /* Shortcut - Already initialized. */
109 :
110 35 : res = npth_mutex_lock (&encryption_lock);
111 35 : if (res)
112 0 : log_fatal ("failed to acquire cache encryption mutex: %s\n", strerror (res));
113 :
114 35 : err = gcry_cipher_open (&encryption_handle, GCRY_CIPHER_AES128,
115 : GCRY_CIPHER_MODE_AESWRAP, GCRY_CIPHER_SECURE);
116 35 : if (!err)
117 : {
118 35 : key = gcry_random_bytes (ENCRYPTION_KEYSIZE, GCRY_STRONG_RANDOM);
119 35 : if (!key)
120 0 : err = gpg_error_from_syserror ();
121 : else
122 : {
123 35 : err = gcry_cipher_setkey (encryption_handle, key, ENCRYPTION_KEYSIZE);
124 35 : xfree (key);
125 : }
126 35 : if (err)
127 : {
128 0 : gcry_cipher_close (encryption_handle);
129 0 : encryption_handle = NULL;
130 : }
131 : }
132 35 : if (err)
133 0 : log_error ("error initializing cache encryption context: %s\n",
134 : gpg_strerror (err));
135 :
136 35 : res = npth_mutex_unlock (&encryption_lock);
137 35 : if (res)
138 0 : log_fatal ("failed to release cache encryption mutex: %s\n", strerror (res));
139 :
140 35 : return err? gpg_error (GPG_ERR_NOT_INITIALIZED) : 0;
141 : }
142 :
143 :
144 :
145 : static void
146 3 : release_data (struct secret_data_s *data)
147 : {
148 3 : xfree (data);
149 3 : }
150 :
151 : static gpg_error_t
152 144 : 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 144 : *r_data = NULL;
161 :
162 144 : err = init_encryption ();
163 144 : if (err)
164 0 : return err;
165 :
166 144 : 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 144 : total = (length + 8) + 32 - ((length+8) % 32);
174 :
175 144 : d = xtrymalloc_secure (sizeof *d + total - 1);
176 144 : if (!d)
177 0 : return gpg_error_from_syserror ();
178 144 : memcpy (d->data, string, length);
179 :
180 144 : d_enc = xtrymalloc (sizeof *d_enc + total - 1);
181 144 : if (!d_enc)
182 : {
183 0 : err = gpg_error_from_syserror ();
184 0 : xfree (d);
185 0 : return err;
186 : }
187 :
188 144 : d_enc->totallen = total;
189 144 : res = npth_mutex_lock (&encryption_lock);
190 144 : if (res)
191 0 : log_fatal ("failed to acquire cache encryption mutex: %s\n",
192 : strerror (res));
193 :
194 288 : err = gcry_cipher_encrypt (encryption_handle, d_enc->data, total,
195 288 : d->data, total - 8);
196 144 : xfree (d);
197 144 : res = npth_mutex_unlock (&encryption_lock);
198 144 : if (res)
199 0 : log_fatal ("failed to release cache encryption mutex: %s\n", strerror (res));
200 144 : if (err)
201 : {
202 0 : xfree (d_enc);
203 0 : return err;
204 : }
205 144 : *r_data = d_enc;
206 144 : return 0;
207 : }
208 :
209 :
210 :
211 : /* Check whether there are items to expire. */
212 : static void
213 352 : housekeeping (void)
214 : {
215 : ITEM r, rprev;
216 352 : time_t current = gnupg_get_time ();
217 :
218 : /* First expire the actual data */
219 1538 : for (r=thecache; r; r = r->next)
220 : {
221 1186 : 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 1538 : for (r=thecache; r; r = r->next)
235 : {
236 : unsigned long maxttl;
237 :
238 1186 : switch (r->cache_mode)
239 : {
240 6 : case CACHE_MODE_SSH: maxttl = opt.max_cache_ttl_ssh; break;
241 1180 : default: maxttl = opt.max_cache_ttl; break;
242 : }
243 1186 : 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 1890 : for (rprev=NULL, r=thecache; r; )
257 : {
258 1186 : 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 1186 : rprev = r;
274 1186 : r = r->next;
275 : }
276 : }
277 352 : }
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 13 : 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 18 : return ((a == CACHE_MODE_ANY && b != CACHE_MODE_IGNORE)
308 21 : || (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 146 : agent_put_cache (const char *key, cache_mode_t cache_mode,
320 : const char *data, int ttl)
321 : {
322 146 : gpg_error_t err = 0;
323 : ITEM r;
324 :
325 146 : if (DBG_CACHE)
326 0 : log_debug ("agent_put_cache '%s' (mode %d) requested ttl=%d\n",
327 : key, cache_mode, ttl);
328 146 : housekeeping ();
329 :
330 146 : if (!ttl)
331 : {
332 7 : switch(cache_mode)
333 : {
334 4 : case CACHE_MODE_SSH: ttl = opt.def_cache_ttl_ssh; break;
335 3 : default: ttl = opt.def_cache_ttl; break;
336 : }
337 : }
338 146 : if ((!ttl && data) || cache_mode == CACHE_MODE_IGNORE)
339 1 : return 0;
340 :
341 387 : for (r=thecache; r; r = r->next)
342 : {
343 245 : if (((cache_mode != CACHE_MODE_USER
344 245 : && cache_mode != CACHE_MODE_NONCE)
345 7 : || cache_mode_equal (r->cache_mode, cache_mode))
346 245 : && !strcmp (r->key, key))
347 3 : break;
348 : }
349 145 : if (r) /* Replace. */
350 : {
351 3 : if (r->pw)
352 : {
353 3 : release_data (r->pw);
354 3 : r->pw = NULL;
355 : }
356 3 : if (data)
357 : {
358 2 : r->created = r->accessed = gnupg_get_time ();
359 2 : r->ttl = ttl;
360 2 : r->cache_mode = cache_mode;
361 2 : err = new_data (data, &r->pw);
362 2 : if (err)
363 0 : log_error ("error replacing cache item: %s\n", gpg_strerror (err));
364 : }
365 : }
366 142 : else if (data) /* Insert. */
367 : {
368 142 : r = xtrycalloc (1, sizeof *r + strlen (key));
369 142 : if (!r)
370 0 : err = gpg_error_from_syserror ();
371 : else
372 : {
373 142 : strcpy (r->key, key);
374 142 : r->created = r->accessed = gnupg_get_time ();
375 142 : r->ttl = ttl;
376 142 : r->cache_mode = cache_mode;
377 142 : err = new_data (data, &r->pw);
378 142 : if (err)
379 0 : xfree (r);
380 : else
381 : {
382 142 : r->next = thecache;
383 142 : thecache = r;
384 : }
385 : }
386 142 : if (err)
387 0 : log_error ("error inserting cache item: %s\n", gpg_strerror (err));
388 : }
389 145 : 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 207 : agent_get_cache (const char *key, cache_mode_t cache_mode)
398 : {
399 : gpg_error_t err;
400 : ITEM r;
401 207 : char *value = NULL;
402 : int res;
403 207 : int last_stored = 0;
404 :
405 207 : if (cache_mode == CACHE_MODE_IGNORE)
406 0 : return NULL;
407 :
408 207 : if (!key)
409 : {
410 1 : key = last_stored_cache_key;
411 1 : if (!key)
412 1 : return NULL;
413 0 : last_stored = 1;
414 : }
415 :
416 :
417 206 : 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 206 : housekeeping ();
422 :
423 502 : for (r=thecache; r; r = r->next)
424 : {
425 446 : if (r->pw
426 443 : && ((cache_mode != CACHE_MODE_USER
427 442 : && cache_mode != CACHE_MODE_NONCE)
428 6 : || cache_mode_equal (r->cache_mode, cache_mode))
429 443 : && !strcmp (r->key, key))
430 : {
431 : /* Note: To avoid races KEY may not be accessed anymore below. */
432 150 : r->accessed = gnupg_get_time ();
433 150 : if (DBG_CACHE)
434 0 : log_debug ("... hit\n");
435 150 : if (r->pw->totallen < 32)
436 0 : err = gpg_error (GPG_ERR_INV_LENGTH);
437 150 : else if ((err = init_encryption ()))
438 : ;
439 150 : else if (!(value = xtrymalloc_secure (r->pw->totallen - 8)))
440 0 : err = gpg_error_from_syserror ();
441 : else
442 : {
443 150 : res = npth_mutex_lock (&encryption_lock);
444 150 : if (res)
445 0 : log_fatal ("failed to acquire cache encryption mutex: %s\n",
446 : strerror (res));
447 300 : err = gcry_cipher_decrypt (encryption_handle,
448 150 : value, r->pw->totallen - 8,
449 300 : r->pw->data, r->pw->totallen);
450 150 : res = npth_mutex_unlock (&encryption_lock);
451 150 : if (res)
452 0 : log_fatal ("failed to release cache encryption mutex: %s\n",
453 : strerror (res));
454 : }
455 150 : 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 150 : return value;
463 : }
464 : }
465 56 : if (DBG_CACHE)
466 0 : log_debug ("... miss\n");
467 :
468 56 : 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 141 : agent_store_cache_hit (const char *key)
477 : {
478 141 : xfree (last_stored_cache_key);
479 141 : last_stored_cache_key = key? xtrystrdup (key) : NULL;
480 141 : }
|