2 This file is part of GNUnet
3 (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file fs/fs_namespace.c
23 * @brief create and destroy namespaces
24 * @author Christian Grothoff
27 #include "gnunet_fs_service.h"
31 * Publish an advertismement for a namespace.
33 * @param h handle to the file sharing subsystem
34 * @param namespace handle for the namespace that should be advertised
35 * @param meta meta-data for the namespace advertisement
36 * @param anonymity for the namespace advertismement
37 * @param priority for the namespace advertisement
38 * @param expiration for the namespace advertisement
39 * @param advertisementURI the keyword (!) URI to advertise the
40 * namespace under (we will create a GNUNET_EC_KNBlock)
41 * @param rootEntry name of the root entry in the namespace (for
42 * the namespace advertisement)
44 * @return uri of the advertisement
46 struct GNUNET_FS_Uri *
47 GNUNET_FS_namespace_advertise (struct GNUNET_FS_Handle *h,
48 struct GNUNET_FS_Namespace *namespace,
49 const struct GNUNET_CONTAINER_MetaData *meta,
52 struct GNUNET_TIME_Absolute expiration,
53 const struct GNUNET_FS_Uri *advertisementURI,
54 const char *rootEntry)
62 * Create a namespace with the given name; if one already
63 * exists, return a handle to the existing namespace.
65 * @param h handle to the file sharing subsystem
66 * @param name name to use for the namespace
67 * @return handle to the namespace, NULL on error
69 struct GNUNET_FS_Namespace *
70 GNUNET_FS_namespace_create (struct GNUNET_FS_Handle *h,
79 * Delete a namespace handle. Can be used for a clean shutdown (free
80 * memory) or also to freeze the namespace to prevent further
81 * insertions by anyone.
83 * @param namespace handle to the namespace that should be deleted / freed
84 * @param freeze prevents future insertions; creating a namespace
85 * with the same name again will create a fresh namespace instead
87 * @return GNUNET_OK on success, GNUNET_SYSERR on error
90 GNUNET_FS_namespace_delete (struct GNUNET_FS_Namespace *namespace,
99 * Build a list of all available local (!) namespaces The returned
100 * names are only the nicknames since we only iterate over the local
103 * @param h handle to the file sharing subsystem
104 * @param cb function to call on each known namespace
105 * @param cb_cls closure for cb
108 GNUNET_FS_namespace_list (struct GNUNET_FS_Handle *h,
109 GNUNET_FS_NamespaceInfoProcessor cb,
115 /* end of fs_namespace.c */
119 This file is part of GNUnet
120 (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
122 GNUnet is free software; you can redistribute it and/or modify
123 it under the terms of the GNU General Public License as published
124 by the Free Software Foundation; either version 2, or (at your
125 option) any later version.
127 GNUnet is distributed in the hope that it will be useful, but
128 WITHOUT ANY WARRANTY; without even the implied warranty of
129 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
130 General Public License for more details.
132 You should have received a copy of the GNU General Public License
133 along with GNUnet; see the file COPYING. If not, write to the
134 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
135 Boston, MA 02111-1307, USA.
139 * @file applications/fs/ecrs/namespace.c
140 * @brief creation, deletion and advertising of namespaces
141 * @author Christian Grothoff
144 #include "platform.h"
145 #include "gnunet_directories.h"
146 #include "gnunet_protocols.h"
147 #include "gnunet_ecrs_lib.h"
148 #include "gnunet_fs_lib.h"
149 #include "ecrs_core.h"
152 #define PSEUDODIR "data/namespace/keys/"
153 #define INITVALUE "GNUnet!!"
154 #define MAX_SBLOCK_SIZE 32000
157 getPseudonymFileName (struct GNUNET_GE_Context *ectx,
158 struct GNUNET_GC_Configuration *cfg,
159 const GNUNET_HashCode * pid)
165 GNUNET_GC_get_configuration_value_filename (cfg,
168 GNUNET_DEFAULT_HOME_DIRECTORY,
170 gnHome = GNUNET_expand_file_name (ectx, fileName);
171 GNUNET_free (fileName);
173 GNUNET_malloc (strlen (gnHome) + strlen (PSEUDODIR) +
174 sizeof (GNUNET_EncName) + 2);
175 strcpy (fileName, gnHome);
176 GNUNET_free (gnHome);
177 strcat (fileName, DIR_SEPARATOR_STR);
178 strcat (fileName, PSEUDODIR);
179 GNUNET_disk_directory_create (ectx, fileName);
182 GNUNET_hash_to_enc (pid, &enc);
183 strcat (fileName, (char *) &enc);
190 * Check if the given namespace exists (locally).
192 * @return GNUNET_OK if the namespace exists, GNUNET_SYSERR if not
195 GNUNET_ECRS_namespace_test_exists (struct GNUNET_GE_Context *ectx,
196 struct GNUNET_GC_Configuration *cfg,
197 const GNUNET_HashCode * pid)
202 fileName = getPseudonymFileName (ectx, cfg, pid);
203 ret = GNUNET_disk_file_test (ectx, fileName);
204 GNUNET_free (fileName);
209 * Delete a local namespace.
211 * @return GNUNET_OK on success, GNUNET_SYSERR on error
214 GNUNET_ECRS_namespace_delete (struct GNUNET_GE_Context *ectx,
215 struct GNUNET_GC_Configuration *cfg,
216 const GNUNET_HashCode * pid)
220 fileName = getPseudonymFileName (ectx, cfg, pid);
221 if (GNUNET_YES != GNUNET_disk_file_test (ectx, fileName))
223 GNUNET_free (fileName);
224 return GNUNET_SYSERR; /* no such namespace */
226 if (0 != UNLINK (fileName))
228 GNUNET_GE_LOG_STRERROR_FILE (ectx,
229 GNUNET_GE_WARNING | GNUNET_GE_USER |
230 GNUNET_GE_BULK, "unlink", fileName);
231 GNUNET_free (fileName);
232 return GNUNET_SYSERR;
234 GNUNET_free (fileName);
239 * Write the private key of the namespace to a file.
242 write_namespace_key (struct GNUNET_GC_Configuration *cfg,
243 const struct GNUNET_RSA_PrivateKey *key)
245 GNUNET_RSA_PrivateKeyEncoded *namespace_priv_key_encoded;
247 GNUNET_RSA_PublicKey pubk;
250 GNUNET_RSA_get_public_key (key, &pubk);
251 GNUNET_hash (&pubk, sizeof (GNUNET_RSA_PublicKey), &pid);
252 fileName = getPseudonymFileName (NULL, cfg, &pid);
253 if (GNUNET_YES == GNUNET_disk_file_test (NULL, fileName))
255 GNUNET_GE_BREAK (NULL, 0); /* hash collision!? */
256 GNUNET_free (fileName);
257 return GNUNET_SYSERR;
259 namespace_priv_key_encoded = GNUNET_RSA_encode_key (key);
260 GNUNET_disk_file_write (NULL, fileName,
261 (const char *) namespace_priv_key_encoded,
262 ntohs (namespace_priv_key_encoded->len), "600");
263 GNUNET_free (fileName);
264 GNUNET_free (namespace_priv_key_encoded);
269 * Create a new namespace (and publish an advertismement).
270 * This publishes both an GNUNET_EC_NBlock in the namespace itself
271 * as well as KNBlocks under all keywords specified in
272 * the advertisementURI.
274 * @param anonymity_level for the namespace advertismement
275 * @param priority for the namespace advertisement
276 * @param expiration for the namespace advertisement
277 * @param advertisementURI the keyword (!) URI to advertise the
278 * namespace under (GNUNET_EC_KNBlock)
279 * @param meta meta-data for the namespace advertisement
280 * (will be used to derive a name)
281 * @param rootEntry name of the root entry in the namespace (for
282 * the namespace advertisement)
283 * @param rootURI set to the URI of the namespace, NULL if
284 * no advertisement was created
286 * @return URI on success, NULL on error
288 struct GNUNET_ECRS_URI *
289 GNUNET_ECRS_namespace_create (struct GNUNET_GE_Context *ectx,
290 struct GNUNET_GC_Configuration *cfg,
291 const struct GNUNET_CONTAINER_MetaData *meta,
292 uint32_t anonymityLevel,
294 GNUNET_CronTime expiration,
295 const struct GNUNET_ECRS_URI *advertisementURI,
296 const char *rootEntry)
298 struct GNUNET_ECRS_URI *rootURI;
299 struct GNUNET_RSA_PrivateKey *namespace_priv_key;
301 struct GNUNET_ClientServerConnection *sock;
302 GNUNET_DatastoreValue *value;
303 GNUNET_DatastoreValue *knvalue;
306 struct GNUNET_RSA_PrivateKey *pk;
307 GNUNET_EC_SBlock *sb;
308 GNUNET_EC_KSBlock *ksb;
311 unsigned int keywordCount;
316 if ((advertisementURI != NULL)
317 && (!GNUNET_ECRS_uri_test_ksk (advertisementURI)))
319 GNUNET_GE_BREAK (ectx, 0);
322 namespace_priv_key = GNUNET_RSA_create_key ();
323 if (GNUNET_OK != write_namespace_key (cfg, namespace_priv_key))
325 GNUNET_RSA_free_key (namespace_priv_key);
329 /* create advertisements */
330 mdsize = GNUNET_meta_data_get_serialized_size (meta, GNUNET_SERIALIZE_PART);
331 size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (rootEntry) + 2;
332 if (size > MAX_SBLOCK_SIZE)
334 size = MAX_SBLOCK_SIZE;
335 mdsize = size - sizeof (GNUNET_EC_SBlock) - strlen (rootEntry) - 2;
337 value = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
338 memset (value, 0, sizeof (GNUNET_DatastoreValue) + size);
339 sb = (GNUNET_EC_SBlock *) & value[1];
340 sb->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
341 GNUNET_RSA_get_public_key (namespace_priv_key, &sb->subspace);
342 rtgt = (char *) &sb[1];
343 memcpy (rtgt, rootEntry, strlen (rootEntry) + 1);
344 mdsize = GNUNET_meta_data_serialize (ectx,
346 &rtgt[strlen (rootEntry) + 2],
347 mdsize, GNUNET_SERIALIZE_PART);
350 GNUNET_GE_BREAK (ectx, 0);
351 GNUNET_RSA_free_key (namespace_priv_key);
355 size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (rootEntry) + 2;
356 GNUNET_GE_ASSERT (ectx,
357 GNUNET_OK == GNUNET_RSA_sign (namespace_priv_key,
361 (GNUNET_RSA_Signature) -
363 (GNUNET_RSA_PublicKey) -
364 sizeof (unsigned int),
367 value->size = htonl (sizeof (GNUNET_DatastoreValue) + size);
368 value->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
369 value->priority = htonl (priority);
370 value->anonymity_level = htonl (anonymityLevel);
371 value->expiration_time = GNUNET_htonll (expiration);
372 sock = GNUNET_client_connection_create (ectx, cfg);
376 GNUNET_RSA_free_key (namespace_priv_key);
379 if (GNUNET_OK != GNUNET_FS_insert (sock, value))
382 GNUNET_client_connection_destroy (sock);
383 GNUNET_RSA_free_key (namespace_priv_key);
388 /* publish KNBlocks */
389 size += sizeof (GNUNET_EC_KSBlock) - sizeof (GNUNET_EC_SBlock);
390 knvalue = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
392 knvalue->type = htonl (GNUNET_ECRS_BLOCKTYPE_KEYWORD_SIGNED);
393 knvalue->size = htonl (sizeof (GNUNET_DatastoreValue) + size);
394 ksb = (GNUNET_EC_KSBlock *) & knvalue[1];
395 ksb->type = htonl (GNUNET_ECRS_BLOCKTYPE_KEYWORD_SIGNED);
396 memcpy (&ksb->sblock,
397 sb, sizeof (GNUNET_EC_SBlock) + mdsize + strlen (rootEntry) + 2);
399 if (advertisementURI != NULL)
401 keywords = advertisementURI->data.ksk.keywords;
402 keywordCount = advertisementURI->data.ksk.keywordCount;
404 GNUNET_malloc (size - sizeof (GNUNET_EC_KBlock) -
405 sizeof (unsigned int));
408 size - sizeof (GNUNET_EC_KBlock) - sizeof (unsigned int));
409 for (i = 0; i < keywordCount; i++)
411 keyword = keywords[i];
412 /* first character of keyword indicates
413 mandatory or not -- ignore for hashing! */
414 GNUNET_hash (&keyword[1], strlen (&keyword[1]), &hc);
415 pk = GNUNET_RSA_create_key_from_hash (&hc);
416 GNUNET_RSA_get_public_key (pk, &ksb->kblock.keyspace);
417 GNUNET_GE_ASSERT (ectx,
418 size - sizeof (GNUNET_EC_KBlock) -
419 sizeof (unsigned int) ==
420 sizeof (GNUNET_EC_SBlock) + mdsize +
421 strlen (rootEntry) + 2);
422 GNUNET_ECRS_encryptInPlace (&hc, &ksb->sblock,
423 size - sizeof (GNUNET_EC_KBlock) -
424 sizeof (unsigned int));
426 GNUNET_GE_ASSERT (ectx,
427 GNUNET_OK == GNUNET_RSA_sign (pk,
436 /* extra check: verify sig */
437 GNUNET_RSA_free_key (pk);
438 if (GNUNET_OK != GNUNET_FS_insert (sock, knvalue))
440 GNUNET_GE_BREAK (ectx, 0);
442 GNUNET_free (knvalue);
444 GNUNET_client_connection_destroy (sock);
445 GNUNET_RSA_free_key (namespace_priv_key);
448 /* restore nblock to avoid re-encryption! */
449 memcpy (&ksb->sblock,
451 size - sizeof (GNUNET_EC_KBlock) - sizeof (unsigned int));
455 rootURI = GNUNET_malloc (sizeof (URI));
457 GNUNET_hash (&sb->subspace,
458 sizeof (GNUNET_RSA_PublicKey), &rootURI->data.sks.namespace);
459 rootURI->data.sks.identifier = GNUNET_strdup (rootEntry);
460 GNUNET_free (knvalue);
462 GNUNET_client_connection_destroy (sock);
463 GNUNET_RSA_free_key (namespace_priv_key);
468 static struct GNUNET_RSA_PrivateKey *
469 read_namespace_key (struct GNUNET_GC_Configuration *cfg,
470 const GNUNET_HashCode * pid)
473 GNUNET_RSA_PrivateKeyEncoded *hke;
474 struct GNUNET_RSA_PrivateKey *hk;
476 unsigned long long len;
478 fileName = getPseudonymFileName (NULL, cfg, pid);
479 if (GNUNET_OK != GNUNET_disk_file_size (NULL, fileName, &len, GNUNET_YES))
481 GNUNET_free (fileName);
486 GNUNET_GE_LOG (NULL, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
487 _("File `%s' does not contain a pseudonym.\n"),
489 GNUNET_free (fileName);
492 dst = GNUNET_malloc (len);
493 len = GNUNET_disk_file_read (NULL, fileName, len, dst);
494 hke = (GNUNET_RSA_PrivateKeyEncoded *) dst;
495 if (ntohs (hke->len) != len)
497 GNUNET_GE_LOG (NULL, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
498 _("Format of pseudonym `%s' is invalid.\n"), fileName);
499 GNUNET_free (fileName);
503 GNUNET_free (fileName);
504 hk = GNUNET_RSA_decode_key (hke);
511 * Add an entry into a namespace.
513 * @param dstU to which URI should the namespace entry refer?
514 * @param md what meta-data should be associated with the
516 * @param thisId name of this entry in the namespace (keyword/identifier)
517 * @param nextId name of the update for this entry (to be published in
518 * the future; maybe NULL)
519 * @param pid unique identifier of the namespace/pseudonym
520 * @return URI on success, NULL on error
522 struct GNUNET_ECRS_URI *
523 GNUNET_ECRS_namespace_add_content (struct GNUNET_GE_Context *ectx,
524 struct GNUNET_GC_Configuration *cfg,
525 const GNUNET_HashCode * pid,
526 uint32_t anonymityLevel,
528 GNUNET_CronTime expiration,
531 const struct GNUNET_ECRS_URI *dstU,
532 const struct GNUNET_MetaData *md)
534 struct GNUNET_ECRS_URI *uri;
535 struct GNUNET_ClientServerConnection *sock;
536 GNUNET_DatastoreValue *value;
539 struct GNUNET_RSA_PrivateKey *hk;
540 GNUNET_EC_SBlock *sb;
543 GNUNET_HashCode hc; /* hash of thisId = key */
544 GNUNET_HashCode hc2; /* hash of hc = identifier */
548 hk = read_namespace_key (cfg, pid);
552 /* THEN: construct GNUNET_EC_SBlock */
553 dstURI = GNUNET_ECRS_uri_to_string (dstU);
554 mdsize = GNUNET_meta_data_get_serialized_size (md, GNUNET_SERIALIZE_PART);
557 nidlen = strlen (nextId) + 1;
558 size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (dstURI) + 1 + nidlen;
559 if (size > MAX_SBLOCK_SIZE)
561 size = MAX_SBLOCK_SIZE;
563 size - (sizeof (GNUNET_EC_SBlock) + strlen (dstURI) + 1 + nidlen);
565 value = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
566 sb = (GNUNET_EC_SBlock *) & value[1];
567 sb->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
568 destPos = (char *) &sb[1];
569 memcpy (destPos, nextId, nidlen);
571 memcpy (destPos, dstURI, strlen (dstURI) + 1);
572 destPos += strlen (dstURI) + 1;
573 mdsize = GNUNET_meta_data_serialize (ectx,
576 mdsize, GNUNET_SERIALIZE_PART);
579 GNUNET_GE_BREAK (ectx, 0);
580 GNUNET_free (dstURI);
581 GNUNET_RSA_free_key (hk);
585 size = sizeof (GNUNET_EC_SBlock) + mdsize + strlen (dstURI) + 1 + nidlen;
586 value->size = htonl (sizeof (GNUNET_DatastoreValue) + size);
587 value->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
588 value->priority = htonl (priority);
589 value->anonymity_level = htonl (anonymityLevel);
590 value->expiration_time = GNUNET_htonll (expiration);
591 GNUNET_hash (thisId, strlen (thisId), &hc);
592 GNUNET_hash (&hc, sizeof (GNUNET_HashCode), &hc2);
593 uri = GNUNET_malloc (sizeof (URI));
595 GNUNET_RSA_get_public_key (hk, &sb->subspace);
596 GNUNET_hash (&sb->subspace,
597 sizeof (GNUNET_RSA_PublicKey), &uri->data.sks.namespace);
598 GNUNET_GE_BREAK (ectx, 0 == memcmp (&uri->data.sks.namespace,
599 pid, sizeof (GNUNET_HashCode)));
600 uri->data.sks.identifier = GNUNET_strdup (thisId);
601 GNUNET_hash_xor (&hc2, &uri->data.sks.namespace, &sb->identifier);
602 GNUNET_ECRS_encryptInPlace (&hc, &sb[1], size - sizeof (GNUNET_EC_SBlock));
603 GNUNET_GE_ASSERT (ectx,
604 GNUNET_OK == GNUNET_RSA_sign (hk,
608 (GNUNET_RSA_Signature) -
610 (GNUNET_RSA_PublicKey) -
611 sizeof (unsigned int),
614 GNUNET_RSA_free_key (hk);
615 sock = GNUNET_client_connection_create (ectx, cfg);
616 ret = GNUNET_FS_insert (sock, value);
617 if (ret != GNUNET_OK)
622 GNUNET_client_connection_destroy (sock);
624 GNUNET_free (dstURI);
631 struct GNUNET_GE_Context *ectx;
632 struct GNUNET_GC_Configuration *cfg;
633 GNUNET_ECRS_NamespaceInfoProcessor cb;
639 processFile_ (void *cls, const char *fileName)
641 struct lNCLS *c = cls;
642 struct GNUNET_RSA_PrivateKey *hk;
643 GNUNET_RSA_PrivateKeyEncoded *hke;
645 unsigned long long len;
646 GNUNET_HashCode namespace;
647 GNUNET_RSA_PublicKey pk;
651 GNUNET_disk_file_size (c->ectx, fileName, &len, GNUNET_YES))
655 GNUNET_GE_LOG (c->ectx,
656 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
657 _("Format of file `%s' is invalid, trying to remove.\n"),
662 dst = GNUNET_malloc (len);
663 len = GNUNET_disk_file_read (c->ectx, fileName, len, dst);
664 hke = (GNUNET_RSA_PrivateKeyEncoded *) dst;
665 if (ntohs (hke->len) != len)
667 GNUNET_GE_LOG (c->ectx,
668 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
669 _("Format of file `%s' is invalid, trying to remove.\n"),
675 hk = GNUNET_RSA_decode_key (hke);
679 GNUNET_GE_LOG (c->ectx,
680 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
681 _("Format of file `%s' is invalid, trying to remove.\n"),
684 GNUNET_GE_BREAK (c->ectx, 0);
685 return GNUNET_SYSERR;
687 GNUNET_RSA_get_public_key (hk, &pk);
688 GNUNET_RSA_free_key (hk);
689 GNUNET_hash (&pk, sizeof (GNUNET_RSA_PublicKey), &namespace);
693 while (NULL != strstr (name, DIR_SEPARATOR_STR))
694 name = 1 + strstr (name, DIR_SEPARATOR_STR);
695 if (GNUNET_OK == c->cb (&namespace, name, c->cls))
698 c->cnt = GNUNET_SYSERR;
706 * Build a list of all available namespaces
708 * @param list where to store the names (is allocated, caller frees)
709 * @return GNUNET_SYSERR on error, otherwise the number of pseudonyms in list
712 GNUNET_ECRS_get_namespaces (struct GNUNET_GE_Context *ectx,
713 struct GNUNET_GC_Configuration *cfg,
714 GNUNET_ECRS_NamespaceInfoProcessor cb, void *cls)
724 dirName = getPseudonymFileName (ectx, cfg, NULL);
725 GNUNET_disk_directory_scan (ectx, dirName, &processFile_, &myCLS);
726 GNUNET_free (dirName);
732 /* end of namespace.c */