/*
This file is part of Anastasis
Copyright (C) 2022 Anastasis SARL
Anastasis 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.
Anastasis 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
Anastasis; see the file COPYING.GPL. If not, see
*/
/**
* @brief anastasis client api to get recovery document meta data
* @author Christian Grothoff
*/
#include "platform.h"
#include "anastasis.h"
#include
#include
#include
/**
* Handle for a version check operation.
*/
struct ANASTASIS_VersionCheck
{
/**
* Function to call with results.
*/
ANASTASIS_MetaPolicyCallback mpc;
/**
* Closure for @e mpc.
*/
void *mpc_cls;
/**
* Handle for the actual REST operation.
*/
struct ANASTASIS_PolicyMetaLookupOperation *plm;
/**
* User identifier (needed to decrypt).
*/
struct ANASTASIS_CRYPTO_UserIdentifierP id;
};
/**
* Function called with results from a GET /policy/$POL/meta request
*
* @param cls closure with the `struct ANASTASIS_VersionCheck *`
* @param http_status HTTP status code for this request
* @param dd the response details
*/
static void
meta_cb (
void *cls,
unsigned int http_status,
const struct ANASTASIS_MetaDownloadDetails *dd)
{
struct ANASTASIS_VersionCheck *vc = cls;
vc->plm = NULL;
if ( (MHD_HTTP_OK != http_status) ||
(NULL == dd) )
{
vc->mpc (vc->mpc_cls,
0,
GNUNET_TIME_UNIT_ZERO_TS,
NULL,
NULL);
ANASTASIS_recovery_get_versions_cancel (vc);
return;
}
for (size_t i = 0; imetas_length; i++)
{
const struct ANASTASIS_MetaDataEntry *meta = &dd->metas[i];
const char *secret_name = NULL;
const struct GNUNET_HashCode *eph;
void *dec;
size_t dec_len;
if (GNUNET_OK !=
ANASTASIS_CRYPTO_recovery_metadata_decrypt (
&vc->id,
meta->meta_data,
meta->meta_data_size,
&dec,
&dec_len))
{
GNUNET_break_op (0);
continue;
}
if (sizeof (*eph) > dec_len)
{
GNUNET_break_op (0);
GNUNET_free (dec);
continue;
}
eph = dec;
if (sizeof (*eph) < dec_len)
{
secret_name = (const char *) &eph[1];
dec_len -= sizeof (*eph);
if ('\0' != secret_name[dec_len - 1])
{
GNUNET_break_op (0);
GNUNET_free (dec);
continue;
}
}
vc->mpc (vc->mpc_cls,
meta->version,
meta->server_time,
eph,
secret_name);
GNUNET_free (dec);
}
vc->mpc (vc->mpc_cls,
0,
GNUNET_TIME_UNIT_ZERO_TS,
NULL,
NULL);
ANASTASIS_recovery_get_versions_cancel (vc);
}
struct ANASTASIS_VersionCheck *
ANASTASIS_recovery_get_versions (
struct GNUNET_CURL_Context *ctx,
const json_t *id_data,
unsigned int max_version,
const char *anastasis_provider_url,
const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt,
ANASTASIS_MetaPolicyCallback mpc,
void *mpc_cls)
{
struct ANASTASIS_VersionCheck *vc;
struct ANASTASIS_CRYPTO_AccountPublicKeyP account_pub;
vc = GNUNET_new (struct ANASTASIS_VersionCheck);
vc->mpc = mpc;
vc->mpc_cls = mpc_cls;
ANASTASIS_CRYPTO_user_identifier_derive (id_data,
provider_salt,
&vc->id);
ANASTASIS_CRYPTO_account_public_key_derive (&vc->id,
&account_pub);
vc->plm = ANASTASIS_policy_meta_lookup (ctx,
anastasis_provider_url,
&account_pub,
max_version,
&meta_cb,
vc);
if (NULL == vc->plm)
{
GNUNET_break (0);
GNUNET_free (vc);
return NULL;
}
return vc;
}
void
ANASTASIS_recovery_get_versions_cancel (struct ANASTASIS_VersionCheck *vc)
{
if (NULL != vc->plm)
{
ANASTASIS_policy_meta_lookup_cancel (vc->plm);
vc->plm = NULL;
}
GNUNET_free (vc);
}