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/>.
30 #include "pwmd-error.h"
36 #include "util-misc.h"
37 #include "util-string.h"
44 static pthread_mutex_t cache_mutex
;
45 static struct slist_s
*key_cache
;
47 static struct agent_s
*cache_agent
;
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
);
59 get_entry (const unsigned char *md5file
)
61 int t
= slist_length (key_cache
);
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
)))
79 cache_lock_mutex (void *ctx
, const unsigned char *md5file
,
80 long lock_timeout
, int add
, int timeout
)
82 MUTEX_LOCK (&cache_mutex
);
84 file_cache_t
*p
= get_entry (md5file
);
88 MUTEX_UNLOCK (&cache_mutex
);
89 MUTEX_TRYLOCK (ctx
, p
->mutex
, rc
, lock_timeout
);
93 rc
= cache_add_file (md5file
, NULL
, NULL
, timeout
);
96 p
= get_entry (md5file
);
97 MUTEX_UNLOCK (&cache_mutex
);
98 MUTEX_TRYLOCK (ctx
, p
->mutex
, rc
, lock_timeout
);
102 MUTEX_UNLOCK (&cache_mutex
);
107 MUTEX_UNLOCK (&cache_mutex
);
110 return !p
&& !rc
? GPG_ERR_NO_DATA
: rc
;
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
);
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.
130 pthread_cleanup_pop (1);
135 cache_unlock_mutex (const unsigned char *md5file
, int remove
)
137 MUTEX_LOCK (&cache_mutex
);
138 file_cache_t
*p
= get_entry (md5file
);
142 MUTEX_UNLOCK (p
->mutex
);
144 remove_entry (md5file
);
147 MUTEX_UNLOCK (&cache_mutex
);
148 return p
? 0 : GPG_ERR_NO_DATA
;
152 static int valid_agent_grip (file_cache_t
*e
)
156 for (c
= 0; c
< sizeof (e
->grip
); c
++)
158 if (e
->grip
[c
] && e
->grip
[c
] != '0')
167 valid_grip (file_cache_t
* e
)
169 if (e
->data
&& e
->data
->key
)
173 return valid_agent_grip (e
);
180 iscached (const unsigned char *md5file
, int *defer
)
183 file_cache_t
*p
= get_entry (md5file
);
185 if (!p
|| !p
->data
|| !valid_grip (p
))
186 return GPG_ERR_NO_DATA
;
189 *defer
= p
->defer_clear
;
191 if (p
->data
&& p
->data
->key
)
197 rc
= send_to_agent (cache_agent
, &line
, NULL
, "KEYINFO --data %s", p
->grip
);
200 char **fields
= str_split (line
, " ", 0);
202 /* Smartcard with a cached document. */
203 if (*fields
[1] == 'T' && p
->data
->doc
)
206 rc
= isdigit (*fields
[4]) || *fields
[5] == 'C' ? 0 : GPG_ERR_NO_DATA
;
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
))
232 pthread_cleanup_pop (1);
237 cache_adjust_timeout ()
239 MUTEX_LOCK (&cache_mutex
);
240 int t
= slist_length (key_cache
);
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
);
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
258 send_status_all (STATUS_CACHE
, NULL
);
262 pthread_cleanup_pop (1);
266 setgrip (file_cache_t
* p
, const unsigned char *grip
)
270 char *tmp
= bin2hex (grip
, 20);
272 memcpy (p
->grip
, tmp
, sizeof (p
->grip
));
276 memset (p
->grip
, 0, sizeof(p
->grip
));
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
);
288 MUTEX_UNLOCK (&cache_mutex
);
289 return GPG_ERR_NOT_FOUND
;
293 if (!p
->defer_clear
&& (p
->timeout
== -1 || force
))
294 p
->timeout
= timeout
;
296 if (!timeout
|| defer
)
300 send_status_all (STATUS_CACHE
, NULL
);
303 MUTEX_UNLOCK (&cache_mutex
);
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
);
318 set_timeout (md5file
, p
->reset
, p
->defer_clear
, 0);
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
);
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
);
364 rc
= set_timeout (md5file
, timeout
, p
->defer_clear
, 0);
365 MUTEX_UNLOCK (&cache_mutex
);
366 send_status_all (STATUS_CACHE
, NULL
);
370 p
= xcalloc (1, sizeof (file_cache_t
));
373 MUTEX_UNLOCK (&cache_mutex
);
374 return GPG_ERR_ENOMEM
;
377 p
->mutex
= (pthread_mutex_t
*) xmalloc (sizeof (pthread_mutex_t
));
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
));
394 new = slist_append (key_cache
, p
);
397 pthread_mutex_destroy (p
->mutex
);
400 MUTEX_UNLOCK (&cache_mutex
);
401 return GPG_ERR_ENOMEM
;
405 rc
= cache_set_timeout(md5file
, timeout
);
406 MUTEX_UNLOCK (&cache_mutex
);
407 send_status_all (STATUS_CACHE
, NULL
);
412 clear_once (file_cache_t
* p
)
414 gpg_error_t rc
= free_data_fn (p
);
416 if (!rc
&& valid_grip (p
))
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
);
424 log_write ("%s(): %s", __FUNCTION__
, pwmd_strerror (rc
));
427 memset (p
->grip
, 0, sizeof (p
->grip
));
434 free_entry (file_cache_t
* p
)
443 log_write ("%s(): %s", __FUNCTION__
, pwmd_strerror (rc
));
447 pthread_mutex_destroy (p
->mutex
);
451 key_cache
= slist_remove (key_cache
, p
);
456 cache_clear (const unsigned char *md5file
)
462 MUTEX_LOCK (&cache_mutex
);
466 p
= get_entry (md5file
);
469 MUTEX_UNLOCK (&cache_mutex
);
473 pthread_cleanup_push (cleanup_mutex_cb
, &cache_mutex
);
475 pthread_cleanup_pop (1);
477 log_write ("%s(): %s", __FUNCTION__
, pwmd_strerror (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
);
490 pthread_cleanup_pop (1);
495 cache_iscached (const char *filename
, int *defer
)
498 unsigned char md5file
[16];
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
);
533 cache_defer_clear (const unsigned char *md5file
)
535 MUTEX_LOCK (&cache_mutex
);
536 file_cache_t
*p
= get_entry (md5file
);
540 rc
= GPG_ERR_NOT_FOUND
;
544 MUTEX_UNLOCK (&cache_mutex
);
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
);
566 memcpy (grip
, p
->grip
, sizeof (p
->grip
));
567 MUTEX_UNLOCK (&cache_mutex
);
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. */
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
);
586 if (atfork
&& valid_agent_grip (p
))
591 t
= slist_length (key_cache
);
596 if (use_agent
&& cache_agent
)
597 cleanup_agent (cache_agent
);
601 gcry_free (cache_key
);
605 pthread_cleanup_pop (1);
606 pthread_mutex_destroy (&cache_mutex
);
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
);
621 cache_init (free_data_fn_t fn
)
627 rc
= gcry_cipher_algo_info (GCRY_CIPHER_AES
, GCRYCTL_GET_BLKLEN
, NULL
,
632 rc
= gcry_cipher_algo_info (GCRY_CIPHER_AES
, GCRYCTL_GET_KEYLEN
, NULL
,
637 cache_key
= gcry_malloc (cache_keysize
);
639 return GPG_ERR_ENOMEM
;
641 cache_iv
= xmalloc (cache_blocksize
);
644 gcry_free (cache_key
);
646 return GPG_ERR_ENOMEM
;
649 gcry_create_nonce (cache_key
, cache_keysize
);
650 gcry_create_nonce (cache_iv
, cache_blocksize
);
654 if (use_agent
&& !cache_agent
)
656 rc
= agent_init (&cache_agent
);
661 rc
= send_to_agent (cache_agent
, &line
, NULL
, "GETINFO version");
664 char **fields
= str_split (line
, ".", 0);
667 major
= atoi (fields
[0]);
668 minor
= atoi (fields
[1]);
669 if (major
< 2 || minor
< 1)
670 rc
= GPG_ERR_UNKNOWN_VERSION
;
686 cache_is_shadowed (const char *grip
)
688 MUTEX_LOCK (&cache_mutex
);
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);
699 char **fields
= str_split (line
, " ", 0);
701 rc
= (*fields
[1] == 'T') ? 0 : GPG_ERR_NO_DATA
;
713 MUTEX_LOCK (&cache_mutex
);
719 MUTEX_UNLOCK (&cache_mutex
);
723 free_cache_data_once (struct cache_data_s
*data
)
730 gcry_sexp_release (data
->pubkey
);
733 gcry_sexp_release (data
->sigkey
);
736 gcry_free (data
->doc
);
737 gcry_free (data
->key
);