diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-03-05 16:10:55 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-03-05 16:10:55 +0000 |
commit | 2a23e57e4216593e83e7235e23988564825e4229 (patch) | |
tree | 89cdee0dd816e722214f76f4b9762140416ade20 /src/fs | |
parent | dfeb2b787f31255761a808007779c6e992c47591 (diff) |
starting major change towards implementing #2564, this breaks some FS tests and FS APIs
Diffstat (limited to 'src/fs')
-rw-r--r-- | src/fs/Makefile.am | 1 | ||||
-rw-r--r-- | src/fs/fs.h | 15 | ||||
-rw-r--r-- | src/fs/fs_api.h | 18 | ||||
-rw-r--r-- | src/fs/fs_namespace.c | 288 | ||||
-rw-r--r-- | src/fs/fs_namespace_advertise.c | 363 | ||||
-rw-r--r-- | src/fs/fs_publish_ksk.c | 89 | ||||
-rw-r--r-- | src/fs/fs_search.c | 249 | ||||
-rw-r--r-- | src/fs/fs_unindex.c | 84 | ||||
-rw-r--r-- | src/fs/fs_uri.c | 71 | ||||
-rw-r--r-- | src/fs/gnunet-pseudonym.c | 41 | ||||
-rw-r--r-- | src/fs/gnunet-service-fs.c | 4 | ||||
-rw-r--r-- | src/fs/gnunet-service-fs.h | 6 | ||||
-rw-r--r-- | src/fs/gnunet-service-fs_cp.c | 18 | ||||
-rw-r--r-- | src/fs/gnunet-service-fs_lc.c | 12 | ||||
-rw-r--r-- | src/fs/gnunet-service-fs_pr.c | 36 | ||||
-rw-r--r-- | src/fs/gnunet-service-fs_pr.h | 8 | ||||
-rw-r--r-- | src/fs/gnunet-service-fs_put.c | 4 | ||||
-rw-r--r-- | src/fs/plugin_block_fs.c | 181 | ||||
-rw-r--r-- | src/fs/test_fs_namespace.c | 182 | ||||
-rw-r--r-- | src/fs/test_fs_uri.c | 23 |
20 files changed, 457 insertions, 1236 deletions
diff --git a/src/fs/Makefile.am b/src/fs/Makefile.am index 84c0a61d98..54267c57c6 100644 --- a/src/fs/Makefile.am +++ b/src/fs/Makefile.am @@ -38,7 +38,6 @@ libgnunetfs_la_SOURCES = \ fs_publish_ksk.c \ fs_misc.c \ fs_namespace.c \ - fs_namespace_advertise.c \ fs_search.c \ fs_sharetree.c \ fs_tree.c fs_tree.h \ diff --git a/src/fs/fs.h b/src/fs/fs.h index ffd448d2b8..9a987303b1 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h @@ -240,26 +240,21 @@ struct SearchMessage * nevertheless, we should probably not use it for a DHT-lookup * or similar blunt actions in order to avoid exposing ourselves). * <p> - * If the request is for an SBLOCK, this is the identity of the - * pseudonym to which the SBLOCK belongs. - * <p> - * If the request is for a KBLOCK, "target" must be all zeros. + * Otherwise, "target" must be all zeros. */ struct GNUNET_HashCode target; /** - * Hash of the keyword (aka query) for KBLOCKs; Hash of - * the CHK-encoded block for DBLOCKS and IBLOCKS (aka query) - * and hash of the identifier XORed with the target for - * SBLOCKS (aka query). + * Hash of the public key for UBLOCKs; Hash of + * the CHK-encoded block for DBLOCKS and IBLOCKS. */ struct GNUNET_HashCode query; /* this is followed by the hash codes of already-known * results (which should hence be excluded from what * the service returns); naturally, this only applies - * to queries that can have multiple results, such as - * those for KBLOCKS (KSK) and SBLOCKS (SKS) */ + * to queries that can have multiple results (UBLOCKS). + */ }; diff --git a/src/fs/fs_api.h b/src/fs/fs_api.h index 61a568fa04..b2744237ee 100644 --- a/src/fs/fs_api.h +++ b/src/fs/fs_api.h @@ -204,9 +204,9 @@ struct GNUNET_FS_Uri struct { /** - * Hash of the public key for the namespace. + * Identifier of the namespace. */ - struct GNUNET_HashCode ns; + struct GNUNET_PseudonymIdentifier ns; /** * Human-readable identifier chosen for this @@ -1390,14 +1390,14 @@ struct GNUNET_FS_UnindexContext struct GNUNET_DATASTORE_QueueEntry *dqe; /** - * Current key for decrypting KBLocks from 'get_key' operation. + * Current key for decrypting UBLocks from 'get_key' operation. */ - struct GNUNET_HashCode key; + struct GNUNET_HashCode ukey; /** * Current query of 'get_key' operation. */ - struct GNUNET_HashCode query; + struct GNUNET_HashCode uquery; /** * First content UID, 0 for none. @@ -1449,15 +1449,15 @@ struct GNUNET_FS_UnindexContext struct SearchRequestEntry { /** - * Hash of the original keyword, also known as the + * Hash of the original keyword, used to derive the * key (for decrypting the KBlock). */ - struct GNUNET_HashCode key; + struct GNUNET_HashCode ukey; /** * Hash of the public key, also known as the query. */ - struct GNUNET_HashCode query; + struct GNUNET_HashCode uquery; /** * Map that contains a "struct GNUNET_FS_SearchResult" for each result that @@ -2008,7 +2008,7 @@ struct GNUNET_FS_Namespace /** * Private key for the namespace. */ - struct GNUNET_CRYPTO_RsaPrivateKey *key; + struct GNUNET_PseudonymHandle *key; /** * Hash map mapping identifiers of update nodes diff --git a/src/fs/fs_namespace.c b/src/fs/fs_namespace.c index 3cc3ca2998..87ddb667f9 100644 --- a/src/fs/fs_namespace.c +++ b/src/fs/fs_namespace.c @@ -32,49 +32,6 @@ /** - * Maximum legal size for an sblock. - */ -#define MAX_SBLOCK_SIZE (60 * 1024) - - -/** - * Context for creating a namespace asynchronously. - */ -struct GNUNET_FS_NamespaceCreationContext -{ - /** - * Context for asynchronous key creation. - */ - struct GNUNET_CRYPTO_RsaKeyGenerationContext *keycreator; - - /** - * Name of the file to store key in / read key from. - */ - char *filename; - - /** - * Name of the namespace. - */ - char *name; - - /** - * Global fs handle - */ - struct GNUNET_FS_Handle *h; - - /** - * Function to call when generation ends (successfully or not) - */ - GNUNET_FS_NamespaceCreationCallback cont; - - /** - * Client value to pass to continuation function. - */ - void *cont_cls; -}; - - -/** * Return the name of the directory in which we store * our local namespaces (or rather, their public keys). * @@ -288,7 +245,7 @@ GNUNET_FS_namespace_create (struct GNUNET_FS_Handle *h, const char *name) ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Namespace)); ret->h = h; ret->rc = 1; - ret->key = GNUNET_CRYPTO_rsa_key_create_from_file (fn); + ret->key = GNUNET_PSEUDONYM_create (fn); if (NULL == ret->key) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -332,7 +289,7 @@ GNUNET_FS_namespace_open_existing (struct GNUNET_FS_Handle *h, const char *name) ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Namespace)); ret->h = h; ret->rc = 1; - ret->key = GNUNET_CRYPTO_rsa_key_create_from_existing_file (fn); + ret->key = GNUNET_PSEUDONYM_create_from_existing_file (fn); if (NULL == ret->key) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -348,118 +305,6 @@ GNUNET_FS_namespace_open_existing (struct GNUNET_FS_Handle *h, const char *name) /** - * Function called upon completion of 'GNUNET_CRYPTO_rsa_key_create_start'. - * - * @param cls closure - * @param pk NULL on error, otherwise the private key (which must be free'd by the callee) - * @param emsg NULL on success, otherwise an error message - */ -static void -ns_key_created (void *cls, struct GNUNET_CRYPTO_RsaPrivateKey *pk, - const char *emsg) -{ - struct GNUNET_FS_NamespaceCreationContext *ncc = cls; - - ncc->keycreator = NULL; - - if (pk) - { - struct GNUNET_FS_Namespace *ret; - ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Namespace)); - ret->rc = 1; - ret->key = pk; - ret->h = ncc->h; - ret->name = ncc->name; - ret->filename = ncc->filename; - ncc->cont (ncc->cont_cls, ret, NULL); - } - else - { - GNUNET_free (ncc->filename); - GNUNET_free (ncc->name); - ncc->cont (ncc->cont_cls, NULL, emsg); - } - GNUNET_free (ncc); -} - - -/** - * Create a namespace with the given name. - * If one already exists, the continuation will be called with a handle to - * the existing namespace. - * Otherwise creates a new namespace. - * - * @param h handle to the file sharing subsystem - * @param name name to use for the namespace - * @return namespace creation context, NULL on error (i.e. invalid filename) - */ -struct GNUNET_FS_NamespaceCreationContext * -GNUNET_FS_namespace_create_start (struct GNUNET_FS_Handle *h, const char *name, - GNUNET_FS_NamespaceCreationCallback cont, void *cont_cls) -{ - char *dn; - char *fn; - struct GNUNET_FS_NamespaceCreationContext *ret; - - dn = get_namespace_directory (h); - if (NULL == dn) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Can't determine where namespace directory is\n")); - return NULL; - } - GNUNET_asprintf (&fn, "%s%s%s", dn, DIR_SEPARATOR_STR, name); - GNUNET_free (dn); - - ret = GNUNET_malloc (sizeof (struct GNUNET_FS_NamespaceCreationContext)); - ret->filename = fn; - ret->h = h; - ret->name = GNUNET_strdup (name); - ret->cont = cont; - ret->cont_cls = cont_cls; - - ret->keycreator = GNUNET_CRYPTO_rsa_key_create_start (fn, - ns_key_created, ret); - - if (NULL == ret->keycreator) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Failed to start creating or reading private key for namespace `%s'\n"), - name); - GNUNET_free (fn); - GNUNET_free (ret->name); - GNUNET_free (ret); - return NULL; - } - return ret; -} - - -/** - * Abort namespace creation. - * - * @param ncc namespace creation context to abort - */ -void -GNUNET_FS_namespace_create_stop (struct GNUNET_FS_NamespaceCreationContext *ncc) -{ - if (NULL != ncc->keycreator) - { - GNUNET_CRYPTO_rsa_key_create_stop (ncc->keycreator); - ncc->keycreator = NULL; - } - if (NULL != ncc->filename) - { - if (0 != UNLINK (ncc->filename)) - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", ncc->filename); - GNUNET_free (ncc->filename); - } - GNUNET_free_non_null (ncc->name); - GNUNET_free (ncc); -} - - -/** * Rename a local namespace. * * @param h handle to the file sharing subsystem @@ -468,7 +313,9 @@ GNUNET_FS_namespace_create_stop (struct GNUNET_FS_NamespaceCreationContext *ncc) * @return GNUNET_OK on success, GNUNET_SYSERR on error (see errno for details) */ int -GNUNET_FS_namespace_rename (struct GNUNET_FS_Handle *h, const char *old_name, const char *new_name) +GNUNET_FS_namespace_rename (struct GNUNET_FS_Handle *h, + const char *old_name, + const char *new_name) { char *dn; char *fn_old; @@ -496,6 +343,7 @@ GNUNET_FS_namespace_rename (struct GNUNET_FS_Handle *h, const char *old_name, co return GNUNET_SYSERR; } + /** * Duplicate a namespace handle. * @@ -536,7 +384,7 @@ GNUNET_FS_namespace_delete (struct GNUNET_FS_Namespace *ns, int freeze) } if (0 != ns->rc) return GNUNET_OK; - GNUNET_CRYPTO_rsa_key_free (ns->key); + GNUNET_PSEUDONYM_destroy (ns->key); GNUNET_free (ns->filename); GNUNET_free (ns->name); for (i = 0; i < ns->update_node_count; i++) @@ -584,12 +432,12 @@ struct ProcessNamespaceContext * GNUNET_SYSERR on failure (contents of id remain intact) */ int -GNUNET_FS_namespace_get_public_key_hash (struct GNUNET_FS_Namespace *ns, - struct GNUNET_HashCode *id) +GNUNET_FS_namespace_get_public_identifier (struct GNUNET_FS_Namespace *ns, + struct GNUNET_PseudonymIdentifier *id) { if ((NULL == ns) || (NULL == id)) return GNUNET_SYSERR; - GNUNET_CRYPTO_rsa_get_public_key_hash (ns->key, id); + GNUNET_PSEUDONYM_get_identifier (ns->key, id); return GNUNET_OK; } @@ -607,13 +455,12 @@ static int process_namespace (void *cls, const char *filename) { struct ProcessNamespaceContext *pnc = cls; - struct GNUNET_CRYPTO_RsaPrivateKey *key; - struct GNUNET_HashCode id; + struct GNUNET_PseudonymHandle *ph; + struct GNUNET_PseudonymIdentifier id; const char *name; const char *t; - key = GNUNET_CRYPTO_rsa_key_create_from_file (filename); - if (NULL == key) + if (NULL == (ph = GNUNET_PSEUDONYM_create (filename))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ @@ -623,8 +470,8 @@ process_namespace (void *cls, const char *filename) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); return GNUNET_OK; } - GNUNET_CRYPTO_rsa_get_public_key_hash (key, &id); - GNUNET_CRYPTO_rsa_key_free (key); + GNUNET_PSEUDONYM_get_identifier (ph, &id); + GNUNET_PSEUDONYM_destroy (ph); name = filename; while (NULL != (t = strstr (name, DIR_SEPARATOR_STR))) name = t + 1; @@ -705,7 +552,7 @@ struct GNUNET_FS_PublishSksContext /** * Function called by the datastore API with - * the result from the PUT (SBlock) request. + * the result from the PUT (UBlock) request. * * @param cls closure of type "struct GNUNET_FS_PublishSksContext*" * @param success GNUNET_OK on success @@ -737,7 +584,7 @@ sb_put_cont (void *cls, int success, read_update_information_graph (psc->ns); GNUNET_array_append (psc->ns->update_nodes, psc->ns->update_node_count, psc->nsn); - if (psc->ns->update_map != NULL) + if (NULL != psc->ns->update_map) { GNUNET_CRYPTO_hash (psc->nsn->id, strlen (psc->nsn->id), &hc); GNUNET_CONTAINER_multihashmap_put (psc->ns->update_map, &hc, @@ -788,13 +635,15 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, size_t nidlen; size_t idlen; ssize_t mdsize; - struct SBlock *sb; - struct SBlock *sb_enc; + struct UBlock *ub; + struct UBlock *ub_enc; char *dest; struct GNUNET_CONTAINER_MetaData *mmeta; - struct GNUNET_HashCode key; /* hash of thisId = key */ - struct GNUNET_HashCode id; /* hash of hc = identifier */ - struct GNUNET_HashCode query; /* id ^ nsid = DB query */ + struct GNUNET_HashCode id_hash; /* hash of thisId */ + struct GNUNET_HashCode ns_hash; /* hash of namespace public key */ + struct GNUNET_HashCode key; /* id_hash ^ ns_hash, for AES key */ + struct GNUNET_HashCode signing_key; /* H(key) = input for public key */ + struct GNUNET_HashCode query; /* H(verification_key) = query */ idlen = strlen (identifier); if (NULL != update) @@ -803,11 +652,11 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, nidlen = 1; uris = GNUNET_FS_uri_to_string (uri); slen = strlen (uris) + 1; - if ( (slen >= MAX_SBLOCK_SIZE - sizeof (struct SBlock)) || - (nidlen >= MAX_SBLOCK_SIZE - sizeof (struct SBlock) - slen) ) + if ( (slen >= MAX_UBLOCK_SIZE - sizeof (struct UBlock)) || + (nidlen >= MAX_UBLOCK_SIZE - sizeof (struct UBlock) - slen) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Identifiers or URI too long to create SBlock")); + _("Identifiers or URI too long to create UBlock")); GNUNET_free (uris); return NULL; } @@ -816,15 +665,15 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, else mmeta = GNUNET_CONTAINER_meta_data_duplicate (meta); mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (mmeta); - size = sizeof (struct SBlock) + slen + nidlen + mdsize; - if ( (size > MAX_SBLOCK_SIZE) || - (size < sizeof (struct SBlock) + slen + nidlen) ) + size = sizeof (struct UBlock) + slen + nidlen + mdsize; + if ( (size > MAX_UBLOCK_SIZE) || + (size < sizeof (struct UBlock) + slen + nidlen) ) { - size = MAX_SBLOCK_SIZE; - mdsize = MAX_SBLOCK_SIZE - (sizeof (struct SBlock) + slen + nidlen); + size = MAX_UBLOCK_SIZE; + mdsize = MAX_UBLOCK_SIZE - (sizeof (struct UBlock) + slen + nidlen); } - sb = GNUNET_malloc (sizeof (struct SBlock) + size); - dest = (char *) &sb[1]; + ub = GNUNET_malloc (sizeof (struct UBlock) + size); + dest = (char *) &ub[1]; if (NULL != update) memcpy (dest, update, nidlen); else @@ -840,34 +689,44 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, if (-1 == mdsize) { GNUNET_break (0); - GNUNET_free (sb); + GNUNET_free (ub); if (NULL != cont) cont (cont_cls, NULL, _("Internal error.")); return NULL; } - size = sizeof (struct SBlock) + mdsize + slen + nidlen; - sb_enc = GNUNET_malloc (size); - GNUNET_CRYPTO_hash (identifier, idlen, &key); - GNUNET_CRYPTO_hash (&key, sizeof (struct GNUNET_HashCode), &id); sks_uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); sks_uri->type = GNUNET_FS_URI_SKS; - GNUNET_CRYPTO_rsa_key_get_public (ns->key, &sb_enc->subspace); - GNUNET_CRYPTO_hash (&sb_enc->subspace, - sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &sks_uri->data.sks.ns); sks_uri->data.sks.identifier = GNUNET_strdup (identifier); - GNUNET_CRYPTO_hash_xor (&id, &sks_uri->data.sks.ns, - &sb_enc->identifier); + GNUNET_FS_namespace_get_public_identifier (ns, + &sks_uri->data.sks.ns); + + size = sizeof (struct UBlock) + mdsize + slen + nidlen; + ub_enc = GNUNET_malloc (size); + GNUNET_CRYPTO_hash (identifier, idlen, &id_hash); + GNUNET_CRYPTO_hash (&sks_uri->data.sks.ns, + sizeof (sks_uri->data.sks.ns), &ns_hash); + GNUNET_CRYPTO_hash_xor (&id_hash, &ns_hash, &key); GNUNET_CRYPTO_hash_to_aes_key (&key, &sk, &iv); - GNUNET_CRYPTO_aes_encrypt (&sb[1], size - sizeof (struct SBlock), &sk, &iv, - &sb_enc[1]); - sb_enc->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_SBLOCK); - sb_enc->purpose.size = - htonl (slen + mdsize + nidlen + sizeof (struct SBlock) - - sizeof (struct GNUNET_CRYPTO_RsaSignature)); - GNUNET_assert (GNUNET_OK == - GNUNET_CRYPTO_rsa_sign (ns->key, &sb_enc->purpose, - &sb_enc->signature)); + GNUNET_CRYPTO_hash (&key, sizeof (struct GNUNET_HashCode), &signing_key); + + GNUNET_CRYPTO_aes_encrypt (&ub[1], + size - sizeof (struct UBlock), + &sk, &iv, + &ub_enc[1]); + ub_enc->purpose.size = htonl (nidlen + slen + mdsize + sizeof (struct UBlock) + - sizeof (struct GNUNET_PseudonymSignature)); + ub_enc->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK); + GNUNET_PSEUDONYM_sign (ns->key, + &ub_enc->purpose, + NULL, + &signing_key, + &ub_enc->signature); + GNUNET_PSEUDONYM_derive_verification_key (&sks_uri->data.sks.ns, + &signing_key, + &ub_enc->verification_key); + GNUNET_CRYPTO_hash (&ub_enc->verification_key, + sizeof (ub_enc->verification_key), + &query); psc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishSksContext)); psc->uri = sks_uri; psc->cont = cont; @@ -875,20 +734,20 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, psc->cont_cls = cont_cls; if (0 != (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) { - GNUNET_free (sb_enc); - GNUNET_free (sb); + GNUNET_free (ub_enc); + GNUNET_free (ub); sb_put_cont (psc, GNUNET_OK, GNUNET_TIME_UNIT_ZERO_ABS, NULL); return NULL; } psc->dsh = GNUNET_DATASTORE_connect (h->cfg); if (NULL == psc->dsh) { - GNUNET_free (sb_enc); - GNUNET_free (sb); + GNUNET_free (ub_enc); + GNUNET_free (ub); sb_put_cont (psc, GNUNET_NO, GNUNET_TIME_UNIT_ZERO_ABS, _("Failed to connect to datastore.")); return NULL; } - GNUNET_CRYPTO_hash_xor (&sks_uri->data.sks.ns, &id, &query); + if (NULL != update) { psc->nsn = GNUNET_malloc (sizeof (struct NamespaceUpdateNode)); @@ -897,13 +756,14 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, psc->nsn->md = GNUNET_CONTAINER_meta_data_duplicate (meta); psc->nsn->uri = GNUNET_FS_uri_dup (uri); } - psc->dqe = GNUNET_DATASTORE_put (psc->dsh, 0, &sb_enc->identifier, size, sb_enc, - GNUNET_BLOCK_TYPE_FS_SBLOCK, bo->content_priority, + + psc->dqe = GNUNET_DATASTORE_put (psc->dsh, 0, &query, size, ub_enc, + GNUNET_BLOCK_TYPE_FS_UBLOCK, bo->content_priority, bo->anonymity_level, bo->replication_level, bo->expiration_time, -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT, &sb_put_cont, psc); - GNUNET_free (sb); - GNUNET_free (sb_enc); + GNUNET_free (ub); + GNUNET_free (ub_enc); return psc; } diff --git a/src/fs/fs_namespace_advertise.c b/src/fs/fs_namespace_advertise.c deleted file mode 100644 index 554f616576..0000000000 --- a/src/fs/fs_namespace_advertise.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - This file is part of GNUnet - (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Christian Grothoff (and other contributing authors) - - GNUnet 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. - - 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file fs/fs_namespace_advertise.c - * @brief advertise namespaces (creating NBlocks) - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_constants.h" -#include "gnunet_signatures.h" -#include "gnunet_util_lib.h" -#include "gnunet_fs_service.h" -#include "fs_api.h" - - -/** - * Maximum legal size for an nblock. - */ -#define MAX_NBLOCK_SIZE (60 * 1024) - - -/** - * Context for advertising a namespace. - */ -struct GNUNET_FS_AdvertisementContext -{ - /** - * Function to call with the result. - */ - GNUNET_FS_PublishContinuation cont; - - /** - * Closure for cont. - */ - void *cont_cls; - - /** - * Datastore handle. - */ - struct GNUNET_DATASTORE_Handle *dsh; - - /** - * Our KSK URI. - */ - struct GNUNET_FS_Uri *ksk_uri; - - /** - * Plaintext. - */ - char *pt; - - /** - * NBlock to sign and store. - */ - struct NBlock *nb; - - /** - * The namespace. - */ - struct GNUNET_FS_Namespace *ns; - - /** - * Current datastore queue entry for advertising. - */ - struct GNUNET_DATASTORE_QueueEntry *dqe; - - /** - * Block options. - */ - struct GNUNET_FS_BlockOptions bo; - - /** - * Number of bytes of plaintext. - */ - size_t pt_size; - - /** - * Current keyword offset. - */ - unsigned int pos; -}; - - -// FIXME: I see no good reason why this should need to be done -// in a new task (anymore). Integrate with 'cancel' function below? -/** - * Disconnect from the datastore. - * - * @param cls datastore handle - * @param tc scheduler context - */ -static void -do_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_DATASTORE_Handle *dsh = cls; - - GNUNET_DATASTORE_disconnect (dsh, GNUNET_NO); -} - - -/** - * Continuation called to notify client about result of the - * operation. - * - * @param cls closure (our struct GNUNET_FS_AdvertismentContext) - * @param success GNUNET_SYSERR on failure - * @param min_expiration minimum expiration time required for content to be stored - * @param msg NULL on success, otherwise an error message - */ -static void -advertisement_cont (void *cls, int success, - struct GNUNET_TIME_Absolute min_expiration, - const char *msg) -{ - struct GNUNET_FS_AdvertisementContext *ac = cls; - const char *keyword; - struct GNUNET_HashCode key; - struct GNUNET_HashCode query; - struct GNUNET_CRYPTO_AesSessionKey skey; - struct GNUNET_CRYPTO_AesInitializationVector iv; - struct GNUNET_CRYPTO_RsaPrivateKey *pk; - - ac->dqe = NULL; - if (GNUNET_SYSERR == success) - { - /* error! */ - (void) GNUNET_SCHEDULER_add_now (&do_disconnect, ac->dsh); - ac->dsh = NULL; - if (msg == NULL) - { - GNUNET_break (0); - msg = _("Unknown error"); - } - if (ac->cont != NULL) - { - ac->cont (ac->cont_cls, NULL, msg); - ac->cont = NULL; - } - GNUNET_FS_namespace_advertise_cancel (ac); - return; - } - if (ac->pos == ac->ksk_uri->data.ksk.keywordCount) - { - /* done! */ - (void) GNUNET_SCHEDULER_add_now (&do_disconnect, ac->dsh); - ac->dsh = NULL; - if (ac->cont != NULL) - { - ac->cont (ac->cont_cls, ac->ksk_uri, NULL); - ac->cont = NULL; - } - GNUNET_FS_namespace_advertise_cancel (ac); - return; - } - keyword = ac->ksk_uri->data.ksk.keywords[ac->pos++]; - /* first character of keyword indicates if it is - * mandatory or not -- ignore for hashing */ - GNUNET_CRYPTO_hash (&keyword[1], strlen (&keyword[1]), &key); - GNUNET_CRYPTO_hash_to_aes_key (&key, &skey, &iv); - GNUNET_CRYPTO_aes_encrypt (ac->pt, ac->pt_size, &skey, &iv, &ac->nb[1]); - GNUNET_break (GNUNET_OK == - GNUNET_CRYPTO_rsa_sign (ac->ns->key, &ac->nb->ns_purpose, - &ac->nb->ns_signature)); - pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&key); - GNUNET_assert (pk != NULL); - GNUNET_CRYPTO_rsa_key_get_public (pk, &ac->nb->keyspace); - GNUNET_CRYPTO_hash (&ac->nb->keyspace, - sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &query); - GNUNET_break (GNUNET_OK == - GNUNET_CRYPTO_rsa_sign (pk, &ac->nb->ksk_purpose, - &ac->nb->ksk_signature)); - GNUNET_CRYPTO_rsa_key_free (pk); - ac->dqe = GNUNET_DATASTORE_put (ac->dsh, 0 /* no reservation */ , - &query, ac->pt_size + sizeof (struct NBlock), ac->nb, - GNUNET_BLOCK_TYPE_FS_NBLOCK, ac->bo.content_priority, - ac->bo.anonymity_level, ac->bo.replication_level, - ac->bo.expiration_time, -2, 1, - GNUNET_CONSTANTS_SERVICE_TIMEOUT, &advertisement_cont, - ac); -} - - -/** - * Create an SKS uri that points to the root entry of the namespace, - * then insert that SKS uri into metadata. - * - * @param ns handle for the namespace that should be advertised - * @param meta meta-data into which namespace advertisement should be inserted - * @param rootEntry name of the root of the namespace (use NULL to use default) - * @return GNUNET_OK on success, GNUNET_SYSERR on error - */ -int -GNUNET_FS_namespace_insert_advertisement_into_metadata ( - struct GNUNET_FS_Namespace *ns, struct GNUNET_CONTAINER_MetaData *meta, - const char *rootEntry) -{ - struct GNUNET_FS_Uri *sks_uri; - char *emsg; - char *sks_uri_string; - int md_insert; - - if (NULL == rootEntry) - rootEntry = "/"; - - emsg = NULL; - sks_uri = GNUNET_FS_uri_sks_create (ns, rootEntry, &emsg); - GNUNET_free_non_null (emsg); - if (NULL == sks_uri) - return GNUNET_SYSERR; - - sks_uri_string = GNUNET_FS_uri_to_string (sks_uri); - GNUNET_FS_uri_destroy (sks_uri); - if (NULL == sks_uri_string) - return GNUNET_SYSERR; - - md_insert = GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>", - EXTRACTOR_METATYPE_URI, EXTRACTOR_METAFORMAT_UTF8, - "text/plain", sks_uri_string, strlen (sks_uri_string) + 1); - GNUNET_free (sks_uri_string); - return md_insert; -} - -/** - * Publish an advertismement for a namespace. - * - * @param h handle to the file sharing subsystem - * @param ksk_uri keywords to use for advertisment - * @param ns handle for the namespace that should be advertised - * @param meta meta-data for the namespace advertisement - * @param bo block options - * @param rootEntry name of the root of the namespace - * @param cont continuation - * @param cont_cls closure for cont - * @return NULL on error ('cont' is still called) - */ -struct GNUNET_FS_AdvertisementContext * -GNUNET_FS_namespace_advertise (struct GNUNET_FS_Handle *h, - struct GNUNET_FS_Uri *ksk_uri, - struct GNUNET_FS_Namespace *ns, - const struct GNUNET_CONTAINER_MetaData *meta, - const struct GNUNET_FS_BlockOptions *bo, - const char *rootEntry, - GNUNET_FS_PublishContinuation cont, - void *cont_cls) -{ - size_t reslen; - size_t size; - ssize_t mdsize; - struct NBlock *nb; - char *mdst; - struct GNUNET_DATASTORE_Handle *dsh; - struct GNUNET_FS_AdvertisementContext *ctx; - char *pt; - - /* create advertisements */ - mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta); - if (-1 == mdsize) - { - cont (cont_cls, NULL, _("Failed to serialize meta data")); - return NULL; - } - reslen = strlen (rootEntry) + 1; - size = mdsize + sizeof (struct NBlock) + reslen; - if (size > MAX_NBLOCK_SIZE) - { - size = MAX_NBLOCK_SIZE; - mdsize = size - sizeof (struct NBlock) - reslen; - } - - pt = GNUNET_malloc (mdsize + reslen); - memcpy (pt, rootEntry, reslen); - mdst = &pt[reslen]; - mdsize = - GNUNET_CONTAINER_meta_data_serialize (meta, &mdst, mdsize, - GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); - if (-1 == mdsize) - { - GNUNET_break (0); - GNUNET_free (pt); - cont (cont_cls, NULL, _("Failed to serialize meta data")); - return NULL; - } - size = mdsize + sizeof (struct NBlock) + reslen; - nb = GNUNET_malloc (size); - GNUNET_CRYPTO_rsa_key_get_public (ns->key, &nb->subspace); - nb->ns_purpose.size = - htonl (mdsize + reslen + - sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + - sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); - nb->ns_purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK); - nb->ksk_purpose.size = - htonl (size - sizeof (struct GNUNET_CRYPTO_RsaSignature)); - nb->ksk_purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK_KSIG); - dsh = GNUNET_DATASTORE_connect (h->cfg); - if (NULL == dsh) - { - GNUNET_free (nb); - GNUNET_free (pt); - cont (cont_cls, NULL, _("Failed to connect to datastore service")); - return NULL; - } - ctx = GNUNET_malloc (sizeof (struct GNUNET_FS_AdvertisementContext)); - ctx->cont = cont; - ctx->cont_cls = cont_cls; - ctx->dsh = dsh; - ctx->ksk_uri = GNUNET_FS_uri_dup (ksk_uri); - ctx->nb = nb; - ctx->pt = pt; - ctx->pt_size = mdsize + reslen; - ctx->ns = ns; - ctx->ns->rc++; - ctx->bo = *bo; - advertisement_cont (ctx, GNUNET_OK, GNUNET_TIME_UNIT_ZERO_ABS, NULL); - return ctx; -} - - -/** - * Abort the namespace advertisement operation. - * - * @param ac context of the operation to abort. - */ -void -GNUNET_FS_namespace_advertise_cancel (struct GNUNET_FS_AdvertisementContext *ac) -{ - if (NULL != ac->dqe) - { - GNUNET_DATASTORE_cancel (ac->dqe); - ac->dqe = NULL; - } - if (NULL != ac->dsh) - { - GNUNET_DATASTORE_disconnect (ac->dsh, GNUNET_NO); - ac->dsh = NULL; - } - GNUNET_FS_uri_destroy (ac->ksk_uri); - GNUNET_free (ac->pt); - GNUNET_free (ac->nb); - GNUNET_FS_namespace_delete (ac->ns |