diff options
author | Christian Grothoff <christian@grothoff.org> | 2009-08-22 17:57:31 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2009-08-22 17:57:31 +0000 |
commit | 2ae973618f3b51fa9bbf5532eaa1352cafc24ecc (patch) | |
tree | ea8bb13a4c7d390f88318b61bc6caf50ea6cf400 /src/fs/fs_namespace.c | |
parent | 9a10e9c06a3b08c8ab73edb7d2093a6d452ecc05 (diff) | |
download | gnunet-2ae973618f3b51fa9bbf5532eaa1352cafc24ecc.tar.gz gnunet-2ae973618f3b51fa9bbf5532eaa1352cafc24ecc.zip |
stuff
Diffstat (limited to 'src/fs/fs_namespace.c')
-rw-r--r-- | src/fs/fs_namespace.c | 729 |
1 files changed, 729 insertions, 0 deletions
diff --git a/src/fs/fs_namespace.c b/src/fs/fs_namespace.c new file mode 100644 index 000000000..fb45d99e9 --- /dev/null +++ b/src/fs/fs_namespace.c | |||
@@ -0,0 +1,729 @@ | |||
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_MetaData *meta, | ||
50 | unsigned int anonymity, | ||
51 | unsigned int 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_MetaData *meta, | ||
288 | unsigned int anonymityLevel, | ||
289 | unsigned int 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 | unsigned int anonymityLevel, | ||
523 | unsigned int 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 | ||