fix
[oweals/gnunet.git] / src / fs / fs_namespace.c
1 /*
2      This file is part of GNUnet
3      (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19 */
20
21 /**
22  * @file fs/fs_namespace.c
23  * @brief create and destroy namespaces
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_fs_service.h"
28
29
30 /**
31  * Publish an advertismement for a namespace.  
32  *
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)
43  *
44  * @return uri of the advertisement
45  */
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,
50                                uint32_t anonymity,
51                                uint32_t priority,
52                                struct GNUNET_TIME_Absolute expiration,
53                                const struct GNUNET_FS_Uri *advertisementURI,
54                                const char *rootEntry)
55 {
56   GNUNET_break (0);
57   return NULL;
58 }
59
60
61 /**
62  * Create a namespace with the given name; if one already
63  * exists, return a handle to the existing namespace.
64  *
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
68  */
69 struct GNUNET_FS_Namespace *
70 GNUNET_FS_namespace_create (struct GNUNET_FS_Handle *h,
71                             const char *name)
72 {
73   GNUNET_break (0);
74   return NULL;
75 }
76
77
78 /**
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.
82  *
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
86  *
87  * @return GNUNET_OK on success, GNUNET_SYSERR on error
88  */
89 int 
90 GNUNET_FS_namespace_delete (struct GNUNET_FS_Namespace *namespace,
91                             int freeze)
92 {
93   GNUNET_break (0);
94   return GNUNET_SYSERR;
95 }
96
97
98 /**
99  * Build a list of all available local (!) namespaces The returned
100  * names are only the nicknames since we only iterate over the local
101  * namespaces.
102  *
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
106  */
107 void 
108 GNUNET_FS_namespace_list (struct GNUNET_FS_Handle *h,
109                           GNUNET_FS_NamespaceInfoProcessor cb,
110                           void *cb_cls)
111 {
112   GNUNET_break (0);
113 }
114
115 /* end of fs_namespace.c */
116
117 #if 0
118 /*
119      This file is part of GNUnet
120      (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
121
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.
126
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.
131
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.
136 */
137
138 /**
139  * @file applications/fs/ecrs/namespace.c
140  * @brief creation, deletion and advertising of namespaces
141  * @author Christian Grothoff
142  */
143
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"
150 #include "ecrs.h"
151
152 #define PSEUDODIR "data/namespace/keys/"
153 #define INITVALUE "GNUnet!!"
154 #define MAX_SBLOCK_SIZE 32000
155
156 static char *
157 getPseudonymFileName (struct GNUNET_GE_Context *ectx,
158                       struct GNUNET_GC_Configuration *cfg,
159                       const GNUNET_HashCode * pid)
160 {
161   char *gnHome;
162   char *fileName;
163   GNUNET_EncName enc;
164
165   GNUNET_GC_get_configuration_value_filename (cfg,
166                                               "GNUNET",
167                                               "GNUNET_HOME",
168                                               GNUNET_DEFAULT_HOME_DIRECTORY,
169                                               &fileName);
170   gnHome = GNUNET_expand_file_name (ectx, fileName);
171   GNUNET_free (fileName);
172   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);
180   if (pid != NULL)
181     {
182       GNUNET_hash_to_enc (pid, &enc);
183       strcat (fileName, (char *) &enc);
184     }
185   return fileName;
186 }
187
188
189 /**
190  * Check if the given namespace exists (locally).
191  *
192  * @return GNUNET_OK if the namespace exists, GNUNET_SYSERR if not
193  */
194 int
195 GNUNET_ECRS_namespace_test_exists (struct GNUNET_GE_Context *ectx,
196                                    struct GNUNET_GC_Configuration *cfg,
197                                    const GNUNET_HashCode * pid)
198 {
199   char *fileName;
200   int ret;
201
202   fileName = getPseudonymFileName (ectx, cfg, pid);
203   ret = GNUNET_disk_file_test (ectx, fileName);
204   GNUNET_free (fileName);
205   return ret;
206 }
207
208 /**
209  * Delete a local namespace.
210  *
211  * @return GNUNET_OK on success, GNUNET_SYSERR on error
212  */
213 int
214 GNUNET_ECRS_namespace_delete (struct GNUNET_GE_Context *ectx,
215                               struct GNUNET_GC_Configuration *cfg,
216                               const GNUNET_HashCode * pid)
217 {
218   char *fileName;
219
220   fileName = getPseudonymFileName (ectx, cfg, pid);
221   if (GNUNET_YES != GNUNET_disk_file_test (ectx, fileName))
222     {
223       GNUNET_free (fileName);
224       return GNUNET_SYSERR;     /* no such namespace */
225     }
226   if (0 != UNLINK (fileName))
227     {
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;
233     }
234   GNUNET_free (fileName);
235   return GNUNET_OK;
236 }
237
238 /**
239  * Write the private key of the namespace to a file.
240  */
241 static int
242 write_namespace_key (struct GNUNET_GC_Configuration *cfg,
243                      const struct GNUNET_RSA_PrivateKey *key)
244 {
245   GNUNET_RSA_PrivateKeyEncoded *namespace_priv_key_encoded;
246   char *fileName;
247   GNUNET_RSA_PublicKey pubk;
248   GNUNET_HashCode pid;
249
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))
254     {
255       GNUNET_GE_BREAK (NULL, 0);        /* hash collision!? */
256       GNUNET_free (fileName);
257       return GNUNET_SYSERR;
258     }
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);
265   return GNUNET_OK;
266 }
267
268 /**
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.
273  *
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
285  *
286  * @return URI on success, NULL on error
287  */
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,
293                               uint32_t priority,
294                               GNUNET_CronTime expiration,
295                               const struct GNUNET_ECRS_URI *advertisementURI,
296                               const char *rootEntry)
297 {
298   struct GNUNET_ECRS_URI *rootURI;
299   struct GNUNET_RSA_PrivateKey *namespace_priv_key;
300   GNUNET_HashCode hc;
301   struct GNUNET_ClientServerConnection *sock;
302   GNUNET_DatastoreValue *value;
303   GNUNET_DatastoreValue *knvalue;
304   unsigned int size;
305   unsigned int mdsize;
306   struct GNUNET_RSA_PrivateKey *pk;
307   GNUNET_EC_SBlock *sb;
308   GNUNET_EC_KSBlock *ksb;
309   char **keywords;
310   const char *keyword;
311   unsigned int keywordCount;
312   int i;
313   char *cpy;
314   char *rtgt;
315
316   if ((advertisementURI != NULL)
317       && (!GNUNET_ECRS_uri_test_ksk (advertisementURI)))
318     {
319       GNUNET_GE_BREAK (ectx, 0);
320       return NULL;
321     }
322   namespace_priv_key = GNUNET_RSA_create_key ();
323   if (GNUNET_OK != write_namespace_key (cfg, namespace_priv_key))
324     {
325       GNUNET_RSA_free_key (namespace_priv_key);
326       return NULL;
327     }
328
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)
333     {
334       size = MAX_SBLOCK_SIZE;
335       mdsize = size - sizeof (GNUNET_EC_SBlock) - strlen (rootEntry) - 2;
336     }
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,
345                                        meta,
346                                        &rtgt[strlen (rootEntry) + 2],
347                                        mdsize, GNUNET_SERIALIZE_PART);
348   if (mdsize == -1)
349     {
350       GNUNET_GE_BREAK (ectx, 0);
351       GNUNET_RSA_free_key (namespace_priv_key);
352       GNUNET_free (value);
353       return NULL;
354     }
355   size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (rootEntry) + 2;
356   GNUNET_GE_ASSERT (ectx,
357                     GNUNET_OK == GNUNET_RSA_sign (namespace_priv_key,
358                                                   size
359                                                   -
360                                                   sizeof
361                                                   (GNUNET_RSA_Signature) -
362                                                   sizeof
363                                                   (GNUNET_RSA_PublicKey) -
364                                                   sizeof (unsigned int),
365                                                   &sb->identifier,
366                                                   &sb->signature));
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);
373   if (sock == NULL)
374     {
375       GNUNET_free (value);
376       GNUNET_RSA_free_key (namespace_priv_key);
377       return NULL;
378     }
379   if (GNUNET_OK != GNUNET_FS_insert (sock, value))
380     {
381       GNUNET_free (value);
382       GNUNET_client_connection_destroy (sock);
383       GNUNET_RSA_free_key (namespace_priv_key);
384       return NULL;
385     }
386
387
388   /* publish KNBlocks */
389   size += sizeof (GNUNET_EC_KSBlock) - sizeof (GNUNET_EC_SBlock);
390   knvalue = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
391   *knvalue = *value;
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);
398
399   if (advertisementURI != NULL)
400     {
401       keywords = advertisementURI->data.ksk.keywords;
402       keywordCount = advertisementURI->data.ksk.keywordCount;
403       cpy =
404         GNUNET_malloc (size - sizeof (GNUNET_EC_KBlock) -
405                        sizeof (unsigned int));
406       memcpy (cpy,
407               &ksb->sblock,
408               size - sizeof (GNUNET_EC_KBlock) - sizeof (unsigned int));
409       for (i = 0; i < keywordCount; i++)
410         {
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));
425
426           GNUNET_GE_ASSERT (ectx,
427                             GNUNET_OK == GNUNET_RSA_sign (pk,
428                                                           size -
429                                                           sizeof
430                                                           (GNUNET_EC_KBlock) -
431                                                           sizeof (unsigned
432                                                                   int),
433                                                           &ksb->sblock,
434                                                           &ksb->
435                                                           kblock.signature));
436           /* extra check: verify sig */
437           GNUNET_RSA_free_key (pk);
438           if (GNUNET_OK != GNUNET_FS_insert (sock, knvalue))
439             {
440               GNUNET_GE_BREAK (ectx, 0);
441               GNUNET_free (cpy);
442               GNUNET_free (knvalue);
443               GNUNET_free (value);
444               GNUNET_client_connection_destroy (sock);
445               GNUNET_RSA_free_key (namespace_priv_key);
446               return NULL;
447             }
448           /* restore nblock to avoid re-encryption! */
449           memcpy (&ksb->sblock,
450                   cpy,
451                   size - sizeof (GNUNET_EC_KBlock) - sizeof (unsigned int));
452         }
453       GNUNET_free (cpy);
454     }
455   rootURI = GNUNET_malloc (sizeof (URI));
456   rootURI->type = sks;
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);
461   GNUNET_free (value);
462   GNUNET_client_connection_destroy (sock);
463   GNUNET_RSA_free_key (namespace_priv_key);
464
465   return rootURI;
466 }
467
468 static struct GNUNET_RSA_PrivateKey *
469 read_namespace_key (struct GNUNET_GC_Configuration *cfg,
470                     const GNUNET_HashCode * pid)
471 {
472   char *fileName;
473   GNUNET_RSA_PrivateKeyEncoded *hke;
474   struct GNUNET_RSA_PrivateKey *hk;
475   char *dst;
476   unsigned long long len;
477
478   fileName = getPseudonymFileName (NULL, cfg, pid);
479   if (GNUNET_OK != GNUNET_disk_file_size (NULL, fileName, &len, GNUNET_YES))
480     {
481       GNUNET_free (fileName);
482       return NULL;
483     }
484   if (len < 2)
485     {
486       GNUNET_GE_LOG (NULL, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
487                      _("File `%s' does not contain a pseudonym.\n"),
488                      fileName);
489       GNUNET_free (fileName);
490       return NULL;
491     }
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)
496     {
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);
500       GNUNET_free (hke);
501       return NULL;
502     }
503   GNUNET_free (fileName);
504   hk = GNUNET_RSA_decode_key (hke);
505   GNUNET_free (hke);
506   return hk;
507 }
508
509
510 /**
511  * Add an entry into a namespace.
512  *
513  * @param dstU to which URI should the namespace entry refer?
514  * @param md what meta-data should be associated with the
515  *        entry?
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
521  */
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,
527                                    uint32_t priority,
528                                    GNUNET_CronTime expiration,
529                                    const char *thisId,
530                                    const char *nextId,
531                                    const struct GNUNET_ECRS_URI *dstU,
532                                    const struct GNUNET_MetaData *md)
533 {
534   struct GNUNET_ECRS_URI *uri;
535   struct GNUNET_ClientServerConnection *sock;
536   GNUNET_DatastoreValue *value;
537   unsigned int size;
538   unsigned int mdsize;
539   struct GNUNET_RSA_PrivateKey *hk;
540   GNUNET_EC_SBlock *sb;
541   char *dstURI;
542   char *destPos;
543   GNUNET_HashCode hc;           /* hash of thisId = key */
544   GNUNET_HashCode hc2;          /* hash of hc = identifier */
545   int ret;
546   unsigned int nidlen;
547
548   hk = read_namespace_key (cfg, pid);
549   if (hk == NULL)
550     return NULL;
551
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);
555   if (nextId == NULL)
556     nextId = "";
557   nidlen = strlen (nextId) + 1;
558   size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (dstURI) + 1 + nidlen;
559   if (size > MAX_SBLOCK_SIZE)
560     {
561       size = MAX_SBLOCK_SIZE;
562       mdsize =
563         size - (sizeof (GNUNET_EC_SBlock) + strlen (dstURI) + 1 + nidlen);
564     }
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);
570   destPos += nidlen;
571   memcpy (destPos, dstURI, strlen (dstURI) + 1);
572   destPos += strlen (dstURI) + 1;
573   mdsize = GNUNET_meta_data_serialize (ectx,
574                                        md,
575                                        destPos,
576                                        mdsize, GNUNET_SERIALIZE_PART);
577   if (mdsize == -1)
578     {
579       GNUNET_GE_BREAK (ectx, 0);
580       GNUNET_free (dstURI);
581       GNUNET_RSA_free_key (hk);
582       GNUNET_free (value);
583       return NULL;
584     }
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));
594   uri->type = sks;
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,
605                                                   size
606                                                   -
607                                                   sizeof
608                                                   (GNUNET_RSA_Signature) -
609                                                   sizeof
610                                                   (GNUNET_RSA_PublicKey) -
611                                                   sizeof (unsigned int),
612                                                   &sb->identifier,
613                                                   &sb->signature));
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)
618     {
619       GNUNET_free (uri);
620       uri = NULL;
621     }
622   GNUNET_client_connection_destroy (sock);
623   GNUNET_free (value);
624   GNUNET_free (dstURI);
625
626   return uri;
627 }
628
629 struct lNCLS
630 {
631   struct GNUNET_GE_Context *ectx;
632   struct GNUNET_GC_Configuration *cfg;
633   GNUNET_ECRS_NamespaceInfoProcessor cb;
634   void *cls;
635   int cnt;
636 };
637
638 static int
639 processFile_ (void *cls, const char *fileName)
640 {
641   struct lNCLS *c = cls;
642   struct GNUNET_RSA_PrivateKey *hk;
643   GNUNET_RSA_PrivateKeyEncoded *hke;
644   char *dst;
645   unsigned long long len;
646   GNUNET_HashCode namespace;
647   GNUNET_RSA_PublicKey pk;
648   const char *name;
649
650   if (GNUNET_OK !=
651       GNUNET_disk_file_size (c->ectx, fileName, &len, GNUNET_YES))
652     return GNUNET_OK;
653   if (len < 2)
654     {
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"),
658                      fileName);
659       UNLINK (fileName);
660       return GNUNET_OK;
661     }
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)
666     {
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"),
670                      fileName);
671       UNLINK (fileName);
672       GNUNET_free (hke);
673       return GNUNET_OK;
674     }
675   hk = GNUNET_RSA_decode_key (hke);
676   GNUNET_free (hke);
677   if (hk == NULL)
678     {
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"),
682                      fileName);
683       UNLINK (fileName);
684       GNUNET_GE_BREAK (c->ectx, 0);
685       return GNUNET_SYSERR;
686     }
687   GNUNET_RSA_get_public_key (hk, &pk);
688   GNUNET_RSA_free_key (hk);
689   GNUNET_hash (&pk, sizeof (GNUNET_RSA_PublicKey), &namespace);
690   if (NULL != c->cb)
691     {
692       name = fileName;
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))
696         c->cnt++;
697       else
698         c->cnt = GNUNET_SYSERR;
699     }
700   else
701     c->cnt++;
702   return GNUNET_OK;
703 }
704
705 /**
706  * Build a list of all available namespaces
707  *
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
710  */
711 int
712 GNUNET_ECRS_get_namespaces (struct GNUNET_GE_Context *ectx,
713                             struct GNUNET_GC_Configuration *cfg,
714                             GNUNET_ECRS_NamespaceInfoProcessor cb, void *cls)
715 {
716   char *dirName;
717   struct lNCLS myCLS;
718
719   myCLS.cls = cls;
720   myCLS.cb = cb;
721   myCLS.cnt = 0;
722   myCLS.ectx = ectx;
723   myCLS.cfg = cfg;
724   dirName = getPseudonymFileName (ectx, cfg, NULL);
725   GNUNET_disk_directory_scan (ectx, dirName, &processFile_, &myCLS);
726   GNUNET_free (dirName);
727   return myCLS.cnt;
728 }
729
730
731
732 /* end of namespace.c */
733 #endif