2016-05-06 19:22:39 +02:00
|
|
|
/*
|
|
|
|
This file is part of TALER
|
|
|
|
Copyright (C) 2014, 2015, 2016 Inria & GNUnet e.V.
|
|
|
|
|
|
|
|
TALER is free software; you can redistribute it and/or modify it under the
|
|
|
|
terms of the GNU General Public License as published by the Free Software
|
|
|
|
Foundation; either version 3, or (at your option) any later version.
|
|
|
|
|
|
|
|
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
2016-07-07 17:55:25 +02:00
|
|
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
2016-05-06 19:22:39 +02:00
|
|
|
*/
|
|
|
|
/**
|
|
|
|
* @file exchangedb/exchangedb_signkeys.c
|
|
|
|
* @brief I/O operations for the Exchange's private online signing keys
|
|
|
|
* @author Florian Dold
|
|
|
|
* @author Benedikt Mueller
|
|
|
|
* @author Sree Harsha Totakura
|
|
|
|
* @author Christian Grothoff
|
|
|
|
*/
|
|
|
|
#include "platform.h"
|
|
|
|
#include "taler_exchangedb_lib.h"
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Closure for the #signkeys_iterate_dir_iter().
|
|
|
|
*/
|
|
|
|
struct SignkeysIterateContext
|
|
|
|
{
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function to call on each signing key.
|
|
|
|
*/
|
|
|
|
TALER_EXCHANGEDB_SigningKeyIterator it;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Closure for @e it.
|
|
|
|
*/
|
|
|
|
void *it_cls;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function called on each file in the directory with our signing
|
|
|
|
* keys. Parses the file and calls the iterator from @a cls.
|
|
|
|
*
|
|
|
|
* @param cls the `struct SignkeysIterateContext *`
|
|
|
|
* @param filename name of the file to parse
|
|
|
|
* @return #GNUNET_OK to continue,
|
|
|
|
* #GNUNET_NO to stop iteration without error,
|
|
|
|
* #GNUNET_SYSERR to stop iteration with error
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
signkeys_iterate_dir_iter (void *cls,
|
|
|
|
const char *filename)
|
|
|
|
{
|
|
|
|
struct SignkeysIterateContext *skc = cls;
|
|
|
|
ssize_t nread;
|
|
|
|
struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP issue;
|
|
|
|
|
|
|
|
nread = GNUNET_DISK_fn_read (filename,
|
|
|
|
&issue,
|
2019-08-25 16:18:24 +02:00
|
|
|
sizeof (struct
|
|
|
|
TALER_EXCHANGEDB_PrivateSigningKeyInformationP));
|
2016-05-06 19:22:39 +02:00
|
|
|
if (nread != sizeof (struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP))
|
|
|
|
{
|
|
|
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
|
|
"Invalid signkey file `%s': wrong size (%d, expected %u)\n",
|
|
|
|
filename,
|
|
|
|
(int) nread,
|
2019-08-25 16:18:24 +02:00
|
|
|
(unsigned int) sizeof (struct
|
|
|
|
TALER_EXCHANGEDB_PrivateSigningKeyInformationP));
|
2016-05-06 19:22:39 +02:00
|
|
|
return GNUNET_OK;
|
|
|
|
}
|
2019-02-14 13:41:46 +01:00
|
|
|
if (0 == GNUNET_TIME_absolute_get_remaining
|
2019-08-25 16:18:24 +02:00
|
|
|
(GNUNET_TIME_absolute_ntoh (issue.issue.expire)).rel_value_us)
|
2019-02-14 13:41:46 +01:00
|
|
|
{
|
2019-09-13 21:12:15 +02:00
|
|
|
if (0 != unlink (filename))
|
2019-03-11 03:24:32 +01:00
|
|
|
{
|
|
|
|
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
|
|
|
"unlink",
|
|
|
|
filename);
|
|
|
|
return GNUNET_OK; /* yes, we had an error, but continue to iterate anyway */
|
|
|
|
}
|
|
|
|
/* Expired file deleted, continue to iterate -without- calling iterator
|
|
|
|
as this key is expired */
|
|
|
|
return GNUNET_OK;
|
2019-02-14 13:41:46 +01:00
|
|
|
}
|
2016-05-06 19:22:39 +02:00
|
|
|
return skc->it (skc->it_cls,
|
|
|
|
filename,
|
|
|
|
&issue);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Call @a it for each signing key found in the @a exchange_base_dir.
|
|
|
|
*
|
|
|
|
* @param exchange_base_dir base directory for the exchange,
|
|
|
|
* the signing keys must be in the #TALER_EXCHANGEDB_DIR_SIGNING_KEYS
|
|
|
|
* subdirectory
|
|
|
|
* @param it function to call on each signing key
|
|
|
|
* @param it_cls closure for @a it
|
|
|
|
* @return number of files found (may not match
|
|
|
|
* number of keys given to @a it as malformed
|
|
|
|
* files are simply skipped), -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
TALER_EXCHANGEDB_signing_keys_iterate (const char *exchange_base_dir,
|
|
|
|
TALER_EXCHANGEDB_SigningKeyIterator it,
|
|
|
|
void *it_cls)
|
|
|
|
{
|
|
|
|
char *signkey_dir;
|
|
|
|
struct SignkeysIterateContext skc;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
GNUNET_asprintf (&signkey_dir,
|
|
|
|
"%s" DIR_SEPARATOR_STR TALER_EXCHANGEDB_DIR_SIGNING_KEYS,
|
|
|
|
exchange_base_dir);
|
|
|
|
skc.it = it;
|
|
|
|
skc.it_cls = it_cls;
|
|
|
|
ret = GNUNET_DISK_directory_scan (signkey_dir,
|
|
|
|
&signkeys_iterate_dir_iter,
|
|
|
|
&skc);
|
|
|
|
GNUNET_free (signkey_dir);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Obtain the name of the directory we use to store signing
|
|
|
|
* keys created at time @a start.
|
|
|
|
*
|
2017-04-20 07:49:56 +02:00
|
|
|
* @param exchange_directory base director where we store key material
|
2016-05-06 19:22:39 +02:00
|
|
|
* @param start time at which we create the signing key
|
|
|
|
* @return name of the directory we should use, basically "$EXCHANGEDIR/$TIME/";
|
|
|
|
* (valid until next call to this function)
|
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
get_signkey_file (const char *exchange_directory,
|
|
|
|
struct GNUNET_TIME_Absolute start)
|
|
|
|
{
|
2016-09-20 13:11:39 +02:00
|
|
|
char *fn;
|
2016-05-06 19:22:39 +02:00
|
|
|
|
2016-09-20 13:11:39 +02:00
|
|
|
GNUNET_asprintf (&fn,
|
2019-08-25 16:18:24 +02:00
|
|
|
"%s" DIR_SEPARATOR_STR TALER_EXCHANGEDB_DIR_SIGNING_KEYS
|
|
|
|
DIR_SEPARATOR_STR "%llu",
|
2016-05-06 19:22:39 +02:00
|
|
|
exchange_directory,
|
|
|
|
(unsigned long long) start.abs_value_us);
|
2016-09-20 13:11:39 +02:00
|
|
|
return fn;
|
2016-05-06 19:22:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Exports a signing key to the given file.
|
|
|
|
*
|
|
|
|
* @param exchange_base_dir base directory for the keys
|
|
|
|
* @param start start time of the validity for the key
|
|
|
|
* @param ski the signing key
|
|
|
|
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
TALER_EXCHANGEDB_signing_key_write (const char *exchange_base_dir,
|
|
|
|
struct GNUNET_TIME_Absolute start,
|
2019-08-25 16:18:24 +02:00
|
|
|
const struct
|
|
|
|
TALER_EXCHANGEDB_PrivateSigningKeyInformationP
|
|
|
|
*ski)
|
2016-05-06 19:22:39 +02:00
|
|
|
{
|
|
|
|
char *skf;
|
|
|
|
ssize_t nwrite;
|
|
|
|
|
|
|
|
skf = get_signkey_file (exchange_base_dir,
|
|
|
|
start);
|
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_DISK_directory_create_for_file (skf))
|
|
|
|
return GNUNET_SYSERR;
|
|
|
|
nwrite = GNUNET_DISK_fn_write (skf,
|
|
|
|
ski,
|
2019-08-25 16:18:24 +02:00
|
|
|
sizeof (struct
|
|
|
|
TALER_EXCHANGEDB_PrivateSigningKeyInformationP),
|
|
|
|
GNUNET_DISK_PERM_USER_WRITE
|
|
|
|
| GNUNET_DISK_PERM_USER_READ);
|
2016-05-06 19:22:39 +02:00
|
|
|
if (sizeof (struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP) != nwrite)
|
|
|
|
{
|
|
|
|
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
|
|
|
"write",
|
|
|
|
skf);
|
|
|
|
GNUNET_free (skf);
|
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
|
|
|
GNUNET_free (skf);
|
|
|
|
return GNUNET_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* end of exchangedb_signkeys.c */
|