Also clear FLAG_ACL_ERROR after target validation.
[pwmd.git] / src / cache.c
blob7e5d86a251836908d7905f6bdbfadb4329b72d59
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of pwmd.
7 Pwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Pwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <pthread.h>
27 #include <ctype.h>
28 #include <errno.h>
30 #include "pwmd-error.h"
31 #include <gcrypt.h>
32 #include "mutex.h"
33 #include "cache.h"
34 #include "status.h"
35 #include "mem.h"
36 #include "util-misc.h"
37 #include "util-string.h"
38 #include "crypto.h"
40 #ifdef HAVE_TIME_H
41 #include <time.h>
42 #endif
44 static pthread_mutex_t cache_mutex;
45 static struct slist_s *key_cache;
46 #ifdef WITH_AGENT
47 static struct agent_s *cache_agent;
48 #endif
50 extern void log_write (const char *fmt, ...);
52 typedef gpg_error_t (*free_data_fn_t) (file_cache_t *);
53 static free_data_fn_t free_data_fn;
54 static gpg_error_t clear_once (file_cache_t * p);
55 static int remove_entry (const unsigned char *md5file);
56 static void free_entry (file_cache_t * p);
58 static file_cache_t *
59 get_entry (const unsigned char *md5file)
61 int t = slist_length (key_cache);
62 int i;
64 if (!md5file)
65 return NULL;
67 for (i = 0; i < t; i++)
69 file_cache_t *p = slist_nth_data (key_cache, i);
71 if (!memcmp (p->filename, md5file, sizeof (p->filename)))
72 return p;
75 return NULL;
78 gpg_error_t
79 cache_lock_mutex (void *ctx, const unsigned char *md5file,
80 long lock_timeout, int add, int timeout)
82 MUTEX_LOCK (&cache_mutex);
83 gpg_error_t rc = 0;
84 file_cache_t *p = get_entry (md5file);
86 if (p)
88 MUTEX_UNLOCK (&cache_mutex);
89 MUTEX_TRYLOCK (ctx, p->mutex, rc, lock_timeout);
91 else if (add)
93 rc = cache_add_file (md5file, NULL, NULL, timeout);
94 if (!rc)
96 p = get_entry (md5file);
97 MUTEX_UNLOCK (&cache_mutex);
98 MUTEX_TRYLOCK (ctx, p->mutex, rc, lock_timeout);
100 else
102 MUTEX_UNLOCK (&cache_mutex);
105 else
107 MUTEX_UNLOCK (&cache_mutex);
110 return !p && !rc ? GPG_ERR_NO_DATA : rc;
113 static int
114 remove_entry (const unsigned char *md5file)
116 MUTEX_LOCK (&cache_mutex);
117 file_cache_t *p = get_entry (md5file);
119 pthread_cleanup_push (cleanup_mutex_cb, &cache_mutex);
120 if (p)
122 /* Keep a refcount because another client maybe editing this same new
123 * file. The entry needs to be kept in case the other client SAVE's.
125 p->refcount--;
126 if (!p->refcount)
127 free_entry (p);
130 pthread_cleanup_pop (1);
131 return p ? 1 : 0;
134 gpg_error_t
135 cache_unlock_mutex (const unsigned char *md5file, int remove)
137 MUTEX_LOCK (&cache_mutex);
138 file_cache_t *p = get_entry (md5file);
140 if (p)
142 MUTEX_UNLOCK (p->mutex);
143 if (remove)
144 remove_entry (md5file);
147 MUTEX_UNLOCK (&cache_mutex);
148 return p ? 0 : GPG_ERR_NO_DATA;
151 #ifdef WITH_AGENT
152 static int valid_agent_grip (file_cache_t *e)
154 size_t c;
156 for (c = 0; c < sizeof (e->grip); c++)
158 if (e->grip[c] && e->grip[c] != '0')
159 return 1;
162 return 0;
164 #endif
166 static int
167 valid_grip (file_cache_t * e)
169 if (e->data && e->data->key)
170 return 1;
172 #ifdef WITH_AGENT
173 return valid_agent_grip (e);
174 #else
175 return 0;
176 #endif
179 static gpg_error_t
180 iscached (const unsigned char *md5file, int *defer)
182 gpg_error_t rc = 0;
183 file_cache_t *p = get_entry (md5file);
185 if (!p || !p->data || !valid_grip (p))
186 return GPG_ERR_NO_DATA;
188 if (defer)
189 *defer = p->defer_clear;
191 if (p->data && p->data->key)
192 return 0;
194 #ifdef WITH_AGENT
195 char *line;
197 rc = send_to_agent (cache_agent, &line, NULL, "KEYINFO --data %s", p->grip);
198 if (!rc)
200 char **fields = str_split (line, " ", 0);
202 /* Smartcard with a cached document. */
203 if (*fields[1] == 'T' && p->data->doc)
204 rc = 0;
205 else
206 rc = isdigit (*fields[4]) || *fields[5] == 'C' ? 0 : GPG_ERR_NO_DATA;
208 strv_free (fields);
209 xfree (line);
211 #endif
213 return rc;
216 unsigned
217 cache_file_count ()
219 MUTEX_LOCK (&cache_mutex);
220 unsigned total = 0, i, n;
222 pthread_cleanup_push (cleanup_mutex_cb, &cache_mutex);
223 n = slist_length (key_cache);
224 for (i = 0; i < n; i++)
226 file_cache_t *p = slist_nth_data (key_cache, i);
228 if (!iscached (p->filename, NULL))
229 total++;
232 pthread_cleanup_pop (1);
233 return total;
236 void
237 cache_adjust_timeout ()
239 MUTEX_LOCK (&cache_mutex);
240 int t = slist_length (key_cache);
241 int i;
243 pthread_cleanup_push (cleanup_mutex_cb, &cache_mutex);
245 for (i = 0; i < t; i++)
247 file_cache_t *p = slist_nth_data (key_cache, i);
249 if (p->timeout > 0)
250 p->timeout--;
252 if (!p->timeout || p->defer_clear)
254 /* The file associated with this cache entry may be locked by a
255 * client. Defer freeing this cache entry until the next timeout
256 * check. */
257 if (!clear_once (p))
258 send_status_all (STATUS_CACHE, NULL);
262 pthread_cleanup_pop (1);
265 static void
266 setgrip (file_cache_t * p, const unsigned char *grip)
268 if (grip)
270 char *tmp = bin2hex (grip, 20);
272 memcpy (p->grip, tmp, sizeof (p->grip));
273 xfree (tmp);
275 else
276 memset (p->grip, 0, sizeof(p->grip));
279 static gpg_error_t
280 set_timeout (const unsigned char *md5file, int timeout, int defer, int force)
282 MUTEX_LOCK (&cache_mutex);
283 file_cache_t *p = get_entry (md5file);
284 gpg_error_t rc = 0;
286 if (!p)
288 MUTEX_UNLOCK (&cache_mutex);
289 return GPG_ERR_NOT_FOUND;
292 p->reset = timeout;
293 if (!p->defer_clear && (p->timeout == -1 || force))
294 p->timeout = timeout;
296 if (!timeout || defer)
298 rc = clear_once (p);
299 if (!rc)
300 send_status_all (STATUS_CACHE, NULL);
303 MUTEX_UNLOCK (&cache_mutex);
304 return rc;
307 gpg_error_t
308 cache_set_data (const unsigned char *md5file, struct cache_data_s * data,
309 const unsigned char *grip)
311 MUTEX_LOCK (&cache_mutex);
312 file_cache_t *p = get_entry (md5file);
314 if (p)
316 setgrip (p, grip);
317 p->data = data;
318 set_timeout (md5file, p->reset, p->defer_clear, 0);
319 if (!p->reset)
321 clear_once (p);
322 send_status_all (STATUS_CACHE, NULL);
326 MUTEX_UNLOCK (&cache_mutex);
327 return p ? 0 : GPG_ERR_NO_DATA;
330 struct cache_data_s *
331 cache_get_data (const unsigned char *md5file)
333 MUTEX_LOCK (&cache_mutex);
334 file_cache_t *p = get_entry (md5file);
336 MUTEX_UNLOCK (&cache_mutex);
337 return p ? p->data : NULL;
341 struct cache_data_s *
342 cache_get_data_filename (const char *filename)
344 unsigned char md5file[16];
346 gcry_md_hash_buffer (GCRY_MD_MD5, md5file, filename, strlen (filename));
347 return cache_get_data (md5file);
350 gpg_error_t
351 cache_add_file (const unsigned char *md5file, const unsigned char *grip,
352 struct cache_data_s *data, int timeout)
354 MUTEX_LOCK (&cache_mutex);
355 file_cache_t *p = get_entry (md5file);
356 struct slist_s *new;
357 gpg_error_t rc;
359 if (p)
361 setgrip (p, grip);
362 p->data = data;
363 p->refcount++;
364 rc = set_timeout (md5file, timeout, p->defer_clear, 0);
365 MUTEX_UNLOCK (&cache_mutex);
366 send_status_all (STATUS_CACHE, NULL);
367 return rc;
370 p = xcalloc (1, sizeof (file_cache_t));
371 if (!p)
373 MUTEX_UNLOCK (&cache_mutex);
374 return GPG_ERR_ENOMEM;
377 p->mutex = (pthread_mutex_t *) xmalloc (sizeof (pthread_mutex_t));
378 if (!p->mutex)
380 xfree (p);
381 MUTEX_UNLOCK (&cache_mutex);
382 return GPG_ERR_ENOMEM;
385 pthread_mutexattr_t attr;
386 pthread_mutexattr_init (&attr);
387 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
388 pthread_mutex_init (p->mutex, &attr);
389 pthread_mutexattr_destroy (&attr);
390 memcpy (p->filename, md5file, sizeof (p->filename));
391 setgrip (p, grip);
392 p->data = data;
393 p->refcount++;
394 new = slist_append (key_cache, p);
395 if (!new)
397 pthread_mutex_destroy (p->mutex);
398 xfree (p->mutex);
399 xfree (p);
400 MUTEX_UNLOCK (&cache_mutex);
401 return GPG_ERR_ENOMEM;
404 key_cache = new;
405 rc = cache_set_timeout(md5file, timeout);
406 MUTEX_UNLOCK (&cache_mutex);
407 send_status_all (STATUS_CACHE, NULL);
408 return rc;
411 static gpg_error_t
412 clear_once (file_cache_t * p)
414 gpg_error_t rc = free_data_fn (p);
416 if (!rc && valid_grip (p))
418 #ifdef WITH_AGENT
419 if (use_agent && valid_agent_grip (p))
421 rc = send_to_agent (cache_agent, NULL, NULL,
422 "CLEAR_PASSPHRASE --mode=normal %s", p->grip);
423 if (rc)
424 log_write ("%s(): %s", __FUNCTION__, pwmd_strerror (rc));
426 #endif
427 memset (p->grip, 0, sizeof (p->grip));
430 return rc;
433 static void
434 free_entry (file_cache_t * p)
436 gpg_error_t rc;
438 if (!p)
439 return;
441 rc = clear_once (p);
442 if (rc)
443 log_write ("%s(): %s", __FUNCTION__, pwmd_strerror (rc));
445 if (p->mutex)
447 pthread_mutex_destroy (p->mutex);
448 xfree (p->mutex);
451 key_cache = slist_remove (key_cache, p);
452 xfree (p);
455 gpg_error_t
456 cache_clear (const unsigned char *md5file)
458 file_cache_t *p;
459 gpg_error_t rc = 0;
460 int i, t;
462 MUTEX_LOCK (&cache_mutex);
464 if (md5file)
466 p = get_entry (md5file);
467 if (!p)
469 MUTEX_UNLOCK (&cache_mutex);
470 return 0;
473 pthread_cleanup_push (cleanup_mutex_cb, &cache_mutex);
474 rc = clear_once (p);
475 pthread_cleanup_pop (1);
476 if (rc)
477 log_write ("%s(): %s", __FUNCTION__, pwmd_strerror (rc));
479 return rc;
482 pthread_cleanup_push (cleanup_mutex_cb, &cache_mutex);
483 t = slist_length (key_cache);
484 for (i = 0; i < t; i++)
486 p = slist_nth_data (key_cache, i);
487 clear_once (p);
490 pthread_cleanup_pop (1);
491 return 0;
494 gpg_error_t
495 cache_iscached (const char *filename, int *defer)
497 gpg_error_t rc;
498 unsigned char md5file[16];
500 if (!filename)
501 return GPG_ERR_INV_PARAMETER;
503 MUTEX_LOCK (&cache_mutex);
504 pthread_cleanup_push (cleanup_mutex_cb, &cache_mutex);
505 gcry_md_hash_buffer (GCRY_MD_MD5, md5file, filename, strlen (filename));
506 rc = iscached (md5file, defer);
507 pthread_cleanup_pop (1);
509 /* Test if the data file disappeared from the filesystem. */
510 if ((!rc || gpg_err_code (rc) == GPG_ERR_NO_DATA)
511 && access (filename, R_OK) == -1)
513 rc = gpg_error_from_errno (errno);
514 if (gpg_err_code (rc) == GPG_ERR_ENOENT)
516 /* When -1, don't clear the cache entry. Fixes clearing the
517 * cache entry when saving a new file. */
518 if ((defer && *defer != -1) || !defer)
520 rc = cache_defer_clear (md5file);
521 if (!rc && defer)
522 *defer = 1;
525 rc = GPG_ERR_ENOENT;
529 return rc;
532 gpg_error_t
533 cache_defer_clear (const unsigned char *md5file)
535 MUTEX_LOCK (&cache_mutex);
536 file_cache_t *p = get_entry (md5file);
537 gpg_error_t rc = 0;
539 if (!p)
540 rc = GPG_ERR_NOT_FOUND;
541 else
542 p->defer_clear = 1;
544 MUTEX_UNLOCK (&cache_mutex);
545 return rc;
548 gpg_error_t
549 cache_set_timeout (const unsigned char *md5file, int timeout)
551 return set_timeout (md5file, timeout, 0, 1);
555 cache_get_grip (const unsigned char *md5file, unsigned char *grip)
557 MUTEX_LOCK (&cache_mutex);
558 file_cache_t *p = get_entry (md5file);
560 if (!p || !valid_grip (p))
562 MUTEX_UNLOCK (&cache_mutex);
563 return 0;
566 memcpy (grip, p->grip, sizeof (p->grip));
567 MUTEX_UNLOCK (&cache_mutex);
568 return 1;
571 /* The atfork parameter is needed to prevent clearing gpg-agent
572 cached keys during an atfork callback since the agent is still
573 shared between the two processes. */
574 void
575 cache_deinit (int atfork)
577 MUTEX_LOCK (&cache_mutex);
578 int i, t = slist_length (key_cache);
580 pthread_cleanup_push (cleanup_mutex_cb, &cache_mutex);
581 for (i = 0; i < t; i++)
583 file_cache_t *p = slist_nth_data (key_cache, i);
585 #ifdef WITH_AGENT
586 if (atfork && valid_agent_grip (p))
587 continue;
588 #endif
590 free_entry (p);
591 t = slist_length (key_cache);
592 i = -1;
595 #ifdef WITH_AGENT
596 if (use_agent && cache_agent)
597 cleanup_agent (cache_agent);
599 cache_agent = NULL;
600 #endif
601 gcry_free (cache_key);
602 xfree (cache_iv);
603 cache_key = NULL;
604 cache_iv = NULL;
605 pthread_cleanup_pop (1);
606 pthread_mutex_destroy (&cache_mutex);
609 void
610 cache_mutex_init ()
612 pthread_mutexattr_t attr;
614 pthread_mutexattr_init (&attr);
615 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
616 pthread_mutex_init (&cache_mutex, &attr);
617 pthread_mutexattr_destroy (&attr);
620 gpg_error_t
621 cache_init (free_data_fn_t fn)
623 gpg_error_t rc = 0;
625 if (!cache_key)
627 rc = gcry_cipher_algo_info (GCRY_CIPHER_AES, GCRYCTL_GET_BLKLEN, NULL,
628 &cache_blocksize);
629 if (rc)
630 return rc;
632 rc = gcry_cipher_algo_info (GCRY_CIPHER_AES, GCRYCTL_GET_KEYLEN, NULL,
633 &cache_keysize);
634 if (rc)
635 return rc;
637 cache_key = gcry_malloc (cache_keysize);
638 if (!cache_key)
639 return GPG_ERR_ENOMEM;
641 cache_iv = xmalloc (cache_blocksize);
642 if (!cache_iv)
644 gcry_free (cache_key);
645 cache_key = NULL;
646 return GPG_ERR_ENOMEM;
649 gcry_create_nonce (cache_key, cache_keysize);
650 gcry_create_nonce (cache_iv, cache_blocksize);
653 #ifdef WITH_AGENT
654 if (use_agent && !cache_agent)
656 rc = agent_init (&cache_agent);
657 if (!rc)
659 char *line;
661 rc = send_to_agent (cache_agent, &line, NULL, "GETINFO version");
662 if (!rc)
664 char **fields = str_split (line, ".", 0);
665 int major, minor;
667 major = atoi (fields[0]);
668 minor = atoi (fields[1]);
669 if (major < 2 || minor < 1)
670 rc = GPG_ERR_UNKNOWN_VERSION;
672 strv_free (fields);
673 xfree (line);
677 #endif
679 cache_mutex_init ();
680 free_data_fn = fn;
681 return rc;
684 #ifdef WITH_AGENT
685 gpg_error_t
686 cache_is_shadowed (const char *grip)
688 MUTEX_LOCK (&cache_mutex);
689 char *line;
690 size_t len;
691 gpg_error_t rc;
693 pthread_cleanup_push (cleanup_mutex_cb, &cache_mutex);
694 rc = send_to_agent (cache_agent, &line, &len, "KEYINFO --data %s", grip);
695 pthread_cleanup_pop (1);
697 if (!rc)
699 char **fields = str_split (line, " ", 0);
701 rc = (*fields[1] == 'T') ? 0 : GPG_ERR_NO_DATA;
702 xfree (line);
703 strv_free (fields);
706 return rc;
708 #endif
710 void
711 cache_lock ()
713 MUTEX_LOCK (&cache_mutex);
716 void
717 cache_unlock ()
719 MUTEX_UNLOCK (&cache_mutex);
722 void
723 free_cache_data_once (struct cache_data_s *data)
725 if (!data)
726 return;
728 #ifdef WITH_AGENT
729 if (data->pubkey)
730 gcry_sexp_release (data->pubkey);
732 if (data->sigkey)
733 gcry_sexp_release (data->sigkey);
734 #endif
736 gcry_free (data->doc);
737 gcry_free (data->key);
738 xfree (data->crc);
739 xfree (data);