2 This file is part of GNUnet.
3 (C) 2009, 2010, 2012, 2013 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 3, 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_publish_ksk.c
23 * @brief publish a URI under a keyword in GNUnet
24 * @see https://gnunet.org/encoding and #2564
25 * @author Krista Bennett
26 * @author Christian Grothoff
30 #include "gnunet_constants.h"
31 #include "gnunet_signatures.h"
32 #include "gnunet_util_lib.h"
33 #include "gnunet_fs_service.h"
39 * Context for the KSK publication.
41 struct GNUNET_FS_PublishKskContext
47 struct GNUNET_FS_Uri *ksk_uri;
52 struct GNUNET_FS_Handle *h;
55 * The master block that we are sending
56 * (in plaintext), has "mdsize+slen" more
57 * bytes than the struct would suggest.
62 * Buffer of the same size as "kb" for
63 * the encrypted version.
68 * Handle to the datastore, NULL if we are just
71 struct GNUNET_DATASTORE_Handle *dsh;
74 * Handle to datastore PUT request.
76 struct GNUNET_DATASTORE_QueueEntry *qre;
81 GNUNET_SCHEDULER_TaskIdentifier ksk_task;
84 * Function to call once we're done.
86 GNUNET_FS_PublishContinuation cont;
94 * When should the KBlocks expire?
96 struct GNUNET_FS_BlockOptions bo;
99 * Size of the serialized metadata.
104 * Size of the (CHK) URI as a string.
109 * Keyword that we are currently processing.
117 * Continuation of "GNUNET_FS_publish_ksk" that performs
118 * the actual publishing operation (iterating over all
121 * @param cls closure of type "struct PublishKskContext*"
125 publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
129 * Function called by the datastore API with
130 * the result from the PUT request.
132 * @param cls closure of type "struct GNUNET_FS_PublishKskContext*"
133 * @param success GNUNET_OK on success
134 * @param min_expiration minimum expiration time required for content to be stored
135 * @param msg error message (or NULL)
138 kb_put_cont (void *cls, int success,
139 struct GNUNET_TIME_Absolute min_expiration,
142 struct GNUNET_FS_PublishKskContext *pkc = cls;
145 if (GNUNET_OK != success)
147 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
148 "KBlock PUT operation failed: %s\n", msg);
149 pkc->cont (pkc->cont_cls, NULL, msg);
150 GNUNET_FS_publish_ksk_cancel (pkc);
153 pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc);
158 * Continuation of "GNUNET_FS_publish_ksk" that performs the actual
159 * publishing operation (iterating over all of the keywords).
161 * @param cls closure of type "struct GNUNET_FS_PublishKskContext*"
165 publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
167 struct GNUNET_FS_PublishKskContext *pkc = cls;
169 struct GNUNET_HashCode key;
170 struct GNUNET_HashCode seed;
171 struct GNUNET_HashCode signing_key;
172 struct GNUNET_HashCode query;
173 struct GNUNET_CRYPTO_AesSessionKey skey;
174 struct GNUNET_CRYPTO_AesInitializationVector iv;
175 struct GNUNET_FS_PseudonymHandle *ph;
176 struct GNUNET_FS_PseudonymIdentifier pseudonym;
177 struct UBlock *ub_dst;
179 pkc->ksk_task = GNUNET_SCHEDULER_NO_TASK;
180 if ((pkc->i == pkc->ksk_uri->data.ksk.keywordCount) || (NULL == pkc->dsh))
182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KSK PUT operation complete\n");
183 pkc->cont (pkc->cont_cls, pkc->ksk_uri, NULL);
184 GNUNET_FS_publish_ksk_cancel (pkc);
187 /* derive signing seed from plaintext */
188 GNUNET_CRYPTO_hash (&pkc->ub[1],
189 1 + pkc->slen + pkc->mdsize,
191 keyword = pkc->ksk_uri->data.ksk.keywords[pkc->i++];
192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing under keyword `%s'\n",
194 /* first character of keyword indicates if it is
195 * mandatory or not -- ignore for hashing */
196 GNUNET_CRYPTO_hash (&keyword[1], strlen (&keyword[1]), &key);
197 GNUNET_CRYPTO_hash_to_aes_key (&key, &skey, &iv);
199 GNUNET_CRYPTO_aes_encrypt (&pkc->ub[1],
200 1 + pkc->slen + pkc->mdsize,
203 ph = GNUNET_FS_pseudonym_get_anonymous_pseudonym_handle ();
204 GNUNET_CRYPTO_hash (&key, sizeof (key), &signing_key);
205 ub_dst->purpose.size = htonl (1 + pkc->slen + pkc->mdsize + sizeof (struct UBlock)
206 - sizeof (struct GNUNET_FS_PseudonymSignature));
207 ub_dst->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK);
209 GNUNET_FS_pseudonym_get_identifier (ph, &pseudonym);
210 GNUNET_FS_pseudonym_derive_verification_key (&pseudonym,
212 &ub_dst->verification_key);
213 GNUNET_FS_pseudonym_sign (ph,
219 GNUNET_CRYPTO_hash (&ub_dst->verification_key,
220 sizeof (ub_dst->verification_key),
222 GNUNET_FS_pseudonym_destroy (ph);
224 GNUNET_DATASTORE_put (pkc->dsh, 0, &query,
225 1 + pkc->slen + pkc->mdsize + sizeof (struct UBlock),
226 ub_dst, GNUNET_BLOCK_TYPE_FS_UBLOCK,
227 pkc->bo.content_priority, pkc->bo.anonymity_level,
228 pkc->bo.replication_level, pkc->bo.expiration_time,
229 -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT,
235 * Publish a CHK under various keywords on GNUnet.
237 * @param h handle to the file sharing subsystem
238 * @param ksk_uri keywords to use
239 * @param meta metadata to use
240 * @param uri URI to refer to in the KBlock
241 * @param bo per-block options
242 * @param options publication options
243 * @param cont continuation
244 * @param cont_cls closure for cont
245 * @return NULL on error ('cont' will still be called)
247 struct GNUNET_FS_PublishKskContext *
248 GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h,
249 const struct GNUNET_FS_Uri *ksk_uri,
250 const struct GNUNET_CONTAINER_MetaData *meta,
251 const struct GNUNET_FS_Uri *uri,
252 const struct GNUNET_FS_BlockOptions *bo,
253 enum GNUNET_FS_PublishOptions options,
254 GNUNET_FS_PublishContinuation cont, void *cont_cls)
256 struct GNUNET_FS_PublishKskContext *pkc;
262 GNUNET_assert (NULL != uri);
263 pkc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishKskContext));
267 pkc->cont_cls = cont_cls;
268 if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY))
270 pkc->dsh = GNUNET_DATASTORE_connect (h->cfg);
271 if (NULL == pkc->dsh)
273 cont (cont_cls, NULL, _("Could not connect to datastore."));
281 pkc->mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
282 GNUNET_assert (pkc->mdsize >= 0);
283 uris = GNUNET_FS_uri_to_string (uri);
284 pkc->slen = strlen (uris) + 1;
285 size = pkc->mdsize + sizeof (struct UBlock) + pkc->slen + 1;
286 if (size > MAX_UBLOCK_SIZE)
288 size = MAX_UBLOCK_SIZE;
289 pkc->mdsize = size - sizeof (struct UBlock) - pkc->slen + 1;
291 pkc->ub = GNUNET_malloc (size);
292 kbe = (char *) &pkc->ub[1];
293 kbe++; /* leave one '\0' for the update identifier */
294 memcpy (kbe, uris, pkc->slen);
296 sptr = &kbe[pkc->slen];
299 GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, pkc->mdsize,
300 GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
301 if (-1 == pkc->mdsize)
304 GNUNET_free (pkc->ub);
305 if (NULL != pkc->dsh)
307 GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
311 cont (cont_cls, NULL, _("Internal error."));
314 size = sizeof (struct UBlock) + pkc->slen + pkc->mdsize + 1;
315 pkc->cpy = GNUNET_malloc (size);
316 pkc->ksk_uri = GNUNET_FS_uri_dup (ksk_uri);
317 pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc);
323 * Abort the KSK publishing operation.
325 * @param pkc context of the operation to abort.
328 GNUNET_FS_publish_ksk_cancel (struct GNUNET_FS_PublishKskContext *pkc)
330 if (GNUNET_SCHEDULER_NO_TASK != pkc->ksk_task)
332 GNUNET_SCHEDULER_cancel (pkc->ksk_task);
333 pkc->ksk_task = GNUNET_SCHEDULER_NO_TASK;
335 if (NULL != pkc->qre)
337 GNUNET_DATASTORE_cancel (pkc->qre);
340 if (NULL != pkc->dsh)
342 GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
345 GNUNET_free (pkc->cpy);
346 GNUNET_free (pkc->ub);
347 GNUNET_FS_uri_destroy (pkc->ksk_uri);
352 /* end of fs_publish_ksk.c */