work on downloading
[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   return NULL;
57 }
58
59
60 /**
61  * Create a namespace with the given name; if one already
62  * exists, return a handle to the existing namespace.
63  *
64  * @param h handle to the file sharing subsystem
65  * @param name name to use for the namespace
66  * @return handle to the namespace, NULL on error
67  */
68 struct GNUNET_FS_Namespace *
69 GNUNET_FS_namespace_create (struct GNUNET_FS_Handle *h,
70                             const char *name)
71 {
72   return NULL;
73 }
74
75
76 /**
77  * Delete a namespace handle.  Can be used for a clean shutdown (free
78  * memory) or also to freeze the namespace to prevent further
79  * insertions by anyone.
80  *
81  * @param namespace handle to the namespace that should be deleted / freed
82  * @param freeze prevents future insertions; creating a namespace
83  *        with the same name again will create a fresh namespace instead
84  *
85  * @return GNUNET_OK on success, GNUNET_SYSERR on error
86  */
87 int 
88 GNUNET_FS_namespace_delete (struct GNUNET_FS_Namespace *namespace,
89                             int freeze)
90 {
91   return GNUNET_SYSERR;
92 }
93
94
95 /**
96  * Build a list of all available local (!) namespaces The returned
97  * names are only the nicknames since we only iterate over the local
98  * namespaces.
99  *
100  * @param h handle to the file sharing subsystem
101  * @param cb function to call on each known namespace
102  * @param cb_cls closure for cb
103  */
104 void 
105 GNUNET_FS_namespace_list (struct GNUNET_FS_Handle *h,
106                           GNUNET_FS_NamespaceInfoProcessor cb,
107                           void *cb_cls)
108 {
109 }
110
111 /* end of fs_namespace.c */
112
113 #if 0
114 /*
115      This file is part of GNUnet
116      (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
117
118      GNUnet is free software; you can redistribute it and/or modify
119      it under the terms of the GNU General Public License as published
120      by the Free Software Foundation; either version 2, or (at your
121      option) any later version.
122
123      GNUnet is distributed in the hope that it will be useful, but
124      WITHOUT ANY WARRANTY; without even the implied warranty of
125      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
126      General Public License for more details.
127
128      You should have received a copy of the GNU General Public License
129      along with GNUnet; see the file COPYING.  If not, write to the
130      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
131      Boston, MA 02111-1307, USA.
132 */
133
134 /**
135  * @file applications/fs/ecrs/namespace.c
136  * @brief creation, deletion and advertising of namespaces
137  * @author Christian Grothoff
138  */
139
140 #include "platform.h"
141 #include "gnunet_directories.h"
142 #include "gnunet_protocols.h"
143 #include "gnunet_ecrs_lib.h"
144 #include "gnunet_fs_lib.h"
145 #include "ecrs_core.h"
146 #include "ecrs.h"
147
148 #define PSEUDODIR "data/namespace/keys/"
149 #define INITVALUE "GNUnet!!"
150 #define MAX_SBLOCK_SIZE 32000
151
152 static char *
153 getPseudonymFileName (struct GNUNET_GE_Context *ectx,
154                       struct GNUNET_GC_Configuration *cfg,
155                       const GNUNET_HashCode * pid)
156 {
157   char *gnHome;
158   char *fileName;
159   GNUNET_EncName enc;
160
161   GNUNET_GC_get_configuration_value_filename (cfg,
162                                               "GNUNET",
163                                               "GNUNET_HOME",
164                                               GNUNET_DEFAULT_HOME_DIRECTORY,
165                                               &fileName);
166   gnHome = GNUNET_expand_file_name (ectx, fileName);
167   GNUNET_free (fileName);
168   fileName =
169     GNUNET_malloc (strlen (gnHome) + strlen (PSEUDODIR) +
170                    sizeof (GNUNET_EncName) + 2);
171   strcpy (fileName, gnHome);
172   GNUNET_free (gnHome);
173   strcat (fileName, DIR_SEPARATOR_STR);
174   strcat (fileName, PSEUDODIR);
175   GNUNET_disk_directory_create (ectx, fileName);
176   if (pid != NULL)
177     {
178       GNUNET_hash_to_enc (pid, &enc);
179       strcat (fileName, (char *) &enc);
180     }
181   return fileName;
182 }
183
184
185 /**
186  * Check if the given namespace exists (locally).
187  *
188  * @return GNUNET_OK if the namespace exists, GNUNET_SYSERR if not
189  */
190 int
191 GNUNET_ECRS_namespace_test_exists (struct GNUNET_GE_Context *ectx,
192                                    struct GNUNET_GC_Configuration *cfg,
193                                    const GNUNET_HashCode * pid)
194 {
195   char *fileName;
196   int ret;
197
198   fileName = getPseudonymFileName (ectx, cfg, pid);
199   ret = GNUNET_disk_file_test (ectx, fileName);
200   GNUNET_free (fileName);
201   return ret;
202 }
203
204 /**
205  * Delete a local namespace.
206  *
207  * @return GNUNET_OK on success, GNUNET_SYSERR on error
208  */
209 int
210 GNUNET_ECRS_namespace_delete (struct GNUNET_GE_Context *ectx,
211                               struct GNUNET_GC_Configuration *cfg,
212                               const GNUNET_HashCode * pid)
213 {
214   char *fileName;
215
216   fileName = getPseudonymFileName (ectx, cfg, pid);
217   if (GNUNET_YES != GNUNET_disk_file_test (ectx, fileName))
218     {
219       GNUNET_free (fileName);
220       return GNUNET_SYSERR;     /* no such namespace */
221     }
222   if (0 != UNLINK (fileName))
223     {
224       GNUNET_GE_LOG_STRERROR_FILE (ectx,
225                                    GNUNET_GE_WARNING | GNUNET_GE_USER |
226                                    GNUNET_GE_BULK, "unlink", fileName);
227       GNUNET_free (fileName);
228       return GNUNET_SYSERR;
229     }
230   GNUNET_free (fileName);
231   return GNUNET_OK;
232 }
233
234 /**
235  * Write the private key of the namespace to a file.
236  */
237 static int
238 write_namespace_key (struct GNUNET_GC_Configuration *cfg,
239                      const struct GNUNET_RSA_PrivateKey *key)
240 {
241   GNUNET_RSA_PrivateKeyEncoded *namespace_priv_key_encoded;
242   char *fileName;
243   GNUNET_RSA_PublicKey pubk;
244   GNUNET_HashCode pid;
245
246   GNUNET_RSA_get_public_key (key, &pubk);
247   GNUNET_hash (&pubk, sizeof (GNUNET_RSA_PublicKey), &pid);
248   fileName = getPseudonymFileName (NULL, cfg, &pid);
249   if (GNUNET_YES == GNUNET_disk_file_test (NULL, fileName))
250     {
251       GNUNET_GE_BREAK (NULL, 0);        /* hash collision!? */
252       GNUNET_free (fileName);
253       return GNUNET_SYSERR;
254     }
255   namespace_priv_key_encoded = GNUNET_RSA_encode_key (key);
256   GNUNET_disk_file_write (NULL, fileName,
257                           (const char *) namespace_priv_key_encoded,
258                           ntohs (namespace_priv_key_encoded->len), "600");
259   GNUNET_free (fileName);
260   GNUNET_free (namespace_priv_key_encoded);
261   return GNUNET_OK;
262 }
263
264 /**
265  * Create a new namespace (and publish an advertismement).
266  * This publishes both an GNUNET_EC_NBlock in the namespace itself
267  * as well as KNBlocks under all keywords specified in
268  * the advertisementURI.
269  *
270  * @param anonymity_level for the namespace advertismement
271  * @param priority for the namespace advertisement
272  * @param expiration for the namespace advertisement
273  * @param advertisementURI the keyword (!) URI to advertise the
274  *        namespace under (GNUNET_EC_KNBlock)
275  * @param meta meta-data for the namespace advertisement
276  *        (will be used to derive a name)
277  * @param rootEntry name of the root entry in the namespace (for
278  *        the namespace advertisement)
279  * @param rootURI set to the URI of the namespace, NULL if
280  *        no advertisement was created
281  *
282  * @return URI on success, NULL on error
283  */
284 struct GNUNET_ECRS_URI *
285 GNUNET_ECRS_namespace_create (struct GNUNET_GE_Context *ectx,
286                               struct GNUNET_GC_Configuration *cfg,
287                               const struct GNUNET_CONTAINER_MetaData *meta,
288                               uint32_t anonymityLevel,
289                               uint32_t priority,
290                               GNUNET_CronTime expiration,
291                               const struct GNUNET_ECRS_URI *advertisementURI,
292                               const char *rootEntry)
293 {
294   struct GNUNET_ECRS_URI *rootURI;
295   struct GNUNET_RSA_PrivateKey *namespace_priv_key;
296   GNUNET_HashCode hc;
297   struct GNUNET_ClientServerConnection *sock;
298   GNUNET_DatastoreValue *value;
299   GNUNET_DatastoreValue *knvalue;
300   unsigned int size;
301   unsigned int mdsize;
302   struct GNUNET_RSA_PrivateKey *pk;
303   GNUNET_EC_SBlock *sb;
304   GNUNET_EC_KSBlock *ksb;
305   char **keywords;
306   const char *keyword;
307   unsigned int keywordCount;
308   int i;
309   char *cpy;
310   char *rtgt;
311
312   if ((advertisementURI != NULL)
313       && (!GNUNET_ECRS_uri_test_ksk (advertisementURI)))
314     {
315       GNUNET_GE_BREAK (ectx, 0);
316       return NULL;
317     }
318   namespace_priv_key = GNUNET_RSA_create_key ();
319   if (GNUNET_OK != write_namespace_key (cfg, namespace_priv_key))
320     {
321       GNUNET_RSA_free_key (namespace_priv_key);
322       return NULL;
323     }
324
325   /* create advertisements */
326   mdsize = GNUNET_meta_data_get_serialized_size (meta, GNUNET_SERIALIZE_PART);
327   size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (rootEntry) + 2;
328   if (size > MAX_SBLOCK_SIZE)
329     {
330       size = MAX_SBLOCK_SIZE;
331       mdsize = size - sizeof (GNUNET_EC_SBlock) - strlen (rootEntry) - 2;
332     }
333   value = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
334   memset (value, 0, sizeof (GNUNET_DatastoreValue) + size);
335   sb = (GNUNET_EC_SBlock *) & value[1];
336   sb->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
337   GNUNET_RSA_get_public_key (namespace_priv_key, &sb->subspace);
338   rtgt = (char *) &sb[1];
339   memcpy (rtgt, rootEntry, strlen (rootEntry) + 1);
340   mdsize = GNUNET_meta_data_serialize (ectx,
341                                        meta,
342                                        &rtgt[strlen (rootEntry) + 2],
343                                        mdsize, GNUNET_SERIALIZE_PART);
344   if (mdsize == -1)
345     {
346       GNUNET_GE_BREAK (ectx, 0);
347       GNUNET_RSA_free_key (namespace_priv_key);
348       GNUNET_free (value);
349       return NULL;
350     }
351   size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (rootEntry) + 2;
352   GNUNET_GE_ASSERT (ectx,
353                     GNUNET_OK == GNUNET_RSA_sign (namespace_priv_key,
354                                                   size
355                                                   -
356                                                   sizeof
357                                                   (GNUNET_RSA_Signature) -
358                                                   sizeof
359                                                   (GNUNET_RSA_PublicKey) -
360                                                   sizeof (unsigned int),
361                                                   &sb->identifier,
362                                                   &sb->signature));
363   value->size = htonl (sizeof (GNUNET_DatastoreValue) + size);
364   value->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
365   value->priority = htonl (priority);
366   value->anonymity_level = htonl (anonymityLevel);
367   value->expiration_time = GNUNET_htonll (expiration);
368   sock = GNUNET_client_connection_create (ectx, cfg);
369   if (sock == NULL)
370     {
371       GNUNET_free (value);
372       GNUNET_RSA_free_key (namespace_priv_key);
373       return NULL;
374     }
375   if (GNUNET_OK != GNUNET_FS_insert (sock, value))
376     {
377       GNUNET_free (value);
378       GNUNET_client_connection_destroy (sock);
379       GNUNET_RSA_free_key (namespace_priv_key);
380       return NULL;
381     }
382
383
384   /* publish KNBlocks */
385   size += sizeof (GNUNET_EC_KSBlock) - sizeof (GNUNET_EC_SBlock);
386   knvalue = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
387   *knvalue = *value;
388   knvalue->type = htonl (GNUNET_ECRS_BLOCKTYPE_KEYWORD_SIGNED);
389   knvalue->size = htonl (sizeof (GNUNET_DatastoreValue) + size);
390   ksb = (GNUNET_EC_KSBlock *) & knvalue[1];
391   ksb->type = htonl (GNUNET_ECRS_BLOCKTYPE_KEYWORD_SIGNED);
392   memcpy (&ksb->sblock,
393           sb, sizeof (GNUNET_EC_SBlock) + mdsize + strlen (rootEntry) + 2);
394
395   if (advertisementURI != NULL)
396     {
397       keywords = advertisementURI->data.ksk.keywords;
398       keywordCount = advertisementURI->data.ksk.keywordCount;
399       cpy =
400         GNUNET_malloc (size - sizeof (GNUNET_EC_KBlock) -
401                        sizeof (unsigned int));
402       memcpy (cpy,
403               &ksb->sblock,
404               size - sizeof (GNUNET_EC_KBlock) - sizeof (unsigned int));
405       for (i = 0; i < keywordCount; i++)
406         {
407           keyword = keywords[i];
408           /* first character of keyword indicates
409              mandatory or not -- ignore for hashing! */
410           GNUNET_hash (&keyword[1], strlen (&keyword[1]), &hc);
411           pk = GNUNET_RSA_create_key_from_hash (&hc);
412           GNUNET_RSA_get_public_key (pk, &ksb->kblock.keyspace);
413           GNUNET_GE_ASSERT (ectx,
414                             size - sizeof (GNUNET_EC_KBlock) -
415                             sizeof (unsigned int) ==
416                             sizeof (GNUNET_EC_SBlock) + mdsize +
417                             strlen (rootEntry) + 2);
418           GNUNET_ECRS_encryptInPlace (&hc, &ksb->sblock,
419                                       size - sizeof (GNUNET_EC_KBlock) -
420                                       sizeof (unsigned int));
421
422           GNUNET_GE_ASSERT (ectx,
423                             GNUNET_OK == GNUNET_RSA_sign (pk,
424                                                           size -
425                                                           sizeof
426                                                           (GNUNET_EC_KBlock) -
427                                                           sizeof (unsigned
428                                                                   int),
429                                                           &ksb->sblock,
430                                                           &ksb->
431                                                           kblock.signature));
432           /* extra check: verify sig */
433           GNUNET_RSA_free_key (pk);
434           if (GNUNET_OK != GNUNET_FS_insert (sock, knvalue))
435             {
436               GNUNET_GE_BREAK (ectx, 0);
437               GNUNET_free (cpy);
438               GNUNET_free (knvalue);
439               GNUNET_free (value);
440               GNUNET_client_connection_destroy (sock);
441               GNUNET_RSA_free_key (namespace_priv_key);
442               return NULL;
443             }
444           /* restore nblock to avoid re-encryption! */
445           memcpy (&ksb->sblock,
446                   cpy,
447                   size - sizeof (GNUNET_EC_KBlock) - sizeof (unsigned int));
448         }
449       GNUNET_free (cpy);
450     }
451   rootURI = GNUNET_malloc (sizeof (URI));
452   rootURI->type = sks;
453   GNUNET_hash (&sb->subspace,
454                sizeof (GNUNET_RSA_PublicKey), &rootURI->data.sks.namespace);
455   rootURI->data.sks.identifier = GNUNET_strdup (rootEntry);
456   GNUNET_free (knvalue);
457   GNUNET_free (value);
458   GNUNET_client_connection_destroy (sock);
459   GNUNET_RSA_free_key (namespace_priv_key);
460
461   return rootURI;
462 }
463
464 static struct GNUNET_RSA_PrivateKey *
465 read_namespace_key (struct GNUNET_GC_Configuration *cfg,
466                     const GNUNET_HashCode * pid)
467 {
468   char *fileName;
469   GNUNET_RSA_PrivateKeyEncoded *hke;
470   struct GNUNET_RSA_PrivateKey *hk;
471   char *dst;
472   unsigned long long len;
473
474   fileName = getPseudonymFileName (NULL, cfg, pid);
475   if (GNUNET_OK != GNUNET_disk_file_size (NULL, fileName, &len, GNUNET_YES))
476     {
477       GNUNET_free (fileName);
478       return NULL;
479     }
480   if (len < 2)
481     {
482       GNUNET_GE_LOG (NULL, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
483                      _("File `%s' does not contain a pseudonym.\n"),
484                      fileName);
485       GNUNET_free (fileName);
486       return NULL;
487     }
488   dst = GNUNET_malloc (len);
489   len = GNUNET_disk_file_read (NULL, fileName, len, dst);
490   hke = (GNUNET_RSA_PrivateKeyEncoded *) dst;
491   if (ntohs (hke->len) != len)
492     {
493       GNUNET_GE_LOG (NULL, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
494                      _("Format of pseudonym `%s' is invalid.\n"), fileName);
495       GNUNET_free (fileName);
496       GNUNET_free (hke);
497       return NULL;
498     }
499   GNUNET_free (fileName);
500   hk = GNUNET_RSA_decode_key (hke);
501   GNUNET_free (hke);
502   return hk;
503 }
504
505
506 /**
507  * Add an entry into a namespace.
508  *
509  * @param dstU to which URI should the namespace entry refer?
510  * @param md what meta-data should be associated with the
511  *        entry?
512  * @param thisId name of this entry in the namespace (keyword/identifier)
513  * @param nextId name of the update for this entry (to be published in
514  *               the future; maybe NULL)
515  * @param pid unique identifier of the namespace/pseudonym
516  * @return URI on success, NULL on error
517  */
518 struct GNUNET_ECRS_URI *
519 GNUNET_ECRS_namespace_add_content (struct GNUNET_GE_Context *ectx,
520                                    struct GNUNET_GC_Configuration *cfg,
521                                    const GNUNET_HashCode * pid,
522                                    uint32_t anonymityLevel,
523                                    uint32_t priority,
524                                    GNUNET_CronTime expiration,
525                                    const char *thisId,
526                                    const char *nextId,
527                                    const struct GNUNET_ECRS_URI *dstU,
528                                    const struct GNUNET_MetaData *md)
529 {
530   struct GNUNET_ECRS_URI *uri;
531   struct GNUNET_ClientServerConnection *sock;
532   GNUNET_DatastoreValue *value;
533   unsigned int size;
534   unsigned int mdsize;
535   struct GNUNET_RSA_PrivateKey *hk;
536   GNUNET_EC_SBlock *sb;
537   char *dstURI;
538   char *destPos;
539   GNUNET_HashCode hc;           /* hash of thisId = key */
540   GNUNET_HashCode hc2;          /* hash of hc = identifier */
541   int ret;
542   unsigned int nidlen;
543
544   hk = read_namespace_key (cfg, pid);
545   if (hk == NULL)
546     return NULL;
547
548   /* THEN: construct GNUNET_EC_SBlock */
549   dstURI = GNUNET_ECRS_uri_to_string (dstU);
550   mdsize = GNUNET_meta_data_get_serialized_size (md, GNUNET_SERIALIZE_PART);
551   if (nextId == NULL)
552     nextId = "";
553   nidlen = strlen (nextId) + 1;
554   size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (dstURI) + 1 + nidlen;
555   if (size > MAX_SBLOCK_SIZE)
556     {
557       size = MAX_SBLOCK_SIZE;
558       mdsize =
559         size - (sizeof (GNUNET_EC_SBlock) + strlen (dstURI) + 1 + nidlen);
560     }
561   value = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
562   sb = (GNUNET_EC_SBlock *) & value[1];
563   sb->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
564   destPos = (char *) &sb[1];
565   memcpy (destPos, nextId, nidlen);
566   destPos += nidlen;
567   memcpy (destPos, dstURI, strlen (dstURI) + 1);
568   destPos += strlen (dstURI) + 1;
569   mdsize = GNUNET_meta_data_serialize (ectx,
570                                        md,
571                                        destPos,
572                                        mdsize, GNUNET_SERIALIZE_PART);
573   if (mdsize == -1)
574     {
575       GNUNET_GE_BREAK (ectx, 0);
576       GNUNET_free (dstURI);
577       GNUNET_RSA_free_key (hk);
578       GNUNET_free (value);
579       return NULL;
580     }
581   size = sizeof (GNUNET_EC_SBlock) + mdsize + strlen (dstURI) + 1 + nidlen;
582   value->size = htonl (sizeof (GNUNET_DatastoreValue) + size);
583   value->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
584   value->priority = htonl (priority);
585   value->anonymity_level = htonl (anonymityLevel);
586   value->expiration_time = GNUNET_htonll (expiration);
587   GNUNET_hash (thisId, strlen (thisId), &hc);
588   GNUNET_hash (&hc, sizeof (GNUNET_HashCode), &hc2);
589   uri = GNUNET_malloc (sizeof (URI));
590   uri->type = sks;
591   GNUNET_RSA_get_public_key (hk, &sb->subspace);
592   GNUNET_hash (&sb->subspace,
593                sizeof (GNUNET_RSA_PublicKey), &uri->data.sks.namespace);
594   GNUNET_GE_BREAK (ectx, 0 == memcmp (&uri->data.sks.namespace,
595                                       pid, sizeof (GNUNET_HashCode)));
596   uri->data.sks.identifier = GNUNET_strdup (thisId);
597   GNUNET_hash_xor (&hc2, &uri->data.sks.namespace, &sb->identifier);
598   GNUNET_ECRS_encryptInPlace (&hc, &sb[1], size - sizeof (GNUNET_EC_SBlock));
599   GNUNET_GE_ASSERT (ectx,
600                     GNUNET_OK == GNUNET_RSA_sign (hk,
601                                                   size
602                                                   -
603                                                   sizeof
604                                                   (GNUNET_RSA_Signature) -
605                                                   sizeof
606                                                   (GNUNET_RSA_PublicKey) -
607                                                   sizeof (unsigned int),
608                                                   &sb->identifier,
609                                                   &sb->signature));
610   GNUNET_RSA_free_key (hk);
611   sock = GNUNET_client_connection_create (ectx, cfg);
612   ret = GNUNET_FS_insert (sock, value);
613   if (ret != GNUNET_OK)
614     {
615       GNUNET_free (uri);
616       uri = NULL;
617     }
618   GNUNET_client_connection_destroy (sock);
619   GNUNET_free (value);
620   GNUNET_free (dstURI);
621
622   return uri;
623 }
624
625 struct lNCLS
626 {
627   struct GNUNET_GE_Context *ectx;
628   struct GNUNET_GC_Configuration *cfg;
629   GNUNET_ECRS_NamespaceInfoProcessor cb;
630   void *cls;
631   int cnt;
632 };
633
634 static int
635 processFile_ (void *cls, const char *fileName)
636 {
637   struct lNCLS *c = cls;
638   struct GNUNET_RSA_PrivateKey *hk;
639   GNUNET_RSA_PrivateKeyEncoded *hke;
640   char *dst;
641   unsigned long long len;
642   GNUNET_HashCode namespace;
643   GNUNET_RSA_PublicKey pk;
644   const char *name;
645
646   if (GNUNET_OK !=
647       GNUNET_disk_file_size (c->ectx, fileName, &len, GNUNET_YES))
648     return GNUNET_OK;
649   if (len < 2)
650     {
651       GNUNET_GE_LOG (c->ectx,
652                      GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
653                      _("Format of file `%s' is invalid, trying to remove.\n"),
654                      fileName);
655       UNLINK (fileName);
656       return GNUNET_OK;
657     }
658   dst = GNUNET_malloc (len);
659   len = GNUNET_disk_file_read (c->ectx, fileName, len, dst);
660   hke = (GNUNET_RSA_PrivateKeyEncoded *) dst;
661   if (ntohs (hke->len) != len)
662     {
663       GNUNET_GE_LOG (c->ectx,
664                      GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
665                      _("Format of file `%s' is invalid, trying to remove.\n"),
666                      fileName);
667       UNLINK (fileName);
668       GNUNET_free (hke);
669       return GNUNET_OK;
670     }
671   hk = GNUNET_RSA_decode_key (hke);
672   GNUNET_free (hke);
673   if (hk == NULL)
674     {
675       GNUNET_GE_LOG (c->ectx,
676                      GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
677                      _("Format of file `%s' is invalid, trying to remove.\n"),
678                      fileName);
679       UNLINK (fileName);
680       GNUNET_GE_BREAK (c->ectx, 0);
681       return GNUNET_SYSERR;
682     }
683   GNUNET_RSA_get_public_key (hk, &pk);
684   GNUNET_RSA_free_key (hk);
685   GNUNET_hash (&pk, sizeof (GNUNET_RSA_PublicKey), &namespace);
686   if (NULL != c->cb)
687     {
688       name = fileName;
689       while (NULL != strstr (name, DIR_SEPARATOR_STR))
690         name = 1 + strstr (name, DIR_SEPARATOR_STR);
691       if (GNUNET_OK == c->cb (&namespace, name, c->cls))
692         c->cnt++;
693       else
694         c->cnt = GNUNET_SYSERR;
695     }
696   else
697     c->cnt++;
698   return GNUNET_OK;
699 }
700
701 /**
702  * Build a list of all available namespaces
703  *
704  * @param list where to store the names (is allocated, caller frees)
705  * @return GNUNET_SYSERR on error, otherwise the number of pseudonyms in list
706  */
707 int
708 GNUNET_ECRS_get_namespaces (struct GNUNET_GE_Context *ectx,
709                             struct GNUNET_GC_Configuration *cfg,
710                             GNUNET_ECRS_NamespaceInfoProcessor cb, void *cls)
711 {
712   char *dirName;
713   struct lNCLS myCLS;
714
715   myCLS.cls = cls;
716   myCLS.cb = cb;
717   myCLS.cnt = 0;
718   myCLS.ectx = ectx;
719   myCLS.cfg = cfg;
720   dirName = getPseudonymFileName (ectx, cfg, NULL);
721   GNUNET_disk_directory_scan (ectx, dirName, &processFile_, &myCLS);
722   GNUNET_free (dirName);
723   return myCLS.cnt;
724 }
725
726
727
728 /* end of namespace.c */
729 #endif