Add STATUS_MODIFIED.
[pwmd.git] / src / cache.c
blob8e0606e19323dd1eff6916d3040d36acbe7c4f99
1 /*
2 Copyright (C) 2006-2022 Ben Kibbey <bjk@luxsci.net>
4 This file is part of pwmd.
6 Pwmd is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation.
10 Pwmd is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
22 #include <stdio.h>
23 #ifdef HAVE_UNISTD_H
24 #include <unistd.h>
25 #endif
26 #include <time.h>
27 #include <pthread.h>
28 #include <ctype.h>
29 #include <errno.h>
31 #include "pwmd-error.h"
32 #include <gcrypt.h>
33 #include "mutex.h"
34 #include "cache.h"
35 #include "status.h"
36 #include "mem.h"
37 #include "util-misc.h"
38 #include "util-string.h"
39 #include "agent.h"
40 #include "acl.h"
42 struct plaintext_s
44 xmlDocPtr plaintext;
45 unsigned refcount;
46 char *filename;
47 int modified;
50 static pthread_mutex_t cache_mutex;
51 static struct slist_s *key_cache;
52 static struct slist_s *plaintext_list;
53 static unsigned char *cache_iv;
54 static unsigned char *cache_key;
55 static size_t cache_blocksize;
56 static size_t cache_keysize;
57 static struct agent_s *cache_agent;
58 static int exiting;
60 void log_write (const char *fmt, ...);
62 static gpg_error_t clear_once (file_cache_t * p, int agent, int force);
63 static int remove_entry (const char *);
64 static void free_entry (file_cache_t * p, int agent);
66 static file_cache_t *
67 get_entry (const char *filename)
69 if (!filename)
70 return NULL;
72 MUTEX_LOCK (&cache_mutex);
73 int t = slist_length (key_cache);
74 int i;
75 file_cache_t *p = NULL;
77 for (i = 0; i < t; i++)
79 p = slist_nth_data (key_cache, i);
80 if (!strcmp (p->filename, filename))
81 break;
82 p = NULL;
85 MUTEX_UNLOCK (&cache_mutex);
86 return p;
89 gpg_error_t
90 cache_lock_mutex (void *ctx, const char *filename, long lock_timeout, int add,
91 long timeout)
93 gpg_error_t rc = 0;
94 file_cache_t *p = get_entry (filename);
96 if (p)
98 MUTEX_TRYLOCK (ctx, p->mutex, rc, lock_timeout);
99 if (!rc)
100 p->flags |= CACHE_FLAG_LOCKED;
102 else if (add)
104 rc = cache_add_file (filename, NULL, timeout);
105 if (!rc)
107 p = get_entry (filename);
108 if (p)
110 MUTEX_TRYLOCK (ctx, p->mutex, rc, lock_timeout);
111 if (!rc)
112 p->flags |= CACHE_FLAG_LOCKED;
117 return !p && !rc ? GPG_ERR_NO_DATA : rc;
120 static int
121 remove_entry (const char *filename)
123 MUTEX_LOCK (&cache_mutex);
124 file_cache_t *p = get_entry (filename);
126 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
127 if (p)
129 /* Keep a refcount because another client may be editing this same new
130 * file. The entry needs to be kept in case the other client SAVE's.
132 p->refcount--;
133 if (!p->refcount)
134 free_entry (p, 0);
137 pthread_cleanup_pop (1);
138 return p ? 1 : 0;
141 static gpg_error_t
142 free_cache_data (file_cache_t *cache, int force)
144 gpg_error_t rc = GPG_ERR_NO_DATA;
145 int i, t;
146 struct client_thread_s *found = NULL;
147 int self = 0;
149 if (!cache->data)
150 return 0;
152 MUTEX_LOCK (&cn_mutex);
153 t = slist_length (cn_thread_list);
155 /* Prevent clearing the cache entry when there are any connected clients
156 * using this cache entry to prevent clearing the plaintext which would cause
157 * cache_plaintext_set() to return GPG_ERR_NO_DATA and prevent CoW commands
158 * from working. */
159 for (i = 0; i < t; i++)
161 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
163 if (!thd->cl)
164 continue;
166 if (thd->cl->filename && !strcmp (thd->cl->filename, cache->filename)
167 && !force)
169 cache->defer_clear = 1;
170 MUTEX_UNLOCK (&cn_mutex);
171 return 0;
175 pthread_cleanup_push (release_mutex_cb, &cn_mutex);
176 MUTEX_LOCK (&cache_mutex);
177 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
179 for (i = 0; i < t; i++)
181 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
183 if (!thd->cl)
184 continue;
186 self = pthread_equal (pthread_self (), thd->tid);
188 if (thd->cl->filename && !strcmp (thd->cl->filename, cache->filename))
190 if (self)
192 found = thd;
193 continue;
196 /* Continue trying to find a client who has the same file open and
197 * also has a lock. */
198 rc = cache_lock_mutex (thd->cl->ctx, thd->cl->filename, -1, 0, -1);
199 if (!rc)
201 found = thd;
202 break;
207 if (self && (!rc || rc == GPG_ERR_NO_DATA) && found)
208 rc = cache_lock_mutex (found->cl->ctx, found->cl->filename, -1, 0, -1);
210 if (exiting || !rc || rc == GPG_ERR_NO_DATA)
212 cache_free_data_once (cache->data);
213 cache->data = NULL;
214 cache->defer_clear = 0;
215 cache->timeout = (long)-1;
217 if (found)
218 cache_unlock_mutex (found->cl->filename, 0);
220 rc = 0;
223 if (rc)
224 cache->defer_clear = 1;
226 pthread_cleanup_pop (1);
227 pthread_cleanup_pop (1);
228 return rc;
231 gpg_error_t
232 cache_unlock_mutex (const char *filename, int remove)
234 MUTEX_LOCK (&cache_mutex);
235 file_cache_t *p = get_entry (filename);
237 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
239 if (p)
241 p->flags &= ~CACHE_FLAG_LOCKED;
242 if (remove)
243 remove_entry (filename);
244 else
245 MUTEX_UNLOCK (p->mutex);
248 pthread_cleanup_pop (1);
249 return p ? 0 : GPG_ERR_NO_DATA;
252 static gpg_error_t
253 get_keyinfo (const char *grip, char ***r_fields)
255 gpg_error_t rc;
256 char *line;
258 rc = agent_command (cache_agent, &line, NULL, "KEYINFO --data %s", grip);
259 if (rc)
260 return rc;
262 *r_fields = str_split (line, " ", 0);
263 xfree (line);
264 return !(*r_fields) ? GPG_ERR_ENOMEM : rc;
267 gpg_error_t
268 cache_is_shadowed (const char *filename)
270 MUTEX_LOCK (&cache_mutex);
271 file_cache_t *f = get_entry (filename);
272 char **p;
273 char **fields = NULL;
274 gpg_error_t rc = GPG_ERR_NO_DATA, trc;
276 if (!f)
277 return GPG_ERR_NOT_FOUND;
279 for (p = f->grip; p && *p; p++)
281 trc = get_keyinfo (*p, &fields);
282 if (!trc && *fields[1] == 'T')
284 rc = 0;
285 break;
287 else if (trc)
289 rc = trc;
290 break;
294 strv_free (fields);
295 fields = NULL;
297 if (rc == GPG_ERR_NO_DATA && f->siggrip)
299 trc = get_keyinfo (f->siggrip, &fields);
300 if (!trc && *fields[1] == 'T')
301 rc = 0;
302 else if (trc)
303 rc = trc;
306 strv_free (fields);
307 MUTEX_UNLOCK (&cache_mutex);
308 return rc;
311 static gpg_error_t
312 test_agent_cache_once (file_cache_t *p, const char *grip)
314 gpg_error_t rc;
315 char **fields = NULL;
317 (void)p;
318 rc = get_keyinfo (grip, &fields);
319 if (rc)
320 return rc;
322 /* Smartcard. */
323 if (*fields[1] == 'T')
324 rc = GPG_ERR_NO_DATA;
325 else
326 rc = isdigit (*fields[4]) || *fields[5] == 'C' ? 0 : GPG_ERR_NO_DATA;
328 strv_free (fields);
329 return rc;
332 /* Test each keygrip in data->(sig)grip for gpg-agent cache status. The file is
333 * considered cached if at least one grip is cached in the agent or one siggrip
334 * is cached in the case of 'sign'.
336 static gpg_error_t
337 test_agent_cache (file_cache_t *data, int sign)
339 gpg_error_t rc = 0;
340 char **p;
342 if ((!data->grip && !sign) || (!data->siggrip && sign))
343 return GPG_ERR_NO_DATA;
345 for (p = data->grip; !sign && p && *p; p++)
347 rc = test_agent_cache_once (data, *p);
348 if (!rc || rc != GPG_ERR_NO_DATA)
349 break;
352 if (!rc && sign)
353 rc = test_agent_cache_once (data, data->siggrip);
355 return rc;
358 static gpg_error_t
359 extract_keygrip_once (struct crypto_s *crypto, char **keyids, int sign,
360 char ***dst)
362 gpgme_key_t *result;
363 gpgme_error_t rc;
364 int i;
365 char **grips = NULL;
367 rc = crypto_list_keys (crypto, keyids, sign, &result);
368 if (rc)
369 return rc;
371 for (i = 0; result[i]; i++)
373 gpgme_subkey_t s;
375 for (s = result[i]->subkeys; s; s = s->next)
377 char **k;
379 if (sign && !s->can_sign)
380 continue;
382 for (k = keyids; *k; k++)
384 if (!strcmp (*k, s->keyid) && s->keygrip)
386 char **tmp;
387 size_t len = strv_length (grips);
389 tmp = xrealloc (grips, len+2 * sizeof (char *));
390 if (!tmp)
392 rc = GPG_ERR_ENOMEM;
393 break;
396 grips = tmp;
397 grips[len] = str_dup (s->keygrip);
398 if (!grips[len])
400 rc = GPG_ERR_ENOMEM;
401 break;
404 grips[++len] = NULL;
410 if (!rc)
412 strv_free (*dst);
413 *dst = grips;
415 else
417 strv_free (grips);
418 grips = NULL;
421 crypto_free_key_list (result);
422 return rc ? rc : grips ? rc : GPG_ERR_NO_DATA;
425 static gpg_error_t
426 extract_keygrips (file_cache_t *data)
428 gpg_error_t rc = 0;
429 struct crypto_s *crypto;
430 char **grips = NULL, **siggrips = NULL;
432 if (!data || !data->data)
433 return 0;
435 rc = crypto_init (&crypto, NULL, NULL, 0, NULL);
436 if (rc)
437 return rc;
439 pthread_cleanup_push ((void *)crypto_free, crypto);
441 if (data->data->pubkey)
442 rc = extract_keygrip_once (crypto, data->data->pubkey, 0, &grips);
444 if (!rc && data->data->sigkey)
446 char **tmp = NULL;
448 strv_printf (&tmp, "%s", data->data->sigkey);
449 rc = extract_keygrip_once (crypto, tmp, 1, &siggrips);
450 strv_free (tmp);
453 if (!rc)
455 strv_free (data->grip);
456 data->grip = grips;
457 xfree (data->siggrip);
458 data->siggrip = NULL;
459 if (siggrips && *siggrips)
460 data->siggrip = str_dup (*siggrips);
461 strv_free (siggrips);
463 else
465 strv_free (grips);
466 strv_free (siggrips);
469 pthread_cleanup_pop (1);
470 return rc;
473 static gpg_error_t
474 iscached (const char *filename, int *defer, int agent, int sign)
476 file_cache_t *p = get_entry (filename);
477 gpg_error_t rc = 0;
479 if (!agent)
481 if (!p || !p->data)
482 return GPG_ERR_NO_DATA;
484 if (defer)
485 *defer = p->defer_clear;
487 return 0;
490 if (!p)
491 return GPG_ERR_NO_DATA;
493 if (defer)
494 *defer = p->defer_clear;
496 if (!rc && (p->grip || p->siggrip))
497 rc = test_agent_cache (p, sign);
498 else if (!rc)
499 rc = GPG_ERR_NO_DATA;
501 return rc;
504 unsigned
505 cache_file_count ()
507 MUTEX_LOCK (&cache_mutex);
508 unsigned total = 0, i, n;
510 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
511 n = slist_length (key_cache);
512 for (i = 0; i < n; i++)
514 file_cache_t *p = slist_nth_data (key_cache, i);
516 if (!iscached (p->filename, NULL, 0, 0))
517 total++;
520 pthread_cleanup_pop (1);
521 return total;
524 void
525 cache_adjust_timeout ()
527 MUTEX_LOCK (&cache_mutex);
528 int t = slist_length (key_cache);
529 int i;
531 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
533 for (i = 0; i < t; i++)
535 file_cache_t *p = slist_nth_data (key_cache, i);
537 if (p->timeout > 0)
538 p->timeout--;
540 /* Test the cache entry timeout for expiration and also whether the file
541 * is a new one (no crc) and without any associated clients (refcount ==
542 * 1) and remove the cache entry accordingly. */
543 if (!p->timeout || (p->defer_clear && p->timeout != (long)-1)
544 || (p->timeout > 0 && p->refcount == 1
545 && (!p->data || !p->data->crc)
546 && !(p->flags & CACHE_FLAG_LOCKED)))
548 /* The file associated with this cache entry may be locked by a
549 * client. Defer freeing this cache entry until the next timeout
550 * check. */
551 gpg_error_t rc = clear_once (p, 1, 0);
553 if (!rc && !p->defer_clear)
555 free_entry (p, 0);
556 t = slist_length (key_cache);
557 send_status_all (STATUS_CACHE, NULL);
562 pthread_cleanup_pop (1);
565 static gpg_error_t
566 set_timeout (const char *filename, long timeout, int defer, int force)
568 MUTEX_LOCK (&cache_mutex);
569 file_cache_t *p = get_entry (filename);
570 gpg_error_t rc = 0;
572 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
574 if (p)
576 p->reset = timeout;
577 if (!p->defer_clear && (p->timeout == -1 || force))
578 p->timeout = timeout;
580 if (!timeout || defer)
582 rc = clear_once (p, 1, 0);
583 if (!rc)
584 send_status_all (STATUS_CACHE, NULL);
587 else
588 rc = GPG_ERR_NOT_FOUND;
590 pthread_cleanup_pop (1);
591 return rc;
594 gpg_error_t
595 cache_set_data (const char *filename, struct cache_data_s *data)
597 MUTEX_LOCK (&cache_mutex);
598 gpg_error_t rc = GPG_ERR_NO_DATA;
599 file_cache_t *p = get_entry (filename);
601 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
603 if (p)
605 xfree (data->filename);
606 data->filename = NULL;
607 if (p->filename)
608 data->filename = str_dup (p->filename);
610 p->data = data;
611 rc = set_timeout (filename, p->reset, p->defer_clear, 0);
612 if (!rc && !p->reset)
614 clear_once (p, 0, 0);
615 send_status_all (STATUS_CACHE, NULL);
617 else if (!rc)
618 rc = extract_keygrips (p);
621 pthread_cleanup_pop (1);
622 return p && !rc ? 0 : rc;
625 struct cache_data_s *
626 cache_get_data (const char *filename, int *defer)
628 MUTEX_LOCK (&cache_mutex);
629 file_cache_t *p = get_entry (filename);
631 if (defer && p)
632 *defer = p->defer_clear;
633 MUTEX_UNLOCK (&cache_mutex);
634 return p ? p->data : NULL;
637 gpg_error_t
638 cache_add_file (const char *filename, struct cache_data_s *data, long timeout)
640 MUTEX_LOCK (&cache_mutex);
641 file_cache_t *p = get_entry (filename);
642 struct slist_s *new;
643 gpg_error_t rc = 0;
645 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
647 if (p)
649 if (data)
651 char *str = p->filename ? str_dup (p->filename) : NULL;
653 if (p->filename && !str)
654 rc = GPG_ERR_ENOMEM;
655 else
657 xfree (data->filename);
658 data->filename = str;
662 if (!rc)
664 p->data = data;
665 p->refcount++;
666 rc = set_timeout (filename, timeout, p->defer_clear, 0);
669 else
671 p = xcalloc (1, sizeof (file_cache_t));
672 if (p)
674 p->mutex = (pthread_mutex_t *) xmalloc (sizeof (pthread_mutex_t));
675 if (p->mutex)
677 pthread_mutexattr_t attr;
678 pthread_mutexattr_init (&attr);
679 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
680 pthread_mutex_init (p->mutex, &attr);
681 pthread_mutexattr_destroy (&attr);
682 p->filename = str_dup (filename);
684 if (data)
686 xfree (data->filename);
687 data->filename = NULL;
688 data->filename = str_dup (p->filename);
691 p->data = data;
692 p->refcount++;
693 new = slist_append (key_cache, p);
694 if (new)
696 key_cache = new;
697 rc = cache_set_timeout(filename, timeout);
699 else
701 pthread_mutex_destroy (p->mutex);
702 xfree (p->mutex);
703 xfree (p->filename);
704 xfree (p);
705 p = NULL;
706 rc = GPG_ERR_ENOMEM;
709 else
711 xfree (p);
712 p = NULL;
713 rc = GPG_ERR_ENOMEM;
716 else
717 rc = GPG_ERR_ENOMEM;
720 if (!rc)
721 rc = extract_keygrips (p);
723 pthread_cleanup_pop (1);
725 if (!rc)
726 send_status_all (STATUS_CACHE, NULL);
728 return rc;
731 gpg_error_t
732 cache_clear_agent_keys (const char *filename, int decrypt, int sign)
734 MUTEX_LOCK (&cache_mutex);
735 gpg_error_t rc = 0;
736 char **key;
737 file_cache_t *p = get_entry (filename);
739 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
741 if (p)
743 for (key = p->grip; decrypt && key && *key; key++)
745 rc = agent_command (cache_agent, NULL, NULL,
746 "CLEAR_PASSPHRASE --mode=normal %s", *key);
747 if (rc)
748 break;
751 if (p->siggrip && sign)
752 rc = agent_command (cache_agent, NULL, NULL,
753 "CLEAR_PASSPHRASE --mode=normal %s", p->siggrip);
755 else
756 rc = GPG_ERR_NOT_FOUND;
758 pthread_cleanup_pop (1);
759 return rc;
762 static gpg_error_t
763 clear_once (file_cache_t *p, int agent, int force)
765 gpg_error_t rc = 0, trc;
767 if (agent)
768 rc = cache_clear_agent_keys (p->filename, 1, 1);
770 trc = free_cache_data (p, force);
771 return rc ? rc : trc;
774 static void
775 free_entry (file_cache_t *p, int agent)
777 gpg_error_t rc;
779 if (!p)
780 return;
782 rc = clear_once (p, agent, 0);
783 if (rc)
784 log_write ("%s(): %s", __FUNCTION__, pwmd_strerror (rc));
786 key_cache = slist_remove (key_cache, p);
788 if (p->mutex)
790 if ((p->flags & CACHE_FLAG_LOCKED))
791 MUTEX_UNLOCK (p->mutex);
793 pthread_mutex_destroy (p->mutex);
794 xfree (p->mutex);
797 strv_free (p->grip);
798 xfree (p->siggrip);
799 xfree (p->filename);
800 xfree (p);
803 gpg_error_t
804 cache_clear (struct client_s *client, const char *filename, int agent,
805 int force)
807 file_cache_t *p;
808 gpg_error_t rc = 0, all_rc = 0;
809 int i, t;
811 MUTEX_LOCK (&cache_mutex);
812 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
814 if (filename)
816 p = get_entry (filename);
817 if (p)
819 rc = clear_once (p, agent, force);
820 if (rc)
821 log_write ("%s(): %s", __FUNCTION__, pwmd_strerror (rc));
824 else
826 t = slist_length (key_cache);
827 for (i = 0; i < t; i++)
829 p = slist_nth_data (key_cache, i);
831 if (client)
833 assuan_peercred_t peer;
835 rc = do_validate_peer (client->ctx, p->filename, &peer, NULL);
836 if (rc == GPG_ERR_FORBIDDEN)
837 rc = peer_is_invoker (client);
839 if (rc)
841 all_rc = !all_rc ? rc : all_rc;
842 continue;
846 clear_once (p, agent, 0);
850 pthread_cleanup_pop (1);
851 return filename ? rc : all_rc;
854 gpg_error_t
855 cache_iscached (const char *filename, int *defer, int agent, int sign)
857 gpg_error_t rc;
859 if (!filename)
860 return GPG_ERR_INV_PARAMETER;
862 MUTEX_LOCK (&cache_mutex);
863 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
864 rc = iscached (filename, defer, agent, sign);
866 /* Test if the data file disappeared from the filesystem. */
867 if ((!rc || gpg_err_code (rc) == GPG_ERR_NO_DATA)
868 && access (filename, R_OK) == -1)
870 rc = gpg_error_from_errno (errno);
871 if (gpg_err_code (rc) == GPG_ERR_ENOENT)
873 /* Fixes clearing the cache entry that was created during OPEN when
874 * SAVE'ing a new file. */
875 if ((defer && *defer == 1) || !defer)
877 rc = cache_defer_clear (filename);
878 if (!rc && defer)
879 *defer = 1;
882 rc = GPG_ERR_ENOENT;
886 pthread_cleanup_pop (1);
887 return rc;
890 gpg_error_t
891 cache_defer_clear (const char *filename)
893 MUTEX_LOCK (&cache_mutex);
894 file_cache_t *p = get_entry (filename);
895 gpg_error_t rc = 0;
897 if (!p)
898 rc = GPG_ERR_NOT_FOUND;
899 else
900 p->defer_clear = 1;
902 MUTEX_UNLOCK (&cache_mutex);
903 return rc;
906 gpg_error_t
907 cache_set_timeout (const char *filename, long timeout)
909 return set_timeout (filename, timeout, 0, 1);
912 void
913 cache_deinit ()
915 exiting = 1;
916 MUTEX_LOCK (&cache_mutex);
917 int i, t = slist_length (key_cache);
919 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
920 for (i = 0; i < t; i++)
922 file_cache_t *p = slist_nth_data (key_cache, i);
924 free_entry (p, 1);
925 t = slist_length (key_cache);
926 i = -1;
929 gcry_free (cache_key);
930 xfree (cache_iv);
931 cache_key = NULL;
932 cache_iv = NULL;
933 agent_free (cache_agent);
934 cache_agent = NULL;
935 pthread_cleanup_pop (1);
936 pthread_mutex_destroy (&cache_mutex);
939 void
940 cache_mutex_init ()
942 pthread_mutexattr_t attr;
944 pthread_mutexattr_init (&attr);
945 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
946 pthread_mutex_init (&cache_mutex, &attr);
947 pthread_mutexattr_destroy (&attr);
950 gpg_error_t
951 cache_init ()
953 gpg_error_t rc = 0;
955 rc = agent_init (&cache_agent);
956 if (rc)
958 cache_agent = NULL;
959 return rc;
962 if (!cache_key)
964 rc = gcry_cipher_algo_info (GCRY_CIPHER_AES128, GCRYCTL_GET_BLKLEN, NULL,
965 &cache_blocksize);
966 if (rc)
967 return rc;
969 rc = gcry_cipher_algo_info (GCRY_CIPHER_AES128, GCRYCTL_GET_KEYLEN, NULL,
970 &cache_keysize);
971 if (rc)
972 return rc;
974 cache_key = gcry_malloc (cache_keysize);
975 if (!cache_key)
976 return GPG_ERR_ENOMEM;
978 cache_iv = xmalloc (cache_blocksize);
979 if (!cache_iv)
981 gcry_free (cache_key);
982 cache_key = NULL;
983 return GPG_ERR_ENOMEM;
986 gcry_create_nonce (cache_key, cache_keysize);
987 gcry_create_nonce (cache_iv, cache_blocksize);
991 cache_mutex_init ();
992 return rc;
995 void
996 cache_lock ()
998 MUTEX_LOCK (&cache_mutex);
1001 void
1002 cache_unlock ()
1004 MUTEX_UNLOCK (&cache_mutex);
1007 static void
1008 update_plaintext_pointer (xmlDocPtr plaintext)
1010 unsigned i;
1011 unsigned t;
1013 t = slist_length (key_cache);
1014 for (i = 0; i < t; i++)
1016 file_cache_t *p = slist_nth_data (key_cache, i);
1018 if (p->data && p->data->plaintext == plaintext)
1019 p->data->plaintext = NULL;
1023 void
1024 cache_free_data_once (struct cache_data_s *data)
1026 if (!data)
1027 return;
1029 xfree (data->filename);
1030 strv_free (data->pubkey);
1031 xfree (data->sigkey);
1032 xfree (data->crc);
1033 xfree (data->doc);
1034 xfree (data);
1037 static void
1038 release_cipher (void *arg)
1040 gcry_cipher_close ((gcry_cipher_hd_t) arg);
1043 gpg_error_t
1044 cache_encrypt (struct crypto_s *crypto)
1046 gpg_error_t rc;
1047 gcry_cipher_hd_t h;
1048 size_t len = crypto->plaintext_size;
1050 rc = gcry_cipher_open (&h, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0);
1051 if (rc)
1052 return rc;
1054 if (len % cache_blocksize)
1056 unsigned char *p;
1058 len += cache_blocksize - (len % cache_blocksize);
1059 p = xrealloc (crypto->plaintext, len * sizeof (unsigned char));
1060 if (!p)
1062 gcry_cipher_close (h);
1063 return GPG_ERR_ENOMEM;
1066 crypto->plaintext = p;
1067 memset (&crypto->plaintext[crypto->plaintext_size], 0,
1068 len - crypto->plaintext_size);
1071 pthread_cleanup_push (release_cipher, h);
1072 rc = gcry_cipher_setiv (h, cache_iv, cache_blocksize);
1073 if (!rc)
1075 rc = gcry_cipher_setkey (h, cache_key, cache_keysize);
1076 if (!rc)
1078 unsigned char *buf = xmalloc (len);
1080 pthread_cleanup_push (xfree, buf);
1082 if (!buf)
1083 rc = GPG_ERR_ENOMEM;
1085 if (!rc)
1087 rc = gcry_cipher_encrypt (h, buf, len, crypto->plaintext, len);
1088 if (!rc)
1090 xfree (crypto->plaintext);
1091 crypto->plaintext = buf;
1092 crypto->plaintext_size = len;
1096 pthread_cleanup_pop (rc != 0);
1100 pthread_cleanup_pop (1);
1101 return rc;
1104 gpg_error_t
1105 cache_decrypt (struct crypto_s *crypto)
1107 gcry_cipher_hd_t h = NULL;
1108 gpg_error_t rc;
1110 rc = gcry_cipher_open (&h, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0);
1111 if (rc)
1112 return rc;
1114 if (!rc)
1115 rc = gcry_cipher_setiv (h, cache_iv, cache_blocksize);
1117 if (!rc)
1118 rc = gcry_cipher_setkey (h, cache_key, cache_keysize);
1120 pthread_cleanup_push (release_cipher, h);
1122 if (!rc)
1124 rc = gcry_cipher_decrypt (h, crypto->plaintext, crypto->plaintext_size,
1125 NULL, 0);
1126 if (rc || strncmp ((char *)crypto->plaintext, "<?xml ", 6))
1128 if (!rc)
1129 rc = GPG_ERR_BAD_DATA;
1133 pthread_cleanup_pop (1);
1134 return rc;
1137 gpg_error_t
1138 cache_kill_scd ()
1140 gpg_error_t rc;
1142 MUTEX_LOCK (&cache_mutex);
1143 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
1144 rc = agent_kill_scd (cache_agent);
1145 pthread_cleanup_pop (1);
1146 return rc;
1149 gpg_error_t
1150 cache_agent_command (const char *cmd)
1152 gpg_error_t rc;
1154 MUTEX_LOCK (&cache_mutex);
1155 rc = agent_command (cache_agent, NULL, NULL, "%s", cmd);
1156 MUTEX_UNLOCK (&cache_mutex);
1157 return rc;
1160 static gpg_error_t
1161 plaintext_get (struct cache_data_s *data, xmlDocPtr *r_doc)
1163 unsigned i;
1164 unsigned t = slist_length (plaintext_list);
1166 assert (r_doc != NULL);
1168 for (i = 0; i < t; i++)
1170 struct plaintext_s *p = slist_nth_data (plaintext_list, i);
1172 if (!strcmp (p->filename, data->filename) && !p->modified)
1174 *r_doc = p->plaintext;
1175 p->refcount++;
1176 return 0;
1180 return GPG_ERR_NO_DATA;
1183 gpg_error_t
1184 cache_plaintext_get (const char *filename, xmlDocPtr *r_doc)
1186 file_cache_t *p;
1187 gpg_error_t rc = 0;
1189 MUTEX_LOCK (&cache_mutex);
1190 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
1192 p = get_entry (filename);
1193 if (p && p->data)
1194 rc = plaintext_get (p->data, r_doc);
1195 else
1196 rc = GPG_ERR_NO_DATA;
1198 pthread_cleanup_pop (1);
1199 return rc;
1202 static gpg_error_t
1203 release_plaintext (xmlDocPtr *plaintext)
1205 unsigned i;
1206 unsigned t;
1208 if (!plaintext)
1209 return GPG_ERR_NO_DATA;
1211 t = slist_length (plaintext_list);
1212 for (i = 0; i < t; i++)
1214 struct plaintext_s *p = slist_nth_data (plaintext_list, i);
1216 if (p->plaintext == *plaintext)
1218 assert (p->refcount > 0);
1219 if (--p->refcount == 0)
1221 xmlFreeDoc (p->plaintext);
1222 xfree (p->filename);
1223 plaintext_list = slist_remove (plaintext_list, p);
1224 xfree (p);
1225 update_plaintext_pointer (*plaintext);
1226 *plaintext = NULL;
1229 return 0;
1233 return GPG_ERR_NO_DATA;
1236 gpg_error_t
1237 cache_plaintext_release (xmlDocPtr *plaintext)
1239 gpg_error_t rc = 0;
1241 MUTEX_LOCK (&cache_mutex);
1242 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
1243 rc = release_plaintext (plaintext);
1244 pthread_cleanup_pop (1);
1245 return rc;
1248 gpg_error_t
1249 cache_plaintext_set (const char *filename, xmlDocPtr doc, int modified)
1251 file_cache_t *p;
1252 gpg_error_t rc = 0;
1254 MUTEX_LOCK (&cache_mutex);
1255 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
1257 p = get_entry (filename);
1258 if (p && p->data)
1260 struct plaintext_s *s = xcalloc (1, sizeof (struct plaintext_s));
1262 if (s)
1264 s->filename = str_dup (p->data->filename);
1265 if (s->filename)
1267 struct slist_s *l;
1268 int i, t = slist_length (plaintext_list);
1270 /* Prevent cache_plaintext_get() from returning the other
1271 * client's document copy. */
1272 for (i = 0; i < t; i++)
1274 struct plaintext_s *x = slist_nth_data (plaintext_list, i);
1276 if (!strcmp (s->filename, x->filename))
1277 x->modified = 1;
1280 l = slist_append (plaintext_list, s);
1281 if (l)
1283 plaintext_list = l;
1284 s->plaintext = p->data->plaintext = doc;
1285 s->modified = modified;
1286 s->refcount = 1;
1288 else
1290 xfree (s->filename);
1291 rc = GPG_ERR_ENOMEM;
1294 else
1295 rc = GPG_ERR_ENOMEM;
1297 if (rc)
1298 xfree (s);
1300 else
1301 rc = GPG_ERR_ENOMEM;
1303 else
1304 rc = GPG_ERR_NO_DATA;
1306 pthread_cleanup_pop (1);
1307 return rc;