Update copyright header.
[pwmd.git] / src / cache.c
blob4f123f2539d1557b83cefd4b6c1e2d9df70c14c8
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
3 2016, 2017
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of pwmd.
8 Pwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Pwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <stdio.h>
26 #include <unistd.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 #ifdef HAVE_TIME_H
43 #include <time.h>
44 #endif
46 struct plaintext_s
48 xmlDocPtr plaintext;
49 unsigned refcount;
50 char *filename;
51 int modified;
54 static pthread_mutex_t cache_mutex;
55 static struct slist_s *key_cache;
56 static struct slist_s *plaintext_list;
57 static unsigned char *cache_iv;
58 static unsigned char *cache_key;
59 static size_t cache_blocksize;
60 static size_t cache_keysize;
61 static struct agent_s *cache_agent;
62 static int exiting;
64 extern void log_write (const char *fmt, ...);
66 static gpg_error_t clear_once (file_cache_t * p, int agent, int force);
67 static int remove_entry (const char *);
68 static void free_entry (file_cache_t * p, int agent);
70 static file_cache_t *
71 get_entry (const char *filename)
73 int t = slist_length (key_cache);
74 int i;
76 if (!filename)
77 return NULL;
79 for (i = 0; i < t; i++)
81 file_cache_t *p = slist_nth_data (key_cache, i);
83 if (!strcmp (p->filename, filename))
84 return p;
87 return NULL;
90 gpg_error_t
91 cache_lock_mutex (void *ctx, const char *filename, long lock_timeout, int add,
92 long timeout)
94 MUTEX_LOCK (&cache_mutex);
95 gpg_error_t rc = 0;
96 file_cache_t *p = get_entry (filename);
98 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
100 if (p)
102 MUTEX_UNLOCK (&cache_mutex);
103 MUTEX_TRYLOCK (ctx, p->mutex, rc, lock_timeout);
105 else if (add)
107 rc = cache_add_file (filename, NULL, timeout);
108 if (!rc)
110 p = get_entry (filename);
111 MUTEX_UNLOCK (&cache_mutex);
112 if (p)
113 MUTEX_TRYLOCK (ctx, p->mutex, rc, lock_timeout);
115 else
117 MUTEX_UNLOCK (&cache_mutex);
120 else
122 MUTEX_UNLOCK (&cache_mutex);
125 pthread_cleanup_pop (0);
126 return !p && !rc ? GPG_ERR_NO_DATA : rc;
129 static int
130 remove_entry (const char *filename)
132 MUTEX_LOCK (&cache_mutex);
133 file_cache_t *p = get_entry (filename);
135 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
136 if (p)
138 /* Keep a refcount because another client maybe editing this same new
139 * file. The entry needs to be kept in case the other client SAVE's.
141 p->refcount--;
142 if (!p->refcount)
143 free_entry (p, 0);
146 pthread_cleanup_pop (1);
147 return p ? 1 : 0;
150 static gpg_error_t
151 free_cache_data (file_cache_t *cache, int force)
153 gpg_error_t rc = GPG_ERR_NO_DATA;
154 int i, t;
155 struct client_thread_s *found = NULL;
156 int self = 0;
158 if (!cache->data)
159 return 0;
161 MUTEX_LOCK (&cn_mutex);
162 t = slist_length (cn_thread_list);
164 /* Prevent clearing the cache entry when there are any connected clients
165 * using this cache entry to prevent clearing the plaintext which would cause
166 * cache_plaintext_set() to return GPG_ERR_NO_DATA and prevent CoW commands
167 * from working. */
168 for (i = 0; i < t; i++)
170 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
172 if (!thd->cl)
173 continue;
175 if (thd->cl->filename && !strcmp (thd->cl->filename, cache->filename)
176 && !force)
178 cache->defer_clear = 1;
179 MUTEX_UNLOCK (&cn_mutex);
180 return 0;
184 pthread_cleanup_push (release_mutex_cb, &cn_mutex);
185 MUTEX_LOCK (&cache_mutex);
186 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
188 for (i = 0; i < t; i++)
190 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
192 if (!thd->cl)
193 continue;
195 self = pthread_equal (pthread_self (), thd->tid);
197 if (thd->cl->filename && !strcmp (thd->cl->filename, cache->filename))
199 if (self)
201 found = thd;
202 continue;
205 /* Continue trying to find a client who has the same file open and
206 * also has a lock. */
207 rc = cache_lock_mutex (thd->cl->ctx, thd->cl->filename, -1, 0, -1);
208 if (!rc)
210 found = thd;
211 break;
216 if (self && (!rc || rc == GPG_ERR_NO_DATA) && found)
217 rc = cache_lock_mutex (found->cl->ctx, found->cl->filename, -1, 0, -1);
219 if (exiting || !rc || rc == GPG_ERR_NO_DATA)
221 cache_free_data_once (cache->data);
222 cache->data = NULL;
223 cache->defer_clear = 0;
224 cache->timeout = (long)-1;
226 if (found)
227 cache_unlock_mutex (found->cl->filename, 0);
229 rc = 0;
232 if (rc)
233 cache->defer_clear = 1;
235 pthread_cleanup_pop (1);
236 pthread_cleanup_pop (1);
237 return rc;
240 gpg_error_t
241 cache_unlock_mutex (const char *filename, int remove)
243 MUTEX_LOCK (&cache_mutex);
244 file_cache_t *p = get_entry (filename);
246 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
248 if (p)
250 MUTEX_UNLOCK (p->mutex);
251 if (remove)
252 remove_entry (filename);
255 pthread_cleanup_pop (1);
256 return p ? 0 : GPG_ERR_NO_DATA;
259 static gpg_error_t
260 test_agent_cache_once (file_cache_t *p, const char *grip)
262 gpg_error_t rc;
263 char *line;
265 (void)p;
266 rc = agent_command (cache_agent, &line, NULL, "KEYINFO --data %s", grip);
267 if (!rc)
269 char **fields = str_split (line, " ", 0);
271 /* Smartcard. */
272 if (*fields[1] == 'T')
273 rc = GPG_ERR_NO_DATA;
274 else
275 rc = isdigit (*fields[4]) || *fields[5] == 'C' ? 0 : GPG_ERR_NO_DATA;
277 strv_free (fields);
278 xfree (line);
281 return rc;
284 /* Test each keygrip in data->(sig)grip for gpg-agent cache status. The file is
285 * considered cached if at least one grip is cached in the agent or one siggrip
286 * is cached in the case of 'sign'.
288 static gpg_error_t
289 test_agent_cache (file_cache_t *data, int sign)
291 gpg_error_t rc = 0;
292 char **p;
294 if ((!data->grip && !sign) || (!data->siggrip && sign))
295 return GPG_ERR_NO_DATA;
297 for (p = data->grip; !sign && p && *p; p++)
299 rc = test_agent_cache_once (data, *p);
300 if (!rc || rc != GPG_ERR_NO_DATA)
301 break;
304 if (!rc && sign)
305 rc = test_agent_cache_once (data, data->siggrip);
307 return rc;
310 static gpg_error_t
311 extract_keygrip_once (struct crypto_s *crypto, char **keyids, int sign,
312 char ***dst)
314 gpgme_key_t *result;
315 gpgme_error_t rc;
316 int i;
317 char **grips = NULL;
319 rc = crypto_list_keys (crypto, keyids, sign, &result);
320 if (rc)
321 return rc;
323 for (i = 0; result[i]; i++)
325 gpgme_subkey_t s;
327 for (s = result[i]->subkeys; s; s = s->next)
329 char **k;
331 if (sign && !s->can_sign)
332 continue;
334 for (k = keyids; *k; k++)
336 if (!strcmp (*k, s->keyid) && s->keygrip)
338 char **tmp;
339 size_t len = strv_length (grips);
341 tmp = xrealloc (grips, len+2 * sizeof (char *));
342 if (!tmp)
344 rc = GPG_ERR_ENOMEM;
345 break;
348 grips = tmp;
349 grips[len] = str_dup (s->keygrip);
350 if (!grips[len])
352 rc = GPG_ERR_ENOMEM;
353 break;
356 grips[++len] = NULL;
362 if (!rc)
364 strv_free (*dst);
365 *dst = grips;
367 else
369 strv_free (grips);
370 grips = NULL;
373 crypto_free_key_list (result);
374 return rc ? rc : grips ? rc : GPG_ERR_NO_DATA;
377 static gpg_error_t
378 extract_keygrips (file_cache_t *data)
380 gpg_error_t rc = 0;
381 struct crypto_s *crypto;
382 char **grips = NULL, **siggrips = NULL;
384 if (!data || !data->data)
385 return 0;
387 rc = crypto_init (&crypto, NULL, NULL, 0, NULL);
388 if (rc)
389 return rc;
391 pthread_cleanup_push ((void *)crypto_free, crypto);
393 if (data->data->pubkey)
394 rc = extract_keygrip_once (crypto, data->data->pubkey, 0, &grips);
396 if (!rc && data->data->sigkey)
398 char **tmp = NULL;
400 strv_printf (&tmp, "%s", data->data->sigkey);
401 rc = extract_keygrip_once (crypto, tmp, 1, &siggrips);
402 strv_free (tmp);
405 if (!rc)
407 strv_free (data->grip);
408 data->grip = grips;
409 xfree (data->siggrip);
410 data->siggrip = NULL;
411 if (siggrips && *siggrips)
412 data->siggrip = str_dup (*siggrips);
413 strv_free (siggrips);
415 else
417 strv_free (grips);
418 strv_free (siggrips);
421 pthread_cleanup_pop (1);
422 return rc;
425 static gpg_error_t
426 iscached (const char *filename, int *defer, int agent, int sign)
428 file_cache_t *p = get_entry (filename);
429 gpg_error_t rc = 0;
431 if (!agent)
433 if (!p || !p->data)
434 return GPG_ERR_NO_DATA;
436 if (defer)
437 *defer = p->defer_clear;
439 return 0;
442 if (!p)
443 return GPG_ERR_NO_DATA;
445 if (defer)
446 *defer = p->defer_clear;
448 if (!rc && (p->grip || p->siggrip))
449 rc = test_agent_cache (p, sign);
450 else if (!rc)
451 rc = GPG_ERR_NO_DATA;
453 return rc;
456 unsigned
457 cache_file_count ()
459 MUTEX_LOCK (&cache_mutex);
460 unsigned total = 0, i, n;
462 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
463 n = slist_length (key_cache);
464 for (i = 0; i < n; i++)
466 file_cache_t *p = slist_nth_data (key_cache, i);
468 if (!iscached (p->filename, NULL, 0, 0))
469 total++;
472 pthread_cleanup_pop (1);
473 return total;
476 void
477 cache_adjust_timeout ()
479 MUTEX_LOCK (&cache_mutex);
480 int t = slist_length (key_cache);
481 int i;
483 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
485 for (i = 0; i < t; i++)
487 file_cache_t *p = slist_nth_data (key_cache, i);
489 if (p->timeout > 0)
490 p->timeout--;
492 if (!p->timeout || (p->defer_clear && p->timeout != (long)-1))
494 /* The file associated with this cache entry may be locked by a
495 * client. Defer freeing this cache entry until the next timeout
496 * check. */
497 gpg_error_t rc = clear_once (p, 1, 0);
499 if (!rc && !p->defer_clear)
500 send_status_all (STATUS_CACHE, NULL);
504 pthread_cleanup_pop (1);
507 static gpg_error_t
508 set_timeout (const char *filename, long timeout, int defer, int force)
510 MUTEX_LOCK (&cache_mutex);
511 file_cache_t *p = get_entry (filename);
512 gpg_error_t rc = 0;
514 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
516 if (p)
518 p->reset = timeout;
519 if (!p->defer_clear && (p->timeout == -1 || force))
520 p->timeout = timeout;
522 if (!timeout || defer)
524 rc = clear_once (p, 1, 0);
525 if (!rc)
526 send_status_all (STATUS_CACHE, NULL);
529 else
530 rc = GPG_ERR_NOT_FOUND;
532 pthread_cleanup_pop (1);
533 return rc;
536 gpg_error_t
537 cache_set_data (const char *filename, struct cache_data_s *data)
539 MUTEX_LOCK (&cache_mutex);
540 gpg_error_t rc = GPG_ERR_NO_DATA;
541 file_cache_t *p = get_entry (filename);
543 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
545 if (p)
547 xfree (data->filename);
548 data->filename = NULL;
549 if (p->filename)
550 data->filename = str_dup (p->filename);
552 p->data = data;
553 rc = set_timeout (filename, p->reset, p->defer_clear, 0);
554 if (!rc && !p->reset)
556 clear_once (p, 0, 0);
557 send_status_all (STATUS_CACHE, NULL);
559 else if (!rc)
560 rc = extract_keygrips (p);
563 pthread_cleanup_pop (1);
564 return p && !rc ? 0 : rc;
567 struct cache_data_s *
568 cache_get_data (const char *filename, int *defer)
570 MUTEX_LOCK (&cache_mutex);
571 file_cache_t *p = get_entry (filename);
573 if (defer && p)
574 *defer = p->defer_clear;
575 MUTEX_UNLOCK (&cache_mutex);
576 return p ? p->data : NULL;
579 gpg_error_t
580 cache_add_file (const char *filename, struct cache_data_s *data, long timeout)
582 MUTEX_LOCK (&cache_mutex);
583 file_cache_t *p = get_entry (filename);
584 struct slist_s *new;
585 gpg_error_t rc = 0;
587 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
589 if (p)
591 if (data)
593 char *str = p->filename ? str_dup (p->filename) : NULL;
595 if (p->filename && !str)
596 rc = GPG_ERR_ENOMEM;
597 else
599 xfree (data->filename);
600 data->filename = str;
604 if (!rc)
606 p->data = data;
607 p->refcount++;
608 rc = set_timeout (filename, timeout, p->defer_clear, 0);
611 else
613 p = xcalloc (1, sizeof (file_cache_t));
614 if (p)
616 p->mutex = (pthread_mutex_t *) xmalloc (sizeof (pthread_mutex_t));
617 if (p->mutex)
619 pthread_mutexattr_t attr;
620 pthread_mutexattr_init (&attr);
621 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
622 pthread_mutex_init (p->mutex, &attr);
623 pthread_mutexattr_destroy (&attr);
624 p->filename = str_dup (filename);
626 if (data)
628 xfree (data->filename);
629 data->filename = NULL;
630 data->filename = str_dup (p->filename);
633 p->data = data;
634 p->refcount++;
635 new = slist_append (key_cache, p);
636 if (new)
638 key_cache = new;
639 rc = cache_set_timeout(filename, timeout);
641 else
643 pthread_mutex_destroy (p->mutex);
644 xfree (p->mutex);
645 xfree (p->filename);
646 xfree (p);
647 p = NULL;
648 rc = GPG_ERR_ENOMEM;
651 else
653 xfree (p);
654 p = NULL;
655 rc = GPG_ERR_ENOMEM;
658 else
659 rc = GPG_ERR_ENOMEM;
662 if (!rc)
663 rc = extract_keygrips (p);
665 pthread_cleanup_pop (1);
667 if (!rc)
668 send_status_all (STATUS_CACHE, NULL);
670 return rc;
673 gpg_error_t
674 cache_clear_agent_keys (const char *filename, int decrypt, int sign)
676 MUTEX_LOCK (&cache_mutex);
677 gpg_error_t rc = 0;
678 char **key;
679 file_cache_t *p = get_entry (filename);
681 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
683 if (p)
685 for (key = p->grip; decrypt && key && *key; key++)
687 rc = agent_command (cache_agent, NULL, NULL,
688 "CLEAR_PASSPHRASE --mode=normal %s", *key);
689 if (rc)
690 break;
693 if (p->siggrip && sign)
695 rc = agent_command (cache_agent, NULL, NULL,
696 "CLEAR_PASSPHRASE --mode=normal %s", p->siggrip);
697 if (rc)
698 break;
701 else
702 rc = GPG_ERR_NOT_FOUND;
704 pthread_cleanup_pop (1);
705 return rc;
708 static gpg_error_t
709 clear_once (file_cache_t *p, int agent, int force)
711 gpg_error_t rc = 0, trc;
713 if (agent)
714 rc = cache_clear_agent_keys (p->filename, 1, 1);
716 trc = free_cache_data (p, force);
717 return rc ? rc : trc;
720 static void
721 free_entry (file_cache_t *p, int agent)
723 gpg_error_t rc;
725 if (!p)
726 return;
728 rc = clear_once (p, agent, 0);
729 if (rc)
730 log_write ("%s(): %s", __FUNCTION__, pwmd_strerror (rc));
732 if (p->mutex)
734 pthread_mutex_destroy (p->mutex);
735 xfree (p->mutex);
738 strv_free (p->grip);
739 xfree (p->siggrip);
740 xfree (p->filename);
741 key_cache = slist_remove (key_cache, p);
742 xfree (p);
745 gpg_error_t
746 cache_clear (struct client_s *client, const char *filename, int agent,
747 int force)
749 file_cache_t *p;
750 gpg_error_t rc = 0, all_rc = 0;
751 int i, t;
753 MUTEX_LOCK (&cache_mutex);
754 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
756 if (filename)
758 p = get_entry (filename);
759 if (p)
761 rc = clear_once (p, agent, force);
762 if (rc)
763 log_write ("%s(): %s", __FUNCTION__, pwmd_strerror (rc));
766 else
768 t = slist_length (key_cache);
769 for (i = 0; i < t; i++)
771 p = slist_nth_data (key_cache, i);
773 if (client)
775 assuan_peercred_t peer;
776 int n = client->no_access_param;
778 client->no_access_param = 1;
779 rc = do_validate_peer (client->ctx, p->filename, &peer);
780 client->no_access_param = n;
781 if (rc == GPG_ERR_FORBIDDEN)
782 rc = peer_is_invoker (client);
784 if (rc)
786 all_rc = !all_rc ? rc : all_rc;
787 continue;
791 clear_once (p, agent, 0);
795 pthread_cleanup_pop (1);
796 return filename ? rc : all_rc;
799 gpg_error_t
800 cache_iscached (const char *filename, int *defer, int agent, int sign)
802 gpg_error_t rc;
804 if (!filename)
805 return GPG_ERR_INV_PARAMETER;
807 MUTEX_LOCK (&cache_mutex);
808 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
809 rc = iscached (filename, defer, agent, sign);
811 /* Test if the data file disappeared from the filesystem. */
812 if ((!rc || gpg_err_code (rc) == GPG_ERR_NO_DATA)
813 && access (filename, R_OK) == -1)
815 rc = gpg_error_from_errno (errno);
816 if (gpg_err_code (rc) == GPG_ERR_ENOENT)
818 /* Fixes clearing the cache entry that was created during OPEN when
819 * SAVE'ing a new file. */
820 if ((defer && *defer == 1) || !defer)
822 rc = cache_defer_clear (filename);
823 if (!rc && defer)
824 *defer = 1;
827 rc = GPG_ERR_ENOENT;
831 pthread_cleanup_pop (1);
832 return rc;
835 gpg_error_t
836 cache_defer_clear (const char *filename)
838 MUTEX_LOCK (&cache_mutex);
839 file_cache_t *p = get_entry (filename);
840 gpg_error_t rc = 0;
842 if (!p)
843 rc = GPG_ERR_NOT_FOUND;
844 else
845 p->defer_clear = 1;
847 MUTEX_UNLOCK (&cache_mutex);
848 return rc;
851 gpg_error_t
852 cache_set_timeout (const char *filename, long timeout)
854 return set_timeout (filename, timeout, 0, 1);
857 void
858 cache_deinit ()
860 exiting = 1;
861 MUTEX_LOCK (&cache_mutex);
862 int i, t = slist_length (key_cache);
864 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
865 for (i = 0; i < t; i++)
867 file_cache_t *p = slist_nth_data (key_cache, i);
869 free_entry (p, 1);
870 t = slist_length (key_cache);
871 i = -1;
874 gcry_free (cache_key);
875 xfree (cache_iv);
876 cache_key = NULL;
877 cache_iv = NULL;
878 agent_free (cache_agent);
879 cache_agent = NULL;
880 pthread_cleanup_pop (1);
881 pthread_mutex_destroy (&cache_mutex);
884 void
885 cache_mutex_init ()
887 pthread_mutexattr_t attr;
889 pthread_mutexattr_init (&attr);
890 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
891 pthread_mutex_init (&cache_mutex, &attr);
892 pthread_mutexattr_destroy (&attr);
895 gpg_error_t
896 cache_init ()
898 gpg_error_t rc = 0;
900 rc = agent_init (&cache_agent);
901 if (rc)
903 cache_agent = NULL;
904 return rc;
907 if (!cache_key)
909 rc = gcry_cipher_algo_info (GCRY_CIPHER_AES, GCRYCTL_GET_BLKLEN, NULL,
910 &cache_blocksize);
911 if (rc)
912 return rc;
914 rc = gcry_cipher_algo_info (GCRY_CIPHER_AES, GCRYCTL_GET_KEYLEN, NULL,
915 &cache_keysize);
916 if (rc)
917 return rc;
919 cache_key = gcry_malloc (cache_keysize);
920 if (!cache_key)
921 return GPG_ERR_ENOMEM;
923 cache_iv = xmalloc (cache_blocksize);
924 if (!cache_iv)
926 gcry_free (cache_key);
927 cache_key = NULL;
928 return GPG_ERR_ENOMEM;
931 gcry_create_nonce (cache_key, cache_keysize);
932 gcry_create_nonce (cache_iv, cache_blocksize);
936 cache_mutex_init ();
937 return rc;
940 void
941 cache_lock ()
943 MUTEX_LOCK (&cache_mutex);
946 void
947 cache_unlock ()
949 MUTEX_UNLOCK (&cache_mutex);
952 static void
953 update_plaintext_pointer (xmlDocPtr plaintext)
955 unsigned i;
956 unsigned t;
958 t = slist_length (key_cache);
959 for (i = 0; i < t; i++)
961 file_cache_t *p = slist_nth_data (key_cache, i);
963 if (p->data && p->data->plaintext == plaintext)
964 p->data->plaintext = NULL;
968 void
969 cache_free_data_once (struct cache_data_s *data)
971 if (!data)
972 return;
974 xfree (data->filename);
975 strv_free (data->pubkey);
976 xfree (data->sigkey);
977 xfree (data->crc);
978 xfree (data->doc);
979 xfree (data);
982 static void
983 release_cipher (void *arg)
985 gcry_cipher_close ((gcry_cipher_hd_t) arg);
988 gpg_error_t
989 cache_encrypt (struct crypto_s *crypto)
991 gpg_error_t rc;
992 gcry_cipher_hd_t h;
993 size_t len = crypto->plaintext_size;
995 rc = gcry_cipher_open (&h, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0);
996 if (rc)
997 return rc;
999 if (len % cache_blocksize)
1001 unsigned char *p;
1003 len += cache_blocksize - (len % cache_blocksize);
1004 p = xrealloc (crypto->plaintext, len * sizeof (unsigned char));
1005 if (!p)
1007 gcry_cipher_close (h);
1008 return GPG_ERR_ENOMEM;
1011 crypto->plaintext = p;
1012 memset (&crypto->plaintext[crypto->plaintext_size], 0,
1013 len - crypto->plaintext_size);
1016 pthread_cleanup_push (release_cipher, h);
1017 rc = gcry_cipher_setiv (h, cache_iv, cache_blocksize);
1018 if (!rc)
1020 rc = gcry_cipher_setkey (h, cache_key, cache_keysize);
1021 if (!rc)
1023 unsigned char *buf = xmalloc (len);
1025 pthread_cleanup_push (xfree, buf);
1027 if (!buf)
1028 rc = GPG_ERR_ENOMEM;
1030 if (!rc)
1032 rc = gcry_cipher_encrypt (h, buf, len, crypto->plaintext, len);
1033 if (!rc)
1035 xfree (crypto->plaintext);
1036 crypto->plaintext = buf;
1037 crypto->plaintext_size = len;
1041 pthread_cleanup_pop (rc != 0);
1045 pthread_cleanup_pop (1);
1046 return rc;
1049 gpg_error_t
1050 cache_decrypt (struct crypto_s *crypto)
1052 gcry_cipher_hd_t h = NULL;
1053 gpg_error_t rc;
1055 rc = gcry_cipher_open (&h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
1056 if (rc)
1057 return rc;
1059 if (!rc)
1060 rc = gcry_cipher_setiv (h, cache_iv, cache_blocksize);
1062 if (!rc)
1063 rc = gcry_cipher_setkey (h, cache_key, cache_keysize);
1065 pthread_cleanup_push (release_cipher, h);
1067 if (!rc)
1069 rc = gcry_cipher_decrypt (h, crypto->plaintext, crypto->plaintext_size,
1070 NULL, 0);
1071 if (rc || strncmp ((char *)crypto->plaintext, "<?xml ", 6))
1073 if (!rc)
1074 rc = GPG_ERR_BAD_DATA;
1078 pthread_cleanup_pop (1);
1079 return rc;
1082 gpg_error_t
1083 cache_kill_scd ()
1085 gpg_error_t rc;
1087 MUTEX_LOCK (&cache_mutex);
1088 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
1089 rc = agent_kill_scd (cache_agent);
1090 pthread_cleanup_pop (1);
1091 return rc;
1094 gpg_error_t
1095 cache_agent_command (const char *cmd)
1097 gpg_error_t rc;
1099 MUTEX_LOCK (&cache_mutex);
1100 rc = agent_command (cache_agent, NULL, NULL, "%s", cmd);
1101 MUTEX_UNLOCK (&cache_mutex);
1102 return rc;
1105 void
1106 cache_release_mutex ()
1108 MUTEX_UNLOCK (&cache_mutex);
1111 static gpg_error_t
1112 plaintext_get (struct cache_data_s *data, xmlDocPtr *r_doc)
1114 unsigned i;
1115 unsigned t = slist_length (plaintext_list);
1117 assert (r_doc != NULL);
1119 for (i = 0; i < t; i++)
1121 struct plaintext_s *p = slist_nth_data (plaintext_list, i);
1123 if (!strcmp (p->filename, data->filename) && !p->modified)
1125 *r_doc = p->plaintext;
1126 p->refcount++;
1127 return 0;
1131 return GPG_ERR_NO_DATA;
1134 gpg_error_t
1135 cache_plaintext_get (const char *filename, xmlDocPtr *r_doc)
1137 file_cache_t *p;
1138 gpg_error_t rc = 0;
1140 MUTEX_LOCK (&cache_mutex);
1141 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
1143 p = get_entry (filename);
1144 if (p && p->data)
1145 rc = plaintext_get (p->data, r_doc);
1146 else
1147 rc = GPG_ERR_NO_DATA;
1149 pthread_cleanup_pop (1);
1150 return rc;
1153 static gpg_error_t
1154 release_plaintext (xmlDocPtr *plaintext)
1156 unsigned i;
1157 unsigned t;
1159 if (!plaintext)
1160 return GPG_ERR_NO_DATA;
1162 t = slist_length (plaintext_list);
1163 for (i = 0; i < t; i++)
1165 struct plaintext_s *p = slist_nth_data (plaintext_list, i);
1167 if (p->plaintext == *plaintext)
1169 assert (p->refcount > 0);
1170 if (--p->refcount == 0)
1172 xmlFreeDoc (p->plaintext);
1173 xfree (p->filename);
1174 plaintext_list = slist_remove (plaintext_list, p);
1175 xfree (p);
1176 update_plaintext_pointer (*plaintext);
1177 *plaintext = NULL;
1180 return 0;
1184 return GPG_ERR_NO_DATA;
1187 gpg_error_t
1188 cache_plaintext_release (xmlDocPtr *plaintext)
1190 gpg_error_t rc = 0;
1192 MUTEX_LOCK (&cache_mutex);
1193 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
1194 rc = release_plaintext (plaintext);
1195 pthread_cleanup_pop (1);
1196 return rc;
1199 gpg_error_t
1200 cache_plaintext_set (const char *filename, xmlDocPtr doc, int modified)
1202 file_cache_t *p;
1203 gpg_error_t rc = 0;
1205 MUTEX_LOCK (&cache_mutex);
1206 pthread_cleanup_push (release_mutex_cb, &cache_mutex);
1208 p = get_entry (filename);
1209 if (p && p->data)
1211 struct plaintext_s *s = xcalloc (1, sizeof (struct plaintext_s));
1213 if (s)
1215 s->filename = str_dup (p->data->filename);
1216 if (s->filename)
1218 struct slist_s *l;
1220 l = slist_append (plaintext_list, s);
1221 if (l)
1223 plaintext_list = l;
1224 s->plaintext = p->data->plaintext = doc;
1225 s->modified = modified;
1226 s->refcount = 1;
1228 else
1230 xfree (s->filename);
1231 rc = GPG_ERR_ENOMEM;
1234 else
1235 rc = GPG_ERR_ENOMEM;
1237 if (rc)
1238 xfree (s);
1240 else
1241 rc = GPG_ERR_ENOMEM;
1243 else
1244 rc = GPG_ERR_NO_DATA;
1246 pthread_cleanup_pop (1);
1247 return rc;