/* This file is part of GNUnet Copyright (C) 2010-2015 GNUnet e.V. GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNUnet 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . SPDX-License-Identifier: AGPL3.0-or-later */ /** * @file reclaim/did_core.c * @brief Core functionality for DID * @author Tristan Schwieren */ #include "did_core.h" // #define DID_DOCUMENT_LABEL GNUNET_GNS_EMPTY_LABEL_AT #define DID_DOCUMENT_LABEL "didd" #define DID_DOCUMENT_DEFAULT_EXPIRATION_TIME "1d" static DID_resolve_callback *resolve_cb; static DID_action_callback *action_cb; static void *closure; // ------------------------------------------------ // // -------------------- Resolve ------------------- // // ------------------------------------------------ // /** * @brief GNS lookup callback. Calls the given callback function * and gives it the DID Document. * Fails if there is more than one DID record. * * @param cls closure * @param rd_count number of records in rd * @param rd the records in the reply */ static void DID_resolve_gns_lookup_cb ( void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd) { /* * FIXME-MSC: The user may decide to put other records here. * In general I am fine with the constraint here, but not when * we move it to "@" */ char *didd; if (rd_count != 1) resolve_cb (GNUNET_NO, "An ego should only have one DID Document", closure); if (rd[0].record_type == GNUNET_DNSPARSER_TYPE_TXT) { didd = (char *) rd[0].data; resolve_cb (GNUNET_OK, didd, closure); } else resolve_cb (GNUNET_NO, "DID Document is not a TXT record\n", closure); } /** * @brief Resolve a DID. * Calls the given callback function with the resolved DID Document and the given closure. * If the did can not be resolved did_document is NULL. * * @param did DID that is resolved * @param gns_handle pointer to gns handle. * @param cont callback function * @param cls closure */ enum GNUNET_GenericReturnValue DID_resolve (const char *did, struct GNUNET_GNS_Handle *gns_handle, DID_resolve_callback *cont, void *cls) { struct GNUNET_IDENTITY_PublicKey pkey; if ((did == NULL) || (gns_handle == NULL) || (cont == NULL)) return GNUNET_NO; resolve_cb = cont; closure = cls; if (GNUNET_OK != DID_did_to_pkey (did, &pkey)) return GNUNET_NO; GNUNET_GNS_lookup (gns_handle, DID_DOCUMENT_LABEL, &pkey, GNUNET_DNSPARSER_TYPE_TXT, GNUNET_GNS_LO_DEFAULT, &DID_resolve_gns_lookup_cb, NULL); return GNUNET_OK; } // ------------------------------------------------ // // -------------------- Create -------------------- // // ------------------------------------------------ // static void DID_create_did_store_cb (void *cls, int32_t success, const char *emsg) { if (GNUNET_OK == success) { // TEST struct GNUNET_IDENTITY_PublicKey *pkey_test; GNUNET_IDENTITY_ego_get_public_key ((struct GNUNET_IDENTITY_Ego *) closure, pkey_test); printf ("pkey1: %s\n", GNUNET_IDENTITY_public_key_to_string (pkey_test)); printf ("cls3: %s\n", (char *) closure); action_cb (GNUNET_OK, closure); } else { printf ("%s\n", emsg); action_cb (GNUNET_NO, closure); } } /** * @brief Store DID Document in Namestore * * @param didd_str String endoced DID Docuement * @param ego Identity whos DID Document is stored */ static enum GNUNET_GenericReturnValue DID_create_did_store (struct GNUNET_NAMESTORE_Handle *namestore_handle, char *didd_str, struct GNUNET_IDENTITY_Ego *ego) { struct GNUNET_TIME_Relative expire_time; struct GNUNET_GNSRECORD_Data record_data; const struct GNUNET_IDENTITY_PrivateKey *skey; if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative ( DID_DOCUMENT_DEFAULT_EXPIRATION_TIME, &expire_time)) { printf ("Failed to read given expiration time\n"); return GNUNET_NO; } record_data.data = didd_str; record_data.expiration_time = expire_time.rel_value_us; record_data.data_size = strlen (didd_str) + 1; record_data.record_type = GNUNET_GNSRECORD_typename_to_number ("TXT"), record_data.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; skey = GNUNET_IDENTITY_ego_get_private_key (ego); // TEST struct GNUNET_IDENTITY_PublicKey *pkey_test; GNUNET_IDENTITY_ego_get_public_key ((struct GNUNET_IDENTITY_Ego *) closure, pkey_test); printf ("pkey1: %s\n", GNUNET_IDENTITY_public_key_to_string (pkey_test)); GNUNET_NAMESTORE_records_store (namestore_handle, skey, DID_DOCUMENT_LABEL, 1, // FIXME what if GNUNET_GNS_EMPTY_LABEL_AT has records &record_data, &DID_create_did_store_cb, NULL); return GNUNET_OK; } // TODO: Expiration time missing /** * @brief Creates a DID and saves DID Document in Namestore. * * @param ego ego for which the DID should be created. * @param did_document did_document that should be saved in namestore. * If did_document==NULL -> Default DID document is created. * @param cfg_handle pointer to configuration handle * @param identity_hanlde pointer to identity handle. Can be NULL if ego!=NULL * @param namestore_handle * @param cont callback function * @param cls closure */ enum GNUNET_GenericReturnValue DID_create (const struct GNUNET_IDENTITY_Ego *ego, const char *did_document, const struct GNUNET_CONFIGURATION_Handle *cfg_handle, struct GNUNET_IDENTITY_Handle *identity_handle, struct GNUNET_NAMESTORE_Handle *namestore_handle, DID_action_callback *cont, void *cls) { struct GNUNET_IDENTITY_PublicKey pkey; GNUNET_IDENTITY_ego_get_public_key (ego, &pkey); if (ntohl (pkey.type) != GNUNET_GNSRECORD_TYPE_EDKEY) { printf ("The EGO has to have an EDDSA key pair\n"); return GNUNET_NO; } if (did_document != NULL) printf ( "DID Docuement is read from \"DID-document\" argument (EXPERIMENTAL)\n"); else did_document = DID_pkey_to_did_document (&pkey); // TEST struct GNUNET_IDENTITY_PublicKey *pkey_test; GNUNET_IDENTITY_ego_get_public_key ((struct GNUNET_IDENTITY_Ego *) cls, pkey_test); printf ("pkey1: %s\n", GNUNET_IDENTITY_public_key_to_string (pkey_test)); action_cb = cont; closure = cls; return DID_create_did_store (namestore_handle, did_document, ego); }